diff options
author | James <> | 2015-11-04 11:49:21 +0000 |
---|---|---|
committer | James <> | 2015-11-04 11:49:21 +0000 |
commit | 716ca530e1c4515d8683c9d5be3d56b301758b66 (patch) | |
tree | 700eb5bcc1a462a5f21dcec15ce7c97ecfefa772 /target/linux/ramips | |
download | trunk-47381-master.tar.gz trunk-47381-master.tar.bz2 trunk-47381-master.zip |
Diffstat (limited to 'target/linux/ramips')
378 files changed, 73525 insertions, 0 deletions
diff --git a/target/linux/ramips/Makefile b/target/linux/ramips/Makefile new file mode 100644 index 0000000..eafd274 --- /dev/null +++ b/target/linux/ramips/Makefile @@ -0,0 +1,26 @@ +# +# Copyright (C) 2008-2011 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +include $(TOPDIR)/rules.mk + +ARCH:=mipsel +BOARD:=ramips +BOARDNAME:=Ralink RT288x/RT3xxx +SUBTARGETS:=rt305x mt7620 mt7621 mt7628 mt7688 rt3883 rt288x +FEATURES:=squashfs gpio +MAINTAINER:=John Crispin <blogic@openwrt.org> + +KERNEL_PATCHVER:=3.18 + +include $(INCLUDE_DIR)/target.mk +DEFAULT_PACKAGES += \ + kmod-leds-gpio kmod-gpio-button-hotplug wpad-mini swconfig + +define Target/Description + Build firmware images for Ralink RT288x/RT3xxx based boards. +endef + +$(eval $(call BuildTarget)) diff --git a/target/linux/ramips/base-files.mk b/target/linux/ramips/base-files.mk new file mode 100644 index 0000000..d6682bd --- /dev/null +++ b/target/linux/ramips/base-files.mk @@ -0,0 +1,5 @@ +define Package/base-files/install-target + rm -f $(1)/etc/config/network +endef + + diff --git a/target/linux/ramips/base-files/etc/board.d/01_leds b/target/linux/ramips/base-files/etc/board.d/01_leds new file mode 100755 index 0000000..5627c8c --- /dev/null +++ b/target/linux/ramips/base-files/etc/board.d/01_leds @@ -0,0 +1,275 @@ +#!/bin/sh + +. /lib/functions/uci-defaults-new.sh +. /lib/ramips.sh + +set_usb_led() { + ucidef_set_led_usbdev "usb" "USB" "$1" "1-1" +} + +set_wifi_led() { + ucidef_set_led_netdev "wifi_led" "wifi" "$1" "wlan0" +} + + +board=$(ramips_board_name) + +board_config_update + +case $board in +3g150b|\ +3g300m) + set_usb_led "$board:blue:3g" + ;; +3g-6200n) + set_wifi_led "$board:amber:wlan" + set_usb_led "$board:blue:3g" + ;; +3g-6200nl|\ +br-6475nd|\ +mzk-w300nh2) + set_wifi_led "$board:amber:wlan" + ;; +a5-v11) + ucidef_set_led_default "power" "POWER" "$board:red:power" "1" + ;; +ai-br100) + ucidef_set_led_netdev "wan" "wan" "$board:blue:wan" "eth0.2" + set_wifi_led "$board:blue:wlan" + ;; +air3gii) + set_wifi_led "$board:green:wlan" + set_usb_led "$board:green:mobile" + ;; +all0239-3g|\ +hw550-3g|\ +mofi3500-3gn|\ +sap-g3200u3) + set_usb_led "$board:green:usb" + ;; +all0256n) + ucidef_set_rssimon "wlan0" "40000" "1" + ucidef_set_led_rssi "rssilow" "RSSILOW" "$board:green:rssilow" "wlan0" "1" "40" "0" "6" + ucidef_set_led_rssi "rssimedium" "RSSIMEDIUM" "$board:green:rssimed" "wlan0" "30" "80" "-29" "5" + ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "$board:green:rssihigh" "wlan0" "70" "100" "-69" "8" + set_wifi_led "rt2800pci-phy0::radio" + ;; +ar670w|\ +ar725w|\ +awapn2403) + set_wifi_led "rt2800soc-phy0::radio" + ;; +asl26555) + ucidef_set_led_default "power" "POWER" "$board:green:power" "1" + ucidef_set_led_netdev "eth" "ETH" "$board:green:eth" "eth0" + set_wifi_led "$board:green:wlan" + set_usb_led "$board:green:3g" + ;; +bc2) + set_usb_led "$board:blue:usb" + ;; +br-6425) + set_wifi_led "$board:orange:wlan" + ;; +broadway) + set_usb_led "$board:red:diskmounted" + set_wifi_led "$board:red:wps_active" + ;; +cf-wr800n) + ucidef_set_led_netdev "lan" "lan" "$board:white:ethernet" eth0.1 + set_wifi_led "$board:white:wifi" + ;; +cy-swr1100) + ucidef_set_led_default "wps" "WPS" "$board:blue:wps" "0" + set_usb_led "$board:blue:usb" + ;; +d105) + ucidef_set_led_default "power" "POWER" "$board:red:power" "1" + set_usb_led "$board:green:usb" + ;; +db-wrt01) + ucidef_set_led_default "power" "power" "$board:orange:power" "1" + ;; +dcs-930l-b1) + ucidef_set_led_default "power" "POWER" "$board:red:power" "1" + ucidef_set_led_netdev "wifi" "WiFi" "$board:blue:wps" + ;; +dir-300-b1|\ +dir-600-b1|\ +dir-600-b2|\ +dir-620-a1) + ucidef_set_led_default "wan" "WAN LED (amber)" "$board:amber:wan" "1" + set_wifi_led "rt2800pci-phy0::radio" + ;; +dir-300-b7|\ +dir-320-b1|\ +dir-610-a1|\ +esr-9753|\ +hlk-rm04|\ +sl-r7205|\ +v11st-fe|\ +w306r-v20|\ +wt1520) + set_wifi_led "rt2800pci-phy0::radio" + ;; +dir-615-d|\ +dir-615-h1) + ucidef_set_led_default "status" "Status LED (amber)" "$board:amber:status" "0" + set_wifi_led "rt2800pci-phy0::radio" + ;; +dir-620-d1) + set_wifi_led "$board:green:wifi" + ;; +dir-810l|\ +mzk-dp150n) + ucidef_set_led_default "power" "power" "$board:green:power" "1" + ;; +f5d8235-v1|\ +f5d8235-v2) + set_usb_led "$board:blue:storage" + ;; +fonera20n) + set_usb_led "$board:orange:usb" + set_wifi_led "$board:orange:wifi" + ;; +hc5661) + ucidef_set_led_default "system" "system" "$board:blue:system" "1" + ucidef_set_led_netdev "internet" "internet" "$board:blue:internet" "eth0.2" + set_wifi_led "$board:blue:wlan2g" + ;; +hc5761) + ucidef_set_led_default "system" "system" "$board:blue:system" "1" + ucidef_set_led_netdev "internet" "internet" "$board:blue:internet" "eth0.2" + set_wifi_led "$board:blue:wlan2g" + ucidef_set_led_netdev "wifi5g" "wifi5g" "$board:blue:wlan5g" "rai0" + ;; +hc5861) + ucidef_set_led_default "system" "system" "$board:blue:system" "1" + ucidef_set_led_netdev "internet" "internet" "$board:blue:internet" "eth0.2" + set_wifi_led "$board:blue:wlan2g" + ucidef_set_led_netdev "wifi5g" "wifi5g" "$board:blue:wlan5g" "rai0" + ucidef_set_led_default "turbo" "turbo" "$board:blue:turbo" "0" + ;; +hg255d) + set_wifi_led "$board:green:wlan" + set_usb_led "$board:green:usb" + ucidef_set_led_interface "lan" "$board:green:internet" + ;; +hpm) + ucidef_set_led_default "power" "POWER" "$board:orange:power" "1" + ucidef_set_led_netdev "eth" "ETH" "$board:green:eth" "eth0" + set_wifi_led "$board:green:wifi" + ;; +ht-tm02) + ucidef_set_led_netdev "eth" "Ethernet" "$board:green:lan" "eth0" + set_wifi_led "$board:blue:wlan" + ;; +m2m) + set_wifi_led "$board:blue:wifi" + ucidef_set_led_netdev "eth" "Ethernet" "$board:green:wan" "eth0" + ;; +miniembplug) + set_wifi_led "$board:red:wlan" + set_usb_led "$board:green:mobile" + ;; +miwifi-mini) + ucidef_set_led_default "power" "power" "$board:red:status" "1" + ;; +mlw221|\ +mlwg2) + set_wifi_led "$board:blue:wifi" + ucidef_set_led_default "system" "system" "$board:blue:system" "1" + ;; +mpr-a1|\ +mpr-a2) + set_wifi_led "$board:blue:system" + ;; +mr-102n) + set_wifi_led "$board:green:wlan" + set_usb_led "$board:green:usb" + ;; +na930) + set_usb_led "$board:blue:status" + ;; +nw718) + set_usb_led "$board:amber:usb" + ;; +oy-0001) + ucidef_set_led_default "power" "power" "$board:green:power" "1" + set_wifi_led "$board:green:wifi" + ;; +pbr-m1) + ucidef_set_led_netdev "internet" "internet" "$board:green:internet" "eth0.2" + ucidef_set_led_default "power" "power" "$board:green:power" "1" + ucidef_set_led_default "sys" "sys" "$board:green:sys" "1" + ;; +px-4885) + set_wifi_led "$board:orange:wifi" + set_usb_led "$board:blue:storage" + ;; +re6500) + ucidef_set_led_default "power" "power" "$board:white:power" "1" + ucidef_set_led_default "wifi" "wifi" "$board:orange:wifi" "1" + ;; +rp-n53) + ucidef_set_led_netdev "eth" "Network" "$board:white:back" "eth0" + set_wifi_led "$board:blue:wifi" + ;; +rt-n14u) + ucidef_set_led_default "power" "power" "$board:blue:power" "1" + ucidef_set_led_netdev "lan" "lan" "$board:blue:lan" eth0.1 + ucidef_set_led_netdev "wan" "wan" "$board:blue:wan" eth0.2 + set_wifi_led "$board:blue:air" + set_usb_led "$board:blue:usb" + ;; +tiny-ac) + set_wifi_led "$board:orange:wifi" + set_usb_led "$board:green:usb" + ;; +vocore) + ucidef_set_led_netdev "eth" "ETH" "$board:orange:eth" "eth0" + set_wifi_led "$board:green:status" + ;; +w502u) + set_usb_led "$board:blue:usb" + set_wifi_led "rt2800pci-phy0::radio" + ;; +wcr-150gn) + set_usb_led "$board:amber:user" + ;; +whr-1166d|\ +whr-300hp2|\ +whr-600d) + ucidef_set_led_default "power" "power" "$board:green:power" "1" + ucidef_set_led_default "router" "router" "$board:green:router" "1" + ;; +wnce2001) + set_wifi_led "$board:green:wlan" + ;; +wt3020) + ucidef_set_led_default "power" "power" "$board:blue:power" "0" + ;; +y1|\ +y1s) + ucidef_set_led_default "power" "power" "$board:blue:power" "1" + set_usb_led "$board:blue:usb" + set_wifi_led "$board:blue:wifi" + ;; +zbt-wa05) + ucidef_set_led_default "power" "power" "$board:blue:power" "1" + set_wifi_led "$board:blue:air" + set_usb_led "$board:blue:usb" + ;; +zbt-wr8305rt) + ucidef_set_led_default "power" "power" "$board:green:sys" "1" + set_usb_led "$board:green:usb" + set_wifi_led "$board:green:wifi" + ;; +zte-q7) + set_wifi_led "$board:blue:status" + ;; +esac + +board_config_flush + +exit 0 diff --git a/target/linux/ramips/base-files/etc/board.d/02_network b/target/linux/ramips/base-files/etc/board.d/02_network new file mode 100755 index 0000000..3821742 --- /dev/null +++ b/target/linux/ramips/base-files/etc/board.d/02_network @@ -0,0 +1,381 @@ +#!/bin/sh + +. /lib/functions.sh +. /lib/ramips.sh +. /lib/functions/uci-defaults-new.sh +. /lib/functions/system.sh + +ramips_setup_rt3x5x_vlans() +{ + if [ ! -x /sbin/swconfig ]; then + # legacy default + ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + return + fi + local wanports="" + local lanports="" + for port in 5 4 3 2 1 0; do + if [ `swconfig dev rt305x port $port get disable` = "1" ]; then + continue + fi + if [ `swconfig dev rt305x port $port get lan` = "0" ]; then + wanports="$port $wanports" + else + lanports="$port $lanports" + fi + done + ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + ucidef_add_switch "rt305x" "1" "1" + ucidef_add_switch_vlan "rt305x" "1" "$lanports 6t" + ucidef_add_switch_vlan "rt305x" "2" "$wanports 6t" +} + +ramips_setup_interfaces() +{ + local board="$1" + + ucidef_set_interface_loopback + + case $board in + 3g150b|\ + 3g300m|\ + all0256n|\ + all5002|\ + all5003|\ + broadway|\ + dcs-930|\ + dcs-930l-b1|\ + ht-tm02|\ + linkits7688 | \ + linkits7688d | \ + microwrt|\ + ncs601w|\ + w150m|\ + wnce2001|\ + zte-q7) + ucidef_add_switch "switch0" "1" "0" + ucidef_set_interface_lan "eth0" + ;; + 3g-6200nl|\ + mlw221|\ + mr-102n) + ucidef_set_interface_lan "eth0.2" + ;; + 3g-6200n|\ + ai-br100|\ + db-wrt01|\ + dir-300-b7|\ + dir-320-b1|\ + dir-610-a1|\ + dir-615-h1|\ + firewrt|\ + hlk-rm04|\ + miwifi-mini|\ + mt7621|\ + mt7628|\ + mzk-750dhp|\ + mzk-w300nh2|\ + oy-0001|\ + pbr-m1|\ + sap-g3200u3|\ + whr-300hp2|\ + whr-600d|\ + wsr-1166|\ + wsr-600|\ + wt1520|\ + y1|\ + zbt-wg2626) + ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + ucidef_add_switch "switch0" "1" "1" + ucidef_add_switch_vlan "switch0" "1" "0 1 2 3 6t" + ucidef_add_switch_vlan "switch0" "2" "4 6t" + ;; + a5-v11) + ucidef_set_interface_lan "eth0.1" + ucidef_add_switch "switch0" "1" "1" + ucidef_add_switch_vlan "switch0" "1" "0 6t" + ;; + ar670w|\ + ar725w|\ + rt-n15|\ + wl-351) + ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + ucidef_add_switch "switch0" "1" "1" + ucidef_add_switch_vlan "switch0" "1" "0 1 2 3 5t" + ucidef_add_switch_vlan "switch0" "2" "4 5t" + ;; + asl26555|\ + re6500|\ + rp-n53) + ucidef_set_interface_lan "eth0.1" + ucidef_add_switch "switch0" "1" "1" + ucidef_add_switch_vlan "switch0" "1" "1 2 3 4 6t" + ;; + atp-52b|\ + awm002-evb|\ + awm003-evb|\ + dir-645|\ + dir-860l-b1|\ + f5d8235-v1|\ + f5d8235-v2|\ + hg255d|\ + rt-n14u|\ + ur-326n4g|\ + wrtnode|\ + wt3020|\ + zbt-wa05) + ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + ucidef_add_switch "switch0" "1" "1" + ucidef_add_switch_vlan "switch0" "1" "1 2 3 4 6t" + ucidef_add_switch_vlan "switch0" "2" "0 6t" + ;; + awapn2403) + ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + ucidef_add_switch "switch0" "1" "1" + ucidef_add_switch_vlan "switch0" "1" "0 6t" + ucidef_add_switch_vlan "switch0" "2" "1 6t" + ;; + b2c|\ + nw718|\ + psr-680w|\ + sl-r7205|\ + ur-336un|\ + w502u|\ + wr6202) + ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + ;; + br-6475nd) + ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + ucidef_add_switch "switch0" "1" "1" + ucidef_add_switch_vlan "switch0" "1" "1 2 3 4 9t" + ucidef_add_switch_vlan "switch0" "2" "0 9t" + ;; + cf-wr800n) + ucidef_set_interface_lan "eth0.1" + ucidef_add_switch "switch0" "1" "1" + ucidef_add_switch_vlan "switch0" "1" "4 6t" + ;; + cy-swr1100) + ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + ucidef_add_switch "switch0" "1" "1" + ucidef_add_switch_vlan "switch0" "1" "0 1 2 3 9t" + ucidef_add_switch_vlan "switch0" "2" "4 9t" + ;; + d105|\ + hpm|\ + na930|\ + wli-tx4-ag300n) + ucidef_set_interface_lan "eth0" + ;; + e1700|\ + mt7620a_mt7530) + ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + ucidef_add_switch "switch1" "1" "1" + ucidef_add_switch_vlan "switch1" "1" "0 1 2 3 6t" + ucidef_add_switch_vlan "switch1" "2" "4 6t" + ;; + hc5*61|\ + y1s) + ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + ucidef_add_switch "switch0" "1" "1" + ucidef_add_switch_vlan "switch0" "1" "1 2 3 4 5 6t" + ucidef_add_switch_vlan "switch0" "2" "0 6t" + ;; + m2m) + ucidef_add_switch "switch0" "4" + ucidef_set_interface_lan "eth0" + ;; + mlwg2|\ + wizard8800|\ + wl-330n|\ + wmr-300) + ucidef_set_interface_lan "eth0.1" + ;; + mzk-dp150n|\ + vocore) + ucidef_set_interface_lan "eth0.1" + ucidef_add_switch "switch0" "1" "1" + ucidef_add_switch_vlan "switch0" "1" "0 4 6t" + ;; + rt-n56u) + ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + ucidef_add_switch "switch0" "1" "1" + ucidef_add_switch_vlan "switch0" "1" "0 1 2 3 8t" + ucidef_add_switch_vlan "switch0" "2" "4 8t" + ;; + tew-691gr|\ + tew-692gr) + ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + ucidef_add_switch "switch0" "1" "1" + ucidef_add_switch_vlan "switch0" "1" "0t 1 2 3 4" + ucidef_add_switch_vlan "switch0" "2" "0t 5" + ;; + v11st-fe|\ + wzr-agl300nh) + ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + ucidef_add_switch "switch0" "1" "1" + ucidef_add_switch_vlan "switch0" "1" "1 2 3 4 5t" + ucidef_add_switch_vlan "switch0" "2" "0 5t" + ;; + wcr-150gn) + ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + ucidef_add_switch "switch0" "1" "1" + ucidef_add_switch_vlan "switch0" "1" "0 6t" + ucidef_add_switch_vlan "switch0" "2" "6t" + ;; + whr-1166d) + ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + ucidef_add_switch "switch0" "1" "1" + ucidef_add_switch_vlan "switch0" "1" "0 1 2 3 6t" + ucidef_add_switch_vlan "switch0" "2" "5 6t" + ;; + wizfi630a) + ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + ucidef_add_switch "switch0" "1" "1" + ucidef_add_switch_vlan "switch0" "1" "1 2 6t" + ucidef_add_switch_vlan "switch0" "2" "0 6t" + ;; + zbt-wr8305rt) + ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + ucidef_add_switch "switch0" "1" "1" + ucidef_add_switch_vlan "switch0" "1" "0 1 2 3 4 6t" + ucidef_add_switch_vlan "switch0" "2" "4 6t" + ;; + *) + RT3X5X=`cat /proc/cpuinfo | egrep "(RT3.5|RT5350)"` + if [ -n "${RT3X5X}" ]; then + ramips_setup_rt3x5x_vlans + else + ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" + fi + ;; + esac +} + +ramips_setup_macs() +{ + local board="$1" + local lan_mac="" + local wan_mac="" + + case $board in + a5-v11|\ + bc2|\ + broadway|\ + d105|\ + dir-300-b7|\ + dir-320-b1|\ + dir-620-a1|\ + esr-9753|\ + freestation5|\ + hlk-rm04|\ + mpr-a1|\ + mpr-a2|\ + psr-680w|\ + sl-r7205|\ + y1|\ + y1s) + lan_mac=$(cat /sys/class/net/eth0/address) + lan_mac=$(macaddr_setbit_la "$lan_mac") + wan_mac=$(macaddr_add "$lan_mac" 1) + ;; + all0239-3g|\ + carambola|\ + freestation5|\ + w502u|\ + wnce2001) + wan_mac=$(mtd_get_mac_binary factory 46) + ;; + br-6475nd) + lan_mac=$(cat /sys/class/net/eth0/address) + wan_mac=$(mtd_get_mac_binary devdata 7) + ;; + cy-swr1100|\ + dir-645) + lan_mac=$(mtd_get_mac_ascii nvram lanmac) + wan_mac=$(mtd_get_mac_ascii nvram wanmac) + ;; + e1700) + wan_mac=$(mtd_get_mac_ascii config WAN_MAC_ADDR) + ;; + hc5*61) + lan_mac=`mtd_get_mac_ascii bdinfo "Vfac_mac "` + [ -n "$lan_mac" ] || lan_mac=$(cat /sys/class/net/eth0/address) + wan_mac=$(macaddr_add "$lan_mac" 1) + ;; + ht-tm02) + lan_mac=$(cat /sys/class/net/eth0/address) + ;; + linkits7688 | \ + linkits7688d) + wan_mac=$(mtd_get_mac_binary factory 4) + lan_mac=$(mtd_get_mac_binary factory 46) + ;; + m3|\ + m4|\ + x5|\ + x8) + lan_mac=$(cat /sys/class/net/eth0/address) + lan_mac=$(macaddr_add "$lan_mac" -2) + ;; + oy-0001) + lan_mac=$(mtd_get_mac_binary factory 40) + wan_mac=$(mtd_get_mac_binary factory 46) + ;; + rt-n56u) + lan_mac=$(cat /sys/class/net/eth0/address) + lan_mac=$(macaddr_setbit_la "$lan_mac") + wan_mac=$(mtd_get_mac_binary factory 32772) + ;; + tew-691gr) + lan_mac=$(cat /sys/class/net/eth0/address) + wan_mac=$(macaddr_add "$lan_mac" 3) + ;; + tew-692gr) + lan_mac=$(cat /sys/class/net/eth0/address) + wan_mac=$(macaddr_add "$lan_mac" 4) + ;; + tiny-ac) + lan_mac=$(mtd_get_mac_ascii u-boot-env LAN_MAC_ADDR) + wan_mac=$(mtd_get_mac_ascii u-boot-env WAN_MAC_ADDR) + ;; + w306r-v20) + lan_mac=$(cat /sys/class/net/eth0/address) + wan_mac=$(macaddr_add "$lan_mac" 5) + ;; + wcr-150gn) + wan_mac=$(mtd_get_mac_binary factory 40) + ;; + whr-1166d|\ + whr-300hp2|\ + whr-600d|\ + wsr-600) + wan_mac=$(mtd_get_mac_binary factory 4) + lan_mac=$wan_mac + ;; + wizfi630a) + lan_mac=$(mtd_get_mac_binary factory 4) + wan_mac=$(mtd_get_mac_binary factory 40) + ;; + wsr-1166) + local index="$(find_mtd_index "board_data")" + wan_mac="$(grep -m1 mac= "/dev/mtd${index}" | cut -d= -f2)" + lan_mac=$wan_mac + ;; + *) + lan_mac=$(cat /sys/class/net/eth0/address) + wan_mac=$(macaddr_add "$lan_mac" 1) + ;; + esac + + [ -n "$lan_mac" ] && ucidef_set_interface_macaddr lan $lan_mac + [ -n "$wan_mac" ] && ucidef_set_interface_macaddr wan $wan_mac +} + +board_config_update +board=$(ramips_board_name) +ramips_setup_interfaces $board +ramips_setup_macs $board +board_config_flush + +exit 0 diff --git a/target/linux/ramips/base-files/etc/diag.sh b/target/linux/ramips/base-files/etc/diag.sh new file mode 100644 index 0000000..3013d24 --- /dev/null +++ b/target/linux/ramips/base-files/etc/diag.sh @@ -0,0 +1,203 @@ +#!/bin/sh +# Copyright (C) 2010-2013 OpenWrt.org + +. /lib/functions/leds.sh +. /lib/ramips.sh + +get_status_led() { + board=$(ramips_board_name) + + case $board in + 3g150b|\ + 3g300m|\ + w150m) + status_led="$board:blue:ap" + ;; + 3g-6200n|\ + ar670w|\ + ar725w|\ + asl26555|\ + br-6425|\ + br-6475nd|\ + e1700|\ + fonera20n|\ + mzk-dp150n|\ + mzk-w300nh2|\ + nbg-419n|\ + pwh2004|\ + wnce2001|\ + x5|\ + x8|\ + xdxrn502j) + status_led="$board:green:power" + ;; + a5-v11|\ + d105|\ + dcs-930l-b1|\ + hlk-rm04|\ + mpr-a1|\ + mpr-a2) + status_led="$board:red:power" + ;; + ai-br100|\ + ht-tm02) + status_led="$board:blue:wlan" + ;; + all0239-3g|\ + dcs-930|\ + dir-300-b1|\ + dir-300-b7|\ + dir-320-b1|\ + dir-600-b1|\ + dir-600-b2|\ + dir-610-a1|\ + dir-615-d|\ + dir-615-h1|\ + dir-620-a1|\ + dir-620-d1|\ + hpm|\ + hw550-3g|\ + miniembwifi|\ + mofi3500-3gn|\ + rut5xx|\ + v11st-fe|\ + vocore|\ + wmr-300|\ + zbt-wg2626) + status_led="$board:green:status" + ;; + atp-52b|\ + ip2202) + status_led="$board:green:run" + ;; + awapn2403|\ + dir-645) + status_led="$board:green:wps" + ;; + cf-wr800n) + status_led="$board:white:wps" + ;; + cy-swr1100|\ + w502u) + status_led="$board:blue:wps" + ;; + dap-1350|\ + na930|\ + rt-n13u|\ + rt-n14u|\ + rt-n15|\ + rt-n56u|\ + wl-330n|\ + wl-330n3g|\ + wli-tx4-ag300n|\ + wt3020|\ + y1|\ + y1s) + status_led="$board:blue:power" + ;; + db-wrt01|\ + esr-9753) + status_led="$board:orange:power" + ;; + f5d8235-v2) + status_led="$board:blue:router" + ;; + f7c027) + status_led="$board:orange:status" + ;; + hc5*61|\ + mlw221|\ + mlwg2) + status_led="$board:blue:system" + ;; + linkits7688| \ + linkits7688d) + [ "$1" = "upgrade" ] && status_led="mediatek:orange:wifi" + ;; + m2m) + status_led="$board:blue:wifi" + ;; + m3|\ + m4) + status_led="$board:blue:status" + ;; + miwifi-mini|\ + zte-q7) + status_led="$board:red:status" + ;; + mr-102n) + status_led="$board:amber:status" + ;; + nw718) + status_led="$board:amber:cpu" + ;; + oy-0001|\ + sl-r7205) + status_led="$board:green:wifi" + ;; + pbr-m1|\ + w306r-v20|\ + zbt-wr8305rt) + status_led="$board:green:sys" + ;; + psr-680w) + status_led="$board:red:wan" + ;; + px-4885|\ + re6500|\ + whr-1166d|\ + whr-300hp2|\ + whr-600d) + status_led="$board:orange:wifi" + ;; + rt-n10-plus|\ + tew-691gr|\ + tew-692gr|\ + ur-326n4g|\ + ur-336un|\ + wr512-3gn) + status_led="$board:green:wps" + ;; + sap-g3200u3) + status_led="$board:green:usb" + ;; + v22rw-2x2) + status_led="$board:green:security" + ;; + wcr-150gn|\ + wl-351) + status_led="$board:amber:power" + ;; + whr-g300n|\ + wzr-agl300nh) + status_led="$board:green:router" + ;; + wizfi630a) + status_led="$board::run" + ;; + wsr-1166|\ + wsr-600) + status_led="$board:orange:diag" + ;; + esac +} + +set_state() { + get_status_led $1 + + case "$1" in + preinit) + status_led_blink_preinit + ;; + failsafe) + status_led_blink_failsafe + ;; + upgrade | \ + preinit_regular) + status_led_blink_preinit_regular + ;; + done) + status_led_on + ;; + esac +} diff --git a/target/linux/ramips/base-files/etc/hotplug.d/firmware/10-rt2x00-eeprom b/target/linux/ramips/base-files/etc/hotplug.d/firmware/10-rt2x00-eeprom new file mode 100644 index 0000000..0e02177 --- /dev/null +++ b/target/linux/ramips/base-files/etc/hotplug.d/firmware/10-rt2x00-eeprom @@ -0,0 +1,67 @@ +#!/bin/sh + +rt2x00_eeprom_die() { + echo "rt2x00 eeprom: " "$*" + exit 1 +} + +rt2x00_eeprom_extract() { + local part=$1 + local offset=$2 + local count=$3 + local mtd + + . /lib/functions.sh + + mtd=$(find_mtd_part $part) + [ -n "$mtd" ] || \ + rt2x00_eeprom_die "no mtd device found for partition $part" + + dd if=$mtd of=/lib/firmware/$FIRMWARE bs=1 skip=$offset count=$count 2>/dev/null || \ + rt2x00_eeprom_die "failed to extract from $mtd" +} + +rt2x00_eeprom_set_macaddr() { + local macaddr=$1 + + [ -n "$macaddr" ] || \ + rt2x00_eeprom_die "invalid wlan mac address" + + macaddr_2bin $macaddr | dd of=/lib/firmware/$FIRMWARE \ + conv=notrunc bs=1 seek=4 count=6 2>/dev/null || \ + rt2x00_eeprom_die "failed to write mac address to eeprom file" +} + +FW="/lib/firmware/$FIRMWARE" +[ -e "$FW" ] && exit 0 + +. /lib/ramips.sh +. /lib/functions/system.sh + +board=$(ramips_board_name) + +case "$FIRMWARE" in +"soc_wmac.eeprom") + case $board in + *) + rt2x00_eeprom_die "Please define mtd-eeprom in $board DTS file!" + ;; + esac + ;; + +"rt2x00pci_1_0.eeprom") + case $board in + cy-swr1100) + rt2x00_eeprom_extract "factory" 8192 512 + ;; + br-6475nd | rt-n56u | whr-600d | whr-1166d) + rt2x00_eeprom_extract "factory" 32768 512 + ;; + tiny-ac) + local wifi_mac=$(mtd_get_mac_ascii u-boot-env INIC_MAC_ADDR) + rt2x00_eeprom_extract "factory" 0 512 + rt2x00_eeprom_set_macaddr $wifi_mac + ;; + esac + ;; +esac diff --git a/target/linux/ramips/base-files/etc/hotplug.d/usb/10-motion b/target/linux/ramips/base-files/etc/hotplug.d/usb/10-motion new file mode 100644 index 0000000..e96acc8 --- /dev/null +++ b/target/linux/ramips/base-files/etc/hotplug.d/usb/10-motion @@ -0,0 +1 @@ +[ "$ACTION" = "motion" ] && logger webcam motion event diff --git a/target/linux/ramips/base-files/etc/inittab b/target/linux/ramips/base-files/etc/inittab new file mode 100644 index 0000000..7817185 --- /dev/null +++ b/target/linux/ramips/base-files/etc/inittab @@ -0,0 +1,3 @@ +::sysinit:/etc/init.d/rcS S boot +::shutdown:/etc/init.d/rcS K shutdown +::askconsole:/bin/ash --login diff --git a/target/linux/ramips/base-files/etc/uci-defaults/09_fix-seama-header b/target/linux/ramips/base-files/etc/uci-defaults/09_fix-seama-header new file mode 100644 index 0000000..35167f1 --- /dev/null +++ b/target/linux/ramips/base-files/etc/uci-defaults/09_fix-seama-header @@ -0,0 +1,22 @@ +#!/bin/sh +# +# Copyright (C) 2012 OpenWrt.org +# + +. /lib/ramips.sh + +fix_seama_header() { + local part=$1 + + mtd fixseama $part +} + +board=$(ramips_board_name) + +case "$board" in +cy-swr1100 | \ +dir-645 | \ +dir-860l-b1) + fix_seama_header kernel + ;; +esac diff --git a/target/linux/ramips/base-files/lib/preinit/03_preinit_do_ramips.sh b/target/linux/ramips/base-files/lib/preinit/03_preinit_do_ramips.sh new file mode 100644 index 0000000..31ef5f8 --- /dev/null +++ b/target/linux/ramips/base-files/lib/preinit/03_preinit_do_ramips.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +do_ramips() { + . /lib/ramips.sh + + ramips_board_detect +} + +boot_hook_add preinit_main do_ramips diff --git a/target/linux/ramips/base-files/lib/preinit/04_handle_checksumming b/target/linux/ramips/base-files/lib/preinit/04_handle_checksumming new file mode 100644 index 0000000..057fe45 --- /dev/null +++ b/target/linux/ramips/base-files/lib/preinit/04_handle_checksumming @@ -0,0 +1,56 @@ +#!/bin/sh + +# Netgear WNCE2001 has does a checksum check on boot and goes into recovery +# tftp mode when the check fails. Initializing the JFFS2 partition triggers +# this, so we make sure to zero checksum and size to be checksummed before +# that happens, so this needs to run very early during boot. + +do_checksumming_disable() { + . /lib/ramips.sh + + local board=$(ramips_board_name) + + case "$board" in + wnce2001) + echo "Board is WNCE2001, updating checksum partition..." + local zeroes=/dev/zero + local tmpfile=/tmp/wnce2001_checksum + local partname=checksum + local mtd=$(find_mtd_part $partname) + dd if=$mtd of=$tmpfile bs=80 count=1 2>/dev/null + signature=$(dd if=$tmpfile bs=1 skip=24 count=20 2>/dev/null) + checksum=$(dd if=$tmpfile bs=1 count=4 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"') + if [ "$signature" != "RT3052-AP-WNCE2001-3" ]; then + echo "Signature of checksum partition is wrong, bailing." + return 0 + fi + if [ "$checksum" != "00000000" ]; then + echo "Checksum is set, zeroing." + # zero out checksum + dd if=$zeroes of=$tmpfile conv=notrunc bs=1 seek=0 count=4 2>/dev/null + # zero out bytecount to be checksummed + dd if=$zeroes of=$tmpfile conv=notrunc bs=1 seek=60 count=4 2>/dev/null + mtd write $tmpfile $partname + else + echo "Checksum is already zero, nothing to do." + fi + ;; + rt-n56u) + echo "Board is ASUS RT-N56U, replacing uImage header..." + local firmware_mtd=$(find_mtd_part firmware) + local rootfs_mtd=$(find_mtd_part rootfs) + local rootfs_data_mtd=$(find_mtd_part rootfs_data) + local rootfs_len=$(grep \"rootfs\" /proc/mtd | awk -F' ' '{print "0x"$2}') + local rootfs_data_len=$(grep \"rootfs_data\" /proc/mtd | awk -F' ' '{print "0x"$2}') + local offset=$(echo "$rootfs_len $rootfs_data_len 0x40" | awk -F' ' '{printf "%i",$1-$2-$3}') + local signature=$(dd if=$rootfs_mtd skip=$offset bs=1 count=4 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"') + if [ "$signature" = "27051956" ]; then + dd conv=notrunc if=$rootfs_mtd skip=$offset of=$firmware_mtd bs=1 count=64 2>/dev/null + fi + ;; + esac + + return 0 +} + +boot_hook_add preinit_main do_checksumming_disable diff --git a/target/linux/ramips/base-files/lib/preinit/07_set_preinit_iface_ramips b/target/linux/ramips/base-files/lib/preinit/07_set_preinit_iface_ramips new file mode 100644 index 0000000..3dce1b6 --- /dev/null +++ b/target/linux/ramips/base-files/lib/preinit/07_set_preinit_iface_ramips @@ -0,0 +1,34 @@ +#!/bin/sh +# +# Copyright (C) 2013 OpenWrt.org +# + +. /lib/ramips.sh + +ramips_set_preinit_iface() { + RT3X5X=`cat /proc/cpuinfo | egrep "(RT3.5|RT5350|MT7628|MT7688)"` + if [ -n "${RT3X5X}" ]; then + swconfig dev rt305x set reset 1 + fi + + if echo $RT3X5X | egrep -q "(RT5350|MT7628|MT7688)"; then + # This is a dirty hack to get by while the switch + # problem is investigated. When VLAN is disabled, ICMP + # pings work as expected, but TCP connections time + # out, so telnetting in failsafe is impossible. The + # likely reason is TCP checksumming hardware getting + # disabled: + # https://www.mail-archive.com/openwrt-devel@lists.openwrt.org/msg19870.html + swconfig dev rt305x set enable_vlan 1 + swconfig dev rt305x vlan 1 set ports "0 6" + swconfig dev rt305x port 6 set untag 0 + swconfig dev rt305x set apply 1 + ip link add link eth0 name eth0.1 type vlan id 1 + ip link set eth0 up + ifname=eth0.1 + else + ifname=eth0 + fi +} + +boot_hook_add preinit_main ramips_set_preinit_iface diff --git a/target/linux/ramips/base-files/lib/ramips.sh b/target/linux/ramips/base-files/lib/ramips.sh new file mode 100755 index 0000000..62a79c5 --- /dev/null +++ b/target/linux/ramips/base-files/lib/ramips.sh @@ -0,0 +1,484 @@ +#!/bin/sh +# +# Copyright (C) 2010-2013 OpenWrt.org +# + +RAMIPS_BOARD_NAME= +RAMIPS_MODEL= + +ramips_board_detect() { + local machine + local name + + machine=$(awk 'BEGIN{FS="[ \t]+:[ \t]"} /machine/ {print $2}' /proc/cpuinfo) + + case "$machine" in + *"3G150B") + name="3g150b" + ;; + *"3G300M") + name="3g300m" + ;; + *"3g-6200n") + name="3g-6200n" + ;; + *"3g-6200nl") + name="3g-6200nl" + ;; + *"A5-V11") + name="a5-v11" + ;; + *"Ai-BR100") + name="ai-br100" + ;; + *"Air3GII") + name="air3gii" + ;; + *"ALL0239-3G") + name="all0239-3g" + ;; + *"ALL0256N") + name="all0256n" + ;; + *"ALL5002") + name="all5002" + ;; + *"ALL5003") + name="all5003" + ;; + *"AR670W") + name="ar670w" + ;; + *"AR725W") + name="ar725w" + ;; + *"ASL26555") + name="asl26555" + ;; + *"ATP-52B") + name="atp-52b" + ;; + *"AWAPN2403") + name="awapn2403" + ;; + *"AWM002 EVB") + name="awm002-evb" + ;; + *"AWM003 EVB") + name="awm003-evb" + ;; + *"BC2") + name="bc2" + ;; + *"BR-6425") + name="br-6425" + ;; + *"BR-6475nD") + name="br-6475nd" + ;; + *"Broadway") + name="broadway" + ;; + *"C20i") + name="c20i" + ;; + *"Carambola") + name="carambola" + ;; + *"CF-WR800N") + name="cf-wr800n" + ;; + *"CY-SWR1100") + name="cy-swr1100" + ;; + *"D105") + name="d105" + ;; + *"DAP-1350") + name="dap-1350" + ;; + *"DB-WRT01") + name="db-wrt01" + ;; + *"DCS-930") + name="dcs-930" + ;; + *"DCS-930L B1") + name="dcs-930l-b1" + ;; + *"DIR-300 B1") + name="dir-300-b1" + ;; + *"DIR-300 B7") + name="dir-300-b7" + ;; + *"DIR-320 B1") + name="dir-320-b1" + ;; + *"DIR-600 B1") + name="dir-600-b1" + ;; + *"DIR-600 B2") + name="dir-600-b2" + ;; + *"DIR-610 A1") + name="dir-610-a1" + ;; + *"DIR-615 D") + name="dir-615-d" + ;; + *"DIR-615 H1") + name="dir-615-h1" + ;; + *"DIR-620 A1") + name="dir-620-a1" + ;; + *"DIR-620 D1") + name="dir-620-d1" + ;; + *"DIR-645") + name="dir-645" + ;; + *"DIR-810L") + name="dir-810l" + ;; + *"DIR-860L B1") + name="dir-860l-b1" + ;; + *"Dovado Tiny AC") + name="tiny-ac" + ;; + *"E1700") + name="e1700" + ;; + *"ESR-9753") + name="esr-9753" + ;; + *"F5D8235 v1") + name="f5d8235-v1" + ;; + *"F5D8235 v2") + name="f5d8235-v2" + ;; + *"F7C027") + name="f7c027" + ;; + *"FireWRT") + name="firewrt" + ;; + *"Fonera 2.0N") + name="fonera20n" + ;; + *"FreeStation5") + name="freestation5" + ;; + *"HC5661") + name="hc5661" + ;; + *"HC5761") + name="hc5761" + ;; + *"HC5861") + name="hc5861" + ;; + *"HG255D") + name="hg255d" + ;; + *"HLK-RM04") + name="hlk-rm04" + ;; + *"HPM") + name="hpm" + ;; + *"HT-TM02") + name="ht-tm02" + ;; + *"HW550-3G") + name="hw550-3g" + ;; + *"IP2202") + name="ip2202" + ;; + *"M3") + name="m3" + ;; + *"M4") + name="m4" + ;; + *"MediaTek LinkIt Smart7688") + linkit="$(dd bs=1 skip=1024 count=12 if=/dev/mtd2 2> /dev/null)" + if [ "${linkit}" = "LINKITS7688D" ]; then + name="linkits7688d" + RAMIPS_MODEL="${machine} DUO" + else + name="linkits7688" + fi + ;; + *"Memory 2 Move") + name="m2m" + ;; + *"MicroWRT") + name="microwrt" + ;; + *"MiniEMBPlug") + name="miniembplug" + ;; + *"MiniEMBWiFi") + name="miniembwifi" + ;; + *"MiWiFi Mini") + name="miwifi-mini" + ;; + *"MLW221") + name="mlw221" + ;; + *"MLWG2") + name="mlwg2" + ;; + *"MOFI3500-3GN") + name="mofi3500-3gn" + ;; + *"MPR-A1") + name="mpr-a1" + ;; + *"MPR-A2") + name="mpr-a2" + ;; + *"MR-102N") + name="mr-102n" + ;; + *"MT7620a + MT7530 evaluation"*) + name="mt7620a_mt7530" + ;; + *"MT7620a V22SG"*) + name="mt7620a_v22sg" + ;; + *"MT7621 evaluation"*) + name="mt7621" + ;; + *"MT7628AN evaluation"*) + name="mt7628" + ;; + *"MT7688 evaluation"*) + name="mt7688" + ;; + *"MZK-750DHP") + name="mzk-750dhp" + ;; + *"MZK-DP150N") + name="mzk-dp150n" + ;; + *"MZK-W300NH2"*) + name="mzk-w300nh2" + ;; + *"NA930") + name="na930" + ;; + *"NBG-419N") + name="nbg-419n" + ;; + *"NCS601W") + name="ncs601w" + ;; + *"NW718") + name="nw718" + ;; + *"OY-0001") + name="oy-0001" + ;; + *"PBR-M1") + name="pbr-m1" + ;; + *"PSR-680W"*) + name="psr-680w" + ;; + *"PWH2004") + name="pwh2004" + ;; + *"PX-4885") + name="px-4885" + ;; + *"Q7") + name="zte-q7" + ;; + *"RE6500") + name="re6500" + ;; + *"RN502J") + name="xdxrn502j" + ;; + *"RP-N53") + name="rp-n53" + ;; + *"RT5350F-OLinuXino") + name="rt5350f-olinuxino" + ;; + *"RT5350F-OLinuXino-EVB") + name="rt5350f-olinuxino-evb" + ;; + *"RT-G32 B1") + name="rt-g32-b1" + ;; + *"RT-N10+") + name="rt-n10-plus" + ;; + *"RT-N13U") + name="rt-n13u" + ;; + *"RT-N14U") + name="rt-n14u" + ;; + *"RT-N15") + name="rt-n15" + ;; + *"RT-N56U") + name="rt-n56u" + ;; + *"RUT5XX") + name="rut5xx" + ;; + *"SAP-G3200U3") + name="sap-g3200u3" + ;; + *"SL-R7205"*) + name="sl-r7205" + ;; + *"TEW-691GR") + name="tew-691gr" + ;; + *"TEW-692GR") + name="tew-692gr" + ;; + *"UR-326N4G") + name="ur-326n4g" + ;; + *"UR-336UN") + name="ur-336un" + ;; + *"V11ST-FE") + name="v11st-fe" + ;; + *"V22RW-2X2") + name="v22rw-2x2" + ;; + *"VoCore") + name="vocore" + ;; + *"W150M") + name="w150m" + ;; + *"W306R V2.0") + name="w306r-v20" + ;; + *"W502U") + name="w502u" + ;; + *"WCR-150GN") + name="wcr-150gn" + ;; + *"WHR-1166D") + name="whr-1166d" + ;; + *"WHR-300HP2") + name="whr-300hp2" + ;; + *"WHR-600D") + name="whr-600d" + ;; + *"WHR-G300N") + name="whr-g300n" + ;; + *"WIZARD 8800") + name="wizard8800" + ;; + *"WizFi630A") + name="wizfi630a" + ;; + *"WL-330N") + name="wl-330n" + ;; + *"WL-330N3G") + name="wl-330n3g" + ;; + *"WL-341 v3") + name="wl-341v3" + ;; + *"WL-351 v1 002") + name="wl-351" + ;; + *"WLI-TX4-AG300N") + name="wli-tx4-ag300n" + ;; + *"WMR-300") + name="wmr-300" + ;; + *"WNCE2001") + name="wnce2001" + ;; + *"WR512-3GN-like"*) + name="wr512-3gn" + ;; + *"WR6202") + name="wr6202" + ;; + *"WRTNODE") + name="wrtnode" + ;; + *"WSR-1166DHP") + name="wsr-1166" + ;; + *"WSR-600DHP") + name="wsr-600" + ;; + *"WT1520") + name="wt1520" + ;; + *"WT3020") + name="wt3020" + ;; + *"WZR-AGL300NH") + name="wzr-agl300nh" + ;; + *"X5") + name="x5" + ;; + *"X8") + name="x8" + ;; + *"Y1") + name="y1" + ;; + *"Y1S") + name="y1s" + ;; + *"ZBT-WA05") + name="zbt-wa05" + ;; + *"ZBT-WG2626") + name="zbt-wg2626" + ;; + *"ZBT-WR8305RT") + name="zbt-wr8305rt" + ;; + *) + name="generic" + ;; + esac + + [ -z "$RAMIPS_BOARD_NAME" ] && RAMIPS_BOARD_NAME="$name" + [ -z "$RAMIPS_MODEL" ] && RAMIPS_MODEL="$machine" + + [ -e "/tmp/sysinfo/" ] || mkdir -p "/tmp/sysinfo/" + + echo "$RAMIPS_BOARD_NAME" > /tmp/sysinfo/board_name + echo "$RAMIPS_MODEL" > /tmp/sysinfo/model +} + +ramips_board_name() { + local name + + [ -f /tmp/sysinfo/board_name ] && name=$(cat /tmp/sysinfo/board_name) + [ -z "$name" ] && name="unknown" + + echo "$name" +} diff --git a/target/linux/ramips/base-files/lib/upgrade/platform.sh b/target/linux/ramips/base-files/lib/upgrade/platform.sh new file mode 100755 index 0000000..0e8d619 --- /dev/null +++ b/target/linux/ramips/base-files/lib/upgrade/platform.sh @@ -0,0 +1,211 @@ +# +# Copyright (C) 2010 OpenWrt.org +# + +. /lib/ramips.sh + +PART_NAME=firmware +RAMFS_COPY_DATA=/lib/ramips.sh + +platform_check_image() { + local board=$(ramips_board_name) + local magic="$(get_magic_long "$1")" + + [ "$#" -gt 1 ] && return 1 + + case "$board" in + 3g150b|\ + 3g300m|\ + 3g-6200n|\ + 3g-6200nl|\ + a5-v11|\ + ai-br100|\ + air3gii|\ + all0239-3g|\ + all0256n|\ + all5002|\ + all5003|\ + ar725w|\ + asl26555|\ + awapn2403|\ + awm002-evb|\ + awm003-evb|\ + bc2|\ + broadway|\ + carambola|\ + cf-wr800n|\ + d105|\ + dap-1350|\ + db-wrt01|\ + dcs-930|\ + dcs-930l-b1|\ + dir-300-b1|\ + dir-300-b7|\ + dir-320-b1|\ + dir-600-b1|\ + dir-600-b2|\ + dir-615-d|\ + dir-615-h1|\ + dir-620-a1|\ + dir-620-d1|\ + dir-810l|\ + e1700|\ + esr-9753|\ + f7c027|\ + firewrt|\ + fonera20n|\ + freestation5|\ + hc5*61|\ + hg255d|\ + hlk-rm04|\ + hpm|\ + ht-tm02|\ + hw550-3g|\ + ip2202|\ + linkits7688|\ + linkits7688d|\ + m2m|\ + m3|\ + m4|\ + microwrt|\ + miniembplug|\ + miniembwifi|\ + miwifi-mini|\ + mlw221|\ + mlwg2|\ + mofi3500-3gn|\ + mpr-a1|\ + mpr-a2|\ + mr-102n|\ + mzk-dp150n|\ + mzk-w300nh2|\ + nbg-419n|\ + nw718|\ + oy-0001|\ + pbr-m1|\ + psr-680w|\ + px-4885|\ + re6500|\ + rp-n53|\ + rt5350f-olinuxino|\ + rt5350f-olinuxino-evb|\ + rt-g32-b1|\ + rt-n10-plus|\ + rt-n13u|\ + rt-n14u|\ + rt-n15|\ + rt-n56u|\ + rut5xx|\ + sap-g3200u3|\ + sl-r7205|\ + tew-691gr|\ + tew-692gr|\ + tiny-ac|\ + ur-326n4g|\ + ur-336un|\ + v22rw-2x2|\ + vocore|\ + w150m|\ + w306r-v20|\ + w502u|\ + whr-1166d|\ + whr-300hp2|\ + whr-600d|\ + whr-g300n|\ + wizfi630a|\ + wl-330n|\ + wl-330n3g|\ + wl-341v3|\ + wl-351|\ + wli-tx4-ag300n|\ + wmr-300|\ + wnce2001|\ + wr512-3gn|\ + wr6202|\ + wrtnode|\ + wsr-600|\ + wt1520|\ + wt3020|\ + wzr-agl300nh|\ + x5|\ + x8|\ + y1|\ + y1s|\ + zbt-wa05|\ + zbt-wg2626|\ + zbt-wr8305rt|\ + zte-q7) + [ "$magic" != "27051956" ] && { + echo "Invalid image type." + return 1 + } + return 0 + ;; + ar670w) + [ "$magic" != "6d000080" ] && { + echo "Invalid image type." + return 1 + } + return 0 + ;; + br-6475nd) + [ "$magic" != "43535953" ] && { + echo "Invalid image type." + return 1 + } + return 0 + ;; + c20i) + [ "$magic" != "03000000" ] && { + echo "Invalid image type." + return 1 + } + return 0 + ;; + cy-swr1100|\ + dir-610-a1|\ + dir-645|\ + dir-860l-b1) + [ "$magic" != "5ea3a417" ] && { + echo "Invalid image type." + return 1 + } + return 0 + ;; + wsr-1166) + [ "$magic" != "48445230" ] && { + echo "Invalid image type." + return 1 + } + return 0 + ;; + esac + + echo "Sysupgrade is not yet supported on $board." + return 1 +} + +platform_do_upgrade() { + local board=$(ramips_board_name) + + case "$board" in + *) + default_do_upgrade "$ARGV" + ;; + esac +} + +disable_watchdog() { + killall watchdog + ( ps | grep -v 'grep' | grep '/dev/watchdog' ) && { + echo 'Could not disable watchdog' + return 1 + } +} + +blink_led() { + . /etc/diag.sh; set_state upgrade +} + +append sysupgrade_pre_upgrade disable_watchdog +append sysupgrade_pre_upgrade blink_led diff --git a/target/linux/ramips/dts/3G-6200N.dts b/target/linux/ramips/dts/3G-6200N.dts new file mode 100644 index 0000000..5c1e588 --- /dev/null +++ b/target/linux/ramips/dts/3G-6200N.dts @@ -0,0 +1,109 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "3G-6200N", "ralink,rt3050-soc"; + model = "Edimax 3g-6200n"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@3e0000 { + label = "cimage"; + reg = <0x3e0000 0x20000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x390000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "3g-6200n:green:power"; + gpios = <&gpio0 9 1>; + }; + + wlan { + label = "3g-6200n:amber:wlan"; + gpios = <&gpio0 14 1>; + }; + + 3g { + label = "3g-6200n:blue:3g"; + gpios = <&gpio0 7 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + wps { + label = "wps"; + gpios = <&gpio0 12 1>; + linux,code = <0x211>; + }; + + wlanswitch { + label = "wlanswitch"; + gpios = <&gpio0 13 1>; + linux,code = <0x100>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/3G-6200NL.dts b/target/linux/ramips/dts/3G-6200NL.dts new file mode 100644 index 0000000..8f7d383 --- /dev/null +++ b/target/linux/ramips/dts/3G-6200NL.dts @@ -0,0 +1,93 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "3G-6200NL", "ralink,rt3050-soc"; + model = "Edimax 3g-6200nl"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@3e0000 { + label = "cimage"; + reg = <0x3e0000 0x20000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x390000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wlan { + label = "3g-6200nl:amber:wlan"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + wps { + label = "wps"; + gpios = <&gpio0 12 1>; + linux,code = <0x211>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/3G150B.dts b/target/linux/ramips/dts/3G150B.dts new file mode 100644 index 0000000..a8387a4 --- /dev/null +++ b/target/linux/ramips/dts/3G150B.dts @@ -0,0 +1,118 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "3G150B", "ralink,rt5350-soc"; + model = "Tenda 3G150B"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "s25fl064k"; + reg = <0 0>; + linux,modalias = "m25p80", "s25fl064k"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + }; + + gpio1: gpio@660 { + status = "okay"; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf", "led"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + ralink,led-polarity = <1>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + gpio-leds { + compatible = "gpio-leds"; + + ap { + label = "3g150b:blue:ap"; + gpios = <&gpio0 7 1>; + }; + + 3g { + label = "3g150b:blue:3g"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 0 1>; + linux,code = <0x198>; + }; + }; + + gpio_export { + compatible = "gpio-export"; + #size-cells = <0>; + + usb { + gpio-export,name = "usb"; + gpio-export,output = <1>; + gpios = <&gpio0 13 0>; + }; + }; +}; diff --git a/target/linux/ramips/dts/3G300M.dts b/target/linux/ramips/dts/3G300M.dts new file mode 100644 index 0000000..997c081 --- /dev/null +++ b/target/linux/ramips/dts/3G300M.dts @@ -0,0 +1,124 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "3G300M", "ralink,rt3052-soc"; + model = "Tenda 3G300M"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l3205d"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l3205d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + 3grouter { + label = "3g300m:blue:3grouter"; + gpios = <&gpio0 11 1>; + }; + + ap { + label = "3g300m:blue:ap"; + gpios = <&gpio0 12 1>; + }; + + wisprouter { + label = "3g300m:blue:wisprouter"; + gpios = <&gpio0 9 1>; + }; + + wirelessrouter { + label = "3g300m:blue:wirelessrouter"; + gpios = <&gpio0 13 1>; + }; + + 3g { + label = "3g300m:blue:3g"; + gpios = <&gpio0 7 1>; + }; + + wpsreset { + label = "3g300m:blue:wpsreset"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 0 1>; + linux,code = <0x198>; + }; + + mode { + label = "mode"; + gpios = <&gpio0 10 1>; + linux,code = <0x100>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/A5-V11.dts b/target/linux/ramips/dts/A5-V11.dts new file mode 100644 index 0000000..f1d0891 --- /dev/null +++ b/target/linux/ramips/dts/A5-V11.dts @@ -0,0 +1,123 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "A5-V11", "ralink,rt5350-soc"; + model = "A5-V11"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "pm25lq032"; + reg = <0 0>; + linux,modalias = "m25p80", "pm25lq032"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + }; + + gpio1: gpio@660 { + status = "okay"; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "uartf", "led"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + gpio-leds { + compatible = "gpio-leds"; + + system { + label = "a5-v11:blue:system"; + gpios = <&gpio0 20 1>; + }; + + power { + label = "a5-v11:red:power"; + gpios = <&gpio0 17 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 0 1>; + linux,code = <0x198>; + }; + }; + + gpio_export { + compatible = "gpio-export"; + #size-cells = <0>; + + usb { + gpio-export,name = "usb"; + gpio-export,output = <1>; + gpios = <&gpio0 7 0>; + }; + + root_hub { + gpio-export,name = "root_hub"; + gpio-export,output = <1>; + gpios = <&gpio0 12 0>; + }; + }; +}; diff --git a/target/linux/ramips/dts/AI-BR100.dts b/target/linux/ramips/dts/AI-BR100.dts new file mode 100644 index 0000000..f3932ae --- /dev/null +++ b/target/linux/ramips/dts/AI-BR100.dts @@ -0,0 +1,109 @@ +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "AI-BR100", "ralink,mt7620a-soc"; + model = "Aigale Ai-BR100"; + + palmbus@10000000 { + gpio2: gpio@660 { + status = "okay"; + }; + + gpio3: gpio@688 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "en25q64"; + reg = <0 0>; + linux,modalias = "m25p80", "en25q64"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x20000>; + read-only; + }; + + partition@20000 { + label = "u-boot-env"; + reg = <0x20000 0x10000>; + read-only; + }; + + factory: partition@30000 { + label = "factory"; + reg = <0x30000 0x10000>; + read-only; + }; + + partition@40000 { + label = "firmware"; + reg = <0x40000 0x7c0000>; + }; + }; + }; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "uartf", "rgmii1", "rgmii2", "ephy", "wled", "nd_sd"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + pinctrl-names = "default"; + pinctrl-0 = <&ephy_pins>; + mtd-mac-address = <&factory 0x4>; + ralink,port-map = "llllw"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wan { + label = "ai-br100:blue:wan"; + gpios = <&gpio2 4 1>; + }; + + wlan { + label = "ai-br100:blue:wlan"; + gpios = <&gpio3 0 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 12 1>; + linux,code = <0x198>; + }; + }; +}; diff --git a/target/linux/ramips/dts/AIR3GII.dts b/target/linux/ramips/dts/AIR3GII.dts new file mode 100644 index 0000000..40d3228 --- /dev/null +++ b/target/linux/ramips/dts/AIR3GII.dts @@ -0,0 +1,98 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "AIR3GII", "ralink,rt5350-soc"; + model = "AirLive Air3GII"; + + palmbus@10000000 { + gpio0: gpio@600 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "en25q32b"; + reg = <0 0>; + linux,modalias = "m25p80", "en25q32b"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wlan { + label = "air3gii:green:wlan"; + gpios = <&gpio0 8 0>; + }; + + mobile { + label = "air3gii:green:mobile"; + gpios = <&gpio0 9 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + wps { + label = "wps"; + gpios = <&gpio0 7 1>; + linux,code = <0x211>; + }; + }; +}; diff --git a/target/linux/ramips/dts/ALL0239-3G.dts b/target/linux/ramips/dts/ALL0239-3G.dts new file mode 100644 index 0000000..d75bb2c --- /dev/null +++ b/target/linux/ramips/dts/ALL0239-3G.dts @@ -0,0 +1,115 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "ALL0239-3G", "ralink,rt3052-soc"; + model = "Allnet ALL0239-3G"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + status = "okay"; + ralink,portmap = <0x3e>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + usb { + label = "all0239-3g:green:usb"; + gpios = <&gpio0 8 1>; + }; + + 3g { + label = "all0239-3g:green:3g"; + gpios = <&gpio0 11 1>; + }; + + status { + label = "all0239-3g:green:status"; + gpios = <&gpio0 12 1>; + }; + + wps { + label = "all0239-3g:green:wps"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + connect { + label = "connect"; + gpios = <&gpio0 7 1>; + linux,code = <0xda>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/ALL0256N-4M.dts b/target/linux/ramips/dts/ALL0256N-4M.dts new file mode 100644 index 0000000..d0fbb89 --- /dev/null +++ b/target/linux/ramips/dts/ALL0256N-4M.dts @@ -0,0 +1,103 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "ALL0256N", "ralink,rt3050-soc"; + model = "Allnet ALL0256N"; + + palmbus@10000000 { + gpio0: gpio@600 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l3205d"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l3205d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3c8000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x3f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + rssilow { + label = "all0256n:green:rssilow"; + gpios = <&gpio0 14 1>; + }; + + rssimed { + label = "all0256n:green:rssimed"; + gpios = <&gpio0 12 1>; + }; + + rssihigh { + label = "all0256n:green:rssihigh"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 0 1>; + linux,code = <0x198>; + }; + }; +}; diff --git a/target/linux/ramips/dts/ALL0256N-8M.dts b/target/linux/ramips/dts/ALL0256N-8M.dts new file mode 100644 index 0000000..c788869 --- /dev/null +++ b/target/linux/ramips/dts/ALL0256N-8M.dts @@ -0,0 +1,103 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "ALL0256N", "ralink,rt3050-soc"; + model = "Allnet ALL0256N"; + + palmbus@10000000 { + gpio0: gpio@600 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l3205d"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l3205d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x3f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + rssilow { + label = "all0256n:green:rssilow"; + gpios = <&gpio0 14 1>; + }; + + rssimed { + label = "all0256n:green:rssimed"; + gpios = <&gpio0 12 1>; + }; + + rssihigh { + label = "all0256n:green:rssihigh"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 0 1>; + linux,code = <0x198>; + }; + }; +}; diff --git a/target/linux/ramips/dts/ALL5002.dts b/target/linux/ramips/dts/ALL5002.dts new file mode 100644 index 0000000..7717f02 --- /dev/null +++ b/target/linux/ramips/dts/ALL5002.dts @@ -0,0 +1,111 @@ +/dts-v1/; + +/include/ "rt3352.dtsi" + +/ { + compatible = "ALL5002", "ralink,rt3352-soc"; + model = "Allnet ALL5002"; + + palmbus@10000000 { + gpio0: gpio@600 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l25635e"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l25635e"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x1fb0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x3f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + i2c-gpio { + compatible = "i2c-gpio"; + gpios = <&gpio0 1 0 &gpio0 2 0>; + i2c-gpio,delay-us = <10>; + + pcf0: iexp@38 { + #gpio-cells = <2>; + compatible = "inxp,pcf8574a"; + reg = <0x38>; + gpio-controller; + }; + + hwmon@4b { + compatible = "national,lm92"; + reg = <0x4b>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + ld1 { + label = "all5002:green:ld1"; + gpios = <&pcf0 0 1>; + }; + + ld2 { + label = "all5002:green:ld2"; + gpios = <&pcf0 1 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/ALL5003.dts b/target/linux/ramips/dts/ALL5003.dts new file mode 100644 index 0000000..c256145 --- /dev/null +++ b/target/linux/ramips/dts/ALL5003.dts @@ -0,0 +1,111 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "ALL5003", "ralink,rt5350-soc"; + model = "Allnet ALL5003"; + + palmbus@10000000 { + gpio0: gpio@600 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l25635e"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l25635e"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x1fb0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x3f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + i2c-gpio { + compatible = "i2c-gpio"; + gpios = <&gpio0 1 0 &gpio0 2 0>; + i2c-gpio,delay-us = <10>; + + pcf0: iexp@38 { + #gpio-cells = <2>; + compatible = "inxp,pcf8574a"; + reg = <0x38>; + gpio-controller; + }; + + hwmon@4b { + compatible = "national,lm92"; + reg = <0x4b>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + ld1 { + label = "all5003:green:ld1"; + gpios = <&pcf0 0 1>; + }; + + ld2 { + label = "all5003:green:ld2"; + gpios = <&pcf0 1 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/AR670W.dts b/target/linux/ramips/dts/AR670W.dts new file mode 100644 index 0000000..0e29d89 --- /dev/null +++ b/target/linux/ramips/dts/AR670W.dts @@ -0,0 +1,105 @@ +/dts-v1/; + +/include/ "rt2880.dtsi" + +/ { + compatible = "AR670W", "ralink,rt2880-soc"; + model = "Airlink101 AR670W"; + + palmbus@300000 { + gpio0: gpio@600 { + status = "okay"; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "spi", "uartlite"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@400000 { + status = "okay"; + mtd-mac-address = <&factory 0x2004>; + + port@0 { + phy-handle = <&phy0>; + phy-mode = "mii"; + }; + + mdio-bus { + status = "okay"; + + phy0: ethernet-phy@0 { + phy-mode = "mii"; + reg = <0>; + }; + }; + }; + + wmac@480000 { + status = "okay"; + ralink,mtd-eeprom = <&factory 0x2000>; + }; + + cfi@bdc00000 { + compatible = "cfi-flash"; + reg = <0xbc400000 0x800000>; + bank-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + u-boot@0 { + reg = <0x0 0x30000>; + label = "u-boot"; + read-only; + }; + + factory: factory@30000 { + reg = <0x30000 0x10000>; + label = "factory"; + read-only; + }; + + firmware@40000 { + reg = <0x40000 0x3c0000>; + label = "firmware"; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "ar670w:green:power"; + gpios = <&gpio0 7 1>; + }; + + wpsblue { + label = "ar670w:blue:wps"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + + reset { + label = "reset"; + gpios = <&gpio0 9 1>; + linux,code = <0x198>; + }; + }; +}; diff --git a/target/linux/ramips/dts/AR725W.dts b/target/linux/ramips/dts/AR725W.dts new file mode 100644 index 0000000..6f66c3f --- /dev/null +++ b/target/linux/ramips/dts/AR725W.dts @@ -0,0 +1,115 @@ +/dts-v1/; + +/include/ "rt2880.dtsi" + +/ { + compatible = "AR725W", "ralink,rt2880-soc"; + model = "Airlink101 AR725W"; + + palmbus@300000 { + gpio0: gpio@600 { + status = "okay"; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "spi", "uartlite"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@400000 { + status = "okay"; + mtd-mac-address = <&factory 0x4>; + + port@0 { + phy-handle = <&phy0>; + phy-mode = "mii"; + }; + + mdio-bus { + status = "okay"; + + phy0: ethernet-phy@0 { + phy-mode = "mii"; + reg = <0>; + }; + }; + }; + + wmac@480000 { + status = "okay"; + ralink,mtd-eeprom = <&factory 0>; + }; + + cfi@bdc00000 { + compatible = "cfi-flash"; + reg = <0xbc400000 0x800000>; + bank-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + u-boot@0 { + reg = <0x0 0x30000>; + label = "u-boot"; + read-only; + }; + + u-boot-env@30000 { + reg = <0x30000 0x10000>; + label = "u-boot-env"; + }; + + factory: factory@40000 { + reg = <0x40000 0x10000>; + label = "factory"; + read-only; + }; + + firmware@50000 { + reg = <0x50000 0x3B0000>; + label = "firmware"; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "ar725w:green:power"; + gpios = <&gpio0 7 0>; + }; + + wpsred { + label = "ar725w:red:wps"; + gpios = <&gpio0 8 1>; + }; + + wpsblue { + label = "ar725w:blue:wps"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + + reset { + label = "reset"; + gpios = <&gpio0 9 1>; + linux,code = <0x198>; + }; + }; +}; diff --git a/target/linux/ramips/dts/ASL26555-16M.dts b/target/linux/ramips/dts/ASL26555-16M.dts new file mode 100644 index 0000000..2cf1ac6 --- /dev/null +++ b/target/linux/ramips/dts/ASL26555-16M.dts @@ -0,0 +1,156 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "ASL26555", "ralink,rt3050-soc"; + model = "Alpha ASL26555"; + + palmbus@10000000 { + gpio0: gpio@600 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "s25sl12801"; + reg = <0 0>; + linux,modalias = "m25p80", "s25sl12801"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "uboot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "uboot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xf80000>; + }; + + partition@fd0000 { + label = "cert"; + reg = <0xfd0000 0x10000>; + read-only; + }; + + partition@fe0000 { + label = "langpack"; + reg = <0xfe0000 0x10000>; + read-only; + }; + + devdata: partition@ff0000 { + label = "devdata"; + reg = <0xff0000 0x10000>; + read-only; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&devdata 0x4004>; + }; + + esw@10110000 { + ralink,portmap = <0x1e>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&devdata 0x4000>; + }; + + otg@101c0000 { + status = "okay"; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 0>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 12 0>; + linux,code = <0x211>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + eth { + label = "asl26555:green:eth"; + gpios = <&gpio0 0 1>; + }; + + wan-red { + label = "asl26555:red:wan"; + gpios = <&gpio0 1 0>; + }; + + wan-green { + label = "asl26555:green:wan"; + gpios = <&gpio0 2 0>; + }; + + wlan { + label = "asl26555:green:wlan"; + gpios = <&gpio0 7 0>; + }; + + power-green { + label = "asl26555:green:power"; + gpios = <&gpio0 8 0>; + }; + + power-red { + label = "asl26555:red:power"; + gpios = <&gpio0 9 0>; + }; + + 3g-green { + label = "asl26555:green:3g"; + gpios = <&gpio0 14 1>; + }; + + 3g-red { + label = "asl26555:red:3g"; + gpios = <&gpio0 17 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/ASL26555-8M.dts b/target/linux/ramips/dts/ASL26555-8M.dts new file mode 100644 index 0000000..80cf4a4 --- /dev/null +++ b/target/linux/ramips/dts/ASL26555-8M.dts @@ -0,0 +1,150 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "ASL26555", "ralink,rt3050-soc"; + model = "Alpha ASL26555"; + + palmbus@10000000 { + gpio0: gpio@600 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "s25sl064p"; + reg = <0 0>; + linux,modalias = "m25p80", "s25sl064p"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "uboot"; + reg = <0x0 0x30000>; + read-only; + }; + + ubootenv: partition@30000 { + label = "uboot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + partition@40000 { + label = "rgdb"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x790000>; + }; + + partition@7e0000 { + label = "cert"; + reg = <0x7e0000 0x10000>; + read-only; + }; + + partition@7f0000 { + label = "langpack"; + reg = <0x7f0000 0x10000>; + read-only; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&ubootenv 0x4004>; + }; + + esw@10110000 { + ralink,portmap = <0x1e>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&ubootenv 0x4000>; + }; + + otg@101c0000 { + status = "okay"; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 0>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 12 0>; + linux,code = <0x211>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + eth { + label = "asl26555:green:eth"; + gpios = <&gpio0 0 1>; + }; + + wan-red { + label = "asl26555:red:wan"; + gpios = <&gpio0 1 0>; + }; + + wan-green { + label = "asl26555:green:wan"; + gpios = <&gpio0 2 0>; + }; + + wlan { + label = "asl26555:green:wlan"; + gpios = <&gpio0 7 0>; + }; + + power-green { + label = "asl26555:green:power"; + gpios = <&gpio0 8 0>; + }; + + power-red { + label = "asl26555:red:power"; + gpios = <&gpio0 9 0>; + }; + + 3g-green { + label = "asl26555:green:3g"; + gpios = <&gpio0 14 1>; + }; + + 3g-red { + label = "asl26555:red:3g"; + gpios = <&gpio0 17 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/ATP-52B.dts b/target/linux/ramips/dts/ATP-52B.dts new file mode 100644 index 0000000..c3f42bf --- /dev/null +++ b/target/linux/ramips/dts/ATP-52B.dts @@ -0,0 +1,96 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "ATP-52B", "ralink,rt3052-soc"; + model = "Argus ATP-52B"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bootloader"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "config"; + reg = <0x30000 0x10000>; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7a0000>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + run { + label = "atp-52b:green:run"; + gpios = <&gpio0 9 1>; + }; + + net { + label = "atp-52b:amber:net"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x3e>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/AWAPN2403.dts b/target/linux/ramips/dts/AWAPN2403.dts new file mode 100644 index 0000000..b0f81b0 --- /dev/null +++ b/target/linux/ramips/dts/AWAPN2403.dts @@ -0,0 +1,85 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "AWAPN2403", "ralink,rt3052-soc"; + model = "AsiaRF AWAPN2403"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l3205d"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l3205d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + esw@10110000 { + ralink,portmap = <0x3e>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + link { + label = "awapn2403:green:wps"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 0 1>; + linux,code = <0x198>; + }; + }; +}; diff --git a/target/linux/ramips/dts/AWM002-4M.dtsi b/target/linux/ramips/dts/AWM002-4M.dtsi new file mode 100644 index 0000000..2f6a017 --- /dev/null +++ b/target/linux/ramips/dts/AWM002-4M.dtsi @@ -0,0 +1,15 @@ +/include/ "AWM002.dtsi" + +/ { + compatible = "AWM002", "ralink,rt5350-soc"; + model = "AsiaRF AWM002"; + + palmbus@10000000 { + spi@b00 { + m25p80@0 { + compatible = "mx25l3205d"; + linux,modalias = "m25p80", "mx25l3205d"; + }; + }; + }; +}; diff --git a/target/linux/ramips/dts/AWM002-8M.dtsi b/target/linux/ramips/dts/AWM002-8M.dtsi new file mode 100644 index 0000000..d8e4c28 --- /dev/null +++ b/target/linux/ramips/dts/AWM002-8M.dtsi @@ -0,0 +1,15 @@ +/include/ "AWM002.dtsi" + +/ { + compatible = "AWM002", "ralink,rt5350-soc"; + model = "AsiaRF AWM002"; + + palmbus@10000000 { + spi@b00 { + m25p80@0 { + compatible = "mx25l6405d"; + linux,modalias = "m25p80", "mx25l6405d"; + }; + }; + }; +}; diff --git a/target/linux/ramips/dts/AWM002-EVB-4M.dts b/target/linux/ramips/dts/AWM002-EVB-4M.dts new file mode 100644 index 0000000..fe2ff1a --- /dev/null +++ b/target/linux/ramips/dts/AWM002-EVB-4M.dts @@ -0,0 +1,53 @@ +/dts-v1/; + +/include/ "AWM002-4M.dtsi" + +/ { + model = "AsiaRF AWM002 EVB"; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + tx { + label = "awm002-evb:green:tx"; + gpios = <&gpio0 15 1>; + }; + + rx { + label = "awm002-evb:green:rx"; + gpios = <&gpio0 16 1>; + }; + + wps { + label = "awm002-evb:green:wps"; + gpios = <&gpio0 21 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset_wps { + label = "reset_wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x198>; + }; + + mode { + label = "mode"; + gpios = <&gpio0 20 1>; + linux,code = <0x32>; + }; + }; +}; diff --git a/target/linux/ramips/dts/AWM002-EVB-8M.dts b/target/linux/ramips/dts/AWM002-EVB-8M.dts new file mode 100644 index 0000000..d4de3f1 --- /dev/null +++ b/target/linux/ramips/dts/AWM002-EVB-8M.dts @@ -0,0 +1,53 @@ +/dts-v1/; + +/include/ "AWM002-8M.dtsi" + +/ { + model = "AsiaRF AWM002 EVB"; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + tx { + label = "awm002-evb:green:tx"; + gpios = <&gpio0 15 1>; + }; + + rx { + label = "awm002-evb:green:rx"; + gpios = <&gpio0 16 1>; + }; + + wps { + label = "awm002-evb:green:wps"; + gpios = <&gpio0 21 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset_wps { + label = "reset_wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x198>; + }; + + mode { + label = "mode"; + gpios = <&gpio0 20 1>; + linux,code = <0x32>; + }; + }; +}; diff --git a/target/linux/ramips/dts/AWM002.dtsi b/target/linux/ramips/dts/AWM002.dtsi new file mode 100644 index 0000000..1906e6e --- /dev/null +++ b/target/linux/ramips/dts/AWM002.dtsi @@ -0,0 +1,77 @@ +/include/ "rt5350.dtsi" + +/ { + compatible = "AWM002", "ralink,rt5350-soc"; + model = "AsiaRF AWM002"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0 0>; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x1fb0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag"; + ralink,function = "gpio"; + }; + }; + }; + + esw@10110000 { + ralink,portmap = <0x3f>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + gpio-leds { + compatible = "gpio-leds"; + + ld1 { + label = "awm002:green:ld1"; + gpios = <&gpio0 0 1>; + }; + + ld2 { + label = "awm002:green:ld2"; + gpios = <&gpio0 1 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/AWM003-EVB.dts b/target/linux/ramips/dts/AWM003-EVB.dts new file mode 100644 index 0000000..4f3ff1b --- /dev/null +++ b/target/linux/ramips/dts/AWM003-EVB.dts @@ -0,0 +1,68 @@ +/dts-v1/; + +/include/ "AWM002-8M.dtsi" + +/ { + compatible = "AWM003", "ralink,rt5350-soc"; + model = "AsiaRF AWM003 EVB"; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x4000000>; + }; + + palmbus@10000000 { + spi@b00 { + m25p80@0 { + compatible = "mx25l6405d"; + linux,modalias = "m25p80", "mx25l6405d"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + tx { + label = "awm003-evb:green:tx"; + gpios = <&gpio0 15 1>; + }; + + rx { + label = "awm003-evb:green:rx"; + gpios = <&gpio0 16 1>; + }; + + wps { + label = "awm003-evb:green:wps"; + gpios = <&gpio0 21 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset_wps { + label = "reset_wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x198>; + }; + + mode { + label = "mode"; + gpios = <&gpio0 20 1>; + linux,code = <0x32>; + }; + }; +}; diff --git a/target/linux/ramips/dts/ArcherC20i.dts b/target/linux/ramips/dts/ArcherC20i.dts new file mode 100644 index 0000000..0ad4d12 --- /dev/null +++ b/target/linux/ramips/dts/ArcherC20i.dts @@ -0,0 +1,118 @@ +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "ralink,mt7620a-soc"; + model = "TP-Link Archer C20i"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + palmbus@10000000 { + gpio2: gpio@660 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "en25q64"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l6405d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x20000>; + read-only; + }; + + partition@20000 { + label = "firmware"; + reg = <0x20000 0x7a0000>; + }; + + partition@7c0000 { + label = "config"; + reg = <0x7c0000 0x10000>; + }; + + rom: partition@7d0000 { + label = "rom"; + reg = <0x7d0000 0x10000>; + }; + + partition@7e0000 { + label = "romfile"; + reg = <0x7e0000 0x10000>; + }; + + radio: partition@7f0000 { + label = "radio"; + reg = <0x7f0000 0x10000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "uartf", "rgmii1", "rgmii2", "wled", "nd_sd"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + pinctrl-names = "default"; + pinctrl-0 = <&ephy_pins>; + mtd-mac-address = <&rom 0xf100>; + ralink,port-map = "wllll"; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + gsw@10110000 { + ralink,port4 = "ephy"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&radio 0>; + }; + + pcie@10140000 { + status = "okay"; + + pcie-bridge { + mt76@0,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&radio 32768>; + mediatek,2ghz = <0>; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + }; +}; diff --git a/target/linux/ramips/dts/BC2.dts b/target/linux/ramips/dts/BC2.dts new file mode 100644 index 0000000..d920b6e --- /dev/null +++ b/target/linux/ramips/dts/BC2.dts @@ -0,0 +1,87 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "BC2", "ralink,rt3052-soc"; + model = "NexAira BC2"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + usb { + label = "bc2:blue:usb"; + gpios = <&gpio0 20 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 17 1>; + linux,code = <0x198>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/BR-6425.dts b/target/linux/ramips/dts/BR-6425.dts new file mode 100644 index 0000000..cb2c89b --- /dev/null +++ b/target/linux/ramips/dts/BR-6425.dts @@ -0,0 +1,71 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "BR-6425", "ralink,rt3052-soc"; + model = "Edimax BR-6425"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "br-6425:green:power"; + gpios = <&gpio0 9 1>; + }; + + wlan { + label = "br-6425:orange:wlan"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset_wps { + label = "reset_wps"; + gpios = <&gpio0 12 1>; + linux,code = <0x198>; + }; + + rfkill { + label = "RFKILL switch"; + gpios = <&gpio0 13 1>; + linux,code = <0xf7>; + }; + }; +}; diff --git a/target/linux/ramips/dts/BR-6475ND.dts b/target/linux/ramips/dts/BR-6475ND.dts new file mode 100644 index 0000000..8c8a980 --- /dev/null +++ b/target/linux/ramips/dts/BR-6475ND.dts @@ -0,0 +1,183 @@ +/dts-v1/; + +/include/ "rt3883.dtsi" + +/ { + compatible = "BR-6475ND", "ralink,rt3883-soc"; + model = "Edimax BR-6475nD"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "jtag", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + palmbus@10000000 { + timer@100 { + status = "okay"; + }; + + gpio1: gpio@638 { + status = "okay"; + }; + + uartlite@c00 { + status = "okay"; + }; + }; + + ethernet@10100000 { + status = "okay"; + mtd-mac-address = <&devdata 0x0d>; + + port@0 { + ralink,fixed-link = <1000 1 1 1>; + }; + }; + + wmac@10180000 { + status = "okay"; + ralink,mtd-eeprom = <&factory 0>; + }; + + pci@10140000 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pci_pins>; + + pci_pins: pci { + pci { + ralink,group = "pci"; + ralink,function = "pci-fnc"; + }; + }; + + host-bridge { + pci-bridge@1 { + status = "okay"; + + wmac@0,0 { + ralink,5ghz = <0>; + compatible = "ralink,rt2880-pci", "pciclass060400", "pciclass0604"; + reg = < 0x10000 0 0 0 0 >; + ralink,eeprom = "rt2x00pci_1_0.eeprom"; + }; + }; + }; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + nor-flash@1c000000 { + compatible = "cfi-flash"; + reg = <0x1c000000 0x800000>; + bank-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x00000000 0x00030000>; + label = "u-boot"; + read-only; + }; + + partition@30000 { + reg = <0x00030000 0x00010000>; + label = "nvram"; + read-only; + }; + + factory: partition@40000 { + reg = <0x00040000 0x00010000>; + label = "factory"; + read-only; + }; + + devdata: partition@50000 { + reg = <0x00050000 0x00020000>; + label = "devdata"; + read-only; + }; + + partition@70000 { + reg = <0x00070000 0x00790000>; + label = "firmware"; + }; + + partition@170000 { + reg = <0x00270000 0x00590000>; + label = "rootfs"; + }; + }; + + rtl8367 { + compatible = "realtek,rtl8367"; + gpio-sda = <&gpio0 5 0>; + gpio-sck = <&gpio0 4 0>; + realtek,extif0 = <1 0 1 1 1 1 1 1 2>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + reset { + label = "reset"; + gpios = <&gpio0 7 1>; + linux,code = <0x198>; + }; + + rfkill { + label = "rfkill"; + gpios = <&gpio0 9 1>; + linux,input-type = <5>; + linux,code = <0xf7>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "br-6475nd:green:power"; + gpios = <&gpio0 10 1>; + }; + + wlan { + label = "br-6475nd:amber:wlan"; + gpios = <&gpio0 11 1>; + }; + + wlan_5ghz { + label = "br-6475nd:amber:wlan_5ghz"; + gpios = <&gpio0 14 1>; + }; + }; + + /* Unclear if this is the correct gpio setup; the USB ports are + unpopulated on a stock BR-6475nD, even though the hardware exists + and the headers are there. */ + /* + gpio_export { + compatible = "gpio-export"; + #size-cells = <0>; + + usb { + gpio-export,name="usb"; + gpio-export,output=<0>; + gpios = <&gpio0 19 0>; + }; + }; + */ +}; diff --git a/target/linux/ramips/dts/BROADWAY.dts b/target/linux/ramips/dts/BROADWAY.dts new file mode 100644 index 0000000..95c245d --- /dev/null +++ b/target/linux/ramips/dts/BROADWAY.dts @@ -0,0 +1,92 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "BROADWAY", "ralink,rt3052-soc"; + model = "Hauppauge Broadway"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bootloader"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "config"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x790000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x3e>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + diskmounted { + label = "broadway:red:diskmounted"; + gpios = <&gpio0 9 1>; + }; + + wps_active { + label = "broadway:red:wps_active"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + factory { + label = "Factory Reset button"; + gpios = <&gpio0 13 1>; + linux,code = <0x198>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/CARAMBOLA.dts b/target/linux/ramips/dts/CARAMBOLA.dts new file mode 100644 index 0000000..ea3623d --- /dev/null +++ b/target/linux/ramips/dts/CARAMBOLA.dts @@ -0,0 +1,75 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "CARAMBOLA", "ralink,rt3050-soc"; + model = "8devices Carambola"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x3f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + otg@101c0000 { + status = "okay"; + }; + + i2c-gpio { + compatible = "i2c-gpio"; + gpios = <&gpio0 1 0 &gpio0 2 0>; + i2c-gpio,delay-us = <10>; + }; +}; diff --git a/target/linux/ramips/dts/CF-WR800N.dts b/target/linux/ramips/dts/CF-WR800N.dts new file mode 100644 index 0000000..2ee16df --- /dev/null +++ b/target/linux/ramips/dts/CF-WR800N.dts @@ -0,0 +1,115 @@ +/dts-v1/; + +/include/ "mt7620n.dtsi" + +/ { + compatible = "cf-wr800n", "ralink,mt7620n-soc"; + model = "Comfast CF-WR800N"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + palmbus@10000000 { + gpio0: gpio@600 { + status = "okay"; + }; + + gpio1: gpio@638 { + status = "okay"; + }; + + gpio2: gpio@660 { + status = "okay"; + }; + + gpio3: gpio@688 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l6405d"; + reg = <0 0>; + linux,modalias = "m25p80", "w25q64"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pinctrl { + state_default: pinctrl0 { + default { + ralink,group = "ephy", "wled", "spi refclk", "i2c"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + ethernet { + label = "cf-wr800n:white:ethernet"; + gpios = <&gpio2 4 1>; + }; + + wifi { + label = "cf-wr800n:white:wifi"; + gpios = <&gpio3 0 1>; + }; + + wps { + label = "cf-wr800n:white:wps"; + gpios = <&gpio1 15 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 2 1>; + linux,code = <0x198>; + }; + }; +}; diff --git a/target/linux/ramips/dts/CY-SWR1100.dts b/target/linux/ramips/dts/CY-SWR1100.dts new file mode 100644 index 0000000..cec84ac --- /dev/null +++ b/target/linux/ramips/dts/CY-SWR1100.dts @@ -0,0 +1,152 @@ +/dts-v1/; + +/include/ "rt3883.dtsi" + +/ { + compatible = "CY-SWR1100", "ralink,rt3883-soc"; + model = "Samsung CY-SWR1100"; + + palmbus@10000000 { + gpio1: gpio@638 { + status = "okay"; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "spi"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + port@0 { + ralink,fixed-link = <1000 1 1 1>; + phy-mode = "rgmii"; + }; + }; + + pci@10140000 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pci_pins>; + + pci_pins: pci { + pci { + ralink,group = "pci"; + ralink,function = "pci-fnc"; + }; + }; + + host-bridge { + pci-bridge@1 { + status = "okay"; + + wmac@0,0 { + ralink,5ghz = <0>; + compatible = "ralink,rt2880-pci", "pciclass060400", "pciclass0604"; + reg = < 0x10000 0 0 0 0 >; + ralink,eeprom = "rt2x00pci_1_0.eeprom"; + }; + }; + }; + }; + + wmac@10180000 { + status = "okay"; + ralink,2ghz = <0>; + ralink,mtd-eeprom = <&factory 0>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + nor-flash@1c000000 { + compatible = "cfi-flash"; + reg = <0x1c000000 0x800000>; + bank-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "uboot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "uboot-env"; + reg = <0x30000 0x4000>; + read-only; + }; + + factory: partition@34000 { + label = "factory"; + reg = <0x34000 0x4000>; + read-only; + }; + + partition@38000 { + label = "nvram"; + reg = <0x38000 0x8000>; + read-only; + }; + + partition@40000 { + label = "devdata"; + reg = <0x40000 0x10000>; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + + rtl8367 { + compatible = "realtek,rtl8367"; + gpio-sda = <&gpio0 1 0>; + gpio-sck = <&gpio0 2 0>; + realtek,extif0 = <1 0 1 1 1 1 1 1 2>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + reset { + label = "reset"; + gpios = <&gpio0 6 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 3 1>; + linux,code = <0x211>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wps { + label = "cy-swr1100:blue:wps"; + gpios = <&gpio0 0 1>; + }; + + usb { + label = "cy-swr1100:blue:usb"; + gpios = <&gpio1 1 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/D105.dts b/target/linux/ramips/dts/D105.dts new file mode 100644 index 0000000..5ef625c --- /dev/null +++ b/target/linux/ramips/dts/D105.dts @@ -0,0 +1,92 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "D105", "ralink,rt3050-soc"; + model = "Huawei D105"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "d105:red:power"; + gpios = <&gpio0 0 1>; + }; + + wps { + label = "d105:green:usb"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/DAP-1350.dts b/target/linux/ramips/dts/DAP-1350.dts new file mode 100644 index 0000000..ce52945 --- /dev/null +++ b/target/linux/ramips/dts/DAP-1350.dts @@ -0,0 +1,125 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "DAP-1350", "ralink,rt3052-soc"; + model = "D-Link DAP-1350"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + devdata: partition@30000 { + label = "devdata"; + reg = <0x30000 0x10000>; + read-only; + }; + + partition@40000 { + label = "devconf"; + reg = <0x40000 0x30000>; + read-only; + }; + + partition@70000 { + label = "devlang"; + reg = <0x70000 0x40000>; + read-only; + }; + + partition@b0000 { + label = "firmware"; + reg = <0xb0000 0x750000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&devdata 0x2e>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&devdata 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "dap-1350:blue:power"; + gpios = <&gpio0 8 1>; + }; + + power2 { + label = "dap-1350:red:power"; + gpios = <&gpio0 9 1>; + }; + + wps { + label = "dap-1350:blue:wps"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + + rt { + label = "rt"; + gpios = <&gpio0 11 1>; + linux,code = <0x100>; + }; + + ap { + label = "ap"; + gpios = <&gpio0 7 1>; + linux,code = <0x101>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/DB-WRT01.dts b/target/linux/ramips/dts/DB-WRT01.dts new file mode 100644 index 0000000..d0fbaf3 --- /dev/null +++ b/target/linux/ramips/dts/DB-WRT01.dts @@ -0,0 +1,100 @@ +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "ralink,mt7620a-soc"; + model = "Planex DB-WRT01"; + + palmbus@10000000 { + gpio1: gpio@638 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "en25q64"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l6405d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "spi refclk", "rgmii1"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + pinctrl-names = "default"; + pinctrl-0 = <&ephy_pins>; + mtd-mac-address = <&factory 0x4>; + ralink,port-map = "llllw"; + }; + + gsw@10110000 { + ralink,port4 = "ephy"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pcie@10140000 { + status = "okay"; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "db-wrt01:orange:power"; + gpios = <&gpio1 1 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + s1 { + label = "wps"; + gpios = <&gpio0 2 1>; + linux,code = <0x211>; + }; + }; +}; diff --git a/target/linux/ramips/dts/DCS-930.dts b/target/linux/ramips/dts/DCS-930.dts new file mode 100644 index 0000000..3c89f84 --- /dev/null +++ b/target/linux/ramips/dts/DCS-930.dts @@ -0,0 +1,113 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "DCS-930", "ralink,rt3050-soc"; + model = "D-Link DCS-930"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "spi", "jtag", "mdio", "rgmii", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x400000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "kernel"; + reg = <0x50000 0x150000>; + }; + + partition@150000 { + label = "rootfs"; + reg = <0x150000 0x2b0000>; + }; + + partition { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wifi { + label = "dcs-930:red:alert"; + gpios = <&gpio0 8 1>; + }; + + power { + label = "dcs-930:green:status"; + gpios = <&gpio0 9 1>; + }; + + wps { + label = "dcs-930:blue:wps"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x101>; + }; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/DCS-930L-B1.dts b/target/linux/ramips/dts/DCS-930L-B1.dts new file mode 100644 index 0000000..525707c --- /dev/null +++ b/target/linux/ramips/dts/DCS-930L-B1.dts @@ -0,0 +1,108 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "DCS-930L-B1", "ralink,rt5350-soc"; + model = "D-Link DCS-930L B1"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l3205d"; + reg = <0 0>; + linux,modalias = "m25p80", "s25fl064k"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "uartf", "led"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "dcs-930l-b1:red:power"; + gpios = <&gpio0 17 1>; + }; + + wps { + label = "dcs-930l-b1:blue:wps"; + gpios = <&gpio0 19 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 0 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 20 1>; + linux,code = <0x211>; + }; + }; +}; diff --git a/target/linux/ramips/dts/DIR-300-B1.dts b/target/linux/ramips/dts/DIR-300-B1.dts new file mode 100644 index 0000000..6d19f65 --- /dev/null +++ b/target/linux/ramips/dts/DIR-300-B1.dts @@ -0,0 +1,109 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "DIR-300-B1", "ralink,rt3050-soc"; + model = "D-Link DIR-300 B1"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "spi", "jtag", "mdio", "rgmii", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + devdata: partition@30000 { + label = "devdata"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "devconf"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&devdata 0x4004>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&devdata 0x4000>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "dir-300-b1:amber:status"; + gpios = <&gpio0 8 1>; + }; + + status2 { + label = "dir-300-b1:green:status"; + gpios = <&gpio0 9 1>; + }; + + wan { + label = "dir-300-b1:amber:wan"; + gpios = <&gpio0 14 1>; + }; + + wan2 { + label = "dir-300-b1:green:wan"; + gpios = <&gpio0 12 1>; + }; + + wps { + label = "dir-300-b1:blue:wps"; + gpios = <&gpio0 13 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/DIR-300-B7.dts b/target/linux/ramips/dts/DIR-300-B7.dts new file mode 100644 index 0000000..30c2596 --- /dev/null +++ b/target/linux/ramips/dts/DIR-300-B7.dts @@ -0,0 +1,103 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "DIR-300-B7", "ralink,rt5350-soc"; + model = "D-Link DIR-300 B7"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "s25fl064k"; + reg = <0 0>; + linux,modalias = "m25p80", "s25fl064k"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + ralink,led_polarity = <0x17>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "dir-300-b7:green:status"; + gpios = <&gpio0 9 1>; + }; + + wps { + label = "dir-300-b7:blue:wps"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; + + wmac@10180000 { + status = "okay"; + ralink,led-polarity = <1>; + ralink,mtd-eeprom = <&factory 0>; + }; +}; diff --git a/target/linux/ramips/dts/DIR-320-B1.dts b/target/linux/ramips/dts/DIR-320-B1.dts new file mode 100644 index 0000000..c1e5832 --- /dev/null +++ b/target/linux/ramips/dts/DIR-320-B1.dts @@ -0,0 +1,131 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "DIR-320-B1", "ralink,rt5350-soc"; + model = "D-Link DIR-320 B1"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "s25fl064k"; + reg = <0 0>; + linux,modalias = "m25p80", "s25fl064k"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + ralink,led_polarity = <0x17>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "dir-320-b1:green:status"; + gpios = <&gpio0 9 1>; + }; + + usb { + label = "dir-320-b1:green:usb"; + gpios = <&gpio0 14 1>; + }; + + wps { + label = "dir-320-b1:green:wps"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c0000 { + status = "okay"; + }; + + gpio_export { + compatible = "gpio-export"; + #size-cells = <0>; + + usb { + gpio-export,name = "usb"; + gpio-export,output = <1>; + gpios = <&gpio0 7 0>; + }; + + root_hub { + gpio-export,name = "root_hub"; + gpio-export,output = <1>; + gpios = <&gpio0 12 0>; + }; + }; +}; diff --git a/target/linux/ramips/dts/DIR-600-B1.dts b/target/linux/ramips/dts/DIR-600-B1.dts new file mode 100644 index 0000000..5020b78 --- /dev/null +++ b/target/linux/ramips/dts/DIR-600-B1.dts @@ -0,0 +1,109 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "DIR-600-B1", "ralink,rt3050-soc"; + model = "D-Link DIR-600 B1"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "spi", "jtag", "mdio", "rgmii", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + devdata: partition@30000 { + label = "devdata"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "devconf"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&devdata 0x4004>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&devdata 0x4000>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "dir-600-b1:amber:status"; + gpios = <&gpio0 8 1>; + }; + + status2 { + label = "dir-600-b1:green:status"; + gpios = <&gpio0 9 1>; + }; + + wan { + label = "dir-600-b1:amber:wan"; + gpios = <&gpio0 14 1>; + }; + + wan2 { + label = "dir-600-b1:green:wan"; + gpios = <&gpio0 12 1>; + }; + + wps { + label = "dir-600-b1:blue:wps"; + gpios = <&gpio0 13 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/DIR-600-B2.dts b/target/linux/ramips/dts/DIR-600-B2.dts new file mode 100644 index 0000000..d06b853 --- /dev/null +++ b/target/linux/ramips/dts/DIR-600-B2.dts @@ -0,0 +1,105 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "DIR-600-B2", "ralink,rt3050-soc"; + model = "D-Link DIR-600 B2"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "spi", "jtag", "mdio", "rgmii", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + devdata: partition@30000 { + label = "devdata"; + reg = <0x30000 0x10000>; + read-only; + }; + + partition@40000 { + label = "devconf"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&devdata 0x4000>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "dir-600-b2:amber:status"; + gpios = <&gpio0 8 1>; + }; + + status2 { + label = "dir-600-b2:green:status"; + gpios = <&gpio0 9 1>; + }; + + wan { + label = "dir-600-b2:amber:wan"; + gpios = <&gpio0 14 1>; + }; + + wan2 { + label = "dir-600-b2:green:wan"; + gpios = <&gpio0 12 1>; + }; + + wps { + label = "dir-600-b2:blue:wps"; + gpios = <&gpio0 13 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/DIR-610-A1.dts b/target/linux/ramips/dts/DIR-610-A1.dts new file mode 100644 index 0000000..9ec9870 --- /dev/null +++ b/target/linux/ramips/dts/DIR-610-A1.dts @@ -0,0 +1,104 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "DIR-610-A1", "ralink,rt5350-soc"; + model = "D-Link DIR-610 A1"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "f25l32pa", "m25p80"; + reg = <0 0>; + linux,modalias = "m25p80"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + devdata: partition@30000 { + label = "devdata"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&devdata 0x4004>; + }; + + esw@10110000 { + status = "okay"; + ralink,portmap = <0x2f>; + ralink,led_polarity = <0x17>; + }; + + wmac@10180000 { + status = "okay"; + ralink,led-polarity = <1>; + ralink,mtd-eeprom = <&devdata 0x4000>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "dir-610-a1:green:status"; + gpios = <&gpio0 9 1>; + }; + + wps { + label = "dir-610-a1:green:wps"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; +}; diff --git a/target/linux/ramips/dts/DIR-615-D.dts b/target/linux/ramips/dts/DIR-615-D.dts new file mode 100644 index 0000000..a57ea6d --- /dev/null +++ b/target/linux/ramips/dts/DIR-615-D.dts @@ -0,0 +1,105 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "DIR-615-D", "ralink,rt3050-soc"; + model = "D-Link DIR-615 D"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "spi", "jtag", "mdio", "rgmii", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + devdata: partition@30000 { + label = "devdata"; + reg = <0x30000 0x10000>; + read-only; + }; + + partition@40000 { + label = "devconf"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&devdata 0x4000>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "dir-615-d:amber:status"; + gpios = <&gpio0 8 1>; + }; + + status2 { + label = "dir-615-d:green:status"; + gpios = <&gpio0 9 1>; + }; + + wan { + label = "dir-615-d:amber:wan"; + gpios = <&gpio0 14 1>; + }; + + wan2 { + label = "dir-615-d:green:wan"; + gpios = <&gpio0 12 1>; + }; + + wps { + label = "dir-615-d:blue:wps"; + gpios = <&gpio0 13 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/DIR-615-H1.dts b/target/linux/ramips/dts/DIR-615-H1.dts new file mode 100644 index 0000000..f9bdc92 --- /dev/null +++ b/target/linux/ramips/dts/DIR-615-H1.dts @@ -0,0 +1,125 @@ +/dts-v1/; + +/include/ "rt3352.dtsi" + +/ { + compatible = "DIR-615-H1", "ralink,rt3352-soc"; + model = "D-Link DIR-615 H1"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l3205d"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l3205d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "uartf"; + ralink,function = "gpio"; + }; + + rgmii { + ralink,group = "rgmii"; + ralink,function = "rgmii"; + }; + + mdio { + ralink,group = "mdio"; + ralink,function = "mdio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "dir-615-h1:amber:status"; + gpios = <&gpio0 7 0>; + }; + + status2 { + label = "dir-615-h1:green:status"; + gpios = <&gpio0 9 0>; + }; + + wan { + label = "dir-615-h1:amber:wan"; + gpios = <&gpio0 12 1>; + }; + + wan2 { + label = "dir-615-h1:green:wan"; + gpios = <&gpio0 13 1>; + }; + + wps { + label = "dir-615-h1:blue:wps"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; +}; diff --git a/target/linux/ramips/dts/DIR-620-A1.dts b/target/linux/ramips/dts/DIR-620-A1.dts new file mode 100644 index 0000000..212cf88 --- /dev/null +++ b/target/linux/ramips/dts/DIR-620-A1.dts @@ -0,0 +1,118 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "DIR-620-A1", "ralink,rt3050-soc"; + model = "D-Link DIR-620 A1"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "dir-620-a1:amber:status"; + gpios = <&gpio0 8 1>; + }; + + status2 { + label = "dir-620-a1:green:status"; + gpios = <&gpio0 9 1>; + }; + + wan { + label = "dir-620-a1:amber:wan"; + gpios = <&gpio0 14 1>; + }; + + wan2 { + label = "dir-620-a1:green:wan"; + gpios = <&gpio0 12 1>; + }; + + wps { + label = "dir-620-a1:blue:wps"; + gpios = <&gpio0 13 0>; + }; + + wps2 { + label = "dir-620-a1:amber:wps"; + gpios = <&gpio0 11 0>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/DIR-620-D1.dts b/target/linux/ramips/dts/DIR-620-D1.dts new file mode 100644 index 0000000..166d61e --- /dev/null +++ b/target/linux/ramips/dts/DIR-620-D1.dts @@ -0,0 +1,112 @@ +/dts-v1/; + +/include/ "rt3352.dtsi" + +/ { + compatible = "DIR-620-D1", "ralink,rt3352-soc"; + model = "D-Link DIR-620 D1"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l6405d"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l6405d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "uartf"; + ralink,function = "gpio"; + }; + + rgmii { + ralink,group = "rgmii"; + ralink,function = "rgmii"; + }; + + mdio { + ralink,group = "mdio"; + ralink,function = "mdio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "dir-620-d1:green:status"; + gpios = <&gpio0 9 1>; + }; + + wifi { + label = "dir-620-d1:green:wifi"; + gpios = <&gpio0 17 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset_wps { + label = "reset_wps"; + gpios = <&gpio0 7 1>; + linux,code = <0x198>; + }; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/DIR-645.dts b/target/linux/ramips/dts/DIR-645.dts new file mode 100644 index 0000000..58a0788 --- /dev/null +++ b/target/linux/ramips/dts/DIR-645.dts @@ -0,0 +1,142 @@ +/dts-v1/; + +/include/ "rt3883.dtsi" + +/ { + compatible = "DIR-645", "ralink,rt3883-soc"; + model = "D-Link DIR-645"; + + palmbus@10000000 { + gpio1: gpio@638 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l6405d"; + reg = <0 0>; + linux,modalias = "m25p80"; + spi-max-frequency = <25000000>; + + partition@0 { + label = "uboot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "uboot-env"; + reg = <0x30000 0x4000>; + read-only; + }; + + factory: partition@34000 { + label = "factory"; + reg = <0x34000 0x4000>; + read-only; + }; + + partition@38000 { + label = "nvram"; + reg = <0x38000 0x8000>; + read-only; + }; + + partition@40000 { + label = "devdata"; + reg = <0x40000 0x10000>; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + + port@0 { + ralink,fixed-link = <1000 1 1 0>; + }; + }; + + wmac@10180000 { + ralink,5ghz = <0>; + ralink,mtd-eeprom = <&factory 0>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + rtl8367b { + compatible = "realtek,rtl8367b"; + gpio-sda = <&gpio0 1 0>; + gpio-sck = <&gpio0 2 0>; + realtek,extif1 = <1 0 1 1 1 1 1 1 2>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + reset { + label = "reset"; + gpios = <&gpio0 9 0>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 14 0>; + linux,code = <0x211>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + inet { + label = "dir-645:green:inet"; + gpios = <&gpio0 0 1>; + }; + + wps { + label = "dir-645:green:wps"; + gpios = <&gpio1 2 0>; + }; + }; + + gpio_export { + compatible = "gpio-export"; + #size-cells = <0>; + + usb { + gpio-export,name = "usb"; + gpio-export,output = <1>; + gpios = <&gpio1 6 0>; + }; + }; +}; diff --git a/target/linux/ramips/dts/DIR-810L.dts b/target/linux/ramips/dts/DIR-810L.dts new file mode 100644 index 0000000..4f00787 --- /dev/null +++ b/target/linux/ramips/dts/DIR-810L.dts @@ -0,0 +1,136 @@ +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "dlink,dir-810l", "ralink,mt7620a-soc"; + model = "D-Link DIR-810L"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l6405d"; + reg = <0 0>; + linux,modalias = "m25p80"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + factory5g: partition@50000 { + label = "factory5g"; + reg = <0x50000 0x10000>; + read-only; + }; + + partition@60000 { + label = "Wolf_Config"; + reg = <0x60000 0x10000>; + read-only; + }; + + partition@70000 { + label = "MyDlink"; + reg = <0x70000 0x80000>; + read-only; + }; + + partition@e0000 { + label = "Jffs2"; + reg = <0xe0000 0x80000>; + read-only; + }; + + partition@170000 { + label = "firmware"; + reg = <0x170000 0x690000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "mdio", "rgmii1", "i2c", "wled", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + ralink,port-map = "llllw"; + }; + + gsw@10110000 { + ralink,port4 = "ephy"; + pinctrl-names = "default"; + pinctrl-0 = <&ephy_pins>; + }; + + pcie@10140000 { + status = "okay"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 1 1>; + linux,code = <0x100>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 2 1>; + linux,code = <0x100>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "dir-810l:green:power"; + gpios = <&gpio0 9 0>; + }; + + wan { + label = "dir-810l:orange:wan"; + gpios = <&gpio0 12 0>; + }; + + status { + label = "dir-810l:orange:power"; + gpios = <&gpio0 13 0>; + }; + }; +}; diff --git a/target/linux/ramips/dts/DIR-860L-B1.dts b/target/linux/ramips/dts/DIR-860L-B1.dts new file mode 100644 index 0000000..cae93c4 --- /dev/null +++ b/target/linux/ramips/dts/DIR-860L-B1.dts @@ -0,0 +1,109 @@ +/dts-v1/; + +/include/ "mt7621.dtsi" + +/ { + compatible = "ralink,mt7621-eval-board", "ralink,mt7621-soc"; + model = "D-Link DIR-860L B1"; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x8000000>; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + palmbus@1E000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l12805d"; + reg = <0 0>; + linux,modalias = "m25p80"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x4000>; + read-only; + }; + + radio: partition@34000 { + label = "radio"; + reg = <0x34000 0x4000>; + read-only; + }; + + factory: partition@38000 { + label = "factory"; + reg = <0x38000 0x8000>; + read-only; + }; + + partition@40000 { + label = "defaults"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xfb0000>; + }; + }; + }; + }; + + pcie@1e140000 { + status = "okay"; + + pcie0 { + mt76@0,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&radio 0x2000>; + mediatek,2ghz = <0>; + }; + }; + + pcie1 { + mt76@1,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&radio 0>; + mediatek,5ghz = <0>; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + }; +}; diff --git a/target/linux/ramips/dts/E1700.dts b/target/linux/ramips/dts/E1700.dts new file mode 100644 index 0000000..832b715 --- /dev/null +++ b/target/linux/ramips/dts/E1700.dts @@ -0,0 +1,154 @@ +/* + * Device Tree file for the Linksys E1700 + * + * Copyright (C) 2014 Imre Kaloz <kaloz@openwrt.org> + * + * 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. + */ + +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "linksys,e1700", "ralink,mt7620a-soc"; + model = "Linksys E1700"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l6405d"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l6405d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "config"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + status = "okay"; + mtd-mac-address = <&factory 0x28>; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii1_pins &rgmii2_pins &mdio_pins>; + + port@5 { + status = "okay"; + ralink,fixed-link = <1000 1 1 1>; + phy-mode = "rgmii"; + }; + + mdio-bus { + status = "okay"; + + phy0: ethernet-phy@0 { + reg = <0>; + phy-mode = "rgmii"; + }; + + phy1: ethernet-phy@1 { + reg = <1>; + phy-mode = "rgmii"; + }; + + phy2: ethernet-phy@2 { + reg = <2>; + phy-mode = "rgmii"; + }; + + phy3: ethernet-phy@3 { + reg = <3>; + phy-mode = "rgmii"; + }; + + phy4: ethernet-phy@4 { + reg = <4>; + phy-mode = "rgmii"; + }; + + phy1f: ethernet-phy@1f { + reg = <0x1f>; + phy-mode = "rgmii"; + }; + }; + }; + + gsw@10110000 { + ralink,port4 = "gmac"; + mediatek,mt7530 = <1>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 1 0>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 2 0>; + linux,code = <0x211>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "e1700:green:power"; + gpios = <&gpio0 10 1>; + }; + + wan { + label = "e1700:green:wps"; + gpios = <&gpio0 12 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/ESR-9753.dts b/target/linux/ramips/dts/ESR-9753.dts new file mode 100644 index 0000000..b0f9046 --- /dev/null +++ b/target/linux/ramips/dts/ESR-9753.dts @@ -0,0 +1,94 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "ESR-9753", "ralink,rt3052-soc"; + model = "Senao / EnGenius ESR-9753"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "esr-9753:orange:power"; + gpios = <&gpio0 8 1>; + }; + + wps { + label = "esr-9753:orange:wps"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x3e>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; +}; diff --git a/target/linux/ramips/dts/F5D8235_V1.dts b/target/linux/ramips/dts/F5D8235_V1.dts new file mode 100644 index 0000000..2f51025 --- /dev/null +++ b/target/linux/ramips/dts/F5D8235_V1.dts @@ -0,0 +1,111 @@ +/dts-v1/; + +/include/ "rt2880.dtsi" + +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "F5D8235_V1", "ralink,rt2880-soc"; + model = "Belkin F5D8235 v1"; + + palmbus@300000 { + gpio0: gpio@600 { + status = "okay"; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "uboot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "uboot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "linux"; + reg = <0x50000 0x3b0000>; + }; + }; + + ethernet@400000 { + status = "okay"; + mtd-mac-address = <&factory 0x4>; + + port@0 { + ralink,fixed-link = <1000 1 1 1>; + }; + }; + + /* FIXME: no u-boot partition and 0x40000@uboot is out of boundaries */ +/* wmac@480000 { + status = "okay"; + ralink,mtd-eeprom = <&u-boot 0x40000>; + }; +*/ + rtl8366s { + compatible = "realtek,rtl8366s"; + gpio-sda = <&gpio0 1 0>; + gpio-sck = <&gpio0 2 0>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + + reset { + label = "reset"; + gpios = <&gpio0 9 1>; + linux,code = <0x198>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + storage { + label = "f5d8235-v1:blue:storage"; + gpios = <&gpio0 7 1>; + }; + + storage2 { + label = "f5d8235-v1:orange:storage"; + gpios = <&gpio0 8 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/F5D8235_V2.dts b/target/linux/ramips/dts/F5D8235_V2.dts new file mode 100644 index 0000000..d0a49f6 --- /dev/null +++ b/target/linux/ramips/dts/F5D8235_V2.dts @@ -0,0 +1,118 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "F5D8235_V2", "ralink,rt3052-soc"; + model = "Belkin F5D8235 v2"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + uboot: partition@0 { + label = "uboot"; + reg = <0x0 0x50000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x790000>; + }; + + partition@7e0000 { + label = "nvram"; + reg = <0x7e0000 0x10000>; + }; + + factory: partition@7f0000 { + label = "factory"; + reg = <0x7f0000 0x10000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&uboot 0x40004>; + }; + + esw@10110000 { + ralink,portmap = <0x3f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&uboot 0x40000>; + }; + + otg@101c0000 { + status = "okay"; + }; + + rtl8366rb { + compatible = "rtl8366rb"; + gpio-sda = <&gpio0 1 0>; + gpio-sck = <&gpio0 2 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + internet { + label = "f5d8235-v2:blue:internet"; + gpios = <&gpio0 5 1>; + }; + + internet2 { + label = "f5d8235-v2:amber:internet"; + gpios = <&gpio0 6 1>; + }; + + modem { + label = "f5d8235-v2:blue:modem"; + gpios = <&gpio0 11 1>; + }; + + modem2 { + label = "f5d8235-v2:amber:modem"; + gpios = <&gpio0 8 1>; + }; + + router { + label = "f5d8235-v2:blue:router"; + gpios = <&gpio0 9 1>; + }; + + storage { + label = "f5d8235-v2:blue:storage"; + gpios = <&gpio0 23 1>; + }; + + storage2 { + label = "f5d8235-v2:amber:storage"; + gpios = <&gpio0 22 1>; + }; + + security { + label = "f5d8235-v2:blue:security"; + gpios = <&gpio0 13 1>; + }; + + security2 { + label = "f5d8235-v2:amber:security"; + gpios = <&gpio0 12 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/F7C027.dts b/target/linux/ramips/dts/F7C027.dts new file mode 100644 index 0000000..89e9356 --- /dev/null +++ b/target/linux/ramips/dts/F7C027.dts @@ -0,0 +1,133 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "F7C027", "ralink,rt5350-soc"; + model = "Belkin F7C027"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l12805d"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l12805d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x770000>; + }; + + partition@7c0000 { + label = "firmware2"; + reg = <0x7c0000 0x770000>; + }; + + partition@f30000 { + label = "belkin_settings"; + reg = <0xf30000 0xa0000>; + }; + + partition@fd0000 { + label = "unknown"; + reg = <0xfd0000 0x10000>; + }; + + partition@fe0000 { + label = "nvram"; + reg = <0xfe0000 0x10000>; + }; + + partition@ff0000 { + label = "user_factory"; + reg = <0xff0000 0x10000>; + }; + }; + }; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "f7c027:blue:status"; + gpios = <&gpio0 7 1>; + }; + + power { + label = "f7c027:blue:power"; + gpios = <&gpio0 9 1>; + }; + + orange { + label = "f7c027:orange:status"; + gpios = <&gpio0 11 1>; + }; + + relay { + label = "f7c027:device:relay"; + gpios = <&gpio0 13 0>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + top { + label = "top"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + power { + label = "power"; + gpios = <&gpio0 12 1>; + linux,code = <0x100>; + }; + + sensor { + label = "sensor"; + gpios = <&gpio0 14 1>; + linux,code = <0x101>; + }; + }; +}; diff --git a/target/linux/ramips/dts/FIREWRT.dts b/target/linux/ramips/dts/FIREWRT.dts new file mode 100644 index 0000000..b72066a --- /dev/null +++ b/target/linux/ramips/dts/FIREWRT.dts @@ -0,0 +1,122 @@ +/dts-v1/; + +/include/ "mt7621.dtsi" + +/ { + compatible = "mediatek,mt7621-eval-board", "mediatek,mt7621-soc"; + model = "Firefly FireWRT"; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x1c000000>, <0x20000000 0x4000000>; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + sdhci@10130000 { + status = "okay"; + }; + + palmbus@1E000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "w25q128"; + reg = <0 0>; + linux,modalias = "m25p80"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xfb0000>; + }; + }; + }; + }; + + pcie@1e140000 { + status = "okay"; + + pcie0 { + mt76@0,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 0x8000>; + mediatek,2ghz = <0>; + }; + }; + + pcie1 { + mt76@1,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 0x0000>; + mediatek,5ghz = <0>; + }; + }; + }; + + ethernet@1e100000 { + mtd-mac-address = <&factory 0xe000>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "firewrt:green:power"; + gpios = <&gpio0 22 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + wps { + label = "wps"; + gpios = <&gpio0 18 1>; + linux,code = <0x211>; + }; + + power { + label = "power"; + gpios = <&gpio0 23 1>; + linux,code = <116>; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "wdt", "rgmii2"; + ralink,function = "gpio"; + }; + }; + }; +}; diff --git a/target/linux/ramips/dts/FONERA20N.dts b/target/linux/ramips/dts/FONERA20N.dts new file mode 100644 index 0000000..d3479b1 --- /dev/null +++ b/target/linux/ramips/dts/FONERA20N.dts @@ -0,0 +1,134 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "FONERA20N", "ralink,rt3052-soc"; + model = "La Fonera 2.0N"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "spi", "jtag", "mdio", "rgmii", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wifi { + label = "fonera20n:orange:wifi"; + gpios = <&gpio0 7 1>; + }; + + power { + label = "fonera20n:green:power"; + gpios = <&gpio0 9 1>; + }; + + usb { + label = "fonera20n:orange:usb"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 12 1>; + linux,code = <0x198>; + }; + + switch { + label = "switch"; + gpios = <&gpio0 13 1>; + linux,code = <0xf7>; + linux,input-type = <5>; /* EV_SW */ + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + + port@0 { + compatible = "swconfig,port"; + swconfig,segment = "lan"; + swconfig,portmap = <0 4>; + }; + + port@1 { + compatible = "swconfig,port"; + swconfig,segment = "lan"; + swconfig,portmap = <1 3>; + }; + + port@2 { + compatible = "swconfig,port"; + swconfig,segment = "lan"; + swconfig,portmap = <2 2>; + }; + + port@3 { + compatible = "swconfig,port"; + swconfig,segment = "lan"; + swconfig,portmap = <3 1>; + }; + + port@4 { + compatible = "swconfig,port"; + swconfig,segment = "wan"; + swconfig,portmap = <4 0>; + }; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/FREESTATION5.dts b/target/linux/ramips/dts/FREESTATION5.dts new file mode 100644 index 0000000..a6a7402 --- /dev/null +++ b/target/linux/ramips/dts/FREESTATION5.dts @@ -0,0 +1,102 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "FREESTATION5", "ralink,rt3050-soc"; + model = "ARC FreeStation5"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x01>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + otg@101c0000 { + status = "okay"; + }; + + gpio-export { + compatible = "gpio-export"; + + // Used to enable power-over-ethernet passthrough from port0 to port1. + // Disable passthrough by default to prevent accidental equipment damage. + poe { + gpio-export,name = "poe-passthrough"; + gpio-export,output = <1>; // OUT_INIT_HIGH + gpios = <&gpio0 11 1>; // GPIO 11, ACTIVE_LOW + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + // The following leds are defined in the ArcOS firmware, but reportedly + // not present in the Freestation5 device. + wifi { + label = "freestation5:unknown:wifi"; + gpios = <&gpio0 7 1>; + }; + + powerg { + label = "freestation5:unknown:powerg"; + gpios = <&gpio0 9 1>; + }; + + usb { + label = "freestation5:unknown:usb"; + gpios = <&gpio0 14 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/HC5661.dts b/target/linux/ramips/dts/HC5661.dts new file mode 100644 index 0000000..b9a717b --- /dev/null +++ b/target/linux/ramips/dts/HC5661.dts @@ -0,0 +1,32 @@ +/dts-v1/; + +/include/ "HC5XXX.dtsi" + +/ { + compatible = "HC5661", "ralink,mt7620a-soc"; + model = "HiWiFi HC5661"; + + gpio-leds { + compatible = "gpio-leds"; + + system { + label = "hc5661:blue:system"; + gpios = <&gpio0 9 1>; + }; + + internet { + label = "hc5661:blue:internet"; + gpios = <&gpio0 11 1>; + }; + + wlan2g { + label = "hc5661:blue:wlan2g"; + gpios = <&gpio3 0 1>; + }; + + wlan5g { + label = "hc5661:blue:wlan5g"; + gpios = <&gpio0 7 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/HC5761.dts b/target/linux/ramips/dts/HC5761.dts new file mode 100644 index 0000000..a10904c --- /dev/null +++ b/target/linux/ramips/dts/HC5761.dts @@ -0,0 +1,32 @@ +/dts-v1/; + +/include/ "HC5XXX.dtsi" + +/ { + compatible = "HC5761", "ralink,mt7620a-soc"; + model = "HiWiFi HC5761"; + + gpio-leds { + compatible = "gpio-leds"; + + system { + label = "hc5761:blue:system"; + gpios = <&gpio0 9 1>; + }; + + internet { + label = "hc5761:blue:internet"; + gpios = <&gpio0 11 1>; + }; + + wlan2g { + label = "hc5761:blue:wlan2g"; + gpios = <&gpio3 0 1>; + }; + + wlan5g { + label = "hc5761:blue:wlan5g"; + gpios = <&gpio0 7 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/HC5861.dts b/target/linux/ramips/dts/HC5861.dts new file mode 100644 index 0000000..05857ea --- /dev/null +++ b/target/linux/ramips/dts/HC5861.dts @@ -0,0 +1,92 @@ +/dts-v1/; + +/include/ "HC5XXX.dtsi" + +/ { + compatible = "HC5861", "ralink,mt7620a-soc"; + model = "HiWiFi HC5861"; + + ethernet@10100000 { + status = "okay"; + mtd-mac-address = <&factory 0x4>; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii1_pins &rgmii2_pins &mdio_pins>; + ralink,port-map = "wllll"; + + port@4 { + status = "okay"; + phy-handle = <&phy4>; + phy-mode = "rgmii"; + }; + + port@5 { + status = "okay"; + phy-handle = <&phy5>; + phy-mode = "rgmii"; + }; + + mdio-bus { + status = "okay"; + + phy4: ethernet-phy@4 { + reg = <4>; + phy-mode = "rgmii"; + }; + + phy5: ethernet-phy@5 { + reg = <5>; + phy-mode = "rgmii"; + }; + }; + }; + + gsw@10110000 { + ralink,port4 = "gmac"; + }; + + gpio-leds { + compatible = "gpio-leds"; + + system { + label = "hc5861:blue:system"; + gpios = <&gpio0 9 1>; + }; + + wlan2g { + label = "hc5861:blue:wlan2g"; + gpios = <&gpio0 11 1>; + }; + + internet { + label = "hc5861:blue:internet"; + gpios = <&gpio3 0 1>; + }; + + wlan5g { + label = "hc5861:blue:wlan5g"; + gpios = <&gpio0 7 1>; + }; + + turbo { + label = "hc5861:blue:turbo"; + gpios = <&gpio0 10 1>; + }; + }; + + gpio_export { + compatible = "gpio-export"; + #size-cells = <0>; + + usbpower { + gpio-export,name = "usbpower"; + gpio-export,output = <0>; + gpios = <&gpio0 13 0>; + }; + + sdpower { + gpio-export,name = "sdpower"; + gpio-export,output = <0>; + gpios = <&gpio0 8 0>; + }; + }; +}; diff --git a/target/linux/ramips/dts/HC5XXX.dtsi b/target/linux/ramips/dts/HC5XXX.dtsi new file mode 100644 index 0000000..d295fd9 --- /dev/null +++ b/target/linux/ramips/dts/HC5XXX.dtsi @@ -0,0 +1,141 @@ +/include/ "mt7620a.dtsi" + +/ { + chosen { + bootargs = "console=ttyS0,115200"; + }; + + palmbus@10000000 { + sysc@0 { + ralink,gpiomux = "i2c", "jtag"; + ralink,uartmux = "gpio"; + ralink,wdtmux = <1>; + }; + + gpio0: gpio@600 { + status = "okay"; + }; + + gpio2: gpio@660 { + status = "okay"; + }; + + gpio3: gpio@688 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "w25q128"; + reg = <0 0>; + linux,modalias = "m25p80", "w25q128"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xf80000>; + }; + + partition@fd0000 { + label = "hwf_config"; + reg = <0xfd0000 0x10000>; + }; + + bdinfo: partition@fe0000 { + label = "bdinfo"; + reg = <0xfe0000 0x10000>; + }; + + partition@ff0000 { + label = "backup"; + reg = <0xff0000 0x10000>; + }; + }; + }; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + ethernet@10100000 { + pinctrl-names = "default"; + pinctrl-0 = <&ephy_pins>; + mtd-mac-address = <&factory 0x4>; + ralink,port-map = "wllll"; + }; + + sdhci@10130000 { + status = "okay"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pcie@10140000 { + status = "okay"; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "uartf", "wled", "nd_sd"; + ralink,function = "gpio"; + }; + + pa { + ralink,group = "pa"; + ralink,function = "pa"; + }; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 12 1>; + linux,code = <0x198>; + }; + }; + + gpio_export { + compatible = "gpio-export"; + #size-cells = <0>; + + usbpower { + gpio-export,name = "usbpower"; + gpio-export,output = <1>; + gpios = <&gpio0 13 0>; + }; + }; +}; diff --git a/target/linux/ramips/dts/HG255D.dts b/target/linux/ramips/dts/HG255D.dts new file mode 100644 index 0000000..4fbe3e6 --- /dev/null +++ b/target/linux/ramips/dts/HG255D.dts @@ -0,0 +1,130 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "HG255D", "ralink,rt3052-soc"; + model = "HuaWei HG255D"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x1000000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x40000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x40000 0x20000>; + read-only; + }; + + factory: partition@60000 { + label = "factory"; + reg = <0x60000 0x20000>; + read-only; + }; + + partition@80000 { + label = "firmware"; + reg = <0x80000 0xf60000>; + }; + + partition@fa0000 { + label = "factory-orig"; + reg = <0xfa0000 0x20000>; + read-only; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "hg255d:green:power"; + gpios = <&gpio0 8 1>; + }; + + internet { + label = "hg255d:green:internet"; + gpios = <&gpio0 13 1>; + }; + + wifi { + label = "hg255d:green:wlan"; + gpios = <&gpio0 14 1>; + }; + + usb { + label = "hg255d:green:usb"; + gpios = <&gpio0 9 1>; + }; + + wps { + label = "hg255d:green:wps"; + gpios = <&gpio0 12 1>; + }; + + voice { + label = "hg255d:green:voice"; + gpios = <&gpio0 5 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <10>; + + reset { + label = "reset"; + gpios = <&gpio0 4 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 10 1>; + linux,code = <0x211>; + }; + + rfkill { + label = "rfkill"; + gpios = <&gpio0 0 1>; + linux,code = <0xf7>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/HLKRM04.dts b/target/linux/ramips/dts/HLKRM04.dts new file mode 100644 index 0000000..e4a652e --- /dev/null +++ b/target/linux/ramips/dts/HLKRM04.dts @@ -0,0 +1,106 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "HLKRM04", "ralink,rt5350-soc"; + model = "HILINK HLK-RM04"; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x1000000>; + }; + + chosen { + bootargs = "console=ttyS1,57600"; + }; + + palmbus@10000000 { + uart@500 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "gd25q64"; + reg = <0 0>; + linux,modalias = "m25p80", "s25fl064k"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "jtag"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + wps { + label = "reset"; + gpios = <&gpio0 14 1>; + linux,code = <0x198>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "hlk-rm04:red:power"; + gpios = <&gpio0 0 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/HPM.dts b/target/linux/ramips/dts/HPM.dts new file mode 100644 index 0000000..03bf710 --- /dev/null +++ b/target/linux/ramips/dts/HPM.dts @@ -0,0 +1,149 @@ +/dts-v1/; + +/include/ "rt3883.dtsi" + +/ { + compatible = "HPM", "ralink,rt3883-soc"; + model = "Omnima HPM"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + compatible = "macronix,mx25l12805d"; + spi-max-frequency = <25000000>; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x0 0x0030000>; + label = "u-boot"; + read-only; + }; + + partition@30000 { + reg = <0x00030000 0x00010000>; + label = "config"; + read-only; + }; + + factory: partition@40000 { + reg = <0x00040000 0x00010000>; + label = "factory"; + read-only; + }; + + partition@50000 { + reg = <0x00050000 0x00fb0000>; + label = "firmware"; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + phy-handle = <&phy0>; + phy-mode = "rgmii"; + mtd-mac-address = <&factory 0x28>; + + mdio-bus { + status = "okay"; + + phy0: ethernet-phy@4 { + reg = <4>; + }; + }; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + reset { + label = "reset"; + gpios = <&gpio0 14 0>; + linux,code = <0x198>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "hpm:orange:power"; + gpios = <&gpio0 7 1>; + }; + + status { + label = "hpm:green:status"; + gpios = <&gpio0 21 1>; + }; + + eth { + label = "hpm:green:eth"; + gpios = <&gpio0 20 1>; + }; + + eth2 { + label = "hpm:red:eth"; + gpios = <&gpio0 18 1>; + }; + + wifi { + label = "hpm:green:wifi"; + gpios = <&gpio0 17 1>; + }; + + wifi2 { + label = "hpm:red:wifi"; + gpios = <&gpio0 19 1>; + }; + }; + + gpio_export { + compatible = "gpio-export"; + #size-cells = <0>; + /* gpio 12 and 13 handle the OC input */ + + usb0 { + gpio-export,name = "usb0"; + gpio-export,output = <1>; + gpios = <&gpio0 2 0>; + }; + + usb1 { + gpio-export,name = "usb1"; + gpio-export,output = <1>; + gpios = <&gpio0 1 0>; + }; + }; +}; diff --git a/target/linux/ramips/dts/HT-TM02.dts b/target/linux/ramips/dts/HT-TM02.dts new file mode 100644 index 0000000..72feaa9 --- /dev/null +++ b/target/linux/ramips/dts/HT-TM02.dts @@ -0,0 +1,113 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "HT-TM02", "ralink,rt5350-soc"; + model = "HooToo HT-TM02"; + + palmbus@10000000 { + gpio0: gpio@600 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l6405d"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l6405d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x10>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wlan { + label = "ht-tm02:blue:wlan"; + gpios = <&gpio0 7 1>; + }; + + lan { + label = "ht-tm02:green:lan"; + gpios = <&gpio0 12 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + modeswitch { + label = "modeswitch"; + gpios = <&gpio0 14 1>; + linux,code = <0x100>; + linux,input-type = <5>; + }; + }; +}; diff --git a/target/linux/ramips/dts/HW550-3G.dts b/target/linux/ramips/dts/HW550-3G.dts new file mode 100644 index 0000000..8dbd82b --- /dev/null +++ b/target/linux/ramips/dts/HW550-3G.dts @@ -0,0 +1,114 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "HW550-3G", "ralink,rt3052-soc"; + model = "Aztech HW550-3G"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x3e>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + usb { + label = "hw550-3g:green:usb"; + gpios = <&gpio0 8 1>; + }; + + 3g { + label = "hw550-3g:green:3g"; + gpios = <&gpio0 11 1>; + }; + + status { + label = "hw550-3g:green:status"; + gpios = <&gpio0 12 1>; + }; + + wps { + label = "hw550-3g:green:wps"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + connect { + label = "connect"; + gpios = <&gpio0 7 1>; + linux,code = <0xda>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/IP2202.dts b/target/linux/ramips/dts/IP2202.dts new file mode 100644 index 0000000..9eecad6 --- /dev/null +++ b/target/linux/ramips/dts/IP2202.dts @@ -0,0 +1,88 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "IP2202", "ralink,rt3052-soc"; + model = "Poray IP2202"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + run { + label = "ip2202:green:run"; + gpios = <&gpio0 9 1>; + }; + + net { + label = "ip2202:amber:net"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/LINKIT7688.dts b/target/linux/ramips/dts/LINKIT7688.dts new file mode 100644 index 0000000..4d1b964 --- /dev/null +++ b/target/linux/ramips/dts/LINKIT7688.dts @@ -0,0 +1,173 @@ +/dts-v1/; + +/include/ "mt7628an.dtsi" + +/ { + compatible = "mediatek,linkit", "mediatek,mt7628an-soc"; + model = "MediaTek LinkIt Smart7688"; + + chosen { + bootargs = "console=ttyS2,57600"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x8000000>; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "gpio"; + ralink,function = "gpio"; + }; + + perst { + ralink,group = "perst"; + ralink,function = "gpio"; + }; + + refclk { + ralink,group = "refclk"; + ralink,function = "gpio"; + }; + + i2s { + ralink,group = "i2s"; + ralink,function = "gpio"; + }; + + spis { + ralink,group = "spis"; + ralink,function = "gpio"; + }; + + wled_kn { + ralink,group = "wled_kn"; + ralink,function = "gpio"; + }; + + wled_an { + ralink,group = "wled_an"; + ralink,function = "wled_an"; + }; + + wdt { + ralink,group = "wdt"; + ralink,function = "gpio"; + }; + }; + }; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&spi_pins>, <&spi_cs1_pins>; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l25635e"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l25635e"; + spi-max-frequency = <40000000>; + m25p,chunked-io = <31>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x1fb0000>; + }; + }; + + spidev@1 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spidev"; + reg = <1 0>; + spi-max-frequency = <40000000>; + }; + }; + + i2c@900 { + status = "okay"; + }; + + uart1@d00 { + status = "okay"; + }; + + uart2@e00 { + status = "okay"; + }; + + pwm@5000 { + status = "okay"; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + sdhci@10130000 { + status = "okay"; + mediatek,cd-high; + }; + + bootstrap { + compatible = "mediatek,linkit"; + + status = "okay"; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wifi { + label = "mediatek:orange:wifi"; + gpios = <&wgpio 0 0>; + default-state = "on"; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + wps { + label = "reset"; + gpios = <&gpio1 6 1>; + linux,code = <0x211>; + }; + }; + + wgpio: gpio-wifi { + compatible = "mediatek,gpio-wifi"; + #address-cells = <1>; + #size-cells = <0>; + gpio-controller; + #gpio-cells = <2>; + }; + +}; diff --git a/target/linux/ramips/dts/M2M.dts b/target/linux/ramips/dts/M2M.dts new file mode 100644 index 0000000..dbe36da --- /dev/null +++ b/target/linux/ramips/dts/M2M.dts @@ -0,0 +1,112 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "M2M", "ralink,rt5350-soc"; + model = "Intenso Memory 2 Move"; + + chosen { + bootargs = "console=ttyS0,57600n8 root=/dev/mtdblock5"; + }; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l6405d"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l6405d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "Bootloader"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "Config"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "Factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wifi { + label = "m2m:blue:wifi"; + gpios = <&gpio0 7 1>; + }; + + wan { + label = "m2m:green:wan"; + gpios = <&gpio0 12 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + power { + label = "power"; + gpios = <&gpio0 1 1>; + linux,code = <0x116>; + }; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0x0>; + }; +}; diff --git a/target/linux/ramips/dts/M3.dts b/target/linux/ramips/dts/M3.dts new file mode 100644 index 0000000..c10bf3b --- /dev/null +++ b/target/linux/ramips/dts/M3.dts @@ -0,0 +1,106 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "M3", "ralink,rt5350-soc"; + model = "Poray M3"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "w25q32"; + reg = <0 0>; + linux,modalias = "m25p80", "w25q32"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + ralink,led_polarity = <1>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "m3:blue:status"; + gpios = <&gpio0 9 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + mode { + label = "mode"; + gpios = <&gpio0 17 1>; + linux,code = <0x100>; + linux,input-type = <5>; + }; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + ralink,led-polarity = <1>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/M4-4M.dts b/target/linux/ramips/dts/M4-4M.dts new file mode 100644 index 0000000..2443187 --- /dev/null +++ b/target/linux/ramips/dts/M4-4M.dts @@ -0,0 +1,94 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "M4", "ralink,rt5350-soc"; + model = "Poray M4"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "pm25lq032"; + reg = <0 0>; + linux,modalias = "m25p80", "pm25lq032"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + ralink,led_polarity = <1>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "m4:blue:status"; + gpios = <&gpio0 9 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/M4-8M.dts b/target/linux/ramips/dts/M4-8M.dts new file mode 100644 index 0000000..e7e5058 --- /dev/null +++ b/target/linux/ramips/dts/M4-8M.dts @@ -0,0 +1,99 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "M4", "ralink,rt5350-soc"; + model = "Poray M4"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "gd25q64"; + reg = <0 0>; + linux,modalias = "m25p80", "gd25q64"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + ralink,led_polarity = <1>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "m4:blue:status"; + gpios = <&gpio0 9 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + ralink,led-polarity = <1>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/MINIEMBPLUG.dts b/target/linux/ramips/dts/MINIEMBPLUG.dts new file mode 100644 index 0000000..c94c3aa --- /dev/null +++ b/target/linux/ramips/dts/MINIEMBPLUG.dts @@ -0,0 +1,120 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "MINIEMBPLUG", "ralink,rt5350-soc"; + model = "Omnima MiniEMBPlug"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wlan { + label = "miniembplug:red:wlan"; + gpios = <&gpio0 9 0>; + }; + + mobile { + label = "miniembplug:green:mobile"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x211>; + }; + + mode-one { + label = "mode1"; + gpios = <&gpio0 11 1>; + linux,code = <0x211>; + }; + + mode-two { + label = "mode2"; + gpios = <&gpio0 12 1>; + linux,code = <0x211>; + }; + }; + + palmbus@10000000 { + gpio0: gpio@600 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l6405d"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l6405d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/MINIEMBWIFI.dts b/target/linux/ramips/dts/MINIEMBWIFI.dts new file mode 100644 index 0000000..b026f0c --- /dev/null +++ b/target/linux/ramips/dts/MINIEMBWIFI.dts @@ -0,0 +1,92 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "MINIEMBWIFI", "ralink,rt3052-soc"; + model = "Omnima MiniEMBWiFi"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "miniembwifi:green:status"; + gpios = <&gpio0 9 1>; + }; + + wlan { + label = "miniembwifi:green:wlan"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 12 1>; + linux,code = <0x198>; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/MIWIFI-MINI.dts b/target/linux/ramips/dts/MIWIFI-MINI.dts new file mode 100644 index 0000000..dad99c3 --- /dev/null +++ b/target/linux/ramips/dts/MIWIFI-MINI.dts @@ -0,0 +1,155 @@ +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "xiaomi,miwifi-mini", "ralink,mt7620a-soc"; + model = "Xiaomi MiWiFi Mini"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + palmbus@10000000 { + gpio0: gpio@600 { + status = "okay"; + }; + + gpio1: gpio@638 { + status = "okay"; + }; + + gpio2: gpio@660 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "w25q128"; + reg = <0 0>; + linux,modalias = "m25p80", "w25q128"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xf80000>; + }; + + partition@fd0000 { + label = "crash"; + reg = <0xfd0000 0x10000>; + }; + + partition@fe0000 { + label = "reserved"; + reg = <0xfe0000 0x10000>; + read-only; + }; + + partition@ff0000 { + label = "Bdata"; + reg = <0xff0000 0x10000>; + }; + }; + }; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + ethernet@10100000 { + pinctrl-names = "default"; + pinctrl-0 = <&ephy_pins>; + mtd-mac-address = <&factory 0x4>; + ralink,port-map = "llllw"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pcie@10140000 { + status = "okay"; + + pcie-bridge { + mt76@0,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 0x8000>; + mediatek,2ghz = <0>; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "rgmii1"; + ralink,function = "gpio"; + }; + + pa { + ralink,group = "pa"; + ralink,function = "pa"; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + blue { + label = "miwifi-mini:blue:status"; + gpios = <&gpio1 0 1>; + }; + + yellow { + label = "miwifi-mini:yellow:status"; + gpios = <&gpio1 2 1>; + }; + + red { + label = "miwifi-mini:red:status"; + gpios = <&gpio1 5 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio1 6 0>; + linux,code = <0x198>; + }; + }; +}; diff --git a/target/linux/ramips/dts/MLW221.dts b/target/linux/ramips/dts/MLW221.dts new file mode 100644 index 0000000..12bc8c0 --- /dev/null +++ b/target/linux/ramips/dts/MLW221.dts @@ -0,0 +1,122 @@ +/dts-v1/; + +/include/ "mt7620n.dtsi" + +/ { + compatible = "mlw221", "ralink,mt7620n-soc"; + model = "Kingston MLW221"; + + palmbus@10000000 { + gpio0: gpio@600 { + status = "okay"; + }; + + gpio2: gpio@660 { + status = "okay"; + }; + + gpio3: gpio@688 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "s25fl129p1"; + reg = <0 0>; + linux,modalias = "m25p80", "s25fl129p1"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xf60000>; + }; + + partition@fb0000 { + label = "user-config"; + reg = <0xfb0000 0x50000>; + }; + }; + }; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + ralink,port-map = "wllll"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pinctrl { + state_default: pinctrl0 { + default { + ralink,group = "i2c", "ephy", "wled"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + system { + label = "mlw221:blue:system"; + gpios = <&gpio2 3 1>; + }; + + wifi { + label = "mlw221:blue:wifi"; + gpios = <&gpio3 0 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 1 1>; + linux,code = <0x198>; + }; + + system { + label = "system"; + gpios = <&gpio0 2 1>; + linux,code = <0x211>; + }; + }; +}; diff --git a/target/linux/ramips/dts/MLWG2.dts b/target/linux/ramips/dts/MLWG2.dts new file mode 100644 index 0000000..c417bff --- /dev/null +++ b/target/linux/ramips/dts/MLWG2.dts @@ -0,0 +1,122 @@ +/dts-v1/; + +/include/ "mt7620n.dtsi" + +/ { + compatible = "mlwg2", "ralink,mt7620n-soc"; + model = "Kingston MLWG2"; + + palmbus@10000000 { + gpio0: gpio@600 { + status = "okay"; + }; + + gpio2: gpio@660 { + status = "okay"; + }; + + gpio3: gpio@688 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l12805d"; + reg = <0 0>; + linux,modalias = "m25p80"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xf60000>; + }; + + partition@fb0000 { + label = "user-config"; + reg = <0xfb0000 0x50000>; + }; + }; + }; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + ralink,port-map = "wllll"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pinctrl { + state_default: pinctrl0 { + default { + ralink,group = "i2c", "ephy", "wled"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + system { + label = "mlwg2:blue:system"; + gpios = <&gpio2 3 1>; + }; + + wifi { + label = "mlwg2:blue:wifi"; + gpios = <&gpio3 0 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 1 1>; + linux,code = <0x198>; + }; + + system { + label = "system"; + gpios = <&gpio0 2 1>; + linux,code = <0x211>; + }; + }; +}; diff --git a/target/linux/ramips/dts/MOFI3500-3GN.dts b/target/linux/ramips/dts/MOFI3500-3GN.dts new file mode 100644 index 0000000..27c9e83 --- /dev/null +++ b/target/linux/ramips/dts/MOFI3500-3GN.dts @@ -0,0 +1,111 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "MOFI3500-3GN", "ralink,rt3052-soc"; + model = "MoFi Network MOFI3500-3GN"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + usb { + label = "mofi3500-3gn:green:usb"; + gpios = <&gpio0 8 1>; + }; + + 3g { + label = "mofi3500-3gn:green:3g"; + gpios = <&gpio0 11 1>; + }; + + status { + label = "mofi3500-3gn:green:status"; + gpios = <&gpio0 12 1>; + }; + + wps { + label = "mofi3500-3gn:green:wps"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + connect { + label = "connect"; + gpios = <&gpio0 7 1>; + linux,code = <0xda>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; + + wmac@10180000 { + status = "okay"; + ralink,mtd-eeprom = <&factory 0>; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/MPRA1.dts b/target/linux/ramips/dts/MPRA1.dts new file mode 100644 index 0000000..8a7d684 --- /dev/null +++ b/target/linux/ramips/dts/MPRA1.dts @@ -0,0 +1,123 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "MPRA1", "ralink,rt5350-soc"; + model = "HAME MPR-A1"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "s25fl064k"; + reg = <0 0>; + linux,modalias = "m25p80", "s25fl064k"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + }; + + gpio1: gpio@660 { + status = "okay"; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf", "led"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + gpio-leds { + compatible = "gpio-leds"; + + system { + label = "mpr-a1:blue:system"; + gpios = <&gpio0 20 1>; + }; + + power { + label = "mpr-a1:red:power"; + gpios = <&gpio0 17 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + wps { + label = "reset"; + gpios = <&gpio0 0 1>; + linux,code = <0x198>; + }; + }; + + gpio_export { + compatible = "gpio-export"; + #size-cells = <0>; + + usb { + gpio-export,name = "usb"; + gpio-export,output = <1>; + gpios = <&gpio0 7 0>; + }; + + root_hub { + gpio-export,name = "root_hub"; + gpio-export,output = <1>; + gpios = <&gpio0 12 0>; + }; + }; +}; diff --git a/target/linux/ramips/dts/MPRA2.dts b/target/linux/ramips/dts/MPRA2.dts new file mode 100644 index 0000000..4b8fd29 --- /dev/null +++ b/target/linux/ramips/dts/MPRA2.dts @@ -0,0 +1,119 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "MPRA2", "ralink,rt5350-soc"; + model = "HAME MPR-A2"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "s25fl064k"; + reg = <0 0>; + linux,modalias = "m25p80", "s25fl064k"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + gpio-leds { + compatible = "gpio-leds"; + + system { + label = "mpr-a2:blue:system"; + gpios = <&gpio0 20 1>; + }; + + power { + label = "mpr-a2:red:power"; + gpios = <&gpio0 17 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + wps { + label = "reset"; + gpios = <&gpio0 0 1>; + linux,code = <0x198>; + }; + }; + + gpio_export { + compatible = "gpio-export"; + #size-cells = <0>; + + usb { + gpio-export,name = "usb"; + gpio-export,output = <1>; + gpios = <&gpio0 7 0>; + }; + + root_hub { + gpio-export,name = "root_hub"; + gpio-export,output = <1>; + gpios = <&gpio0 12 0>; + }; + }; +}; diff --git a/target/linux/ramips/dts/MR-102N.dts b/target/linux/ramips/dts/MR-102N.dts new file mode 100644 index 0000000..3c392e4 --- /dev/null +++ b/target/linux/ramips/dts/MR-102N.dts @@ -0,0 +1,115 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "MR-102N", "ralink,rt3052-soc"; + model = "AXIMCom MR-102N"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x790000>; + }; + + partition@7e0000 { + label = "nvram"; + reg = <0x7e0000 0x10000>; + }; + + partition@7f0000 { + label = "nvram_backup"; + reg = <0x7f0000 0x10000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + status = "okay"; + #ralink,portmap = <0x3e>; + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + usb { + label = "mr-102n:green:usb"; + gpios = <&gpio0 8 1>; + }; + + status { + label = "mr-102n:amber:status"; + gpios = <&gpio0 9 1>; + }; + + wlan { + label = "mr-102n:green:wlan"; + gpios = <&gpio0 11 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 13 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 18 1>; + linux,code = <0x211>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/MT7620a.dts b/target/linux/ramips/dts/MT7620a.dts new file mode 100644 index 0000000..71b30bd --- /dev/null +++ b/target/linux/ramips/dts/MT7620a.dts @@ -0,0 +1,127 @@ +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "ralink,mt7620a-eval-board", "ralink,mt7620a-soc"; + model = "Ralink MT7620a + MT7610e evaluation board"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "en25q64"; + reg = <0 0>; + linux,modalias = "m25p80", "en25q64"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii1_pins &rgmii2_pins &mdio_pins>; + ralink,port-map = "llllw"; + + port@4 { + status = "okay"; + phy-mode = "rgmii"; + phy-handle = <&phy4>; + }; + + port@5 { + status = "okay"; + phy-mode = "rgmii"; + phy-handle = <&phy5>; + }; + + mdio-bus { + status = "okay"; + + phy4: ethernet-phy@4 { + reg = <4>; + phy-mode = "rgmii"; + }; + + phy5: ethernet-phy@5 { + reg = <5>; + phy-mode = "rgmii"; + }; + }; + }; + + gsw@10110000 { + ralink,port4 = "gmac"; + }; + + sdhci@10130000 { + status = "okay"; + }; + + pcie@10140000 { + status = "okay"; + }; + + gpio-keys-polled { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + s2 { + label = "S2"; + gpios = <&gpio0 1 1>; + linux,code = <0x100>; + }; + + s3 { + label = "S3"; + gpios = <&gpio0 2 1>; + linux,code = <0x101>; + }; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/MT7620a_MT7530.dts b/target/linux/ramips/dts/MT7620a_MT7530.dts new file mode 100644 index 0000000..ac01fd2 --- /dev/null +++ b/target/linux/ramips/dts/MT7620a_MT7530.dts @@ -0,0 +1,119 @@ +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "ralink,mt7620a-eval-board", "ralink,mt7620a-soc"; + model = "Ralink MT7620a + MT7530 evaluation board"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "s25fl064k"; + reg = <0 0>; + linux,modalias = "m25p80", "s25fl064k"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii1_pins &rgmii2_pins &mdio_pins>; + ralink,port-map = "llllw"; + + port@5 { + status = "okay"; + ralink,fixed-link = <1000 1 1 1>; + phy-mode = "rgmii"; + }; + + mdio-bus { + status = "okay"; + + phy0: ethernet-phy@0 { + reg = <0>; + phy-mode = "rgmii"; + }; + + phy1: ethernet-phy@1 { + reg = <1>; + phy-mode = "rgmii"; + }; + + phy2: ethernet-phy@2 { + reg = <2>; + phy-mode = "rgmii"; + }; + + phy3: ethernet-phy@3 { + reg = <3>; + phy-mode = "rgmii"; + }; + + phy4: ethernet-phy@4 { + reg = <4>; + phy-mode = "rgmii"; + }; + + phy1f: ethernet-phy@1f { + reg = <0x1f>; + phy-mode = "rgmii"; + }; + }; + }; + + gsw@10110000 { + ralink,port4 = "gmac"; + mediatek,mt7530 = <1>; + }; + + pcie@10140000 { + status = "okay"; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/MT7620a_MT7610e.dts b/target/linux/ramips/dts/MT7620a_MT7610e.dts new file mode 100644 index 0000000..ba57fae --- /dev/null +++ b/target/linux/ramips/dts/MT7620a_MT7610e.dts @@ -0,0 +1,88 @@ +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "ralink,mt7620a-eval-board", "ralink,mt7620a-soc"; + model = "Ralink MT7620A evaluation board"; + + palmbus@10000000 { + gpio0: gpio@600 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "en25q64"; + reg = <0 0>; + linux,modalias = "m25p80", "en25q64"; + spi-max-frequency = <1000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + ethernet@10100000 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&ephy_pins>; + ralink,port-map = "llllw"; + }; + + gsw@10110000 { + ralink,port4 = "ephy"; + }; + + sdhci@10130000 { + status = "okay"; + }; + + pcie@10140000 { + status = "okay"; + }; + + gpio-keys-polled { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + wps { + label = "wps"; + gpios = <&gpio0 12 1>; + linux,code = <0x100>; + }; + + reset { + label = "reset"; + gpios = <&gpio0 13 1>; + linux,code = <0x101>; + }; + }; +}; diff --git a/target/linux/ramips/dts/MT7620a_V22SG.dts b/target/linux/ramips/dts/MT7620a_V22SG.dts new file mode 100644 index 0000000..ef30195 --- /dev/null +++ b/target/linux/ramips/dts/MT7620a_V22SG.dts @@ -0,0 +1,114 @@ +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "ralink,mt7620a-eval-board", "ralink,mt7620a-soc"; + model = "Ralink MT7620a V22SG High Power evaluation board"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "uartf", "spi"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii1_pins &rgmii2_pins &mdio_pins>; + ralink,port-map = "llllw"; + + port@4 { + status = "okay"; + phy-handle = <&phy4>; + phy-mode = "rgmii"; + }; + + port@5 { + status = "okay"; + phy-handle = <&phy5>; + phy-mode = "rgmii"; + }; + + mdio-bus { + status = "okay"; + + phy4: ethernet-phy@4 { + reg = <4>; + phy-mode = "rgmii"; + }; + + phy5: ethernet-phy@5 { + reg = <5>; + phy-mode = "rgmii"; + }; + }; + }; + + gsw@10110000 { + ralink,port4 = "gmac"; + }; + + pcie@10140000 { + status = "okay"; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 1 1>; + linux,code = <0x198>; + }; + + aoss { + label = "aoss"; + gpios = <&gpio0 2 1>; + linux,code = <0x211>; + }; + }; + + nand { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mtk,mt7620-nand"; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x40000>; + read-only; + }; + + partition@40000 { + label = "u-boot-env"; + reg = <0x40000 0x20000>; + read-only; + }; + + factory: partition@60000 { + label = "factory"; + reg = <0x60000 0x20000>; + read-only; + }; + + partition@80000 { + label = "firmware"; + reg = <0x80000 0x7f80000>; + }; + }; +}; diff --git a/target/linux/ramips/dts/MT7621.dts b/target/linux/ramips/dts/MT7621.dts new file mode 100644 index 0000000..c90fc95 --- /dev/null +++ b/target/linux/ramips/dts/MT7621.dts @@ -0,0 +1,34 @@ +/dts-v1/; + +/include/ "mt7621.dtsi" + +/ { + compatible = "mediatek,mt7621-eval-board", "mediatek,mt7621-soc"; + model = "Mediatek MT7621 evaluation board"; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x2000000>; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + sdhci@10130000 { + status = "okay"; + }; + + xhci@1E1C0000 { + status = "okay"; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; + ralink,function = "gpio"; + }; + }; + }; +}; diff --git a/target/linux/ramips/dts/MT7628.dts b/target/linux/ramips/dts/MT7628.dts new file mode 100644 index 0000000..dd6647f --- /dev/null +++ b/target/linux/ramips/dts/MT7628.dts @@ -0,0 +1,61 @@ +/dts-v1/; + +/include/ "mt7628an.dtsi" + +/ { + compatible = "mediatek,mt7628an-eval-board", "mediatek,mt7628an-soc"; + model = "Mediatek MT7628AN evaluation board"; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x2000000>; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag"; + ralink,function = "gpio"; + }; + }; + }; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "en25q64"; + reg = <0 0>; + linux,modalias = "m25p80", "en25q64"; + spi-max-frequency = <10000000>; + m25p,chunked-io = <32>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; +}; diff --git a/target/linux/ramips/dts/MZK-750DHP.dts b/target/linux/ramips/dts/MZK-750DHP.dts new file mode 100644 index 0000000..bdf3f8f --- /dev/null +++ b/target/linux/ramips/dts/MZK-750DHP.dts @@ -0,0 +1,111 @@ +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "ralink,mt7620a-soc"; + model = "Planex MZK-750DHP"; + + palmbus@10000000 { + gpio1: gpio@638 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "en25q64"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l6405d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "spi refclk", "rgmii1"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + pinctrl-names = "default"; + pinctrl-0 = <&ephy_pins>; + mtd-mac-address = <&factory 0x4>; + ralink,port-map = "llllw"; + }; + + gsw@10110000 { + ralink,port4 = "ephy"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pcie@10140000 { + status = "okay"; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wps { + label = "mzk-750dhp:green:wps"; + gpios = <&gpio1 11 1>; + }; + + power { + label = "mzk-750dhp:green:power"; + gpios = <&gpio1 15 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + s1 { + label = "reset"; + gpios = <&gpio0 1 1>; + linux,code = <0x100>; + }; + + s2 { + label = "wps"; + gpios = <&gpio0 2 1>; + linux,code = <0x211>; + }; + }; +}; diff --git a/target/linux/ramips/dts/MZK-DP150N.dts b/target/linux/ramips/dts/MZK-DP150N.dts new file mode 100644 index 0000000..893807c --- /dev/null +++ b/target/linux/ramips/dts/MZK-DP150N.dts @@ -0,0 +1,100 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "MZK-DP150N", "ralink,rt5350-soc"; + model = "Planex MZK-DP150N"; + + palmbus@10000000 { + gpio1: gpio@660 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "s25fl064k"; + reg = <0>; + linux,modalias = "m25p80", "s25fl064k"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "uboot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "uboot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + + spidev@1 { + compatible = "linux,spidev"; + spi-max-frequency = <10000000>; + reg = <1>; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "jtag", "uartf", "led"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x17>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + ralink,led-polarity = <1>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "mzk-dp150n:green:power"; + gpios = <&gpio0 9 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + }; +}; diff --git a/target/linux/ramips/dts/MZK-W300NH2.dts b/target/linux/ramips/dts/MZK-W300NH2.dts new file mode 100644 index 0000000..06cc292 --- /dev/null +++ b/target/linux/ramips/dts/MZK-W300NH2.dts @@ -0,0 +1,111 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "MZK-W300NH2", "ralink,rt3052-soc"; + model = "Planex MZK-W300NH2"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@3e0000 { + label = "cimage"; + reg = <0x3e0000 0x20000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x390000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "mzk-w300nh2:green:power"; + gpios = <&gpio0 9 1>; + }; + + wlan { + label = "mzk-w300nh2:amber:wlan"; + gpios = <&gpio0 14 1>; + }; + + wps { + label = "mzk-w300nh2:amber:wps"; + gpios = <&gpio0 11 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + wps { + label = "wps"; + gpios = <&gpio0 12 1>; + linux,code = <0x211>; + }; + + reset { + label = "reset"; + gpios = <&gpio0 0 1>; + linux,code = <0x198>; + }; + + rt { + label = "rt"; + gpios = <&gpio0 13 1>; + linux,code = <0x100>; + }; + }; +}; diff --git a/target/linux/ramips/dts/MicroWRT.dts b/target/linux/ramips/dts/MicroWRT.dts new file mode 100644 index 0000000..ac660d4 --- /dev/null +++ b/target/linux/ramips/dts/MicroWRT.dts @@ -0,0 +1,109 @@ +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "microwrt", "ralink,mt7620a-soc"; + model = "Microduino MicroWRT"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + palmbus@10000000 { + gpio2: gpio@660 { + status = "okay"; + }; + + gpio3: gpio@688 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "w25q128"; + reg = <0 0>; + linux,modalias = "m25p80", "w25q128"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x20000>; + read-only; + }; + + partition@20000 { + label = "u-boot-env"; + reg = <0x20000 0x10000>; + read-only; + }; + + factory: partition@30000 { + label = "factory"; + reg = <0x30000 0x10000>; + read-only; + }; + + partition@40000 { + label = "firmware"; + reg = <0x40000 0xfc0000>; + }; + }; + }; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + pcie@10140000 { + status = "okay"; + }; + + ethernet@10100000 { + pinctrl-names = "default"; + pinctrl-0 = <&ephy_pins>; + mtd-mac-address = <&factory 0x4>; + ralink,port-map = "llllw"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pinctrl { + state_default: pinctrl0 { + default { + ralink,group = "wled", "i2c", "wdt", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 1 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 2 1>; + linux,code = <0x211>; + }; + }; +}; diff --git a/target/linux/ramips/dts/NA930.dts b/target/linux/ramips/dts/NA930.dts new file mode 100644 index 0000000..4397b2c --- /dev/null +++ b/target/linux/ramips/dts/NA930.dts @@ -0,0 +1,174 @@ +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "ralink,mt7620a-eval-board", "ralink,mt7620a-soc"; + model = "Sercomm NA930"; + + chosen { + bootargs = "console=ttyS1,57600"; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "rgmii2", "spi", "ephy"; + ralink,function = "gpio"; + }; + + uartf_gpio { + ralink,group = "uartf"; + ralink,function = "gpio uartf"; + }; + }; + }; + + palmbus@10000000 { + uart@500 { + status = "okay"; + }; + + gpio@638 { + status = "okay"; + }; + + gpio@660 { + status = "okay"; + }; + }; + + nand { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mtk,mt7620-nand"; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x20000>; + read-only; + }; + + partition@200000 { + label = "factory"; + reg = <0x200000 0x40000>; + read-only; + }; + + partition@240000 { + label = "Config"; + reg = <0x240000 0x400000>; + read-only; + }; + + partition@640000 { + label = "firmware"; + reg = <0x640000 0x1400000>; + }; + }; + + ethernet@10100000 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii1_pins &mdio_pins>; + ralink,port-map = "llllw"; + + port@4 { + status = "okay"; + phy-handle = <&phy4>; + phy-mode = "rgmii"; + }; + + port@5 { + status = "okay"; + phy-handle = <&phy5>; + phy-mode = "rgmii"; + }; + + mdio-bus { + status = "okay"; + + phy4: ethernet-phy@4 { + reg = <4>; + phy-mode = "rgmii"; + }; + + phy5: ethernet-phy@5 { + reg = <5>; + phy-mode = "rgmii"; + }; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 11 1>; + linux,code = <0x198>; + }; + + zwave { + label = "zwave"; + gpios = <&gpio0 12 1>; + linux,code = <0x100>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 14 1>; + linux,code = <0x211>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + zwave { + label = "na930:blue:zwave"; + gpios = <&gpio2 0 1>; + }; + + status { + label = "na930:blue:status"; + gpios = <&gpio2 26 1>; + }; + + service { + label = "na930:blue:service"; + gpios = <&gpio2 28 1>; + }; + + power { + label = "na930:blue:power"; + gpios = <&gpio2 29 1>; + }; + }; + + gpio_export { + compatible = "gpio-export"; + #size-cells = <0>; + + telit { + gpio-export,name = "telit"; + gpio-export,output = <1>; + gpios = <&gpio0 13 0>; + }; + }; + + gsw@10110000 { + ralink,port4 = "gmac"; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/NBG-419N.dts b/target/linux/ramips/dts/NBG-419N.dts new file mode 100644 index 0000000..50a12cb --- /dev/null +++ b/target/linux/ramips/dts/NBG-419N.dts @@ -0,0 +1,94 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "NBG-419N", "ralink,rt3052-soc"; + model = "ZyXEL NBG-419N"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "nbg-419n:green:power"; + gpios = <&gpio0 9 1>; + }; + + wps { + label = "nbg-419n:green:wps"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; +}; diff --git a/target/linux/ramips/dts/NCS601W.dts b/target/linux/ramips/dts/NCS601W.dts new file mode 100644 index 0000000..dfc47b2 --- /dev/null +++ b/target/linux/ramips/dts/NCS601W.dts @@ -0,0 +1,75 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "NCS601W", "ralink,rt5350-soc"; + model = "Wansview NCS601W"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "s25fl064k"; + reg = <0 0>; + linux,modalias = "m25p80", "s25fl064k"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/NW718.dts b/target/linux/ramips/dts/NW718.dts new file mode 100644 index 0000000..f6411c8 --- /dev/null +++ b/target/linux/ramips/dts/NW718.dts @@ -0,0 +1,109 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "NW718", "ralink,rt3050-soc"; + model = "Netcore NW718"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l3205d"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l3205d"; + spi-max-frequency = <25000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "config"; + reg = <0x30000 0x20000>; + read-only; + }; + + factory: partition@50000 { + label = "factory"; + reg = <0x50000 0x10000>; + read-only; + }; + + partition@60000 { + label = "firmware"; + reg = <0x60000 0x3a0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + cpu { + label = "nw718:amber:cpu"; + gpios = <&gpio0 13 1>; + }; + + usb { + label = "nw718:amber:usb"; + gpios = <&gpio0 8 1>; + }; + + wps { + label = "nw718:amber:wps"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/OY-0001.dts b/target/linux/ramips/dts/OY-0001.dts new file mode 100644 index 0000000..36c783b --- /dev/null +++ b/target/linux/ramips/dts/OY-0001.dts @@ -0,0 +1,125 @@ +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "ralink,mt7620a-soc"; + model = "OY-0001"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + palmbus@10000000 { + gpio2: gpio@660 { + status = "okay"; + }; + + gpio3: gpio@688 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "w25q128"; + reg = <0 0>; + linux,modalias = "m25p80", "w25q128"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xfb0000>; + }; + + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "uartf", "rgmii1", "rgmii2", "wled", "nd_sd"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + pinctrl-names = "default"; + pinctrl-0 = <&ephy_pins>; + ralink,port-map = "llllw"; + }; + + gsw@10110000 { + ralink,port4 = "ephy"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + powerled { + label = "oy-0001:green:power"; + gpios = <&gpio0 9 1>; + }; + + wifiled { + label = "oy-0001:green:wifi"; + gpios = <&gpio3 0 1>; + }; + }; + + sdhci@10130000 { + status = "okay"; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + pcie@10140000 { + status = "okay"; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + s1 { + label = "reset"; + gpios = <&gpio0 1 1>; + linux,code = <0x198>; + }; + }; +}; diff --git a/target/linux/ramips/dts/PBR-M1.dts b/target/linux/ramips/dts/PBR-M1.dts new file mode 100644 index 0000000..7702d9c --- /dev/null +++ b/target/linux/ramips/dts/PBR-M1.dts @@ -0,0 +1,148 @@ +/dts-v1/; + +/include/ "mt7621.dtsi" + +/ { + compatible = "mediatek,mt7621-eval-board", "mediatek,mt7621-soc"; + model = "PBR-M1"; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x10000000>; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + sdhci@10130000 { + status = "okay"; + }; + + palmbus@1E000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "w25q256"; + reg = <0 0>; + linux,modalias = "m25p80"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xfb0000>; + }; + + }; + }; + + i2c@900 { + compatible = "ralink,i2c-mt7621"; + reg = <0x900 0x100>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c_pins>; + status = "okay"; + + pcf8563: rtc@51 { + status = "okay"; + compatible = "nxp,pcf8563"; + reg = <0x51>; + }; + }; + }; + + pcie@1e140000 { + status = "okay"; + + pcie0 { + mt76@0,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 0x0000>; + mediatek,2ghz = <0>; + }; + }; + + pcie1 { + mt76@1,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 0x8000>; + mediatek,5ghz = <0>; + }; + }; + }; + + ethernet@1e100000 { + mtd-mac-address = <&factory 0xe000>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + buzzer { + label = "pbr-m1:buzzer"; + gpios = <&gpio0 27 1>; + }; + + power { + label = "pbr-m1:green:power"; + gpios = <&gpio0 25 1>; + }; + + sys { + label = "pbr-m1:green:sys"; + gpios = <&gpio0 24 1>; + }; + + internet { + label = "pbr-m1:green:internet"; + gpios = <&gpio0 23 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 18 1>; + linux,code = <0x198>; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "wdt", "rgmii2", "wdt rst", "jtag", "mdio"; + ralink,function = "gpio"; + }; + }; + }; +}; diff --git a/target/linux/ramips/dts/PSR-680W.dts b/target/linux/ramips/dts/PSR-680W.dts new file mode 100644 index 0000000..f583009 --- /dev/null +++ b/target/linux/ramips/dts/PSR-680W.dts @@ -0,0 +1,91 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "PSR-680W", "ralink,rt3052-soc"; + model = "Petatel PSR-680W Wireless 3G Router"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x3e>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wan { + label = "psr-680w:red:wan"; + gpios = <&gpio0 19 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 0 1>; + linux,code = <0x198>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/PWH2004.dts b/target/linux/ramips/dts/PWH2004.dts new file mode 100644 index 0000000..fc51c09 --- /dev/null +++ b/target/linux/ramips/dts/PWH2004.dts @@ -0,0 +1,84 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "PWH2004", "ralink,rt3052-soc"; + model = "Prolink PWH2004"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wifi { + label = "pwh2004:red:wifi"; + gpios = <&gpio0 14 1>; + }; + + power { + label = "pwh2004:green:power"; + gpios = <&gpio0 9 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + wps { + label = "wps"; + gpios = <&gpio0 12 1>; + linux,code = <0x198>; + }; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; +}; diff --git a/target/linux/ramips/dts/PX-4885-4M.dts b/target/linux/ramips/dts/PX-4885-4M.dts new file mode 100644 index 0000000..1f79a3c --- /dev/null +++ b/target/linux/ramips/dts/PX-4885-4M.dts @@ -0,0 +1,43 @@ +/dts-v1/; + +/include/ "PX-4885.dtsi" + +/ { + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l3205d"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l3205d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x20000>; + read-only; + }; + + partition@20000 { + label = "devdata"; + reg = <0x20000 0x20000>; + read-only; + }; + + factory: partition@40000 { + label = "devconf"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + }; + }; +}; diff --git a/target/linux/ramips/dts/PX-4885-8M.dts b/target/linux/ramips/dts/PX-4885-8M.dts new file mode 100644 index 0000000..4c94a11 --- /dev/null +++ b/target/linux/ramips/dts/PX-4885-8M.dts @@ -0,0 +1,43 @@ +/dts-v1/; + +/include/ "PX-4885.dtsi" + +/ { + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l3205d"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l3205d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x20000>; + read-only; + }; + + partition@20000 { + label = "devdata"; + reg = <0x20000 0x20000>; + read-only; + }; + + factory: partition@40000 { + label = "devconf"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; +}; diff --git a/target/linux/ramips/dts/PX-4885.dtsi b/target/linux/ramips/dts/PX-4885.dtsi new file mode 100644 index 0000000..350c1a6 --- /dev/null +++ b/target/linux/ramips/dts/PX-4885.dtsi @@ -0,0 +1,54 @@ +/include/ "rt5350.dtsi" + +/ { + compatible = "PX-4885", "ralink,rt5350-soc"; + model = "7Links PX-4885"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x3f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + orange { + label = "px-4885:orange:wifi"; + gpios = <&gpio0 18 1>; + }; + + blue { + label = "px-4885:blue:storage"; + gpios = <&gpio0 19 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/RE6500.dts b/target/linux/ramips/dts/RE6500.dts new file mode 100644 index 0000000..b65ade4 --- /dev/null +++ b/target/linux/ramips/dts/RE6500.dts @@ -0,0 +1,119 @@ +/dts-v1/; + +/include/ "mt7621.dtsi" + +/ { + compatible = "mediatek,mt7621-eval-board", "mediatek,mt7621-soc"; + model = "Linksys RE6500"; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x8000000>; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + palmbus@1E000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l6405d"; + reg = <0 0>; + linux,modalias = "m25p80", "en25q64"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xfb0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "uart2", "uart3", "rgmii2"; + ralink,function = "gpio"; + }; + }; + }; + + pcie@1e140000 { + status = "okay"; + + pcie0 { + mt76@0,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 0x0000>; + mediatek,2ghz = <0>; + }; + }; + + pcie1 { + mt76@1,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 0x8000>; + mediatek,5ghz = <0>; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wifi { + label = "re6500:orange:wifi"; + gpios = <&gpio0 0 1>; + }; + + power { + label = "re6500:white:power"; + gpios = <&gpio0 9 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + wps { + label = "wps"; + gpios = <&gpio0 10 1>; + linux,code = <0x211>; + }; + + reset { + label = "reset"; + gpios = <&gpio0 11 0>; + linux,code = <0x198>; + }; + }; +}; diff --git a/target/linux/ramips/dts/RP-N53.dts b/target/linux/ramips/dts/RP-N53.dts new file mode 100644 index 0000000..39347b9 --- /dev/null +++ b/target/linux/ramips/dts/RP-N53.dts @@ -0,0 +1,166 @@ +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "asus,rp-n53", "ralink,mt7620a-soc"; + model = "Asus RP-N53"; + + palmbus@10000000 { + gpio1: gpio@638 { + status = "okay"; + }; + + i2c@900 { + status = "okay"; + }; + + i2s@a00 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pcm_i2s_pins>; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l6405d"; + reg = <0 0>; + linux,modalias = "m25p80"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + + pcm@2000 { + status = "okay"; + }; + + gdma@2800 { + status = "okay"; + }; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "mdio", "rgmii1"; + ralink,function = "gpio"; + }; + }; + }; + + gsw@10110000 { + ralink,port4 = "ephy"; + pinctrl-names = "default"; + pinctrl-0 = <&ephy_pins>; + }; + + pcie@10140000 { + status = "okay"; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + touch { + label = "touch"; + gpios = <&gpio1 0 1>; + linux,code = <0x100>; + }; + + wps { + label = "wps"; + gpios = <&gpio1 1 1>; + linux,code = <0x100>; + }; + + reset { + label = "reset"; + gpios = <&gpio1 2 1>; + linux,code = <0x100>; + }; + + audio { + label = "audio"; + gpios = <&gpio1 3 0>; + linux,code = <0x101>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + backlight { + label = "rp-n53:white:back"; + gpios = <&gpio1 4 1>; + }; + + wifi0 { + label = "rp-n53:blue:5g3"; + gpios = <&gpio1 5 1>; + }; + + wifi1 { + label = "rp-n53:blue:5g2"; + gpios = <&gpio1 6 1>; + }; + + wifi2 { + label = "rp-n53:blue:5g1"; + gpios = <&gpio1 7 1>; + }; + + wifi3 { + label = "rp-n53:blue:wifi"; + gpios = <&gpio1 8 1>; + }; + + wifi4 { + label = "rp-n53:blue:2g1"; + gpios = <&gpio1 9 1>; + }; + + wifi5 { + label = "rp-n53:blue:2g2"; + gpios = <&gpio1 10 1>; + }; + + wifi6 { + label = "rp-n53:blue:2g3"; + gpios = <&gpio1 11 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/RT-G32-B1.dts b/target/linux/ramips/dts/RT-G32-B1.dts new file mode 100644 index 0000000..b0b7c07 --- /dev/null +++ b/target/linux/ramips/dts/RT-G32-B1.dts @@ -0,0 +1,86 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "RT-G32-B1", "ralink,rt3050-soc"; + model = "Asus RT-G32 B1"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l3205d"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l3205d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "devdata"; + reg = <0x30000 0x10000>; + read-only; + }; + + devconf: partition@40000 { + label = "devconf"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&devconf 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&devconf 0>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; +}; diff --git a/target/linux/ramips/dts/RT-N10-PLUS.dts b/target/linux/ramips/dts/RT-N10-PLUS.dts new file mode 100644 index 0000000..edbd92b --- /dev/null +++ b/target/linux/ramips/dts/RT-N10-PLUS.dts @@ -0,0 +1,80 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "RT-N10-PLUS", "ralink,rt3050-soc"; + model = "Asus RT-N10+"; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "devdata"; + reg = <0x30000 0x10000>; + read-only; + }; + + devconf: partition@40000 { + label = "devconf"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&devconf 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x3e>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&devconf 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wps { + label = "rt-n10-plus:green:wps"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; +}; diff --git a/target/linux/ramips/dts/RT-N13U.dts b/target/linux/ramips/dts/RT-N13U.dts new file mode 100644 index 0000000..7e0fbd2 --- /dev/null +++ b/target/linux/ramips/dts/RT-N13U.dts @@ -0,0 +1,98 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "RT-N13U", "ralink,rt3052-soc"; + model = "Asus RT-N13U"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "rt-n13u:blue:power"; + gpios = <&gpio0 7 1>; + }; + + wifi { + label = "rt-n13u:blue:wifi"; + gpios = <&gpio0 8 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <10>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/RT-N14U.dts b/target/linux/ramips/dts/RT-N14U.dts new file mode 100644 index 0000000..6d1080b --- /dev/null +++ b/target/linux/ramips/dts/RT-N14U.dts @@ -0,0 +1,129 @@ +/dts-v1/; + +/include/ "mt7620n.dtsi" + +/ { + compatible = "asus,rt-n14u", "ralink,mt7620n-soc"; + model = "Asus RT-N14U"; + + palmbus@10000000 { + gpio2: gpio@660 { + status = "okay"; + }; + + gpio3: gpio@688 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + #compatible = "mx25l6405d"; + compatible = "w25q128"; + reg = <0 0>; + linux,modalias = "m25p80", "w25q128"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xfb0000>; + }; + }; + }; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + ralink,port-map = "wllll"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pinctrl { + state_default: pinctrl0 { + default { + ralink,group = "ephy", "wled", "i2c"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wan { + label = "rt-n14u:blue:wan"; + gpios = <&gpio2 0 1>; + }; + + lan { + label = "rt-n14u:blue:lan"; + gpios = <&gpio2 1 1>; + }; + + usb { + label = "rt-n14u:blue:usb"; + gpios = <&gpio2 2 1>; + }; + + power { + label = "rt-n14u:blue:power"; + gpios = <&gpio2 3 1>; + }; + + air { + label = "rt-n14u:blue:air"; + gpios = <&gpio3 0 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 1 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 2 1>; + linux,code = <0x211>; + }; + }; +}; diff --git a/target/linux/ramips/dts/RT-N15.dts b/target/linux/ramips/dts/RT-N15.dts new file mode 100644 index 0000000..03821ca --- /dev/null +++ b/target/linux/ramips/dts/RT-N15.dts @@ -0,0 +1,113 @@ +/dts-v1/; + +/include/ "rt2880.dtsi" + +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "RT-N15", "ralink,rt2880-soc"; + model = "Asus RT-N15"; + + palmbus@300000 { + gpio0: gpio@600 { + status = "okay"; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "uartlite", "mdio"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "uboot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "uboot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + + ethernet@400000 { + status = "okay"; + mtd-mac-address = <&factory 0x4>; + + port@0 { + ralink,fixed-link = <1000 1 1 1>; + }; + + mdio-bus { + status = "okay"; + + phy0: ethernet-phy@0 { + phy-mode = "mii"; + reg = <0>; + }; + }; + }; + + rtl8366s { + compatible = "realtek,rtl8366s"; + gpio-sda = <&gpio0 1 0>; + gpio-sck = <&gpio0 2 0>; + }; + + wmac@480000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + wps { + label = "wps"; + gpios = <&gpio0 0 0>; + linux,code = <0x211>; + }; + + reset { + label = "reset"; + gpios = <&gpio0 12 0>; + linux,code = <0x198>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "rt-n15:blue:power"; + gpios = <&gpio0 11 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/RT-N56U.dts b/target/linux/ramips/dts/RT-N56U.dts new file mode 100644 index 0000000..8ea4970 --- /dev/null +++ b/target/linux/ramips/dts/RT-N56U.dts @@ -0,0 +1,151 @@ +/dts-v1/; + +/include/ "rt3883.dtsi" + +/ { + compatible = "RT-N56U", "ralink,rt3883-soc"; + model = "Asus RT-N56U"; + + palmbus@10000000 { + gpio1: gpio@638 { + status = "okay"; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + + port@0 { + ralink,fixed-link = <1000 1 1 1>; + }; + }; + + pci@10140000 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pci_pins>; + + pci_pins: pci { + pci { + ralink,group = "pci"; + ralink,function = "pci-fnc"; + }; + }; + + host-bridge { + pci-bridge@1 { + status = "okay"; + + wmac@0,0 { + compatible = "ralink,rt2880-pci", "pciclass060400", "pciclass0604"; + reg = < 0x10000 0 0 0 0 >; + ralink,eeprom = "rt2x00pci_1_0.eeprom"; + }; + }; + }; + }; + + wmac@10180000 { + status = "okay"; + ralink,2ghz = <0>; + ralink,mtd-eeprom = <&factory 0>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + nor-flash@1c000000 { + compatible = "cfi-flash"; + reg = <0x1c000000 0x800000>; + bank-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x0 0x0030000>; + label = "u-boot"; + read-only; + }; + + partition@30000 { + reg = <0x00030000 0x00010000>; + label = "u-boot-env"; + read-only; + }; + + factory: partition@40000 { + reg = <0x00040000 0x00010000>; + label = "factory"; + read-only; + }; + + partition@50000 { + reg = <0x00050000 0x007b0000>; + label = "firmware"; + }; + }; + + rtl8367 { + compatible = "realtek,rtl8367"; + gpio-sda = <&gpio0 1 0>; + gpio-sck = <&gpio0 2 0>; + realtek,extif1 = <1 0 1 1 1 1 1 1 2>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + reset { + label = "reset"; + gpios = <&gpio0 13 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio1 2 1>; + linux,code = <0x211>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "rt-n56u:blue:power"; + gpios = <&gpio0 0 1>; + }; + + lan { + label = "rt-n56u:blue:lan"; + gpios = <&gpio0 19 1>; + }; + + wan { + label = "rt-n56u:blue:wan"; + gpios = <&gpio1 3 1>; + }; + + usb { + label = "rt-n56u:blue:usb"; + gpios = <&gpio1 0 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/RT5350F-OLINUXINO-EVB.dts b/target/linux/ramips/dts/RT5350F-OLINUXINO-EVB.dts new file mode 100644 index 0000000..17fa66f --- /dev/null +++ b/target/linux/ramips/dts/RT5350F-OLINUXINO-EVB.dts @@ -0,0 +1,102 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "RT5350F-OLINUXINO-EVB", "ralink,rt5350-soc"; + model = "Olimex RT5350F-OLinuXino-EVB"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "s25fl064k"; + reg = <0 0>; + linux,modalias = "m25p80", "s25fl064k"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + }; + + gpio1: gpio@660 { + status = "okay"; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + ralink,led_polarity = <0x17>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + gpio_export { + compatible = "gpio-export"; + #size-cells = <0>; + + relay1 { + gpio-export,name = "gpio12"; + gpio-export,output = <0>; + gpios = <&gpio0 12 0>; + }; + + relay2 { + gpio-export,name = "gpio14"; + gpio-export,output = <0>; + gpios = <&gpio0 14 0>; + }; + + button { + gpio-export,name = "button"; + gpios = <&gpio0 0 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/RT5350F-OLINUXINO.dts b/target/linux/ramips/dts/RT5350F-OLINUXINO.dts new file mode 100644 index 0000000..40caa6b --- /dev/null +++ b/target/linux/ramips/dts/RT5350F-OLINUXINO.dts @@ -0,0 +1,80 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "RT5350F-OLINUXINO", "ralink,rt5350-soc"; + model = "Olimex RT5350F-OLinuXino"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "s25fl064k"; + reg = <0 0>; + linux,modalias = "m25p80", "s25fl064k"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + }; + + gpio1: gpio@660 { + status = "okay"; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + ralink,led_polarity = <0x17>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/RUT5XX.dts b/target/linux/ramips/dts/RUT5XX.dts new file mode 100644 index 0000000..0af4743 --- /dev/null +++ b/target/linux/ramips/dts/RUT5XX.dts @@ -0,0 +1,93 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "RUT5XX", "ralink,rt3050-soc"; + model = "Teltonika RUT5XX"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "n25q128a13"; + reg = <0 0>; + linux,modalias = "m25p80", "n25q128a13"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xfb0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x3e>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "rut5xx:green:status"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/SAP-G3200U3.dts b/target/linux/ramips/dts/SAP-G3200U3.dts new file mode 100644 index 0000000..e2798fb --- /dev/null +++ b/target/linux/ramips/dts/SAP-G3200U3.dts @@ -0,0 +1,124 @@ +/dts-v1/; + +/include/ "mt7621.dtsi" + +/ { + compatible = "mediatek,mt7621-eval-board", "mediatek,mt7621-soc"; + model = "STORYLiNK SAP-G3200U3"; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x8000000>; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + palmbus@1E000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l6405d"; + reg = <0 0>; + linux,modalias = "m25p80", "en25q64"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x1000>; + read-only; + }; + + partition@31000 { + label = "config"; + reg = <0x31000 0xf000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pcie@1e140000 { + status = "okay"; + + pcie0 { + mt76@0,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 0x8000>; + mediatek,2ghz = <0>; + }; + }; + + pcie1 { + mt76@1,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 0x0000>; + mediatek,5ghz = <0>; + }; + }; + }; + + ethernet@1e100000 { + mtd-mac-address = <&factory 0xe006>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + usb { + label = "sap-g3200u3:green:usb"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 16 1>; + linux,code = <0x198>; + }; + + rfkill { + label = "rfkill"; + gpios = <&gpio0 14 1>; + linux,code = <0xf7>; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "uart3", "jtag"; + ralink,function = "gpio"; + }; + }; + }; +}; diff --git a/target/linux/ramips/dts/SL-R7205.dts b/target/linux/ramips/dts/SL-R7205.dts new file mode 100644 index 0000000..a6d9cc8 --- /dev/null +++ b/target/linux/ramips/dts/SL-R7205.dts @@ -0,0 +1,93 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "SL-R7205", "ralink,rt3052-soc"; + model = "Skyline SL-R7205 Wireless 3G Router"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x3e>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wifi { + label = "sl-r7205:green:wifi"; + gpios = <&gpio0 7 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/TEW-691GR.dts b/target/linux/ramips/dts/TEW-691GR.dts new file mode 100644 index 0000000..5bd6444 --- /dev/null +++ b/target/linux/ramips/dts/TEW-691GR.dts @@ -0,0 +1,109 @@ +/dts-v1/; + +/include/ "rt3883.dtsi" + +/ { + compatible = "TEW-691GR", "ralink,rt3883-soc"; + model = "TRENDnet TEW-691GR"; + + palmbus@10000000 { + gpio1: gpio@638 { + status = "okay"; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + + port@0 { + phy-handle = <&phy0>; + phy-mode = "rgmii"; + }; + + mdio-bus { + status = "okay"; + + phy0: ethernet-phy@0 { + reg = <0>; + }; + }; + }; + + wmac@10180000 { + ralink,5ghz = <0>; + }; + + nor-flash@1c000000 { + compatible = "cfi-flash"; + reg = <0x1c000000 0x800000>; + bank-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x0 0x0030000>; + label = "u-boot"; + read-only; + }; + + partition@30000 { + reg = <0x00030000 0x00010000>; + label = "u-boot-env"; + read-only; + }; + + factory: partition@40000 { + reg = <0x00040000 0x00010000>; + label = "factory"; + read-only; + }; + + partition@50000 { + reg = <0x00050000 0x007b0000>; + label = "firmware"; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio1 2 1>; + linux,code = <0x211>; + }; + + rfkill { + label = "rfkill"; + gpios = <&gpio0 0 1>; + linux,code = <0xf7>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wps { + label = "tew-691gr:green:wps"; + gpios = <&gpio0 9 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/TEW-692GR.dts b/target/linux/ramips/dts/TEW-692GR.dts new file mode 100644 index 0000000..17835f6 --- /dev/null +++ b/target/linux/ramips/dts/TEW-692GR.dts @@ -0,0 +1,128 @@ +/dts-v1/; + +/include/ "rt3883.dtsi" + +/ { + compatible = "TEW-692GR", "ralink,rt3883-soc"; + model = "TRENDnet TEW-692GR"; + + palmbus@10000000 { + gpio1: gpio@638 { + status = "okay"; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + status = "okay"; + mtd-mac-address = <&factory 0x28>; + + port@0 { + phy-handle = <&phy0>; + phy-mode = "rgmii"; + }; + + mdio-bus { + status = "okay"; + + phy0: ethernet-phy@0 { + reg = <0>; + }; + }; + }; + + pci@10140000 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&pci_pins>; + + pci_pins: pci { + pci { + ralink,group = "pci"; + ralink,function = "pci-fnc"; + }; + }; + + host-bridge { + pci-bridge@1 { + status = "okay"; + }; + }; + }; + + wmac@10180000 { + ralink,5ghz = <0>; + }; + + nor-flash@1c000000 { + compatible = "cfi-flash"; + reg = <0x1c000000 0x800000>; + bank-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x0 0x0030000>; + label = "u-boot"; + read-only; + }; + + partition@30000 { + reg = <0x00030000 0x00010000>; + label = "u-boot-env"; + read-only; + }; + + factory: partition@40000 { + reg = <0x00040000 0x00010000>; + label = "factory"; + read-only; + }; + + partition@50000 { + reg = <0x00050000 0x007b0000>; + label = "firmware"; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio1 2 1>; + linux,code = <0x211>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wps { + label = "tew-692gr:orange:wps"; + gpios = <&gpio0 9 1>; + }; + + wps2 { + label = "tew-692gr:green:wps"; + gpios = <&gpio1 4 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/TINY-AC.dts b/target/linux/ramips/dts/TINY-AC.dts new file mode 100644 index 0000000..388f4da --- /dev/null +++ b/target/linux/ramips/dts/TINY-AC.dts @@ -0,0 +1,166 @@ +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "TINY-AC", "ralink,mt7620a-soc"; + model = "Dovado Tiny AC"; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + palmbus@10000000 { + gpio0: gpio@600 { + status = "okay"; + }; + + gpio2: gpio@660 { + status = "okay"; + }; + + gpio3: gpio@688 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l6405d"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l6405d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + ethernet@10100000 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii1_pins &rgmii2_pins &mdio_pins>; + ralink,port-map = "llllw"; + + port@4 { + status = "okay"; + phy-mode = "rgmii"; + phy-handle = <&phy4>; + }; + + port@5 { + status = "okay"; + phy-mode = "rgmii"; + phy-handle = <&phy5>; + }; + + mdio-bus { + status = "okay"; + + phy4: ethernet-phy@4 { + reg = <4>; + phy-mode = "rgmii"; + }; + + phy5: ethernet-phy@5 { + reg = <5>; + phy-mode = "rgmii"; + }; + }; + }; + + gsw@10110000 { + ralink,port4 = "gmac"; + mediatek,mt7530 = <1>; + + }; + + wmac@10180000 { + ralink,eeprom = "rt2x00pci_1_0.eeprom"; + }; + + pcie@10140000 { + status = "okay"; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "uartf", "nd_sd", "wled"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + usb { + label = "tiny-ac:green:usb"; + gpios = <&gpio0 11 1>; + }; + + wifi { + label = "tiny-ac:orange:wifi"; + gpios = <&gpio3 0 1>; + }; + + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 13 1>; + linux,code = <0x198>; + }; + + }; + + gpio_export { + compatible = "gpio-export"; + #size-cells = <0>; + + usbpower { + gpio-export,name = "usbpower"; + gpio-export,output = <1>; + gpios = <&gpio2 5 0>; + }; + }; +}; diff --git a/target/linux/ramips/dts/UR-326N4G.dts b/target/linux/ramips/dts/UR-326N4G.dts new file mode 100644 index 0000000..3eb2526 --- /dev/null +++ b/target/linux/ramips/dts/UR-326N4G.dts @@ -0,0 +1,113 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "UR-326N4G", "ralink,rt3052-soc"; + model = "UPVEL UR-326N4G"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4004>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + 3g { + label = "ur-326n4g:green:3g"; + gpios = <&gpio0 9 1>; + }; + + gateway { + label = "ur-326n4g:green:gateway"; + gpios = <&gpio0 11 1>; + }; + + ap { + label = "ur-326n4g:green:ap"; + gpios = <&gpio0 12 1>; + }; + + wps { + label = "ur-326n4g:green:wps"; + gpios = <&gpio0 14 1>; + }; + + station { + label = "ur-326n4g:green:station"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset_wps { + label = "reset_wps"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + mode { + label = "mode"; + gpios = <&gpio0 7 1>; + linux,code = <0x32>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/UR-336UN.dts b/target/linux/ramips/dts/UR-336UN.dts new file mode 100644 index 0000000..76f669a --- /dev/null +++ b/target/linux/ramips/dts/UR-336UN.dts @@ -0,0 +1,92 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "UR-336UN", "ralink,rt3052-soc"; + model = "UPVEL UR-336UN"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + }; + + /* FIXME: no partitions defined */ +/* ethernet@10100000 { + mtd-mac-address = <&factory 0x4004>; + }; +*/ + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + /* FIXME: no partitions defined */ +/* wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; +*/ + gpio-leds { + compatible = "gpio-leds"; + + 3g { + label = "ur-336un:green:3g"; + gpios = <&gpio0 9 1>; + }; + + gateway { + label = "ur-336un:green:gateway"; + gpios = <&gpio0 11 1>; + }; + + ap { + label = "ur-336un:green:ap"; + gpios = <&gpio0 12 1>; + }; + + wps { + label = "ur-336un:green:wps"; + gpios = <&gpio0 14 1>; + }; + + station { + label = "ur-336un:green:station"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset_wps { + label = "reset_wps"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + mode { + label = "mode"; + gpios = <&gpio0 7 1>; + linux,code = <0x32>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/V11STFE.dts b/target/linux/ramips/dts/V11STFE.dts new file mode 100644 index 0000000..5a43e6d --- /dev/null +++ b/target/linux/ramips/dts/V11STFE.dts @@ -0,0 +1,85 @@ +/dts-v1/; + +/include/ "rt2880.dtsi" + +/ { + compatible = "V11ST-FE", "ralink,rt2880-soc"; + model = "Ralink V11ST-FE"; + + palmbus@300000 { + gpio0: gpio@600 { + status = "okay"; + }; + }; + + ethernet@400000 { + status = "okay"; + }; + + wmac@480000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pci@10140000 { + status = "okay"; + + host-bridge { + pci-bridge@1 { + status = "okay"; + }; + }; + }; + + nor-flash@1c000000 { + compatible = "cfi-flash"; + reg = <0x1c000000 0x800000>; + bank-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x0 0x0030000>; + label = "u-boot"; + read-only; + }; + + partition@30000 { + reg = <0x00030000 0x00010000>; + label = "u-boot-env"; + read-only; + }; + + factory: partition@40000 { + reg = <0x00040000 0x00010000>; + label = "factory"; + read-only; + }; + + partition@50000 { + reg = <0x00050000 0x003b0000>; + label = "firmware"; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + wps { + label = "wps"; + gpios = <&gpio0 0 0>; + linux,code = <0x211>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "v11st-fe:green:status"; + gpios = <&gpio0 12 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/V22RW-2X2.dts b/target/linux/ramips/dts/V22RW-2X2.dts new file mode 100644 index 0000000..e8fc4fe --- /dev/null +++ b/target/linux/ramips/dts/V22RW-2X2.dts @@ -0,0 +1,94 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "V22RW-2X2", "ralink,rt3052-soc"; + model = "Ralink AP-RT3052-V22RW-2X2"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + security { + label = "v22rw-2x2:green:security"; + gpios = <&gpio0 13 1>; + }; + + wps { + label = "v22rw-2x2:red:wps"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/VOCORE-16M.dts b/target/linux/ramips/dts/VOCORE-16M.dts new file mode 100644 index 0000000..464c137 --- /dev/null +++ b/target/linux/ramips/dts/VOCORE-16M.dts @@ -0,0 +1,41 @@ +/dts-v1/; + +/include/ "VOCORE.dtsi" + +/ { + palmbus@10000000 { + spi@b00 { + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "w25q128"; + reg = <0>; + linux,modalias = "m25p80", "w25q128"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "uboot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "uboot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xfb0000>; + }; + }; + }; + }; +}; diff --git a/target/linux/ramips/dts/VOCORE-8M.dts b/target/linux/ramips/dts/VOCORE-8M.dts new file mode 100644 index 0000000..8a081ed --- /dev/null +++ b/target/linux/ramips/dts/VOCORE-8M.dts @@ -0,0 +1,41 @@ +/dts-v1/; + +/include/ "VOCORE.dtsi" + +/ { + palmbus@10000000 { + spi@b00 { + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "s25fl064k"; + reg = <0>; + linux,modalias = "m25p80", "s25fl064k"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "uboot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "uboot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; +}; diff --git a/target/linux/ramips/dts/VOCORE.dtsi b/target/linux/ramips/dts/VOCORE.dtsi new file mode 100644 index 0000000..ff031fa --- /dev/null +++ b/target/linux/ramips/dts/VOCORE.dtsi @@ -0,0 +1,197 @@ +/include/ "rt5350.dtsi" + +/ { + compatible = "VoCore", "ralink,rt5350-soc"; + model = "VoCore"; + + palmbus@10000000 { + gpio1: gpio@660 { + status = "okay"; + }; + + i2c@900 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + spidev@1 { + compatible = "linux,spidev"; + spi-max-frequency = <10000000>; + reg = <1>; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "jtag", "uartf", "led"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x17>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + gpio-export { + compatible = "gpio-export"; + #size-cells = <0>; + + gpio0 { + gpio-export,name = "gpio0"; + gpio-export,direction_may_change = <1>; + gpios = <&gpio0 0 0>; + }; + + /* UARTF */ + gpio7 { + /* UARTF_RTS_N */ + gpio-export,name = "gpio7"; + gpio-export,direction_may_change = <1>; + gpios = <&gpio0 7 0>; + }; + + gpio8 { + /* UARTF_TXD */ + gpio-export,name = "gpio8"; + gpio-export,direction_may_change = <1>; + gpios = <&gpio0 8 0>; + }; + + gpio9 { + /* UARTF_CTS_N */ + gpio-export,name = "gpio9"; + gpio-export,direction_may_change = <1>; + gpios = <&gpio0 9 0>; + }; + + gpio12 { + /* UARTF_DCD_N */ + gpio-export,name = "gpio12"; + gpio-export,direction_may_change = <1>; + gpios = <&gpio0 12 0>; + }; + + gpio13 { + /* UARTF_DSR_N */ + gpio-export,name = "gpio13"; + gpio-export,direction_may_change = <1>; + gpios = <&gpio0 13 0>; + }; + + gpio14 { + /* UARTF_RIN */ + gpio-export,name = "gpio14"; + gpio-export,direction_may_change = <1>; + gpios = <&gpio0 14 0>; + }; + + /* JTAG */ + gpio17 { + /* JTAG_TDO */ + gpio-export,name = "gpio17"; + gpio-export,direction_may_change = <1>; + gpios = <&gpio0 17 0>; + }; + + gpio18 { + /* JTAG_TDI */ + gpio-export,name = "gpio18"; + gpio-export,direction_may_change = <1>; + gpios = <&gpio0 18 0>; + }; + + gpio19 { + /* JTAG_TMS */ + gpio-export,name = "gpio19"; + gpio-export,direction_may_change = <1>; + gpios = <&gpio0 19 0>; + }; + + gpio20 { + /* JTAG_TCLK */ + gpio-export,name = "gpio20"; + gpio-export,direction_may_change = <1>; + gpios = <&gpio0 20 0>; + }; + + gpio21 { + /* JTAG_TRST_N */ + gpio-export,name = "gpio21"; + gpio-export,direction_may_change = <1>; + gpios = <&gpio0 21 0>; + }; + + /* ETH LEDs */ + gpio22 { + /* ETH0_LED */ + gpio-export,name = "gpio22"; + gpio-export,direction_may_change = <1>; + gpios = <&gpio1 0 0>; + }; + + gpio23 { + /* ETH1_LED */ + gpio-export,name = "gpio23"; + gpio-export,direction_may_change = <1>; + gpios = <&gpio1 1 0>; + }; + + gpio24 { + /* ETH2_LED */ + gpio-export,name = "gpio24"; + gpio-export,direction_may_change = <1>; + gpios = <&gpio1 2 0>; + }; + + gpio25 { + /* ETH3_LED */ + gpio-export,name = "gpio25"; + gpio-export,direction_may_change = <1>; + gpios = <&gpio1 3 0>; + }; + + gpio26 { + /* ETH4_LED */ + gpio-export,name = "gpio26"; + gpio-export,direction_may_change = <1>; + gpios = <&gpio1 4 0>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + /* UARTF_RXD */ + label = "vocore:green:status"; + gpios = <&gpio0 10 0>; + }; + + eth { + /* UARTF_DTR_N */ + label = "vocore:orange:eth"; + gpios = <&gpio0 11 0>; + }; + }; +}; diff --git a/target/linux/ramips/dts/W150M.dts b/target/linux/ramips/dts/W150M.dts new file mode 100644 index 0000000..875c468 --- /dev/null +++ b/target/linux/ramips/dts/W150M.dts @@ -0,0 +1,114 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "W150M", "ralink,rt3050-soc"; + model = "Tenda W150M"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3c8000>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + 3grouter { + label = "w150m:blue:3grouter"; + gpios = <&gpio0 11 1>; + }; + + ap { + label = "w150m:blue:ap"; + gpios = <&gpio0 12 1>; + }; + + wisprouter { + label = "w150m:blue:wisprouter"; + gpios = <&gpio0 9 1>; + }; + + wirelessrouter { + label = "w150m:blue:wirelessrouter"; + gpios = <&gpio0 13 1>; + }; + + 3g { + label = "w150m:blue:3g"; + gpios = <&gpio0 7 1>; + }; + + wpsreset { + label = "w150m:blue:wpsreset"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 0 1>; + linux,code = <0x198>; + }; + + mode { + label = "mode"; + gpios = <&gpio0 10 1>; + linux,code = <0x100>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; +}; diff --git a/target/linux/ramips/dts/W306R_V20.dts b/target/linux/ramips/dts/W306R_V20.dts new file mode 100644 index 0000000..72b6ed8 --- /dev/null +++ b/target/linux/ramips/dts/W306R_V20.dts @@ -0,0 +1,88 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "W306R_V20", "ralink,rt3052-soc"; + model = "Tenda W306R V2.0"; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x3e>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + sys { + label = "w306r-v20:green:sys"; + gpios = <&gpio0 9 1>; + }; + + wps { + label = "w306r-v20:green:wps"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "RESET/WPS"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + }; +}; diff --git a/target/linux/ramips/dts/W502U.dts b/target/linux/ramips/dts/W502U.dts new file mode 100644 index 0000000..0f423ba --- /dev/null +++ b/target/linux/ramips/dts/W502U.dts @@ -0,0 +1,102 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "W502U", "ralink,rt3052-soc"; + model = "ALFA Networks W502U"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x3e>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + usb { + label = "w502u:blue:usb"; + gpios = <&gpio0 13 1>; + }; + + wps { + label = "w502u:blue:wps"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/WCR150GN.dts b/target/linux/ramips/dts/WCR150GN.dts new file mode 100644 index 0000000..e197bb9 --- /dev/null +++ b/target/linux/ramips/dts/WCR150GN.dts @@ -0,0 +1,98 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "WCR150GN", "ralink,rt3050-soc"; + model = "Sparklan WCR-150GN"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + user { + label = "wcr-150gn:amber:user"; + gpios = <&gpio0 12 1>; + }; + + power { + label = "wcr-150gn:amber:power"; + gpios = <&gpio0 8 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + wps { + label = "wps"; + gpios = <&gpio0 10 1>; + linux,code = <0x211>; + }; + + reset { + label = "reset"; + gpios = <&gpio0 0 1>; + linux,code = <0x198>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/WHR-1166D.dts b/target/linux/ramips/dts/WHR-1166D.dts new file mode 100644 index 0000000..69b8641 --- /dev/null +++ b/target/linux/ramips/dts/WHR-1166D.dts @@ -0,0 +1,172 @@ +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "ralink,mt7620a-soc"; + model = "Buffalo WHR-1166D"; + + palmbus@10000000 { + gpio2: gpio@660 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "en25q64"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l6405d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xfb0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "uartf", "wled", "nd_sd"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + pinctrl-names = "default"; + pinctrl-0 = <&rgmii1_pins &mdio_pins>; + + port@5 { + status = "okay"; + phy-handle = <&phy5>; + phy-mode = "rgmii"; + }; + + mdio-bus { + status = "okay"; + + phy5: ethernet-phy@5 { + reg = <5>; + phy-mode = "rgmii"; + }; + }; + }; + + gsw@10110000 { + ralink,port4 = "ephy"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pcie@10140000 { + status = "okay"; + + pcie-bridge { + mt76@0,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 32768>; + mediatek,2ghz = <0>; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "whr-1166d:red:power"; + gpios = <&gpio0 7 1>; + }; + + wifi { + label = "whr-1166d:green:wifi"; + gpios = <&gpio0 8 1>; + }; + + power2 { + label = "whr-1166d:green:power"; + gpios = <&gpio0 9 1>; + }; + + wifi2 { + label = "whr-1166d:orange:wifi"; + gpios = <&gpio0 10 1>; + }; + + internet { + label = "whr-1166d:green:internet"; + gpios = <&gpio2 17 1>; + }; + + router { + label = "whr-1166d:orange:router"; + gpios = <&gpio2 18 1>; + }; + + router2 { + label = "whr-1166d:green:router"; + gpios = <&gpio2 19 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio2 12 1>; + linux,code = <0x198>; + }; + + aoss { + label = "aoss"; + gpios = <&gpio2 13 1>; + linux,code = <0x211>; + }; + + ap { + label = "ap"; + gpios = <&gpio2 14 1>; + linux,code = <0x100>; + linux,input-type = <5>; /* EV_SW */ + }; + + bridge { + label = "bridge"; + gpios = <&gpio2 15 1>; + linux,code = <0x100>; + linux,input-type = <5>; /* EV_SW */ + }; + }; +}; diff --git a/target/linux/ramips/dts/WHR-300HP2.dts b/target/linux/ramips/dts/WHR-300HP2.dts new file mode 100644 index 0000000..5916715 --- /dev/null +++ b/target/linux/ramips/dts/WHR-300HP2.dts @@ -0,0 +1,150 @@ +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "ralink,mt7620a-soc"; + model = "Buffalo WHR-300HP2"; + + palmbus@10000000 { + gpio2: gpio@660 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "en25q64"; + reg = <0 0>; + linux,modalias = "m25p80", "s25fl064k"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "uartf", "rgmii1", "rgmii2", "wled", "nd_sd"; + ralink,function = "gpio"; + }; + + pa { + ralink,group = "pa"; + ralink,function = "pa"; + }; + }; + }; + + ethernet@10100000 { + pinctrl-names = "default"; + pinctrl-0 = <&ephy_pins>; + ralink,port-map = "llllw"; + }; + + gsw@10110000 { + ralink,port4 = "ephy"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "whr-300hp2:red:power"; + gpios = <&gpio0 7 1>; + }; + + wifi { + label = "whr-300hp2:green:wifi"; + gpios = <&gpio0 8 1>; + }; + + power2 { + label = "whr-300hp2:green:power"; + gpios = <&gpio0 9 1>; + }; + + wifi2 { + label = "whr-300hp2:orange:wifi"; + gpios = <&gpio0 10 1>; + }; + + internet { + label = "whr-300hp2:green:internet"; + gpios = <&gpio2 17 1>; + }; + + router { + label = "whr-300hp2:green:router"; + gpios = <&gpio2 18 1>; + }; + + router2 { + label = "whr-300hp2:orange:router"; + gpios = <&gpio2 19 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio2 12 1>; + linux,code = <0x198>; + }; + + aoss { + label = "aoss"; + gpios = <&gpio2 13 1>; + linux,code = <0x211>; + }; + + ap { + label = "ap"; + gpios = <&gpio2 14 1>; + linux,code = <0x100>; + linux,input-type = <5>; /* EV_SW */ + }; + + bridge { + label = "bridge"; + gpios = <&gpio2 15 1>; + linux,code = <0x100>; + linux,input-type = <5>; /* EV_SW */ + }; + }; +}; diff --git a/target/linux/ramips/dts/WHR-600D.dts b/target/linux/ramips/dts/WHR-600D.dts new file mode 100644 index 0000000..8e20859 --- /dev/null +++ b/target/linux/ramips/dts/WHR-600D.dts @@ -0,0 +1,150 @@ +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "ralink,mt7620a-soc"; + model = "Buffalo WHR-600D"; + + palmbus@10000000 { + gpio2: gpio@660 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "en25q64"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l6405d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "uartf", "rgmii1", "rgmii2", "wled", "nd_sd"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + pinctrl-names = "default"; + pinctrl-0 = <&ephy_pins>; + mtd-mac-address = <&factory 0x4>; + ralink,port-map = "llllw"; + }; + + gsw@10110000 { + ralink,port4 = "ephy"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pcie@10140000 { + status = "okay"; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "whr-600d:red:power"; + gpios = <&gpio0 7 1>; + }; + + wifi { + label = "whr-600d:green:wifi"; + gpios = <&gpio0 8 1>; + }; + + power2 { + label = "whr-600d:green:power"; + gpios = <&gpio0 9 1>; + }; + + wifi2 { + label = "whr-600d:orange:wifi"; + gpios = <&gpio0 10 1>; + }; + + internet { + label = "whr-600d:green:internet"; + gpios = <&gpio2 17 1>; + }; + + router { + label = "whr-600d:green:router"; + gpios = <&gpio2 18 1>; + }; + + router2 { + label = "whr-600d:orange:router"; + gpios = <&gpio2 19 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio2 12 1>; + linux,code = <0x198>; + }; + + aoss { + label = "aoss"; + gpios = <&gpio2 13 1>; + linux,code = <0x211>; + }; + + ap { + label = "ap"; + gpios = <&gpio2 14 1>; + linux,code = <0x100>; + linux,input-type = <5>; /* EV_SW */ + }; + + bridge { + label = "bridge"; + gpios = <&gpio2 15 1>; + linux,code = <0x100>; + linux,input-type = <5>; /* EV_SW */ + }; + }; +}; diff --git a/target/linux/ramips/dts/WHR-G300N.dts b/target/linux/ramips/dts/WHR-G300N.dts new file mode 100644 index 0000000..1aa9f69 --- /dev/null +++ b/target/linux/ramips/dts/WHR-G300N.dts @@ -0,0 +1,85 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "WHR-G300N", "ralink,rt3052-soc"; + model = "Buffalo WHR-G300N"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + /* FIXME: no partitions defined */ +/* wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; +*/ + gpio-leds { + compatible = "gpio-leds"; + + diag { + label = "whr-g300n:red:diag"; + gpios = <&gpio0 7 1>; + }; + + router { + label = "whr-g300n:green:router"; + gpios = <&gpio0 9 1>; + }; + + security { + label = "whr-g300n:amber:security"; + gpios = <&gpio0 14 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + aoss { + label = "aoss"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + + router-off { + label = "router-off"; + gpios = <&gpio0 11 1>; + linux,code = <0x102>; + }; + + router-on { + label = "router-on"; + gpios = <&gpio0 8 1>; + linux,code = <0x103>; + }; + }; +}; diff --git a/target/linux/ramips/dts/WIZARD8800.dts b/target/linux/ramips/dts/WIZARD8800.dts new file mode 100644 index 0000000..d89c0d5 --- /dev/null +++ b/target/linux/ramips/dts/WIZARD8800.dts @@ -0,0 +1,83 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "WIZARD8800", "ralink,rt5350-soc"; + model = "EASYACC WI-STOR WIZARD 8800"; + + palmbus@10000000 { + gpio1@638 { + status = "okay"; + }; + + gpio2@660 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "w25q32"; + reg = <0 0>; + linux,modalias = "m25p80", "w25q32"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; +}; diff --git a/target/linux/ramips/dts/WIZFI630A.dts b/target/linux/ramips/dts/WIZFI630A.dts new file mode 100644 index 0000000..f2818ce --- /dev/null +++ b/target/linux/ramips/dts/WIZFI630A.dts @@ -0,0 +1,180 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "wizfi630a", "ralink,rt5350-soc"; + model = "WIZnet WizFi630A"; + + chosen { + bootargs = "console=ttyS1,115200"; + }; + + palmbus@10000000 { + gpio1: gpio@660 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "w25q128"; + reg = <0>; + linux,modalias = "m25p80", "w25q128"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "uboot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "uboot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xfb0000>; + }; + }; + }; + + uart@500 { + compatible = "ralink,mt7620a-uart", "ralink,rt2880-uart", "ns16550a"; + reg = <0x500 0x100>; + resets = <&rstctrl 12>; + reset-names = "uart"; + interrupt-parent = <&intc>; + interrupts = <5>; + reg-shift = <2>; + status = "okay"; + }; + + uartlite@c00 { + compatible = "ralink,mt7620a-uart", "ralink,rt2880-uart", "ns16550a"; + reg = <0xc00 0x100>; + resets = <&rstctrl 19>; + reset-names = "uartl"; + interrupt-parent = <&intc>; + interrupts = <12>; + reg-shift = <2>; + pinctrl-names = "default"; + pinctrl-0 = <&uartlite_pins>; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag" ; + ralink,function = "gpio"; + }; + }; + + uartf_gpio_pins: uartf_gpio { + uartf_gpio { + ralink,group = "uartf"; + ralink,function = "uartf"; + }; + }; + + uartlite_pins: uartlite { + uart { + ralink,group = "uartlite"; + ralink,function = "uartlite"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x17>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + gpio-export { + compatible = "gpio-export"; + #size-cells = <0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + run { + label = "wizfi630a::run"; + gpios = <&gpio0 1 1>; + }; + + wps { + label = "wizfi630a::wps"; + gpios = <&gpio0 20 1>; + }; + + uart1 { + label = "wizfi630a::uart1"; + gpios = <&gpio0 18 1>; + }; + + uart2 { + label = "wizfi630a::uart2"; + gpios = <&gpio0 21 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 17 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + + scm1 { + label = "SCM1"; + gpios = <&gpio0 19 1>; + linux,code = <0x100>; + }; + + scm2 { + label = "SCM2"; + gpios = <&gpio0 2 1>; + linux,code = <0x101>; + }; + }; +}; diff --git a/target/linux/ramips/dts/WL-330N.dts b/target/linux/ramips/dts/WL-330N.dts new file mode 100644 index 0000000..a7238dc --- /dev/null +++ b/target/linux/ramips/dts/WL-330N.dts @@ -0,0 +1,100 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "WL-330N", "ralink,rt3050-soc"; + model = "Asus WL-330N"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l3205d"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l3205d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x3e>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + link { + label = "wl-330n:blue:link"; + gpios = <&gpio0 9 1>; + }; + + power { + label = "wl-330n:blue:power"; + gpios = <&gpio0 11 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x198>; + }; + }; +}; diff --git a/target/linux/ramips/dts/WL-330N3G.dts b/target/linux/ramips/dts/WL-330N3G.dts new file mode 100644 index 0000000..c02f6a9 --- /dev/null +++ b/target/linux/ramips/dts/WL-330N3G.dts @@ -0,0 +1,109 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "WL-330N3G", "ralink,rt3050-soc"; + model = "Asus WL-330N3G"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l3205d"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l3205d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x3e>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + 3g { + label = "wl-330n3g:blue:3g"; + gpios = <&gpio0 9 1>; + }; + + 3g2 { + label = "wl-330n3g:red:3g"; + gpios = <&gpio0 13 1>; + }; + + power { + label = "wl-330n3g:blue:power"; + gpios = <&gpio0 11 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x198>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/WL-341V3.dts b/target/linux/ramips/dts/WL-341V3.dts new file mode 100644 index 0000000..ce5e820 --- /dev/null +++ b/target/linux/ramips/dts/WL-341V3.dts @@ -0,0 +1,123 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "WL-341V3", "ralink,rt3052-soc"; + model = "Sitecom WL-341 v3"; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x20000>; + read-only; + }; + + boardnvram: partition@20000 { + label = "board-nvram"; + reg = <0x20000 0x10000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + partition@40000 { + label = "firmware"; + reg = <0x40000 0x3b0000>; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&boardnvram 0xffa0>; + }; + + esw@10110000 { + ralink,portmap = <0x3e>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&boardnvram 0xfd70>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + first { + label = "wl-341v3:amber:first"; + gpios = <&gpio0 9 1>; + }; + + first2 { + label = "wl-341v3:blue:first"; + gpios = <&gpio0 13 1>; + }; + + third { + label = "wl-341v3:amber:third"; + gpios = <&gpio0 11 1>; + }; + + third2 { + label = "wl-341v3:blue:third"; + gpios = <&gpio0 14 1>; + }; + + fourth { + label = "wl-341v3:blue:fourth"; + gpios = <&gpio0 10 1>; + }; + + fifth { + label = "wl-341v3:amber:fifth"; + gpios = <&gpio0 12 1>; + }; + + fifth2 { + label = "wl-341v3:blue:fifth"; + gpios = <&gpio0 8 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 7 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 5 1>; + linux,code = <0x211>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/WL-351.dts b/target/linux/ramips/dts/WL-351.dts new file mode 100644 index 0000000..3fcb222 --- /dev/null +++ b/target/linux/ramips/dts/WL-351.dts @@ -0,0 +1,117 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "WL-351", "ralink,rt3052-soc"; + model = "Sitecom WL-351 v1 002"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x3f>; + ralink,fct2 = <0x0002500c>; + /* + * ext phy base addr 31, rx/tx clock skew 0, + * turbo mii off, rgmi 3.3v off, port 5 polling off + * port5: enabled, gige, full-duplex, rx/tx-flow-control + * port6: enabled, gige, full-duplex, rx/tx-flow-control + */ + ralink,fpa2 = <0x1f003fff>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + otg@101c0000 { + status = "okay"; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "wl-351:amber:power"; + gpios = <&gpio0 8 1>; + }; + + unpopulated { + label = "wl-351:amber:unpopulated"; + gpios = <&gpio0 12 1>; + }; + + unpopulated2 { + label = "wl-351:blue:unpopulated"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; + + rtl8366rb { + compatible = "rtl8366rb"; + gpio-sda = <&gpio0 1 0>; + gpio-sck = <&gpio0 2 0>; + }; +}; diff --git a/target/linux/ramips/dts/WLI-TX4-AG300N.dts b/target/linux/ramips/dts/WLI-TX4-AG300N.dts new file mode 100644 index 0000000..3a456b8 --- /dev/null +++ b/target/linux/ramips/dts/WLI-TX4-AG300N.dts @@ -0,0 +1,105 @@ +/dts-v1/; + +/include/ "rt2880.dtsi" + +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "WLI-TX4-AG300N", "ralink,rt2880-soc"; + model = "Buffalo WLI-TX4-AG300N"; + + palmbus@300000 { + gpio0: gpio@600 { + status = "okay"; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "uboot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "uboot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "linux"; + reg = <0x50000 0x3b0000>; + }; + }; + + ethernet@400000 { + status = "okay"; + mtd-mac-address = <&factory 0x4>; + + port@0 { + ralink,fixed-link = <1000 1 1 1>; + }; + }; + + wmac@480000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + + bandwidth { + label = "bandwidth"; + gpios = <&gpio0 8 0>; + linux,code = <0x198>; + }; + + reset { + label = "reset"; + gpios = <&gpio0 9 1>; + linux,code = <0x198>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + diag { + label = "wli-tx4-ag300n:red:diag"; + gpios = <&gpio0 10 1>; + }; + + power { + label = "wli-tx4-ag300n:blue:power"; + gpios = <&gpio0 12 1>; + }; + + security { + label = "wli-tx4-ag300n:blue:security"; + gpios = <&gpio0 13 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/WMR-300.dts b/target/linux/ramips/dts/WMR-300.dts new file mode 100644 index 0000000..3dae3ae --- /dev/null +++ b/target/linux/ramips/dts/WMR-300.dts @@ -0,0 +1,106 @@ +/dts-v1/; + +/include/ "mt7620n.dtsi" + +/ { + compatible = "buffalo,wmr-300", "ralink,mt7620n-soc"; + model = "Buffalo WMR-300"; + + palmbus@10000000 { + gpio2: gpio@660 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l6405d"; + reg = <0 0>; + linux,modalias = "m25p80", "en25q64"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + ralink,port-map = "wllll"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pinctrl { + state_default: pinctrl0 { + default { + ralink,group = "i2c", "ephy"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + aoss1 { + label = "wmr-300:red:aoss"; + gpios = <&gpio2 1 1>; + }; + + aoss2 { + label = "wmr-300:green:aoss"; + gpios = <&gpio2 2 1>; + }; + + power { + label = "wmr-300:green:status"; + gpios = <&gpio2 4 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 1 1>; + linux,code = <0x198>; + }; + + aoss { + label = "aoss"; + gpios = <&gpio0 2 1>; + linux,code = <0x211>; + }; + }; +}; diff --git a/target/linux/ramips/dts/WNCE2001.dts b/target/linux/ramips/dts/WNCE2001.dts new file mode 100644 index 0000000..36eb473 --- /dev/null +++ b/target/linux/ramips/dts/WNCE2001.dts @@ -0,0 +1,139 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "WNCE2001", "ralink,rt3052-soc"; + model = "Netgear WNCE2001"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l3205d"; + reg = <0 0>; + linux,modalias = "m25p80", "mx25l3205d"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + factory: partition@30000 { + label = "factory"; + reg = <0x30000 0x10000>; + read-only; + }; + + partition@40000 { + label = "config"; + reg = <0x40000 0x20000>; + read-only; + }; + + partition@60000 { + label = "language"; + reg = <0x60000 0x30000>; + read-only; + }; + + partition@90000 { + label = "pot"; + reg = <0x90000 0x10000>; + read-only; + }; + + partition@a0000 { + label = "checksum"; + reg = <0xa0000 0x10000>; + }; + + partition@b0000 { + label = "firmware"; + reg = <0xb0000 0x350000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power-green { + label = "wnce2001:green:power"; + gpios = <&gpio0 8 1>; + }; + + power-red { + label = "wnce2001:red:power"; + gpios = <&gpio0 9 1>; + }; + + wlan-green { + label = "wnce2001:green:wlan"; + gpios = <&gpio0 12 0>; + }; + + wlan-red { + label = "wnce2001:red:wlan"; + gpios = <&gpio0 13 0>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + + rt { + label = "rt"; + gpios = <&gpio0 11 1>; + linux,code = <0x100>; + }; + + ap { + label = "ap"; + gpios = <&gpio0 7 1>; + linux,code = <0x101>; + }; + }; +}; diff --git a/target/linux/ramips/dts/WR512-3GN-4M.dts b/target/linux/ramips/dts/WR512-3GN-4M.dts new file mode 100644 index 0000000..def7751 --- /dev/null +++ b/target/linux/ramips/dts/WR512-3GN-4M.dts @@ -0,0 +1,109 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "WR512-3GN", "ralink,rt3052-soc"; + model = "WR512-3GN-like router"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3c8000>; + }; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + 3g { + label = "wr512-3gn:green:3g"; + gpios = <&gpio0 9 1>; + }; + + gateway { + label = "wr512-3gn:green:gateway"; + gpios = <&gpio0 11 1>; + }; + + ap { + label = "wr512-3gn:green:ap"; + gpios = <&gpio0 12 1>; + }; + + wps { + label = "wr512-3gn:green:wps"; + gpios = <&gpio0 14 1>; + }; + + station { + label = "wr512-3gn:green:station"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset_wps { + label = "reset_wps"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + mode { + label = "mode"; + gpios = <&gpio0 7 1>; + linux,code = <0x32>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/WR512-3GN-8M.dts b/target/linux/ramips/dts/WR512-3GN-8M.dts new file mode 100644 index 0000000..b439f0a --- /dev/null +++ b/target/linux/ramips/dts/WR512-3GN-8M.dts @@ -0,0 +1,109 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "WR512-3GN", "ralink,rt3052-soc"; + model = "WR512-3GN-like router"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + 3g { + label = "wr512-3gn:green:3g"; + gpios = <&gpio0 9 1>; + }; + + gateway { + label = "wr512-3gn:green:gateway"; + gpios = <&gpio0 11 1>; + }; + + ap { + label = "wr512-3gn:green:ap"; + gpios = <&gpio0 12 1>; + }; + + wps { + label = "wr512-3gn:green:wps"; + gpios = <&gpio0 14 1>; + }; + + station { + label = "wr512-3gn:green:station"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset_wps { + label = "reset_wps"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + mode { + label = "mode"; + gpios = <&gpio0 7 1>; + linux,code = <0x32>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/WR6202.dts b/target/linux/ramips/dts/WR6202.dts new file mode 100644 index 0000000..614f696 --- /dev/null +++ b/target/linux/ramips/dts/WR6202.dts @@ -0,0 +1,113 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "WR6202", "ralink,rt3052-soc"; + model = "AWB WR6202"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wps { + label = "wr6202:blue:wps"; + gpios = <&gpio0 14 1>; + }; + + 3g { + label = "wr6202:blue:3g"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x3e>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + otg@101c0000 { + status = "okay"; + }; + + gpio_export { + compatible = "gpio-export"; + #size-cells = <0>; + + usb { + gpio-export,name = "usb"; + gpio-export,output = <0>; + gpios = <&gpio0 11 0>; + }; + }; +}; diff --git a/target/linux/ramips/dts/WRTNODE.dts b/target/linux/ramips/dts/WRTNODE.dts new file mode 100644 index 0000000..23dbf5c --- /dev/null +++ b/target/linux/ramips/dts/WRTNODE.dts @@ -0,0 +1,93 @@ +/dts-v1/; + +/include/ "mt7620n.dtsi" + +/ { + compatible = "wrtnode", "ralink,mt7620n-soc"; + model = "WRTNODE"; + + palmbus@10000000 { + gpio1: gpio@638 { + status = "okay"; + }; + + gpio2: gpio@660 { + status = "okay"; + }; + + gpio3: gpio@688 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l12805d"; + reg = <0 0>; + linux,modalias = "m25p80", "w25q128"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xfb0000>; + }; + }; + }; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + ralink,port-map = "wllll"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pinctrl { + state_default: pinctrl0 { + default { + ralink,group = "ephy", "wled", "pa", "i2c", "wdt", "uartf", "spi refclk"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + indicator { + label = "wrtnode:blue:indicator"; + gpios = <&gpio1 14 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/WSR-1166.dts b/target/linux/ramips/dts/WSR-1166.dts new file mode 100644 index 0000000..2dc59cc --- /dev/null +++ b/target/linux/ramips/dts/WSR-1166.dts @@ -0,0 +1,186 @@ +/dts-v1/; + +/include/ "mt7621.dtsi" + +/ { + compatible = "ralink,mt7621-eval-board", "ralink,mt7621-soc"; + model = "Buffalo WSR-1166DHP"; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x8000000>; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + palmbus@1E000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l12805d"; + reg = <0 0>; + linux,modalias = "m25p80"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xf90000>; + }; + + partition@fe00000 { + label = "board_data"; + reg = <0xfe0000 0x10000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + internet_g { + label = "wsr-1166:green:internet"; + gpios = <&gpio1 9 1>; + }; + + router_g { + label = "wsr-1166:green:router"; + gpios = <&gpio1 10 1>; + }; + + router_o { + label = "wsr-1166:orange:router"; + gpios = <&gpio1 11 1>; + }; + + internet_o { + label = "wsr-1166:orange:internet"; + gpios = <&gpio1 12 1>; + }; + + wifi_o { + label = "wsr-1166:orange:wifi"; + gpios = <&gpio1 13 1>; + }; + + power { + label = "wsr-1166:green:power"; + gpios = <&gpio1 14 1>; + }; + + diag { + label = "wsr-1166:orange:diag"; + gpios = <&gpio1 15 1>; + }; + + wifi_g { + label = "wsr-1166:green:wifi"; + gpios = <&gpio1 16 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + power { + label = "power"; + gpios = <&gpio0 18 1>; + linux,code = <0x74>; + }; + + reset { + label = "reset"; + gpios = <&gpio0 3 1>; + linux,code = <0x198>; + }; + + aoss { + label = "aoss"; + gpios = <&gpio0 6 1>; + linux,code = <0x211>; + }; + + auto { + label = "mode"; + gpios = <&gpio0 7 0>; + linux,code = <0x100>; + linux,input-type = <5>; /* EV_SW */ + }; + + ap { + label = "ap"; + gpios = <&gpio0 10 0>; + linux,code = <0x100>; + linux,input-type = <5>; /* EV_SW */ + }; + + router { + label = "router"; + gpios = <&gpio0 12 0>; + linux,code = <0x100>; + linux,input-type = <5>; /* EV_SW */ + }; + }; + + gpio_poweroff { + compatible = "gpio-poweroff"; + gpios = <&gpio0 0 1>; + }; + + pcie@1e140000 { + status = "okay"; + + pcie0 { + mt76@0,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 0x8000>; + mediatek,2ghz = <0>; + }; + }; + + pcie1 { + mt76@1,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 0x0000>; + mediatek,5ghz = <0>; + }; + }; + }; +}; diff --git a/target/linux/ramips/dts/WSR-600.dts b/target/linux/ramips/dts/WSR-600.dts new file mode 100644 index 0000000..5eb813f --- /dev/null +++ b/target/linux/ramips/dts/WSR-600.dts @@ -0,0 +1,159 @@ +/dts-v1/; + +/include/ "mt7621.dtsi" + +/ { + compatible = "ralink,mt7621-eval-board", "ralink,mt7621-soc"; + model = "Buffalo WSR-600DHP"; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x4000000>; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + palmbus@1E000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l12805d"; + reg = <0 0>; + linux,modalias = "m25p80"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xfb0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "uart2", "uart3", "rgmii2", "sdhci"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "wsr-600:green:power"; + gpios = <&gpio0 12 1>; + }; + + wifi_o { + label = "wsr-600:orange:wifi"; + gpios = <&gpio1 9 1>; + }; + + diag { + label = "wsr-600:orange:diag"; + gpios = <&gpio1 10 1>; + }; + + wifi_g { + label = "wsr-600:green:wifi"; + gpios = <&gpio1 12 1>; + }; + + router_o { + label = "wsr-600:orange:router"; + gpios = <&gpio1 13 1>; + }; + + router_g { + label = "wsr-600:green:router"; + gpios = <&gpio1 14 1>; + }; + + internet_o { + label = "wsr-600:orange:internet"; + gpios = <&gpio1 15 1>; + }; + + internet_g { + label = "wsr-600:green:internet"; + gpios = <&gpio1 16 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + power { + label = "power"; + gpios = <&gpio0 8 1>; + linux,code = <0x74>; + }; + + reset { + label = "reset"; + gpios = <&gpio0 11 1>; + linux,code = <0x198>; + }; + + aoss { + label = "aoss"; + gpios = <&gpio0 18 1>; + linux,code = <0x211>; + }; + + auto { + label = "mode"; + gpios = <&gpio0 7 0>; + linux,code = <0x100>; + linux,input-type = <5>; /* EV_SW */ + }; + + ap { + label = "ap"; + gpios = <&gpio0 6 0>; + linux,code = <0x100>; + linux,input-type = <5>; /* EV_SW */ + }; + + router { + label = "router"; + gpios = <&gpio0 10 0>; + linux,code = <0x100>; + linux,input-type = <5>; /* EV_SW */ + }; + }; + + gpio_poweroff { + compatible = "gpio-poweroff"; + gpios = <&gpio1 11 1>; + }; +}; diff --git a/target/linux/ramips/dts/WT1520-4M.dts b/target/linux/ramips/dts/WT1520-4M.dts new file mode 100644 index 0000000..1291320 --- /dev/null +++ b/target/linux/ramips/dts/WT1520-4M.dts @@ -0,0 +1,43 @@ +/dts-v1/; + +/include/ "WT1520.dtsi" + +/ { + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "w25q32"; + reg = <0 0>; + linux,modalias = "m25p80", "s25fl064k"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + }; + }; +}; diff --git a/target/linux/ramips/dts/WT1520-8M.dts b/target/linux/ramips/dts/WT1520-8M.dts new file mode 100644 index 0000000..999c84d --- /dev/null +++ b/target/linux/ramips/dts/WT1520-8M.dts @@ -0,0 +1,43 @@ +/dts-v1/; + +/include/ "WT1520.dtsi" + +/ { + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "w25q64"; + reg = <0 0>; + linux,modalias = "m25p80", "s25fl064k"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; +}; diff --git a/target/linux/ramips/dts/WT1520.dtsi b/target/linux/ramips/dts/WT1520.dtsi new file mode 100644 index 0000000..b8c4e0a --- /dev/null +++ b/target/linux/ramips/dts/WT1520.dtsi @@ -0,0 +1,46 @@ +/include/ "rt5350.dtsi" + +/ { + compatible = "NEXXWT1520", "ralink,rt5350-soc"; + model = "Nexx WT1520"; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x2000000>; + }; + + chosen { + bootargs = "console=ttyS1,57600"; + }; + + palmbus@10000000 { + uart@500 { + status = "okay"; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "jtag"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/WT3020-4M.dts b/target/linux/ramips/dts/WT3020-4M.dts new file mode 100644 index 0000000..6670a1c --- /dev/null +++ b/target/linux/ramips/dts/WT3020-4M.dts @@ -0,0 +1,102 @@ +/dts-v1/; + +/include/ "mt7620n.dtsi" + +/ { + compatible = "wt3020", "ralink,mt7620n-soc"; + model = "Nexx WT3020"; + + palmbus@10000000 { + gpio2: gpio@660 { + status = "okay"; + }; + + gpio3: gpio@688 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "w25q32"; + reg = <0 0>; + linux,modalias = "m25p80", "w25q32"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + }; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + ralink,port-map = "wllll"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pinctrl { + state_default: pinctrl0 { + default { + ralink,group = "ephy", "wled", "pa", "i2c", "wdt", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 1 1>; + linux,code = <0x198>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "wt3020:blue:power"; + gpios = <&gpio3 0 0>; + }; + }; +}; diff --git a/target/linux/ramips/dts/WT3020-8M.dts b/target/linux/ramips/dts/WT3020-8M.dts new file mode 100644 index 0000000..3abd8fe --- /dev/null +++ b/target/linux/ramips/dts/WT3020-8M.dts @@ -0,0 +1,102 @@ +/dts-v1/; + +/include/ "mt7620n.dtsi" + +/ { + compatible = "wt3020", "ralink,mt7620n-soc"; + model = "Nexx WT3020"; + + palmbus@10000000 { + gpio2: gpio@660 { + status = "okay"; + }; + + gpio3: gpio@688 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "w25q64"; + reg = <0 0>; + linux,modalias = "m25p80", "w25q64"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + ralink,port-map = "wllll"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pinctrl { + state_default: pinctrl0 { + default { + ralink,group = "ephy", "wled", "pa", "i2c", "wdt", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 1 1>; + linux,code = <0x198>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "wt3020:blue:power"; + gpios = <&gpio3 0 0>; + }; + }; +}; diff --git a/target/linux/ramips/dts/WZR-AGL300NH.dts b/target/linux/ramips/dts/WZR-AGL300NH.dts new file mode 100644 index 0000000..98b50ba --- /dev/null +++ b/target/linux/ramips/dts/WZR-AGL300NH.dts @@ -0,0 +1,143 @@ +/dts-v1/; + +/include/ "rt2880.dtsi" + +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "WZR-AGL300NH", "ralink,rt2880-soc"; + model = "Buffalo WZR-AGL300NH"; + + palmbus@300000 { + gpio0: gpio@600 { + status = "okay"; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "uartlite", "mdio"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "uboot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "uboot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + + ethernet@400000 { + status = "okay"; + mtd-mac-address = <&factory 0x4>; + + port@0 { + ralink,fixed-link = <1000 1 1 1>; + }; + + mdio-bus { + status = "okay"; + + phy0: ethernet-phy@0 { + phy-mode = "mii"; + reg = <0>; + }; + }; + }; + + rtl8366s { + compatible = "realtek,rtl8366s"; + gpio-sda = <&gpio0 1 0>; + gpio-sck = <&gpio0 2 0>; + }; + + wmac@480000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + wps { + label = "wps"; + gpios = <&gpio0 0 1>; + linux,code = <0x211>; + }; + + router { + label = "router_switch"; + gpios = <&gpio0 7 0>; + linux,code = <0x100>; + }; + + reset { + label = "reset"; + gpios = <&gpio0 9 1>; + linux,code = <0x198>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + router { + label = "wzr-agl300nh:green:router"; + gpios = <&gpio0 8 1>; + }; + + diag { + label = "wzr-agl300nh:red:diag"; + gpios = <&gpio0 12 1>; + }; + + security_g { + label = "wzr-agl300nh:orange:security_g"; + gpios = <&gpio0 11 1>; + }; + + security_n { + label = "wzr-agl300nh:orange:security_n"; + gpios = <&gpio0 13 1>; + }; + }; + + + pcibus0: pci@00440000 { + compatible = "ralink,rt288x-pci"; + reg = <0x00440000 0x20000>; + #address-cells = <1>; + #size-cells = <1>; + status = "ok"; + }; +}; diff --git a/target/linux/ramips/dts/X5.dts b/target/linux/ramips/dts/X5.dts new file mode 100644 index 0000000..dfaef3b --- /dev/null +++ b/target/linux/ramips/dts/X5.dts @@ -0,0 +1,138 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "X5", "ralink,rt5350-soc"; + model = "Poray X5"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "gd25q64"; + reg = <0 0>; + linux,modalias = "m25p80", "gd25q64"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + ralink,led_polarity = <1>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "x5:green:power"; + gpios = <&gpio0 13 1>; + }; + + 20 { + label = "x5:green:20"; + gpios = <&gpio0 12 1>; + }; + + 50 { + label = "x5:green:50"; + gpios = <&gpio0 11 1>; + }; + + 80 { + label = "x5:green:80"; + gpios = <&gpio0 7 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + bat { + label = "bat"; + gpios = <&gpio0 9 1>; + linux,code = <0x211>; + }; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + mode { + label = "mode"; + gpios = <&gpio0 14 1>; + linux,code = <0x100>; + linux,input-type = <5>; + }; + }; + + gpio_export { + compatible = "gpio-export"; + #size-cells = <0>; + + usb-mode { + gpio-export,name = "usb-mode"; + gpio-export,output = <0>; + gpios = <&gpio0 18 0>; + }; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + ralink,led-polarity = <1>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/X8.dts b/target/linux/ramips/dts/X8.dts new file mode 100644 index 0000000..9c1c046 --- /dev/null +++ b/target/linux/ramips/dts/X8.dts @@ -0,0 +1,99 @@ +/dts-v1/; + +/include/ "rt5350.dtsi" + +/ { + compatible = "X8", "ralink,rt5350-soc"; + model = "Poray X8"; + + palmbus@10000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "gd25q64"; + reg = <0 0>; + linux,modalias = "m25p80", "gd25q64"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "jtag", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + }; + + esw@10110000 { + ralink,portmap = <0x2f>; + ralink,led_polarity = <1>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "x8:green:power"; + gpios = <&gpio0 13 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + ralink,led-polarity = <1>; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/XDXRN502J.dts b/target/linux/ramips/dts/XDXRN502J.dts new file mode 100644 index 0000000..25d3613 --- /dev/null +++ b/target/linux/ramips/dts/XDXRN502J.dts @@ -0,0 +1,92 @@ +/dts-v1/; + +/include/ "rt3050.dtsi" + +/ { + compatible = "XDXRN502J", "ralink,rt3052-soc"; + model = "XDX RN502J"; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "spi", "i2c", "jtag", "rgmii", "mdio", "uartf"; + ralink,function = "gpio"; + }; + }; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x3b0000>; + }; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x28>; + }; + + esw@10110000 { + ralink,portmap = <0x3e>; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + gpio-leds { + compatible = "gpio-leds"; + + wifi { + label = "xdxrn502j:green:wifi"; + gpios = <&gpio0 7 1>; + }; + + power { + label = "xdxrn502j:green:power"; + gpios = <&gpio0 9 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + }; + + otg@101c0000 { + status = "okay"; + }; +}; diff --git a/target/linux/ramips/dts/Y1.dts b/target/linux/ramips/dts/Y1.dts new file mode 100644 index 0000000..4a64115 --- /dev/null +++ b/target/linux/ramips/dts/Y1.dts @@ -0,0 +1,49 @@ +/dts-v1/; + +/include/ "Y1.dtsi" + +/ { + compatible = "lenovo,Y1", "ralink,mt7620a-soc"; + model = "Lenovo Y1"; + + ethernet@10100000 { + pinctrl-names = "default"; + pinctrl-0 = <&ephy_pins>; + mtd-mac-address = <&factory 0x4>; + ralink,port-map = "llllw"; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power1 { + label = "y1:blue:power"; + gpios = <&gpio0 9 1>; + }; + + wlan1 { + label = "y1:blue:wifi"; + gpios = <&gpio3 0 1>; + }; + + wlan2 { + label = "y1:blue:wifi5g"; + gpios = <&gpio2 10 1>; + }; + + usb { + label = "y1:blue:usb"; + gpios = <&gpio2 12 1>; + }; + + lan { + label = "y1:blue:lan"; + gpios = <&gpio2 15 1>; + }; + + internet { + label = "y1:blue:internet"; + gpios = <&gpio2 11 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/Y1.dtsi b/target/linux/ramips/dts/Y1.dtsi new file mode 100644 index 0000000..62e37fc --- /dev/null +++ b/target/linux/ramips/dts/Y1.dtsi @@ -0,0 +1,109 @@ +/include/ "mt7620a.dtsi" + +/ { + chosen { + bootargs = "console=ttyS0,115200"; + }; + + palmbus@10000000 { + gpio0: gpio@600 { + status = "okay"; + }; + + gpio2: gpio@660 { + status = "okay"; + }; + + gpio3: gpio@688 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "w25q128"; + reg = <0 0>; + linux,modalias = "m25p80", "w25q128"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xfb0000>; + }; + }; + }; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + pcie@10140000 { + status = "okay"; + + pcie-bridge { + mt76@0,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 0x8000>; + mediatek,2ghz = <0>; + }; + }; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "uartf", "wled", "nd_sd"; + ralink,function = "gpio"; + }; + + pa { + ralink,group = "pa"; + ralink,function = "pa"; + }; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 11 1>; + linux,code = <0x198>; + }; + }; +}; diff --git a/target/linux/ramips/dts/Y1S.dts b/target/linux/ramips/dts/Y1S.dts new file mode 100644 index 0000000..f61280b --- /dev/null +++ b/target/linux/ramips/dts/Y1S.dts @@ -0,0 +1,85 @@ +/dts-v1/; + +/include/ "Y1.dtsi" + +/ { + compatible = "lenovo,Y1S", "ralink,mt7620a-soc"; + model = "Lenovo Y1S"; + + ethernet@10100000 { + status = "okay"; + mtd-mac-address = <&factory 0x4>; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii1_pins &rgmii2_pins &mdio_pins>; + ralink,port-map = "wllll"; + + port@4 { + status = "okay"; + phy-handle = <&phy4>; + phy-mode = "rgmii"; + }; + + port@5 { + status = "okay"; + phy-handle = <&phy5>; + phy-mode = "rgmii"; + }; + + mdio-bus { + status = "okay"; + + phy4: ethernet-phy@4 { + reg = <4>; + phy-mode = "rgmii"; + }; + + phy5: ethernet-phy@5 { + reg = <5>; + phy-mode = "rgmii"; + }; + }; + }; + + gsw@10110000 { + ralink,port4 = "gmac"; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power1 { + label = "y1s:yellow:power"; + gpios = <&gpio0 14 1>; + }; + + power2 { + label = "y1s:blue:power"; + gpios = <&gpio0 9 1>; + }; + + wlan1 { + label = "y1s:yellow:wifi"; + gpios = <&gpio3 0 1>; + }; + + wlan2 { + label = "y1s:blue:wifi"; + gpios = <&gpio2 10 1>; + }; + + usb1 { + label = "y1s:yellow:usb"; + gpios = <&gpio2 13 1>; + }; + + usb2 { + label = "y1s:blue:usb"; + gpios = <&gpio2 12 1>; + }; + + internet { + label = "y1s:blue:internet"; + gpios = <&gpio2 11 1>; + }; + }; +}; diff --git a/target/linux/ramips/dts/ZBT-WA05.dts b/target/linux/ramips/dts/ZBT-WA05.dts new file mode 100644 index 0000000..84974cf --- /dev/null +++ b/target/linux/ramips/dts/ZBT-WA05.dts @@ -0,0 +1,120 @@ +/dts-v1/; + +/include/ "mt7620n.dtsi" + +/ { + compatible = "zbtlink,zbt-wa05", "ralink,mt7620n-soc"; + model = "Zbtlink ZBT-WA05"; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + palmbus@10000000 { + gpio1: gpio@638 { + status = "okay"; + }; + + gpio2: gpio@660 { + status = "okay"; + }; + + gpio3: gpio@688 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + en25q64@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "w25q64"; + reg = <0 0>; + linux,modalias = "m25p80"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x760000>; + }; + }; + }; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + ralink,port-map = "wllll"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pinctrl { + state_default: pinctrl0 { + default { + ralink,group = "i2c", "spi refclk", "wled"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + power { + label = "zbt-wa05:blue:power"; + gpios = <&gpio1 14 1>; + }; + + usb { + label = "zbt-wa05:blue:usb"; + gpios = <&gpio1 15 0>; + }; + + air { + label = "zbt-wa05:blue:air"; + gpios = <&gpio3 0 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 1 1>; + linux,code = <0x198>; + }; + }; +}; diff --git a/target/linux/ramips/dts/ZBT-WG2626.dts b/target/linux/ramips/dts/ZBT-WG2626.dts new file mode 100644 index 0000000..6170454 --- /dev/null +++ b/target/linux/ramips/dts/ZBT-WG2626.dts @@ -0,0 +1,127 @@ +/dts-v1/; + +/include/ "mt7621.dtsi" + +/ { + compatible = "mediatek,mt7621-eval-board", "mediatek,mt7621-soc"; + model = "ZBT-WG2626"; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x1c000000>, <0x20000000 0x4000000>; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + sdhci@10130000 { + status = "okay"; + }; + + palmbus@1E000000 { + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "w25q128"; + reg = <0 0>; + linux,modalias = "m25p80"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0xfb0000>; + }; + + }; + }; + + i2c@900 { + compatible = "ralink,i2c-mt7621"; + reg = <0x900 0x100>; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c_pins>; + status = "okay"; + }; + }; + + pcie@1e140000 { + status = "okay"; + + pcie0 { + mt76@0,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 0x8000>; + mediatek,2ghz = <0>; + }; + }; + + pcie1 { + mt76@1,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + mediatek,mtd-eeprom = <&factory 0x0000>; + mediatek,5ghz = <0>; + }; + }; + }; + + ethernet@1e100000 { + mtd-mac-address = <&factory 0xe000>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 18 1>; + linux,code = <0x198>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "zbt-wg2626:green:status"; + gpios = <&gpio0 24 1>; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "wdt", "rgmii2", "wdt rst", "jtag", "mdio"; + ralink,function = "gpio"; + }; + }; + }; +}; diff --git a/target/linux/ramips/dts/ZBT-WR8305RT.dts b/target/linux/ramips/dts/ZBT-WR8305RT.dts new file mode 100644 index 0000000..8d21a2d --- /dev/null +++ b/target/linux/ramips/dts/ZBT-WR8305RT.dts @@ -0,0 +1,117 @@ +/dts-v1/; + +/include/ "mt7620n.dtsi" + +/ { + compatible = "zbtlink,zbt-wr8305rt", "ralink,mt7620n-soc"; + model = "Zbtlink ZBT-WR8305RT"; + + palmbus@10000000 { + gpio1: gpio@638 { + status = "okay"; + }; + + gpio3: gpio@688 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mx25l6405d"; + reg = <0 0>; + linux,modalias = "m25p80", "en25q64"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + ethernet@10100000 { + mtd-mac-address = <&factory 0x4>; + ralink,port-map = "llllw"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + pinctrl { + state_default: pinctrl0 { + ephy { + ralink,group = "ephy"; + ralink,function = "ephy"; + }; + + default { + ralink,group = "i2c", "uartf", "spi refclk", "wled"; + ralink,function = "gpio"; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + sys { + label = "zbt-wr8305rt:green:sys"; + gpios = <&gpio1 14 1>; + }; + + lan { + label = "zbt-wr8305rt:green:usb"; + gpios = <&gpio1 15 1>; + }; + + wifi { + label = "zbt-wr8305rt:green:wifi"; + gpios = <&gpio3 0 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 1 1>; + linux,code = <0x198>; + }; + }; +}; diff --git a/target/linux/ramips/dts/ZTE-Q7.dts b/target/linux/ramips/dts/ZTE-Q7.dts new file mode 100644 index 0000000..997349b --- /dev/null +++ b/target/linux/ramips/dts/ZTE-Q7.dts @@ -0,0 +1,113 @@ +/dts-v1/; + +/include/ "mt7620a.dtsi" + +/ { + compatible = "ZTE-Q7", "ralink,mt7620a-soc"; + model = "ZTE Q7"; + + palmbus@10000000 { + gpio0: gpio@600 { + status = "okay"; + }; + + gpio1: gpio@638 { + status = "okay"; + }; + + spi@b00 { + status = "okay"; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "en25q64"; + reg = <0 0>; + linux,modalias = "m25p80", "en25q64"; + spi-max-frequency = <10000000>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + }; + + partition@50000 { + label = "firmware"; + reg = <0x50000 0x7b0000>; + }; + }; + }; + }; + + pinctrl { + state_default: pinctrl0 { + gpio { + ralink,group = "i2c", "uartf", "rgmii1", "rgmii2", "ephy", "wled", "nd_sd"; + ralink,function = "gpio"; + }; + }; + }; + + ethernet@10100000 { + pinctrl-names = "default"; + pinctrl-0 = <&ephy_pins>; + mtd-mac-address = <&factory 0x4>; + ralink,port-map = "wllll"; + }; + + wmac@10180000 { + ralink,mtd-eeprom = <&factory 0>; + }; + + sdhci@10130000 { + status = "okay"; + }; + + ehci@101c0000 { + status = "okay"; + }; + + ohci@101c1000 { + status = "okay"; + }; + + gpio-leds { + compatible = "gpio-leds"; + + statred { + label = "zte-q7:red:status"; + gpios = <&gpio0 13 1>; + }; + + statblue { + label = "zte-q7:blue:status"; + gpios = <&gpio0 9 1>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio1 2 1>; + linux,code = <0x198>; + }; + }; +}; diff --git a/target/linux/ramips/dts/mt7620a.dtsi b/target/linux/ramips/dts/mt7620a.dtsi new file mode 100644 index 0000000..026e745 --- /dev/null +++ b/target/linux/ramips/dts/mt7620a.dtsi @@ -0,0 +1,506 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "ralink,mtk7620a-soc"; + + cpus { + cpu@0 { + compatible = "mips,mips24KEc"; + }; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + cpuintc: cpuintc@0 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + palmbus@10000000 { + compatible = "palmbus"; + reg = <0x10000000 0x200000>; + ranges = <0x0 0x10000000 0x1FFFFF>; + + #address-cells = <1>; + #size-cells = <1>; + + sysc@0 { + compatible = "ralink,mt7620a-sysc", "ralink,rt3050-sysc"; + reg = <0x0 0x100>; + }; + + timer@100 { + compatible = "ralink,mt7620a-timer", "ralink,rt2880-timer"; + reg = <0x100 0x20>; + + interrupt-parent = <&intc>; + interrupts = <1>; + }; + + watchdog@120 { + compatible = "ralink,mt7620a-wdt", "ralink,rt2880-wdt"; + reg = <0x120 0x10>; + + resets = <&rstctrl 8>; + reset-names = "wdt"; + + interrupt-parent = <&intc>; + interrupts = <1>; + }; + + intc: intc@200 { + compatible = "ralink,mt7620a-intc", "ralink,rt2880-intc"; + reg = <0x200 0x100>; + + resets = <&rstctrl 19>; + reset-names = "intc"; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpuintc>; + interrupts = <2>; + }; + + memc@300 { + compatible = "ralink,mt7620a-memc", "ralink,rt3050-memc"; + reg = <0x300 0x100>; + + resets = <&rstctrl 20>; + reset-names = "mc"; + + interrupt-parent = <&intc>; + interrupts = <3>; + }; + + uart@500 { + compatible = "ralink,mt7620a-uart", "ralink,rt2880-uart", "ns16550a"; + reg = <0x500 0x100>; + + resets = <&rstctrl 12>; + reset-names = "uart"; + + interrupt-parent = <&intc>; + interrupts = <5>; + + reg-shift = <2>; + + status = "disabled"; + }; + + gpio0: gpio@600 { + compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio"; + reg = <0x600 0x34>; + + resets = <&rstctrl 13>; + reset-names = "pio"; + + interrupt-parent = <&intc>; + interrupts = <6>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <0>; + ralink,num-gpios = <24>; + ralink,register-map = [ 00 04 08 0c + 20 24 28 2c + 30 34 ]; + }; + + gpio1: gpio@638 { + compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio"; + reg = <0x638 0x24>; + + interrupt-parent = <&intc>; + interrupts = <6>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <24>; + ralink,num-gpios = <16>; + ralink,register-map = [ 00 04 08 0c + 10 14 18 1c + 20 24 ]; + + status = "disabled"; + }; + + gpio2: gpio@660 { + compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio"; + reg = <0x660 0x24>; + + interrupt-parent = <&intc>; + interrupts = <6>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <40>; + ralink,num-gpios = <32>; + ralink,register-map = [ 00 04 08 0c + 10 14 18 1c + 20 24 ]; + + status = "disabled"; + }; + + gpio3: gpio@688 { + compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio"; + reg = <0x688 0x24>; + + interrupt-parent = <&intc>; + interrupts = <6>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <72>; + ralink,num-gpios = <1>; + ralink,register-map = [ 00 04 08 0c + 10 14 18 1c + 20 24 ]; + + status = "disabled"; + }; + + i2c@900 { + compatible = "link,mt7620a-i2c", "ralink,rt2880-i2c"; + reg = <0x900 0x100>; + + resets = <&rstctrl 16>; + reset-names = "i2c"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + pinctrl-names = "default"; + pinctrl-0 = <&i2c_pins>; + }; + + i2s@a00 { + compatible = "ralink,mt7620a-i2s"; + reg = <0xa00 0x100>; + + resets = <&rstctrl 17>; + reset-names = "i2s"; + + interrupt-parent = <&intc>; + interrupts = <10>; + + dmas = <&gdma 4>, + <&gdma 5>; + dma-names = "tx", "rx"; + + status = "disabled"; + }; + + spi@b00 { + compatible = "ralink,mt7620a-spi", "ralink,rt2880-spi"; + reg = <0xb00 0x100>; + + resets = <&rstctrl 18>; + reset-names = "spi"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + pinctrl-names = "default"; + pinctrl-0 = <&spi_pins>; + }; + + uartlite@c00 { + compatible = "ralink,mt7620a-uart", "ralink,rt2880-uart", "ns16550a"; + reg = <0xc00 0x100>; + + resets = <&rstctrl 19>; + reset-names = "uartl"; + + interrupt-parent = <&intc>; + interrupts = <12>; + + reg-shift = <2>; + + pinctrl-names = "default"; + pinctrl-0 = <&uartlite_pins>; + }; + + systick@d00 { + compatible = "ralink,mt7620a-systick", "ralink,cevt-systick"; + reg = <0xd00 0x10>; + + resets = <&rstctrl 28>; + reset-names = "intc"; + + interrupt-parent = <&cpuintc>; + interrupts = <7>; + }; + + pcm@2000 { + compatible = "ralink,mt7620a-pcm"; + reg = <0x2000 0x800>; + + resets = <&rstctrl 11>; + reset-names = "pcm"; + + interrupt-parent = <&intc>; + interrupts = <4>; + + status = "disabled"; + }; + + gdma: gdma@2800 { + compatible = "ralink,mt7620a-gdma", "ralink,rt2880-gdma"; + reg = <0x2800 0x800>; + + resets = <&rstctrl 14>; + reset-names = "dma"; + + interrupt-parent = <&intc>; + interrupts = <7>; + + #dma-cells = <1>; + #dma-channels = <16>; + #dma-requests = <16>; + + status = "disabled"; + }; + }; + + pinctrl { + compatible = "ralink,rt2880-pinmux"; + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinctrl0 { + }; + + pcm_i2s_pins: pcm_i2s { + pcm_i2s { + ralink,group = "uartf"; + ralink,function = "pcm i2s"; + }; + }; + + uartf_gpio_pins: uartf_gpio { + uartf_gpio { + ralink,group = "uartf"; + ralink,function = "gpio uartf"; + }; + }; + + spi_pins: spi { + spi { + ralink,group = "spi"; + ralink,function = "spi"; + }; + }; + + i2c_pins: i2c { + i2c { + ralink,group = "i2c"; + ralink,function = "i2c"; + }; + }; + + uartlite_pins: uartlite { + uart { + ralink,group = "uartlite"; + ralink,function = "uartlite"; + }; + }; + + mdio_pins: mdio { + mdio { + ralink,group = "mdio"; + ralink,function = "mdio"; + }; + }; + + ephy_pins: ephy { + ephy { + ralink,group = "ephy"; + ralink,function = "ephy"; + }; + }; + + wled_pins: wled { + wled { + ralink,group = "wled"; + ralink,function = "wled"; + }; + }; + + rgmii1_pins: rgmii1 { + rgmii1 { + ralink,group = "rgmii1"; + ralink,function = "rgmii1"; + }; + }; + + rgmii2_pins: rgmii2 { + rgmii2 { + ralink,group = "rgmii2"; + ralink,function = "rgmii2"; + }; + }; + + pcie_pins: pcie { + pcie { + ralink,group = "pcie"; + ralink,function = "pcie rst"; + }; + }; + }; + + rstctrl: rstctrl { + compatible = "ralink,mt7620a-reset", "ralink,rt2880-reset"; + #reset-cells = <1>; + }; + + usbphy: usbphy { + compatible = "ralink,mt7620a-usbphy"; + #phy-cells = <1>; + + resets = <&rstctrl 22 &rstctrl 25>; + reset-names = "host", "device"; + }; + + ethernet@10100000 { + compatible = "ralink,mt7620a-eth"; + reg = <0x10100000 10000>; + + #address-cells = <1>; + #size-cells = <0>; + + interrupt-parent = <&cpuintc>; + interrupts = <5>; + + resets = <&rstctrl 21 &rstctrl 23>; + reset-names = "fe", "esw"; + + port@4 { + compatible = "ralink,mt7620a-gsw-port", "ralink,eth-port"; + reg = <4>; + + status = "disabled"; + }; + + port@5 { + compatible = "ralink,mt7620a-gsw-port", "ralink,eth-port"; + reg = <5>; + + status = "disabled"; + }; + + mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + }; + + gsw@10110000 { + compatible = "ralink,mt7620a-gsw"; + reg = <0x10110000 8000>; + + resets = <&rstctrl 23>; + reset-names = "esw"; + + interrupt-parent = <&intc>; + interrupts = <17>; + }; + + sdhci@10130000 { + compatible = "ralink,mt7620-sdhci"; + reg = <0x10130000 4000>; + + interrupt-parent = <&intc>; + interrupts = <14>; + + status = "disabled"; + }; + + ehci@101c0000 { + compatible = "ralink,rt3xxx-ehci"; + reg = <0x101c0000 0x1000>; + + interrupt-parent = <&intc>; + interrupts = <18>; + + phys = <&usbphy 1>; + phy-names = "usb"; + + status = "disabled"; + }; + + ohci@101c1000 { + compatible = "ralink,rt3xxx-ohci"; + reg = <0x101c1000 0x1000>; + + interrupt-parent = <&intc>; + interrupts = <18>; + + phys = <&usbphy 1>; + phy-names = "usb"; + + status = "disabled"; + }; + + pcie@10140000 { + compatible = "mediatek,mt7620-pci"; + reg = <0x10140000 0x100 + 0x10142000 0x100>; + + #address-cells = <3>; + #size-cells = <2>; + + resets = <&rstctrl 26>; + reset-names = "pcie0"; + + interrupt-parent = <&cpuintc>; + interrupts = <4>; + + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pins>; + + device_type = "pci"; + + bus-range = <0 255>; + ranges = < + 0x02000000 0 0x00000000 0x20000000 0 0x10000000 /* pci memory */ + 0x01000000 0 0x00000000 0x10160000 0 0x00010000 /* io space */ + >; + + status = "disabled"; + + pcie-bridge { + reg = <0x0000 0 0 0 0>; + + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + }; + }; + + wmac@10180000 { + compatible = "ralink,rt7620-wmac", "ralink,rt2880-wmac"; + reg = <0x10180000 40000>; + + interrupt-parent = <&cpuintc>; + interrupts = <6>; + + ralink,eeprom = "soc_wmac.eeprom"; + }; +}; diff --git a/target/linux/ramips/dts/mt7620n.dtsi b/target/linux/ramips/dts/mt7620n.dtsi new file mode 100644 index 0000000..b1586ec --- /dev/null +++ b/target/linux/ramips/dts/mt7620n.dtsi @@ -0,0 +1,305 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "ralink,mtk7620n-soc"; + + cpus { + cpu@0 { + compatible = "mips,mips24KEc"; + }; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + cpuintc: cpuintc@0 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + palmbus@10000000 { + compatible = "palmbus"; + reg = <0x10000000 0x200000>; + ranges = <0x0 0x10000000 0x1FFFFF>; + + #address-cells = <1>; + #size-cells = <1>; + + sysc@0 { + compatible = "ralink,mt7620a-sysc", "ralink,rt3050-sysc"; + reg = <0x0 0x100>; + }; + + timer@100 { + compatible = "ralink,mt7620a-timer", "ralink,rt2880-timer"; + reg = <0x100 0x20>; + + interrupt-parent = <&intc>; + interrupts = <1>; + }; + + watchdog@120 { + compatible = "ralink,mt7620a-wdt", "ralink,rt2880-wdt"; + reg = <0x120 0x10>; + + resets = <&rstctrl 8>; + reset-names = "wdt"; + + interrupt-parent = <&intc>; + interrupts = <1>; + }; + + intc: intc@200 { + compatible = "ralink,mt7620a-intc", "ralink,rt2880-intc"; + reg = <0x200 0x100>; + + resets = <&rstctrl 19>; + reset-names = "intc"; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpuintc>; + interrupts = <2>; + }; + + memc@300 { + compatible = "ralink,mt7620a-memc", "ralink,rt3050-memc"; + reg = <0x300 0x100>; + + resets = <&rstctrl 20>; + reset-names = "mc"; + + interrupt-parent = <&intc>; + interrupts = <3>; + }; + + gpio0: gpio@600 { + compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio"; + reg = <0x600 0x34>; + + resets = <&rstctrl 13>; + reset-names = "pio"; + + interrupt-parent = <&intc>; + interrupts = <6>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <0>; + ralink,num-gpios = <24>; + ralink,register-map = [ 00 04 08 0c + 20 24 28 2c + 30 34 ]; + }; + + gpio1: gpio@638 { + compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio"; + reg = <0x638 0x24>; + + interrupt-parent = <&intc>; + interrupts = <6>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <24>; + ralink,num-gpios = <16>; + ralink,register-map = [ 00 04 08 0c + 10 14 18 1c + 20 24 ]; + + status = "disabled"; + }; + + gpio2: gpio@660 { + compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio"; + reg = <0x660 0x24>; + + interrupt-parent = <&intc>; + interrupts = <6>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <40>; + ralink,num-gpios = <32>; + ralink,register-map = [ 00 04 08 0c + 10 14 18 1c + 20 24 ]; + + status = "disabled"; + }; + + gpio3: gpio@688 { + compatible = "ralink,mt7620a-gpio", "ralink,rt2880-gpio"; + reg = <0x688 0x24>; + + interrupt-parent = <&intc>; + interrupts = <6>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <72>; + ralink,num-gpios = <1>; + ralink,register-map = [ 00 04 08 0c + 10 14 18 1c + 20 24 ]; + + status = "disabled"; + }; + + spi@b00 { + compatible = "ralink,mt7620a-spi", "ralink,rt2880-spi"; + reg = <0xb00 0x100>; + + resets = <&rstctrl 18>; + reset-names = "spi"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + pinctrl-names = "default"; + pinctrl-0 = <&spi_pins>; + }; + + uartlite@c00 { + compatible = "ralink,mt7620a-uart", "ralink,rt2880-uart", "ns16550a"; + reg = <0xc00 0x100>; + + resets = <&rstctrl 19>; + reset-names = "uartl"; + + interrupt-parent = <&intc>; + interrupts = <12>; + + reg-shift = <2>; + + pinctrl-names = "default"; + pinctrl-0 = <&uartlite_pins>; + }; + + systick@d00 { + compatible = "ralink,mt7620a-systick", "ralink,cevt-systick"; + reg = <0xd00 0x10>; + + resets = <&rstctrl 28>; + reset-names = "intc"; + + interrupt-parent = <&cpuintc>; + interrupts = <7>; + }; + }; + + pinctrl { + compatible = "ralink,rt2880-pinmux"; + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinctrl0 { + }; + + spi_pins: spi { + spi { + ralink,group = "spi"; + ralink,function = "spi"; + }; + }; + + uartlite_pins: uartlite { + uart { + ralink,group = "uartlite"; + ralink,function = "uartlite"; + }; + }; + }; + + rstctrl: rstctrl { + compatible = "ralink,mt7620a-reset", "ralink,rt2880-reset"; + #reset-cells = <1>; + }; + + usbphy: usbphy { + compatible = "ralink,mt7620a-usbphy"; + #phy-cells = <1>; + + resets = <&rstctrl 22 &rstctrl 25>; + reset-names = "host", "device"; + }; + + ethernet@10100000 { + compatible = "ralink,mt7620a-eth"; + reg = <0x10100000 10000>; + + #address-cells = <1>; + #size-cells = <0>; + + interrupt-parent = <&cpuintc>; + interrupts = <5>; + + resets = <&rstctrl 21 &rstctrl 23>; + reset-names = "fe", "esw"; + + mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + }; + + gsw@10110000 { + compatible = "ralink,mt7620a-gsw"; + reg = <0x10110000 8000>; + + resets = <&rstctrl 23>; + reset-names = "esw"; + + interrupt-parent = <&intc>; + interrupts = <17>; + ralink,port4 = "gmac"; + }; + + ehci@101c0000 { + compatible = "ralink,rt3xxx-ehci"; + reg = <0x101c0000 0x1000>; + + interrupt-parent = <&intc>; + interrupts = <18>; + + phys = <&usbphy 1>; + phy-names = "usb"; + + status = "disabled"; + }; + + ohci@101c1000 { + compatible = "ralink,rt3xxx-ohci"; + reg = <0x101c1000 0x1000>; + + phys = <&usbphy 1>; + phy-names = "usb"; + + interrupt-parent = <&intc>; + interrupts = <18>; + + status = "disabled"; + }; + + wmac@10180000 { + compatible = "ralink,rt7620-wmac", "ralink,rt2880-wmac"; + reg = <0x10180000 40000>; + + interrupt-parent = <&cpuintc>; + interrupts = <6>; + + ralink,eeprom = "soc_wmac.eeprom"; + }; +}; diff --git a/target/linux/ramips/dts/mt7621.dtsi b/target/linux/ramips/dts/mt7621.dtsi new file mode 100644 index 0000000..fd2e100 --- /dev/null +++ b/target/linux/ramips/dts/mt7621.dtsi @@ -0,0 +1,345 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mediatek,mtk7621-soc"; + + cpus { + cpu@0 { + compatible = "mips,mips1004Kc"; + }; + + cpu@1 { + compatible = "mips,mips1004Kc"; + }; + }; + + cpuintc: cpuintc@0 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + palmbus@1E000000 { + compatible = "palmbus"; + reg = <0x1E000000 0x100000>; + ranges = <0x0 0x1E000000 0x0FFFFF>; + + #address-cells = <1>; + #size-cells = <1>; + + sysc@0 { + compatible = "mtk,mt7621-sysc"; + reg = <0x0 0x100>; + }; + + wdt@100 { + compatible = "mtk,mt7621-wdt"; + reg = <0x100 0x100>; + }; + + gpio@600 { + #address-cells = <1>; + #size-cells = <0>; + + compatible = "mtk,mt7621-gpio"; + reg = <0x600 0x100>; + + gpio0: bank@0 { + reg = <0>; + compatible = "mtk,mt7621-gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio1: bank@1 { + reg = <1>; + compatible = "mtk,mt7621-gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio2: bank@2 { + reg = <2>; + compatible = "mtk,mt7621-gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + memc@5000 { + compatible = "mtk,mt7621-memc"; + reg = <0x300 0x100>; + }; + + uartlite@c00 { + compatible = "ns16550a"; + reg = <0xc00 0x100>; + + interrupt-parent = <&gic>; + interrupts = <26>; + + reg-shift = <2>; + reg-io-width = <4>; + no-loopback-test; + }; + + spi@b00 { + status = "okay"; + + compatible = "ralink,mt7621-spi"; + reg = <0xb00 0x100>; + + resets = <&rstctrl 18>; + reset-names = "spi"; + + #address-cells = <1>; + #size-cells = <0>; + + pinctrl-names = "default"; + pinctrl-0 = <&spi_pins>; + + m25p80@0 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0 0>; + spi-max-frequency = <10000000>; + m25p,chunked-io = <32>; + }; + }; + }; + + pinctrl { + compatible = "ralink,rt2880-pinmux"; + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinctrl0 { + }; + + spi_pins: spi { + spi { + ralink,group = "spi"; + ralink,function = "spi"; + }; + }; + + i2c_pins: i2c { + i2c { + ralink,group = "i2c"; + ralink,function = "i2c"; + }; + }; + + uart1_pins: uart1 { + uart1 { + ralink,group = "uart1"; + ralink,function = "uart1"; + }; + }; + + uart2_pins: uart2 { + uart2 { + ralink,group = "uart2"; + ralink,function = "uart2"; + }; + }; + + uart3_pins: uart3 { + uart3 { + ralink,group = "uart3"; + ralink,function = "uart3"; + }; + }; + + rgmii1_pins: rgmii1 { + rgmii1 { + ralink,group = "rgmii1"; + ralink,function = "rgmii1"; + }; + }; + + rgmii2_pins: rgmii2 { + rgmii2 { + ralink,group = "rgmii2"; + ralink,function = "rgmii2"; + }; + }; + + mdio_pins: mdio { + mdio { + ralink,group = "mdio"; + ralink,function = "mdio"; + }; + }; + + pcie_pins: pcie { + pcie { + ralink,group = "pcie"; + ralink,function = "pcie rst"; + }; + }; + + nand_pins: nand { + spi-nand { + ralink,group = "spi"; + ralink,function = "nand1"; + }; + + sdhci-nand { + ralink,group = "sdhci"; + ralink,function = "nand2"; + }; + }; + + sdhci_pins: sdhci { + sdhci { + ralink,group = "sdhci"; + ralink,function = "sdhci"; + }; + }; + }; + + rstctrl: rstctrl { + compatible = "ralink,rt2880-reset"; + #reset-cells = <1>; + }; + + sdhci@1E130000 { + compatible = "ralink,mt7620-sdhci"; + reg = <0x1E130000 4000>; + + interrupt-parent = <&gic>; + interrupts = <20>; + }; + + xhci@1E1C0000 { + status = "disabled"; + + compatible = "xhci-platform"; + reg = <0x1E1C0000 4000>; + + interrupt-parent = <&gic>; + interrupts = <22>; + }; + + gic: gic@1fbc0000 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "ralink,mt7621-gic"; + reg = < 0x1fbc0000 0x80 /* gic */ + 0x1fbf0000 0x8000 /* cpc */ + 0x1fbf8000 0x8000 /* gpmc */ + >; + }; + + nand@1e003000 { + compatible = "mtk,mt7621-nand"; + bank-width = <2>; + reg = <0x1e003000 0x800 + 0x1e003800 0x800>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "uboot"; + reg = <0x00000 0x80000>; /* 64 KB */ + }; + + partition@80000 { + label = "uboot_env"; + reg = <0x80000 0x80000>; /* 64 KB */ + }; + + partition@100000 { + label = "factory"; + reg = <0x100000 0x40000>; + }; + + partition@140000 { + label = "rootfs"; + reg = <0x140000 0xec0000>; + }; + }; + + ethernet@1e100000 { + compatible = "ralink,mt7621-eth"; + reg = <0x1e100000 10000>; + + #address-cells = <1>; + #size-cells = <0>; + + resets = <&rstctrl 6 &rstctrl 23>; + reset-names = "fe", "eth"; + + interrupt-parent = <&gic>; + interrupts = <3>; + + mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + phy1f: ethernet-phy@1f { + reg = <0x1f>; + phy-mode = "rgmii"; + }; + }; + }; + + gsw@1e110000 { + compatible = "ralink,mt7620a-gsw"; + reg = <0x1e110000 8000>; + interrupt-parent = <&gic>; + interrupts = <23>; + }; + + pcie@1e140000 { + compatible = "mediatek,mt7621-pci"; + reg = <0x1e140000 0x100 + 0x1e142000 0x100>; + + #address-cells = <3>; + #size-cells = <2>; + + pinctrl-names = "default"; + pinctrl-0 = <&pcie_pins>; + + device_type = "pci"; + + bus-range = <0 255>; + ranges = < + 0x02000000 0 0x00000000 0x60000000 0 0x10000000 /* pci memory */ + 0x01000000 0 0x00000000 0x1e160000 0 0x00010000 /* io space */ + >; + + status = "okay"; + + pcie0 { + reg = <0x0000 0 0 0 0>; + + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + }; + + pcie1 { + reg = <0x0800 0 0 0 0>; + + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + }; + + pcie2 { + reg = <0x1000 0 0 0 0>; + + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + }; + }; +}; diff --git a/target/linux/ramips/dts/mt7628an.dtsi b/target/linux/ramips/dts/mt7628an.dtsi new file mode 100644 index 0000000..b0d9d80 --- /dev/null +++ b/target/linux/ramips/dts/mt7628an.dtsi @@ -0,0 +1,441 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "ralink,mtk7628an-soc"; + + cpus { + cpu@0 { + compatible = "mips,mips24KEc"; + }; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + cpuintc: cpuintc@0 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + palmbus@10000000 { + compatible = "palmbus"; + reg = <0x10000000 0x200000>; + ranges = <0x0 0x10000000 0x1FFFFF>; + + #address-cells = <1>; + #size-cells = <1>; + + sysc@0 { + compatible = "ralink,mt7620a-sysc"; + reg = <0x0 0x100>; + }; + + watchdog@120 { + compatible = "ralink,mt7628an-wdt", "mtk,mt7621-wdt"; + reg = <0x120 0x10>; + + resets = <&rstctrl 8>; + reset-names = "wdt"; + + interrupt-parent = <&intc>; + interrupts = <24>; + }; + + intc: intc@200 { + compatible = "ralink,mt7628an-intc", "ralink,rt2880-intc"; + reg = <0x200 0x100>; + + resets = <&rstctrl 9>; + reset-names = "intc"; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpuintc>; + interrupts = <2>; + + ralink,intc-registers = <0x9c 0xa0 + 0x6c 0xa4 + 0x80 0x78>; + }; + + memc@300 { + compatible = "ralink,mt7620a-memc", "ralink,rt3050-memc"; + reg = <0x300 0x100>; + + resets = <&rstctrl 20>; + reset-names = "mc"; + + interrupt-parent = <&intc>; + interrupts = <3>; + }; + + gpio@600 { + #address-cells = <1>; + #size-cells = <0>; + + compatible = "mtk,mt7628-gpio", "mtk,mt7621-gpio"; + reg = <0x600 0x100>; + + interrupt-parent = <&intc>; + interrupts = <6>; + + gpio0: bank@0 { + reg = <0>; + compatible = "mtk,mt7621-gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio1: bank@1 { + reg = <1>; + compatible = "mtk,mt7621-gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio2: bank@2 { + reg = <2>; + compatible = "mtk,mt7621-gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + i2c@900 { + compatible = "mediatek,mt7628-i2c"; + reg = <0x900 0x100>; + + resets = <&rstctrl 16>; + reset-names = "i2c"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + pinctrl-names = "default"; + pinctrl-0 = <&i2c_pins>; + }; + + i2s@a00 { + compatible = "ralink,mt7620a-i2s"; + reg = <0xa00 0x100>; + + resets = <&rstctrl 17>; + reset-names = "i2s"; + + interrupt-parent = <&intc>; + interrupts = <10>; + + dmas = <&gdma 2>, + <&gdma 3>; + dma-names = "tx", "rx"; + + status = "disabled"; + }; + + spi@b00 { + compatible = "ralink,mt7621-spi"; + reg = <0xb00 0x100>; + + resets = <&rstctrl 18>; + reset-names = "spi"; + + #address-cells = <1>; + #size-cells = <0>; + + pinctrl-names = "default"; + pinctrl-0 = <&spi_pins>; + + status = "disabled"; + }; + + uartlite@c00 { + compatible = "ns16550a"; + reg = <0xc00 0x100>; + + reg-shift = <2>; + reg-io-width = <4>; + no-loopback-test; + + resets = <&rstctrl 12>; + reset-names = "uartl"; + + interrupt-parent = <&intc>; + interrupts = <20>; + + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + }; + + uart1@d00 { + compatible = "ns16550a"; + reg = <0xd00 0x100>; + + reg-shift = <2>; + reg-io-width = <4>; + no-loopback-test; + + resets = <&rstctrl 19>; + reset-names = "uart1"; + + interrupt-parent = <&intc>; + interrupts = <21>; + + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + + status = "disabled"; + }; + + uart2@e00 { + compatible = "ns16550a"; + reg = <0xe00 0x100>; + + reg-shift = <2>; + reg-io-width = <4>; + no-loopback-test; + + resets = <&rstctrl 20>; + reset-names = "uart2"; + + interrupt-parent = <&intc>; + interrupts = <22>; + + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + + status = "disabled"; + }; + + pwm@5000 { + compatible = "mediatek,mt7628-pwm"; + reg = <0x5000 0x1000>; + + resets = <&rstctrl 31>; + reset-names = "pwm"; + + pinctrl-names = "default"; + pinctrl-0 = <&pwm0_pins>, <&pwm1_pins>; + + status = "disabled"; + }; + + pcm@2000 { + compatible = "ralink,mt7620a-pcm"; + reg = <0x2000 0x800>; + + resets = <&rstctrl 11>; + reset-names = "pcm"; + + interrupt-parent = <&intc>; + interrupts = <4>; + + status = "disabled"; + }; + + gdma: gdma@2800 { + compatible = "ralink,mt7620a-gdma", "ralink,rt2880-gdma"; + reg = <0x2800 0x800>; + + resets = <&rstctrl 14>; + reset-names = "dma"; + + interrupt-parent = <&intc>; + interrupts = <7>; + + #dma-cells = <1>; + #dma-channels = <16>; + #dma-requests = <16>; + + status = "disabled"; + }; + }; + + pinctrl { + compatible = "ralink,rt2880-pinmux"; + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinctrl0 { + }; + + spi_pins: spi { + spi { + ralink,group = "spi"; + ralink,function = "spi"; + }; + }; + + spi_cs1_pins: spi_cs1 { + spi_cs1 { + ralink,group = "spi cs1"; + ralink,function = "spi cs1"; + }; + }; + + i2c_pins: i2c { + i2c { + ralink,group = "i2c"; + ralink,function = "i2c"; + }; + }; + + uart0_pins: uartlite { + uartlite { + ralink,group = "uart0"; + ralink,function = "uart0"; + }; + }; + + uart1_pins: uart1 { + uart1 { + ralink,group = "uart1"; + ralink,function = "uart1"; + }; + }; + + uart2_pins: uart2 { + uart2 { + ralink,group = "uart2"; + ralink,function = "uart2"; + }; + }; + + sdxc_pins: sdxc { + sdxc { + ralink,group = "sdmode"; + ralink,function = "sdxc"; + }; + }; + + pwm0_pins: pwm0 { + pwm0 { + ralink,group = "pwm0"; + ralink,function = "pwm0"; + }; + }; + + pwm1_pins: pwm1 { + pwm1 { + ralink,group = "pwm1"; + ralink,function = "pwm1"; + }; + }; + + pcm_i2s_pins: i2s { + i2s { + ralink,group = "i2s"; + ralink,function = "pcm"; + }; + }; + }; + + rstctrl: rstctrl { + compatible = "ralink,mt7620a-reset", "ralink,rt2880-reset"; + #reset-cells = <1>; + }; + + usbphy: usbphy { + compatible = "ralink,mt7628an-usbphy", "ralink,mt7620a-usbphy"; + #phy-cells = <1>; + + resets = <&rstctrl 22>; + reset-names = "host"; + }; + + sdhci@10130000 { + compatible = "ralink,mt7620-sdhci"; + reg = <0x10130000 4000>; + + interrupt-parent = <&intc>; + interrupts = <14>; + + pinctrl-names = "default"; + pinctrl-0 = <&sdxc_pins>; + + status = "disabled"; + }; + + ehci@101c0000 { + compatible = "ralink,rt3xxx-ehci"; + reg = <0x101c0000 0x1000>; + + phys = <&usbphy 1>; + phy-names = "usb"; + + interrupt-parent = <&intc>; + interrupts = <18>; + }; + + ohci@101c1000 { + compatible = "ralink,rt3xxx-ohci"; + reg = <0x101c1000 0x1000>; + + phys = <&usbphy 1>; + phy-names = "usb"; + + interrupt-parent = <&intc>; + interrupts = <18>; + }; + + ethernet@10100000 { + compatible = "ralink,rt5350-eth"; + reg = <0x10100000 10000>; + + interrupt-parent = <&cpuintc>; + interrupts = <5>; + + resets = <&rstctrl 21 &rstctrl 23>; + reset-names = "fe", "esw"; + }; + + esw@10110000 { + compatible = "ralink,rt3050-esw"; + reg = <0x10110000 8000>; + + resets = <&rstctrl 23>; + reset-names = "esw"; + + interrupt-parent = <&intc>; + interrupts = <17>; + }; + + pcie@10140000 { + compatible = "mediatek,mt7620-pci"; + reg = <0x10140000 0x100 + 0x10142000 0x100>; + + #address-cells = <3>; + #size-cells = <2>; + + resets = <&rstctrl 26>; + reset-names = "pcie0"; + + interrupt-parent = <&cpuintc>; + interrupts = <4>; + + status = "disabled"; + + device_type = "pci"; + + bus-range = <0 255>; + ranges = < + 0x02000000 0 0x00000000 0x20000000 0 0x10000000 /* pci memory */ + 0x01000000 0 0x00000000 0x10160000 0 0x00010000 /* io space */ + >; + + pcie-bridge { + reg = <0x0000 0 0 0 0>; + + #address-cells = <3>; + #size-cells = <2>; + + device_type = "pci"; + }; + }; +}; diff --git a/target/linux/ramips/dts/rt2880.dtsi b/target/linux/ramips/dts/rt2880.dtsi new file mode 100644 index 0000000..c6dfe9a --- /dev/null +++ b/target/linux/ramips/dts/rt2880.dtsi @@ -0,0 +1,194 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "ralink,rt2880-soc"; + + cpus { + cpu@0 { + compatible = "mips,mips24KEc"; + }; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + cpuintc: cpuintc@0 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + palmbus@300000 { + compatible = "palmbus"; + reg = <0x300000 0x200000>; + ranges = <0x0 0x300000 0x1FFFFF>; + + #address-cells = <1>; + #size-cells = <1>; + + sysc@0 { + compatible = "ralink,rt2880-sysc"; + reg = <0x000 0x100>; + }; + + timer@100 { + compatible = "ralink,rt2880-timer"; + reg = <0x100 0x20>; + + interrupt-parent = <&intc>; + interrupts = <1>; + + status = "disabled"; + }; + + watchdog@120 { + compatible = "ralink,rt2880-wdt"; + reg = <0x120 0x10>; + }; + + intc: intc@200 { + compatible = "ralink,rt2880-intc"; + reg = <0x200 0x100>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpuintc>; + interrupts = <2>; + }; + + memc@300 { + compatible = "ralink,rt2880-memc"; + reg = <0x300 0x100>; + }; + + gpio0: gpio@600 { + compatible = "ralink,rt2880-gpio"; + reg = <0x600 0x34>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <0>; + ralink,num-gpios = <24>; + ralink,register-map = [ 00 04 08 0c + 20 24 28 2c + 30 34 ]; + }; + + gpio1: gpio@638 { + compatible = "ralink,rt2880-gpio"; + reg = <0x638 0x24>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <24>; + ralink,num-gpios = <16>; + ralink,register-map = [ 00 04 08 0c + 10 14 18 1c + 20 24 ]; + + status = "disabled"; + }; + + gpio2: gpio@660 { + compatible = "ralink,rt2880-gpio"; + reg = <0x660 0x24>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <40>; + ralink,num-gpios = <32>; + ralink,register-map = [ 00 04 08 0c + 10 14 18 1c + 20 24 ]; + + status = "disabled"; + }; + + uartlite@c00 { + compatible = "ralink,rt2880-uart", "ns16550a"; + reg = <0xc00 0x100>; + + interrupt-parent = <&intc>; + interrupts = <8>; + + reg-shift = <2>; + }; + }; + + pinctrl { + compatible = "ralink,rt2880-pinmux"; + + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinctrl0 { + sdram { + ralink,group = "sdram"; + ralink,function = "sdram"; + }; + }; + + spi_pins: spi { + spi { + ralink,group = "spi"; + ralink,function = "spi"; + }; + }; + + uartlite_pins: uartlite { + uart { + ralink,group = "uartlite"; + ralink,function = "uartlite"; + }; + }; + }; + + rstctrl: rstctrl { + compatible = "ralink,rt2880-reset"; + #reset-cells = <1>; + }; + + ethernet@400000 { + compatible = "ralink,rt2880-eth"; + reg = <0x00400000 10000>; + + #address-cells = <1>; + #size-cells = <0>; + + resets = <&rstctrl 18>; + reset-names = "fe"; + + interrupt-parent = <&cpuintc>; + interrupts = <5>; + + status = "disabled"; + + port@0 { + compatible = "ralink,rt2880-port", "ralink,eth-port"; + reg = <0>; + }; + + mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + }; + + wmac@480000 { + compatible = "ralink,rt2880-wmac"; + reg = <0x480000 40000>; + + interrupt-parent = <&cpuintc>; + interrupts = <6>; + + ralink,eeprom = "soc_wmac.eeprom"; + }; +}; diff --git a/target/linux/ramips/dts/rt3050.dtsi b/target/linux/ramips/dts/rt3050.dtsi new file mode 100644 index 0000000..27e4179 --- /dev/null +++ b/target/linux/ramips/dts/rt3050.dtsi @@ -0,0 +1,257 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "ralink,rt3050-soc", "ralink,rt3052-soc", "ralink,rt3350-soc"; + + cpus { + cpu@0 { + compatible = "mips,mips24KEc"; + }; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + cpuintc: cpuintc@0 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + palmbus@10000000 { + compatible = "palmbus"; + reg = <0x10000000 0x200000>; + ranges = <0x0 0x10000000 0x1FFFFF>; + + #address-cells = <1>; + #size-cells = <1>; + + sysc@0 { + compatible = "ralink,rt3050-sysc"; + reg = <0x0 0x100>; + }; + + timer@100 { + compatible = "ralink,rt3050-timer", "ralink,rt2880-timer"; + reg = <0x100 0x20>; + + interrupt-parent = <&intc>; + interrupts = <1>; + }; + + watchdog@120 { + compatible = "ralink,rt3050-wdt", "ralink,rt2880-wdt"; + reg = <0x120 0x10>; + + resets = <&rstctrl 8>; + reset-names = "wdt"; + + interrupt-parent = <&intc>; + interrupts = <1>; + }; + + intc: intc@200 { + compatible = "ralink,rt3050-intc", "ralink,rt2880-intc"; + reg = <0x200 0x100>; + + resets = <&rstctrl 19>; + reset-names = "intc"; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpuintc>; + interrupts = <2>; + }; + + memc@300 { + compatible = "ralink,rt3050-memc"; + reg = <0x300 0x100>; + + resets = <&rstctrl 20>; + reset-names = "mc"; + + interrupt-parent = <&intc>; + interrupts = <3>; + }; + + uart@500 { + compatible = "ralink,rt3050-uart", "ralink,rt2880-uart", "ns16550a"; + reg = <0x500 0x100>; + + resets = <&rstctrl 12>; + reset-names = "uart"; + + interrupt-parent = <&intc>; + interrupts = <5>; + + reg-shift = <2>; + + status = "disabled"; + }; + + gpio0: gpio@600 { + compatible = "ralink,rt3050-gpio", "ralink,rt2880-gpio"; + reg = <0x600 0x34>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <0>; + ralink,num-gpios = <24>; + ralink,register-map = [ 00 04 08 0c + 20 24 28 2c + 30 34 ]; + + resets = <&rstctrl 13>; + reset-names = "pio"; + + interrupt-parent = <&intc>; + interrupts = <6>; + }; + + gpio1: gpio@638 { + compatible = "ralink,rt3050-gpio", "ralink,rt2880-gpio"; + reg = <0x638 0x24>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <24>; + ralink,num-gpios = <16>; + ralink,register-map = [ 00 04 08 0c + 10 14 18 1c + 20 24 ]; + + status = "disabled"; + }; + + gpio2: gpio@660 { + compatible = "ralink,rt3050-gpio", "ralink,rt2880-gpio"; + reg = <0x660 0x24>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <40>; + ralink,num-gpios = <12>; + ralink,register-map = [ 00 04 08 0c + 10 14 18 1c + 20 24 ]; + + status = "disabled"; + }; + + spi@b00 { + compatible = "ralink,rt3050-spi", "ralink,rt2880-spi"; + reg = <0xb00 0x100>; + + resets = <&rstctrl 18>; + reset-names = "spi"; + + #address-cells = <1>; + #size-cells = <0>; + + pinctrl-names = "default"; + pinctrl-0 = <&spi_pins>; + + status = "disabled"; + }; + + uartlite@c00 { + compatible = "ralink,rt3050-uart", "ralink,rt2880-uart", "ns16550a"; + reg = <0xc00 0x100>; + + resets = <&rstctrl 19>; + reset-names = "uartl"; + + interrupt-parent = <&intc>; + interrupts = <12>; + + reg-shift = <2>; + + pinctrl-names = "default"; + pinctrl-0 = <&uartlite_pins>; + }; + }; + + pinctrl { + compatible = "ralink,rt2880-pinmux"; + + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinctrl0 { + sdram { + ralink,group = "sdram"; + ralink,function = "sdram"; + }; + }; + + spi_pins: spi { + spi { + ralink,group = "spi"; + ralink,function = "spi"; + }; + }; + + uartlite_pins: uartlite { + uart { + ralink,group = "uartlite"; + ralink,function = "uartlite"; + }; + }; + }; + + rstctrl: rstctrl { + compatible = "ralink,rt3050-reset", "ralink,rt2880-reset"; + #reset-cells = <1>; + }; + + ethernet@10100000 { + compatible = "ralink,rt3050-eth"; + reg = <0x10100000 10000>; + + resets = <&rstctrl 21>; + reset-names = "fe"; + + interrupt-parent = <&cpuintc>; + interrupts = <5>; + }; + + esw@10110000 { + compatible = "ralink,rt3050-esw"; + reg = <0x10110000 8000>; + + resets = <&rstctrl 23>; + reset-names = "esw"; + + interrupt-parent = <&intc>; + interrupts = <17>; + }; + + wmac@10180000 { + compatible = "ralink,rt3050-wmac", "ralink,rt2880-wmac"; + reg = <0x10180000 40000>; + + interrupt-parent = <&cpuintc>; + interrupts = <6>; + + ralink,eeprom = "soc_wmac.eeprom"; + }; + + otg@101c0000 { + compatible = "ralink,rt3050-otg", "snps,dwc2"; + reg = <0x101c0000 40000>; + + interrupt-parent = <&intc>; + interrupts = <18>; + + resets = <&rstctrl 22>; + reset-names = "otg"; + + status = "disabled"; + }; +}; diff --git a/target/linux/ramips/dts/rt3352.dtsi b/target/linux/ramips/dts/rt3352.dtsi new file mode 100644 index 0000000..b04845c --- /dev/null +++ b/target/linux/ramips/dts/rt3352.dtsi @@ -0,0 +1,262 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "ralink,rt3352-soc"; + + cpus { + cpu@0 { + compatible = "mips,mips24KEc"; + }; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + cpuintc: cpuintc@0 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + palmbus@10000000 { + compatible = "palmbus"; + reg = <0x10000000 0x200000>; + ranges = <0x0 0x10000000 0x1FFFFF>; + + #address-cells = <1>; + #size-cells = <1>; + + sysc@0 { + compatible = "ralink,rt3352-sysc", "ralink,rt3050-sysc"; + reg = <0x0 0x100>; + }; + + timer@100 { + compatible = "ralink,rt3352-timer", "ralink,rt2880-timer"; + reg = <0x100 0x20>; + + interrupt-parent = <&intc>; + interrupts = <1>; + }; + + watchdog@120 { + compatible = "ralink,rt3352-wdt", "ralink,rt2880-wdt"; + reg = <0x120 0x10>; + + resets = <&rstctrl 8>; + reset-names = "wdt"; + + interrupt-parent = <&intc>; + interrupts = <1>; + }; + + intc: intc@200 { + compatible = "ralink,rt3352-intc", "ralink,rt2880-intc"; + reg = <0x200 0x100>; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpuintc>; + interrupts = <2>; + }; + + memc@300 { + compatible = "ralink,rt3352-memc", "ralink,rt3050-memc"; + reg = <0x300 0x100>; + + resets = <&rstctrl 20>; + reset-names = "mc"; + + interrupt-parent = <&intc>; + interrupts = <3>; + }; + + uart@500 { + compatible = "ralink,rt3352-uart", "ralink,rt2880-uart", "ns16550a"; + reg = <0x500 0x100>; + + resets = <&rstctrl 12>; + reset-names = "uart"; + + interrupt-parent = <&intc>; + interrupts = <5>; + + reg-shift = <2>; + + status = "disabled"; + }; + + gpio0: gpio@600 { + compatible = "ralink,rt3352-gpio", "ralink,rt2880-gpio"; + reg = <0x600 0x34>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <0>; + ralink,num-gpios = <24>; + ralink,register-map = [ 00 04 08 0c + 20 24 28 2c + 30 34 ]; + resets = <&rstctrl 13>; + reset-names = "pio"; + + interrupt-parent = <&intc>; + interrupts = <6>; + }; + + gpio1: gpio@638 { + compatible = "ralink,rt3352-gpio", "ralink,rt2880-gpio"; + reg = <0x638 0x24>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <24>; + ralink,num-gpios = <16>; + ralink,register-map = [ 00 04 08 0c + 10 14 18 1c + 20 24 ]; + + status = "disabled"; + }; + + gpio2: gpio@660 { + compatible = "ralink,rt3352-gpio", "ralink,rt2880-gpio"; + reg = <0x660 0x24>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <40>; + ralink,num-gpios = <6>; + ralink,register-map = [ 00 04 08 0c + 10 14 18 1c + 20 24 ]; + + status = "disabled"; + }; + + spi@b00 { + compatible = "ralink,rt3352-spi", "ralink,rt2880-spi"; + reg = <0xb00 0x100>; + #address-cells = <1>; + #size-cells = <0>; + + resets = <&rstctrl 18>; + reset-names = "spi"; + + pinctrl-names = "default"; + pinctrl-0 = <&spi_pins>; + + status = "disabled"; + }; + + uartlite@c00 { + compatible = "ralink,rt3352-uart", "ralink,rt2880-uart", "ns16550a"; + reg = <0xc00 0x100>; + + resets = <&rstctrl 19>; + reset-names = "uartl"; + + interrupt-parent = <&intc>; + interrupts = <12>; + + reg-shift = <2>; + + pinctrl-names = "default"; + pinctrl-0 = <&uartlite_pins>; + }; + }; + + pinctrl { + compatible = "ralink,rt2880-pinmux"; + + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinctrl0 { + }; + + spi_pins: spi { + spi { + ralink,group = "spi"; + ralink,function = "spi"; + }; + }; + + uartlite_pins: uartlite { + uart { + ralink,group = "uartlite"; + ralink,function = "uartlite"; + }; + }; + }; + + rstctrl: rstctrl { + compatible = "ralink,rt3352-reset", "ralink,rt2880-reset"; + #reset-cells = <1>; + }; + + ethernet@10100000 { + compatible = "ralink,rt3352-eth", "ralink,rt3050-eth"; + reg = <0x10100000 10000>; + + resets = <&rstctrl 21>; + reset-names = "fe"; + + interrupt-parent = <&cpuintc>; + interrupts = <5>; + }; + + esw@10110000 { + compatible = "ralink,rt3352-esw", "ralink,rt3050-esw"; + reg = <0x10110000 8000>; + + resets = <&rstctrl 23>; + reset-names = "esw"; + + interrupt-parent = <&intc>; + interrupts = <17>; + }; + + usbphy { + compatible = "ralink,rt3xxx-usbphy"; + + resets = <&rstctrl 22 &rstctrl 25>; + reset-names = "host", "device"; + }; + + wmac@10180000 { + compatible = "ralink,rt3352-wmac", "ralink,rt2880-wmac"; + reg = <0x10180000 40000>; + + interrupt-parent = <&cpuintc>; + interrupts = <6>; + + ralink,eeprom = "soc_wmac.eeprom"; + }; + + ehci@101c0000 { + compatible = "ralink,rt3xxx-ehci", "ehci-platform"; + reg = <0x101c0000 0x1000>; + + interrupt-parent = <&intc>; + interrupts = <18>; + + status = "disabled"; + }; + + ohci@101c1000 { + compatible = "ralink,rt3xxx-ohci", "ohci-platform"; + reg = <0x101c1000 0x1000>; + + interrupt-parent = <&intc>; + interrupts = <18>; + + status = "disabled"; + }; +}; diff --git a/target/linux/ramips/dts/rt3883.dtsi b/target/linux/ramips/dts/rt3883.dtsi new file mode 100644 index 0000000..dc26782 --- /dev/null +++ b/target/linux/ramips/dts/rt3883.dtsi @@ -0,0 +1,380 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "ralink,rt3883-soc"; + + cpus { + cpu@0 { + compatible = "mips,mips74Kc"; + }; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + aliases { + spi0 = &spi0; + }; + + cpuintc: cpuintc@0 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + palmbus@10000000 { + compatible = "palmbus"; + reg = <0x10000000 0x200000>; + ranges = <0x0 0x10000000 0x1FFFFF>; + + #address-cells = <1>; + #size-cells = <1>; + + sysc@0 { + compatible = "ralink,rt3883-sysc", "ralink,rt3050-sysc"; + reg = <0x0 0x100>; + }; + + timer@100 { + compatible = "ralink,rt3883-timer", "ralink,rt2880-timer"; + reg = <0x100 0x20>; + + interrupt-parent = <&intc>; + interrupts = <1>; + }; + + watchdog@120 { + compatible = "ralink,rt3883-wdt", "ralink,rt2880-wdt"; + reg = <0x120 0x10>; + + resets = <&rstctrl 8>; + reset-names = "wdt"; + + interrupt-parent = <&intc>; + interrupts = <1>; + }; + + intc: intc@200 { + compatible = "ralink,rt3883-intc", "ralink,rt2880-intc"; + reg = <0x200 0x100>; + + resets = <&rstctrl 19>; + reset-names = "intc"; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpuintc>; + interrupts = <2>; + }; + + memc@300 { + compatible = "ralink,rt3883-memc", "ralink,rt3050-memc"; + reg = <0x300 0x100>; + + resets = <&rstctrl 20>; + reset-names = "mc"; + + interrupt-parent = <&intc>; + interrupts = <3>; + }; + + uart@500 { + compatible = "ralink,rt3883-uart", "ralink,rt2880-uart", "ns16550a"; + reg = <0x500 0x100>; + + resets = <&rstctrl 12>; + reset-names = "uart"; + + interrupt-parent = <&intc>; + interrupts = <5>; + + reg-shift = <2>; + + status = "disabled"; + }; + + gpio0: gpio@600 { + compatible = "ralink,rt3883-gpio", "ralink,rt2880-gpio"; + reg = <0x600 0x34>; + + resets = <&rstctrl 13>; + reset-names = "pio"; + + interrupt-parent = <&intc>; + interrupts = <6>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <0>; + ralink,num-gpios = <24>; + ralink,register-map = [ 00 04 08 0c + 20 24 28 2c + 30 34 ]; + }; + + gpio1: gpio@638 { + compatible = "ralink,rt3883-gpio", "ralink,rt2880-gpio"; + reg = <0x638 0x24>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <24>; + ralink,num-gpios = <16>; + ralink,register-map = [ 00 04 08 0c + 10 14 18 1c + 20 24 ]; + + status = "disabled"; + }; + + gpio2: gpio@660 { + compatible = "ralink,rt3883-gpio", "ralink,rt2880-gpio"; + reg = <0x660 0x24>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <40>; + ralink,num-gpios = <32>; + ralink,register-map = [ 00 04 08 0c + 10 14 18 1c + 20 24 ]; + + status = "disabled"; + }; + + gpio3: gpio@688 { + compatible = "ralink,rt3883-gpio", "ralink,rt2880-gpio"; + reg = <0x688 0x24>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <72>; + ralink,num-gpios = <24>; + ralink,register-map = [ 00 04 08 0c + 10 14 18 1c + 20 24 ]; + + status = "disabled"; + }; + + spi0: spi@b00 { + compatible = "ralink,rt3883-spi", "ralink,rt2880-spi"; + reg = <0xb00 0x100>; + #address-cells = <1>; + #size-cells = <0>; + + resets = <&rstctrl 18>; + reset-names = "spi"; + + pinctrl-names = "default"; + pinctrl-0 = <&spi_pins>; + + status = "disabled"; + }; + + uartlite@c00 { + compatible = "ralink,rt3883-uart", "ralink,rt2880-uart", "ns16550a"; + reg = <0xc00 0x100>; + + resets = <&rstctrl 19>; + reset-names = "uartl"; + + interrupt-parent = <&intc>; + interrupts = <12>; + + reg-shift = <2>; + + pinctrl-names = "default"; + pinctrl-0 = <&uartlite_pins>; + }; + }; + + pinctrl { + compatible = "ralink,rt2880-pinmux"; + + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinctrl0 { + }; + + spi_pins: spi { + spi { + ralink,group = "spi"; + ralink,function = "spi"; + }; + }; + + uartlite_pins: uartlite { + uart { + ralink,group = "uartlite"; + ralink,function = "uartlite"; + }; + }; + }; + + ethernet@10100000 { + compatible = "ralink,rt3883-eth"; + reg = <0x10100000 10000>; + + resets = <&rstctrl 21>; + reset-names = "fe"; + + interrupt-parent = <&cpuintc>; + interrupts = <5>; + + port@0 { + compatible = "ralink,rt3883-port", "ralink,eth-port"; + reg = <0>; + }; + + mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + }; + + rstctrl: rstctrl { + compatible = "ralink,rt3883-reset", "ralink,rt2880-reset"; + #reset-cells = <1>; + }; + + pci@10140000 { + compatible = "ralink,rt3883-pci"; + reg = <0x10140000 0x20000>; + #address-cells = <1>; + #size-cells = <1>; + ranges; /* direct mapping */ + + status = "disabled"; + + pciintc: interrupt-controller { + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + + interrupt-parent = <&cpuintc>; + interrupts = <4>; + }; + + host-bridge { + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + + device_type = "pci"; + + bus-range = <0 255>; + ranges = < + 0x02000000 0 0x00000000 0x20000000 0 0x10000000 /* pci memory */ + 0x01000000 0 0x00000000 0x10160000 0 0x00010000 /* io space */ + >; + + interrupt-map-mask = <0xf800 0 0 7>; + interrupt-map = < + /* IDSEL 17 */ + 0x8800 0 0 1 &pciintc 18 + 0x8800 0 0 2 &pciintc 18 + 0x8800 0 0 3 &pciintc 18 + 0x8800 0 0 4 &pciintc 18 + /* IDSEL 18 */ + 0x9000 0 0 1 &pciintc 19 + 0x9000 0 0 2 &pciintc 19 + 0x9000 0 0 3 &pciintc 19 + 0x9000 0 0 4 &pciintc 19 + >; + + pci-bridge@1 { + reg = <0x0800 0 0 0 0>; + device_type = "pci"; + #interrupt-cells = <1>; + #address-cells = <3>; + #size-cells = <2>; + + status = "disabled"; + + ralink,pci-slot = <1>; + + interrupt-map-mask = <0x0 0 0 0>; + interrupt-map = <0x0 0 0 0 &pciintc 20>; + }; + + pci-slot@17 { + reg = <0x8800 0 0 0 0>; + device_type = "pci"; + #interrupt-cells = <1>; + #address-cells = <3>; + #size-cells = <2>; + + ralink,pci-slot = <17>; + + status = "disabled"; + }; + + pci-slot@18 { + reg = <0x9000 0 0 0 0>; + device_type = "pci"; + #interrupt-cells = <1>; + #address-cells = <3>; + #size-cells = <2>; + + ralink,pci-slot = <18>; + + status = "disabled"; + }; + }; + }; + + usbphy: usbphy { + compatible = "ralink,rt3xxx-usbphy"; + #phy-cells = <1>; + + resets = <&rstctrl 22 &rstctrl 25>; + reset-names = "host", "device"; + }; + + wmac@10180000 { + compatible = "ralink,rt3883-wmac", "ralink,rt2880-wmac"; + reg = <0x10180000 40000>; + + interrupt-parent = <&cpuintc>; + interrupts = <6>; + + ralink,eeprom = "soc_wmac.eeprom"; + }; + + ehci@101c0000 { + compatible = "ralink,rt3xxx-ehci", "ehci-platform"; + reg = <0x101c0000 0x1000>; + + phys = <&usbphy 1>; + phy-names = "usb"; + + interrupt-parent = <&intc>; + interrupts = <18>; + + status = "disabled"; + }; + + ohci@101c1000 { + compatible = "ralink,rt3xxx-ohci", "ohci-platform"; + reg = <0x101c1000 0x1000>; + + phys = <&usbphy 1>; + phy-names = "usb"; + + interrupt-parent = <&intc>; + interrupts = <18>; + + status = "disabled"; + }; +}; diff --git a/target/linux/ramips/dts/rt5350.dtsi b/target/linux/ramips/dts/rt5350.dtsi new file mode 100644 index 0000000..8dd06c8 --- /dev/null +++ b/target/linux/ramips/dts/rt5350.dtsi @@ -0,0 +1,312 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "ralink,rt5350-soc"; + + cpus { + cpu@0 { + compatible = "mips,mips24KEc"; + }; + }; + + chosen { + bootargs = "console=ttyS0,57600"; + }; + + cpuintc: cpuintc@0 { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + compatible = "mti,cpu-interrupt-controller"; + }; + + palmbus@10000000 { + compatible = "palmbus"; + reg = <0x10000000 0x200000>; + ranges = <0x0 0x10000000 0x1FFFFF>; + + #address-cells = <1>; + #size-cells = <1>; + + sysc@0 { + compatible = "ralink,rt5350-sysc", "ralink,rt3050-sysc"; + reg = <0x0 0x100>; + }; + + timer@100 { + compatible = "ralink,rt5350-timer", "ralink,rt2880-timer"; + reg = <0x100 0x20>; + + interrupt-parent = <&intc>; + interrupts = <1>; + }; + + watchdog@120 { + compatible = "ralink,rt5350-wdt", "ralink,rt2880-wdt"; + reg = <0x120 0x10>; + + resets = <&rstctrl 8>; + reset-names = "wdt"; + + interrupt-parent = <&intc>; + interrupts = <1>; + }; + + intc: intc@200 { + compatible = "ralink,rt5350-intc", "ralink,rt2880-intc"; + reg = <0x200 0x100>; + + resets = <&rstctrl 19>; + reset-names = "intc"; + + interrupt-controller; + #interrupt-cells = <1>; + + interrupt-parent = <&cpuintc>; + interrupts = <2>; + }; + + memc@300 { + compatible = "ralink,rt5350-memc", "ralink,rt3050-memc"; + reg = <0x300 0x100>; + + resets = <&rstctrl 20>; + reset-names = "mc"; + + interrupt-parent = <&intc>; + interrupts = <3>; + }; + + uart@500 { + compatible = "ralink,rt5350-uart", "ralink,rt2880-uart", "ns16550a"; + reg = <0x500 0x100>; + + resets = <&rstctrl 12>; + reset-names = "uart"; + + interrupt-parent = <&intc>; + interrupts = <5>; + + reg-shift = <2>; + + pinctrl-names = "default"; + pinctrl-0 = <&uartf_pins>; + + status = "disabled"; + }; + + gpio0: gpio@600 { + compatible = "ralink,rt5350-gpio", "ralink,rt2880-gpio"; + reg = <0x600 0x34>; + + resets = <&rstctrl 13>; + reset-names = "pio"; + + interrupt-parent = <&intc>; + interrupts = <6>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <0>; + ralink,num-gpios = <22>; + ralink,register-map = [ 00 04 08 0c + 20 24 28 2c + 30 34 ]; + }; + + gpio1: gpio@660 { + compatible = "ralink,rt5350-gpio", "ralink,rt2880-gpio"; + reg = <0x660 0x24>; + + interrupt-parent = <&intc>; + interrupts = <6>; + + gpio-controller; + #gpio-cells = <2>; + + ralink,gpio-base = <22>; + ralink,num-gpios = <6>; + ralink,register-map = [ 00 04 08 0c + 10 14 18 1c + 20 24 ]; + + status = "disabled"; + }; + + i2c@900 { + compatible = "link,rt5350-i2c", "ralink,rt2880-i2c"; + reg = <0x900 0x100>; + + resets = <&rstctrl 16>; + reset-names = "i2c"; + + #address-cells = <1>; + #size-cells = <0>; + + pinctrl-names = "default"; + pinctrl-0 = <&i2c_pins>; + + status = "disabled"; + }; + + spi@b00 { + compatible = "ralink,rt5350-spi"; + reg = <0xb00 0x100>; + + resets = <&rstctrl 18>; + reset-names = "spi"; + + #address-cells = <1>; + #size-cells = <0>; + + pinctrl-names = "default"; + pinctrl-0 = <&spi_pins &spi_cs1>; + + status = "disabled"; + }; + + uartlite@c00 { + compatible = "ralink,rt5350-uart", "ralink,rt2880-uart", "ns16550a"; + reg = <0xc00 0x100>; + + resets = <&rstctrl 19>; + reset-names = "uartl"; + + interrupt-parent = <&intc>; + interrupts = <12>; + + pinctrl-names = "default"; + pinctrl-0 = <&uartlite_pins>; + + reg-shift = <2>; + }; + + systick@d00 { + compatible = "ralink,rt5350-systick", "ralink,cevt-systick"; + reg = <0xd00 0x10>; + + interrupt-parent = <&cpuintc>; + interrupts = <7>; + }; + }; + + pinctrl { + compatible = "ralink,rt2880-pinmux"; + + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinctrl0 { + }; + + spi_pins: spi { + spi { + ralink,group = "spi"; + ralink,function = "spi"; + }; + }; + + i2c_pins: i2c { + i2c { + ralink,group = "i2c"; + ralink,function = "i2c"; + }; + }; + + phy_led_pins: phy_led { + phy_led { + ralink,group = "led"; + ralink,function = "led"; + }; + }; + + uartlite_pins: uartlite { + uart { + ralink,group = "uartlite"; + ralink,function = "uartlite"; + }; + }; + + uartf_pins: uartf { + uartf { + ralink,group = "uartf"; + ralink,function = "uartf"; + }; + }; + + spi_cs1: spi1 { + spi1 { + ralink,group = "spi_cs1"; + ralink,function = "spi_cs1"; + }; + }; + }; + + rstctrl: rstctrl { + compatible = "ralink,rt5350-reset", "ralink,rt2880-reset"; + #reset-cells = <1>; + }; + + usbphy: usbphy { + compatible = "ralink,rt3xxx-usbphy"; + #phy-cells = <1>; + + resets = <&rstctrl 22 &rstctrl 25>; + reset-names = "host", "device"; + }; + + ethernet@10100000 { + compatible = "ralink,rt5350-eth"; + reg = <0x10100000 10000>; + + resets = <&rstctrl 21 &rstctrl 23>; + reset-names = "fe", "esw"; + + interrupt-parent = <&cpuintc>; + interrupts = <5>; + }; + + esw@10110000 { + compatible = "ralink,rt3050-esw"; + reg = <0x10110000 8000>; + + resets = <&rstctrl 23>; + reset-names = "esw"; + + interrupt-parent = <&intc>; + interrupts = <17>; + }; + + wmac@10180000 { + compatible = "ralink,rt5350-wmac", "ralink,rt2880-wmac"; + reg = <0x10180000 40000>; + + interrupt-parent = <&cpuintc>; + interrupts = <6>; + + ralink,eeprom = "soc_wmac.eeprom"; + }; + + ehci@101c0000 { + compatible = "ralink,rt3xxx-ehci", "ehci-platform"; + reg = <0x101c0000 0x1000>; + + phys = <&usbphy 1>; + phy-names = "usb"; + + interrupt-parent = <&intc>; + interrupts = <18>; + }; + + ohci@101c1000 { + compatible = "ralink,rt3xxx-ohci", "ohci-platform"; + reg = <0x101c1000 0x1000>; + + phys = <&usbphy 1>; + phy-names = "usb"; + + interrupt-parent = <&intc>; + interrupts = <18>; + }; +}; diff --git a/target/linux/ramips/files/arch/mips/include/asm/mach-ralink/rt305x_esw_platform.h b/target/linux/ramips/files/arch/mips/include/asm/mach-ralink/rt305x_esw_platform.h new file mode 100644 index 0000000..2098c5c --- /dev/null +++ b/target/linux/ramips/files/arch/mips/include/asm/mach-ralink/rt305x_esw_platform.h @@ -0,0 +1,27 @@ +/* + * Ralink RT305x SoC platform device registration + * + * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#ifndef _RT305X_ESW_PLATFORM_H +#define _RT305X_ESW_PLATFORM_H + +enum { + RT305X_ESW_VLAN_CONFIG_NONE = 0, + RT305X_ESW_VLAN_CONFIG_LLLLW, + RT305X_ESW_VLAN_CONFIG_WLLLL, +}; + +struct rt305x_esw_platform_data +{ + u8 vlan_config; + u32 reg_initval_fct2; + u32 reg_initval_fpa2; +}; + +#endif /* _RT305X_ESW_PLATFORM_H */ diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/Kconfig b/target/linux/ramips/files/drivers/net/ethernet/ralink/Kconfig new file mode 100644 index 0000000..22df4fe --- /dev/null +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/Kconfig @@ -0,0 +1,51 @@ +config NET_RALINK + tristate "Ralink ethernet driver" + depends on RALINK + help + This driver supports the ethernet mac inside the ralink wisocs + +if NET_RALINK +choice + prompt "MAC type" + +config NET_RALINK_RT288X + bool "RT288X" + depends on SOC_RT288X + +config NET_RALINK_RT305X + bool "RT305X" + depends on (SOC_RT305X || SOC_MT7620) + +config NET_RALINK_RT3883 + bool "RT3883" + depends on SOC_RT3883 + +config NET_RALINK_MT7620 + bool "MT7620" + depends on (SOC_MT7620 || SOC_MT7621) + +endchoice + +config NET_RALINK_MDIO + def_bool NET_RALINK + depends on (NET_RALINK_RT288X || NET_RALINK_RT3883 || NET_RALINK_MT7620 || NET_RALINK_MT7621) + select PHYLIB + +config NET_RALINK_MDIO_RT2880 + def_bool NET_RALINK + depends on (NET_RALINK_RT288X || NET_RALINK_RT3883) + select NET_RALINK_MDIO + +config NET_RALINK_ESW_RT3052 + def_bool NET_RALINK + depends on NET_RALINK_RT305X + select PHYLIB + select SWCONFIG + +config NET_RALINK_GSW_MT7620 + def_bool NET_RALINK + depends on NET_RALINK_MT7620 || NET_RALINK_MT7621 + select NET_RALINK_MDIO + select PHYLIB + select SWCONFIG +endif diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/Makefile b/target/linux/ramips/files/drivers/net/ethernet/ralink/Makefile new file mode 100644 index 0000000..54a07e7 --- /dev/null +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/Makefile @@ -0,0 +1,19 @@ +# +# Makefile for the Ralink SoCs built-in ethernet macs +# + +ralink-eth-y += ralink_soc_eth.o ralink_ethtool.o + +ralink-eth-$(CONFIG_NET_RALINK_MDIO) += mdio.o +ralink-eth-$(CONFIG_NET_RALINK_MDIO_RT2880) += mdio_rt2880.o + +ralink-eth-$(CONFIG_NET_RALINK_ESW_RT3052) += esw_rt3052.o +ralink-eth-$(CONFIG_NET_RALINK_GSW_MT7620) += gsw_mt7620a.o mt7530.o + +ralink-eth-$(CONFIG_NET_RALINK_RT288X) += soc_rt2880.o +ralink-eth-$(CONFIG_NET_RALINK_RT305X) += soc_rt305x.o +ralink-eth-$(CONFIG_NET_RALINK_RT3883) += soc_rt3883.o +ralink-eth-$(CONFIG_NET_RALINK_MT7620) += soc_mt7620.o +ralink-eth-$(CONFIG_NET_RALINK_MT7621) += soc_mt7621.o + +obj-$(CONFIG_NET_RALINK) += ralink-eth.o diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3052.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3052.c new file mode 100644 index 0000000..55d5729 --- /dev/null +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3052.c @@ -0,0 +1,1503 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2009-2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/dma-mapping.h> +#include <linux/init.h> +#include <linux/skbuff.h> +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/platform_device.h> +#include <linux/of_device.h> +#include <linux/clk.h> +#include <linux/of_net.h> +#include <linux/of_mdio.h> + +#include <asm/mach-ralink/ralink_regs.h> + +#include "ralink_soc_eth.h" + +#include <linux/ioport.h> +#include <linux/switch.h> +#include <linux/mii.h> + +#include <ralink_regs.h> + +#include <asm/mach-ralink/rt305x_esw_platform.h> + +/* + * HW limitations for this switch: + * - No large frame support (PKT_MAX_LEN at most 1536) + * - Can't have untagged vlan and tagged vlan on one port at the same time, + * though this might be possible using the undocumented PPE. + */ + +#define RT305X_ESW_REG_ISR 0x00 +#define RT305X_ESW_REG_IMR 0x04 +#define RT305X_ESW_REG_FCT0 0x08 +#define RT305X_ESW_REG_PFC1 0x14 +#define RT305X_ESW_REG_ATS 0x24 +#define RT305X_ESW_REG_ATS0 0x28 +#define RT305X_ESW_REG_ATS1 0x2c +#define RT305X_ESW_REG_ATS2 0x30 +#define RT305X_ESW_REG_PVIDC(_n) (0x40 + 4 * (_n)) +#define RT305X_ESW_REG_VLANI(_n) (0x50 + 4 * (_n)) +#define RT305X_ESW_REG_VMSC(_n) (0x70 + 4 * (_n)) +#define RT305X_ESW_REG_POA 0x80 +#define RT305X_ESW_REG_FPA 0x84 +#define RT305X_ESW_REG_SOCPC 0x8c +#define RT305X_ESW_REG_POC0 0x90 +#define RT305X_ESW_REG_POC1 0x94 +#define RT305X_ESW_REG_POC2 0x98 +#define RT305X_ESW_REG_SGC 0x9c +#define RT305X_ESW_REG_STRT 0xa0 +#define RT305X_ESW_REG_PCR0 0xc0 +#define RT305X_ESW_REG_PCR1 0xc4 +#define RT305X_ESW_REG_FPA2 0xc8 +#define RT305X_ESW_REG_FCT2 0xcc +#define RT305X_ESW_REG_SGC2 0xe4 +#define RT305X_ESW_REG_P0LED 0xa4 +#define RT305X_ESW_REG_P1LED 0xa8 +#define RT305X_ESW_REG_P2LED 0xac +#define RT305X_ESW_REG_P3LED 0xb0 +#define RT305X_ESW_REG_P4LED 0xb4 +#define RT305X_ESW_REG_PXPC(_x) (0xe8 + (4 * _x)) +#define RT305X_ESW_REG_P1PC 0xec +#define RT305X_ESW_REG_P2PC 0xf0 +#define RT305X_ESW_REG_P3PC 0xf4 +#define RT305X_ESW_REG_P4PC 0xf8 +#define RT305X_ESW_REG_P5PC 0xfc + +#define RT305X_ESW_LED_LINK 0 +#define RT305X_ESW_LED_100M 1 +#define RT305X_ESW_LED_DUPLEX 2 +#define RT305X_ESW_LED_ACTIVITY 3 +#define RT305X_ESW_LED_COLLISION 4 +#define RT305X_ESW_LED_LINKACT 5 +#define RT305X_ESW_LED_DUPLCOLL 6 +#define RT305X_ESW_LED_10MACT 7 +#define RT305X_ESW_LED_100MACT 8 +/* Additional led states not in datasheet: */ +#define RT305X_ESW_LED_BLINK 10 +#define RT305X_ESW_LED_ON 12 + +#define RT305X_ESW_LINK_S 25 +#define RT305X_ESW_DUPLEX_S 9 +#define RT305X_ESW_SPD_S 0 + +#define RT305X_ESW_PCR0_WT_NWAY_DATA_S 16 +#define RT305X_ESW_PCR0_WT_PHY_CMD BIT(13) +#define RT305X_ESW_PCR0_CPU_PHY_REG_S 8 + +#define RT305X_ESW_PCR1_WT_DONE BIT(0) + +#define RT305X_ESW_ATS_TIMEOUT (5 * HZ) +#define RT305X_ESW_PHY_TIMEOUT (5 * HZ) + +#define RT305X_ESW_PVIDC_PVID_M 0xfff +#define RT305X_ESW_PVIDC_PVID_S 12 + +#define RT305X_ESW_VLANI_VID_M 0xfff +#define RT305X_ESW_VLANI_VID_S 12 + +#define RT305X_ESW_VMSC_MSC_M 0xff +#define RT305X_ESW_VMSC_MSC_S 8 + +#define RT305X_ESW_SOCPC_DISUN2CPU_S 0 +#define RT305X_ESW_SOCPC_DISMC2CPU_S 8 +#define RT305X_ESW_SOCPC_DISBC2CPU_S 16 +#define RT305X_ESW_SOCPC_CRC_PADDING BIT(25) + +#define RT305X_ESW_POC0_EN_BP_S 0 +#define RT305X_ESW_POC0_EN_FC_S 8 +#define RT305X_ESW_POC0_DIS_RMC2CPU_S 16 +#define RT305X_ESW_POC0_DIS_PORT_M 0x7f +#define RT305X_ESW_POC0_DIS_PORT_S 23 + +#define RT305X_ESW_POC2_UNTAG_EN_M 0xff +#define RT305X_ESW_POC2_UNTAG_EN_S 0 +#define RT305X_ESW_POC2_ENAGING_S 8 +#define RT305X_ESW_POC2_DIS_UC_PAUSE_S 16 + +#define RT305X_ESW_SGC2_DOUBLE_TAG_M 0x7f +#define RT305X_ESW_SGC2_DOUBLE_TAG_S 0 +#define RT305X_ESW_SGC2_LAN_PMAP_M 0x3f +#define RT305X_ESW_SGC2_LAN_PMAP_S 24 + +#define RT305X_ESW_PFC1_EN_VLAN_M 0xff +#define RT305X_ESW_PFC1_EN_VLAN_S 16 +#define RT305X_ESW_PFC1_EN_TOS_S 24 + +#define RT305X_ESW_VLAN_NONE 0xfff + +#define RT305X_ESW_GSC_BC_STROM_MASK 0x3 +#define RT305X_ESW_GSC_BC_STROM_SHIFT 4 + +#define RT305X_ESW_GSC_LED_FREQ_MASK 0x3 +#define RT305X_ESW_GSC_LED_FREQ_SHIFT 23 + +#define RT305X_ESW_POA_LINK_MASK 0x1f +#define RT305X_ESW_POA_LINK_SHIFT 25 + +#define RT305X_ESW_PORT_ST_CHG BIT(26) +#define RT305X_ESW_PORT0 0 +#define RT305X_ESW_PORT1 1 +#define RT305X_ESW_PORT2 2 +#define RT305X_ESW_PORT3 3 +#define RT305X_ESW_PORT4 4 +#define RT305X_ESW_PORT5 5 +#define RT305X_ESW_PORT6 6 + +#define RT305X_ESW_PORTS_NONE 0 + +#define RT305X_ESW_PMAP_LLLLLL 0x3f +#define RT305X_ESW_PMAP_LLLLWL 0x2f +#define RT305X_ESW_PMAP_WLLLLL 0x3e + +#define RT305X_ESW_PORTS_INTERNAL \ + (BIT(RT305X_ESW_PORT0) | BIT(RT305X_ESW_PORT1) | \ + BIT(RT305X_ESW_PORT2) | BIT(RT305X_ESW_PORT3) | \ + BIT(RT305X_ESW_PORT4)) + +#define RT305X_ESW_PORTS_NOCPU \ + (RT305X_ESW_PORTS_INTERNAL | BIT(RT305X_ESW_PORT5)) + +#define RT305X_ESW_PORTS_CPU BIT(RT305X_ESW_PORT6) + +#define RT305X_ESW_PORTS_ALL \ + (RT305X_ESW_PORTS_NOCPU | RT305X_ESW_PORTS_CPU) + +#define RT305X_ESW_NUM_VLANS 16 +#define RT305X_ESW_NUM_VIDS 4096 +#define RT305X_ESW_NUM_PORTS 7 +#define RT305X_ESW_NUM_LANWAN 6 +#define RT305X_ESW_NUM_LEDS 5 + +#define RT5350_ESW_REG_PXTPC(_x) (0x150 + (4 * _x)) +#define RT5350_EWS_REG_LED_POLARITY 0x168 +#define RT5350_RESET_EPHY BIT(24) + +enum { + /* Global attributes. */ + RT305X_ESW_ATTR_ENABLE_VLAN, + RT305X_ESW_ATTR_ALT_VLAN_DISABLE, + RT305X_ESW_ATTR_BC_STATUS, + RT305X_ESW_ATTR_LED_FREQ, + /* Port attributes. */ + RT305X_ESW_ATTR_PORT_DISABLE, + RT305X_ESW_ATTR_PORT_DOUBLETAG, + RT305X_ESW_ATTR_PORT_UNTAG, + RT305X_ESW_ATTR_PORT_LED, + RT305X_ESW_ATTR_PORT_LAN, + RT305X_ESW_ATTR_PORT_RECV_BAD, + RT305X_ESW_ATTR_PORT_RECV_GOOD, + RT5350_ESW_ATTR_PORT_TR_BAD, + RT5350_ESW_ATTR_PORT_TR_GOOD, +}; + +struct esw_port { + bool disable; + bool doubletag; + bool untag; + u8 led; + u16 pvid; +}; + +struct esw_vlan { + u8 ports; + u16 vid; +}; + +struct rt305x_esw { + struct device *dev; + void __iomem *base; + int irq; + const struct rt305x_esw_platform_data *pdata; + /* Protects against concurrent register rmw operations. */ + spinlock_t reg_rw_lock; + + unsigned char port_map; + unsigned int reg_initval_fct2; + unsigned int reg_initval_fpa2; + unsigned int reg_led_polarity; + + + struct switch_dev swdev; + bool global_vlan_enable; + bool alt_vlan_disable; + int bc_storm_protect; + int led_frequency; + struct esw_vlan vlans[RT305X_ESW_NUM_VLANS]; + struct esw_port ports[RT305X_ESW_NUM_PORTS]; + +}; + +static inline void esw_w32(struct rt305x_esw *esw, u32 val, unsigned reg) +{ + __raw_writel(val, esw->base + reg); +} + +static inline u32 esw_r32(struct rt305x_esw *esw, unsigned reg) +{ + return __raw_readl(esw->base + reg); +} + +static inline void esw_rmw_raw(struct rt305x_esw *esw, unsigned reg, unsigned long mask, + unsigned long val) +{ + unsigned long t; + + t = __raw_readl(esw->base + reg) & ~mask; + __raw_writel(t | val, esw->base + reg); +} + +static void esw_rmw(struct rt305x_esw *esw, unsigned reg, unsigned long mask, + unsigned long val) +{ + unsigned long flags; + + spin_lock_irqsave(&esw->reg_rw_lock, flags); + esw_rmw_raw(esw, reg, mask, val); + spin_unlock_irqrestore(&esw->reg_rw_lock, flags); +} + +static u32 rt305x_mii_write(struct rt305x_esw *esw, u32 phy_addr, u32 phy_register, + u32 write_data) +{ + unsigned long t_start = jiffies; + int ret = 0; + + while (1) { + if (!(esw_r32(esw, RT305X_ESW_REG_PCR1) & + RT305X_ESW_PCR1_WT_DONE)) + break; + if (time_after(jiffies, t_start + RT305X_ESW_PHY_TIMEOUT)) { + ret = 1; + goto out; + } + } + + write_data &= 0xffff; + esw_w32(esw, + (write_data << RT305X_ESW_PCR0_WT_NWAY_DATA_S) | + (phy_register << RT305X_ESW_PCR0_CPU_PHY_REG_S) | + (phy_addr) | RT305X_ESW_PCR0_WT_PHY_CMD, + RT305X_ESW_REG_PCR0); + + t_start = jiffies; + while (1) { + if (esw_r32(esw, RT305X_ESW_REG_PCR1) & + RT305X_ESW_PCR1_WT_DONE) + break; + + if (time_after(jiffies, t_start + RT305X_ESW_PHY_TIMEOUT)) { + ret = 1; + break; + } + } +out: + if (ret) + printk(KERN_ERR "ramips_eth: MDIO timeout\n"); + return ret; +} + +static unsigned esw_get_vlan_id(struct rt305x_esw *esw, unsigned vlan) +{ + unsigned s; + unsigned val; + + s = RT305X_ESW_VLANI_VID_S * (vlan % 2); + val = esw_r32(esw, RT305X_ESW_REG_VLANI(vlan / 2)); + val = (val >> s) & RT305X_ESW_VLANI_VID_M; + + return val; +} + +static void esw_set_vlan_id(struct rt305x_esw *esw, unsigned vlan, unsigned vid) +{ + unsigned s; + + s = RT305X_ESW_VLANI_VID_S * (vlan % 2); + esw_rmw(esw, + RT305X_ESW_REG_VLANI(vlan / 2), + RT305X_ESW_VLANI_VID_M << s, + (vid & RT305X_ESW_VLANI_VID_M) << s); +} + +static unsigned esw_get_pvid(struct rt305x_esw *esw, unsigned port) +{ + unsigned s, val; + + s = RT305X_ESW_PVIDC_PVID_S * (port % 2); + val = esw_r32(esw, RT305X_ESW_REG_PVIDC(port / 2)); + return (val >> s) & RT305X_ESW_PVIDC_PVID_M; +} + +static void esw_set_pvid(struct rt305x_esw *esw, unsigned port, unsigned pvid) +{ + unsigned s; + + s = RT305X_ESW_PVIDC_PVID_S * (port % 2); + esw_rmw(esw, + RT305X_ESW_REG_PVIDC(port / 2), + RT305X_ESW_PVIDC_PVID_M << s, + (pvid & RT305X_ESW_PVIDC_PVID_M) << s); +} + +static unsigned esw_get_vmsc(struct rt305x_esw *esw, unsigned vlan) +{ + unsigned s, val; + + s = RT305X_ESW_VMSC_MSC_S * (vlan % 4); + val = esw_r32(esw, RT305X_ESW_REG_VMSC(vlan / 4)); + val = (val >> s) & RT305X_ESW_VMSC_MSC_M; + + return val; +} + +static void esw_set_vmsc(struct rt305x_esw *esw, unsigned vlan, unsigned msc) +{ + unsigned s; + + s = RT305X_ESW_VMSC_MSC_S * (vlan % 4); + esw_rmw(esw, + RT305X_ESW_REG_VMSC(vlan / 4), + RT305X_ESW_VMSC_MSC_M << s, + (msc & RT305X_ESW_VMSC_MSC_M) << s); +} + +static unsigned esw_get_port_disable(struct rt305x_esw *esw) +{ + unsigned reg; + reg = esw_r32(esw, RT305X_ESW_REG_POC0); + return (reg >> RT305X_ESW_POC0_DIS_PORT_S) & + RT305X_ESW_POC0_DIS_PORT_M; +} + +static void esw_set_port_disable(struct rt305x_esw *esw, unsigned disable_mask) +{ + unsigned old_mask; + unsigned enable_mask; + unsigned changed; + int i; + + old_mask = esw_get_port_disable(esw); + changed = old_mask ^ disable_mask; + enable_mask = old_mask & disable_mask; + + /* enable before writing to MII */ + esw_rmw(esw, RT305X_ESW_REG_POC0, + (RT305X_ESW_POC0_DIS_PORT_M << + RT305X_ESW_POC0_DIS_PORT_S), + enable_mask << RT305X_ESW_POC0_DIS_PORT_S); + + for (i = 0; i < RT305X_ESW_NUM_LEDS; i++) { + if (!(changed & (1 << i))) + continue; + if (disable_mask & (1 << i)) { + /* disable */ + rt305x_mii_write(esw, i, MII_BMCR, + BMCR_PDOWN); + } else { + /* enable */ + rt305x_mii_write(esw, i, MII_BMCR, + BMCR_FULLDPLX | + BMCR_ANENABLE | + BMCR_ANRESTART | + BMCR_SPEED100); + } + } + + /* disable after writing to MII */ + esw_rmw(esw, RT305X_ESW_REG_POC0, + (RT305X_ESW_POC0_DIS_PORT_M << + RT305X_ESW_POC0_DIS_PORT_S), + disable_mask << RT305X_ESW_POC0_DIS_PORT_S); +} + +static void esw_set_gsc(struct rt305x_esw *esw) +{ + esw_rmw(esw, RT305X_ESW_REG_SGC, + RT305X_ESW_GSC_BC_STROM_MASK << RT305X_ESW_GSC_BC_STROM_SHIFT, + esw->bc_storm_protect << RT305X_ESW_GSC_BC_STROM_SHIFT); + esw_rmw(esw, RT305X_ESW_REG_SGC, + RT305X_ESW_GSC_LED_FREQ_MASK << RT305X_ESW_GSC_LED_FREQ_SHIFT, + esw->led_frequency << RT305X_ESW_GSC_LED_FREQ_SHIFT); +} + +static int esw_apply_config(struct switch_dev *dev); + +static void esw_hw_init(struct rt305x_esw *esw) +{ + int i; + u8 port_disable = 0; + u8 port_map = RT305X_ESW_PMAP_LLLLLL; + + /* vodoo from original driver */ + esw_w32(esw, 0xC8A07850, RT305X_ESW_REG_FCT0); + esw_w32(esw, 0x00000000, RT305X_ESW_REG_SGC2); + /* Port priority 1 for all ports, vlan enabled. */ + esw_w32(esw, 0x00005555 | + (RT305X_ESW_PORTS_ALL << RT305X_ESW_PFC1_EN_VLAN_S), + RT305X_ESW_REG_PFC1); + + /* Enable Back Pressure, and Flow Control */ + esw_w32(esw, + ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC0_EN_BP_S) | + (RT305X_ESW_PORTS_ALL << RT305X_ESW_POC0_EN_FC_S)), + RT305X_ESW_REG_POC0); + + /* Enable Aging, and VLAN TAG removal */ + esw_w32(esw, + ((RT305X_ESW_PORTS_ALL << RT305X_ESW_POC2_ENAGING_S) | + (RT305X_ESW_PORTS_NOCPU << RT305X_ESW_POC2_UNTAG_EN_S)), + RT305X_ESW_REG_POC2); + + if (esw->reg_initval_fct2) + esw_w32(esw, esw->reg_initval_fct2, RT305X_ESW_REG_FCT2); + else + esw_w32(esw, esw->pdata->reg_initval_fct2, RT305X_ESW_REG_FCT2); + + /* + * 300s aging timer, max packet len 1536, broadcast storm prevention + * disabled, disable collision abort, mac xor48 hash, 10 packet back + * pressure jam, GMII disable was_transmit, back pressure disabled, + * 30ms led flash, unmatched IGMP as broadcast, rmc tb fault to all + * ports. + */ + esw_w32(esw, 0x0008a301, RT305X_ESW_REG_SGC); + + /* Setup SoC Port control register */ + esw_w32(esw, + (RT305X_ESW_SOCPC_CRC_PADDING | + (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISUN2CPU_S) | + (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISMC2CPU_S) | + (RT305X_ESW_PORTS_CPU << RT305X_ESW_SOCPC_DISBC2CPU_S)), + RT305X_ESW_REG_SOCPC); + + if (esw->reg_initval_fpa2) + esw_w32(esw, esw->reg_initval_fpa2, RT305X_ESW_REG_FPA2); + else + esw_w32(esw, esw->pdata->reg_initval_fpa2, RT305X_ESW_REG_FPA2); + esw_w32(esw, 0x00000000, RT305X_ESW_REG_FPA); + + /* Force Link/Activity on ports */ + esw_w32(esw, 0x00000005, RT305X_ESW_REG_P0LED); + esw_w32(esw, 0x00000005, RT305X_ESW_REG_P1LED); + esw_w32(esw, 0x00000005, RT305X_ESW_REG_P2LED); + esw_w32(esw, 0x00000005, RT305X_ESW_REG_P3LED); + esw_w32(esw, 0x00000005, RT305X_ESW_REG_P4LED); + + /* Copy disabled port configuration from bootloader setup */ + port_disable = esw_get_port_disable(esw); + for (i = 0; i < 6; i++) + esw->ports[i].disable = (port_disable & (1 << i)) != 0; + + if (ralink_soc == RT305X_SOC_RT3352) { + /* reset EPHY */ + fe_reset(RT5350_RESET_EPHY); + + rt305x_mii_write(esw, 0, 31, 0x8000); + for (i = 0; i < 5; i++) { + if (esw->ports[i].disable) { + rt305x_mii_write(esw, i, MII_BMCR, BMCR_PDOWN); + } else { + rt305x_mii_write(esw, i, MII_BMCR, + BMCR_FULLDPLX | + BMCR_ANENABLE | + BMCR_SPEED100); + } + /* TX10 waveform coefficient LSB=0 disable PHY */ + rt305x_mii_write(esw, i, 26, 0x1601); + /* TX100/TX10 AD/DA current bias */ + rt305x_mii_write(esw, i, 29, 0x7016); + /* TX100 slew rate control */ + rt305x_mii_write(esw, i, 30, 0x0038); + } + + /* select global register */ + rt305x_mii_write(esw, 0, 31, 0x0); + /* enlarge agcsel threshold 3 and threshold 2 */ + rt305x_mii_write(esw, 0, 1, 0x4a40); + /* enlarge agcsel threshold 5 and threshold 4 */ + rt305x_mii_write(esw, 0, 2, 0x6254); + /* enlarge agcsel threshold */ + rt305x_mii_write(esw, 0, 3, 0xa17f); + rt305x_mii_write(esw, 0,12, 0x7eaa); + /* longer TP_IDL tail length */ + rt305x_mii_write(esw, 0, 14, 0x65); + /* increased squelch pulse count threshold. */ + rt305x_mii_write(esw, 0, 16, 0x0684); + /* set TX10 signal amplitude threshold to minimum */ + rt305x_mii_write(esw, 0, 17, 0x0fe0); + /* set squelch amplitude to higher threshold */ + rt305x_mii_write(esw, 0, 18, 0x40ba); + /* tune TP_IDL tail and head waveform, enable power down slew rate control */ + rt305x_mii_write(esw, 0, 22, 0x253f); + /* set PLL/Receive bias current are calibrated */ + rt305x_mii_write(esw, 0, 27, 0x2fda); + /* change PLL/Receive bias current to internal(RT3350) */ + rt305x_mii_write(esw, 0, 28, 0xc410); + /* change PLL bias current to internal(RT3052_MP3) */ + rt305x_mii_write(esw, 0, 29, 0x598b); + /* select local register */ + rt305x_mii_write(esw, 0, 31, 0x8000); + } else if (ralink_soc == RT305X_SOC_RT5350) { + /* reset EPHY */ + fe_reset(RT5350_RESET_EPHY); + + /* set the led polarity */ + esw_w32(esw, esw->reg_led_polarity & 0x1F, RT5350_EWS_REG_LED_POLARITY); + + /* local registers */ + rt305x_mii_write(esw, 0, 31, 0x8000); + for (i = 0; i < 5; i++) { + if (esw->ports[i].disable) { + rt305x_mii_write(esw, i, MII_BMCR, BMCR_PDOWN); + } else { + rt305x_mii_write(esw, i, MII_BMCR, + BMCR_FULLDPLX | + BMCR_ANENABLE | + BMCR_SPEED100); + } + /* TX10 waveform coefficient LSB=0 disable PHY */ + rt305x_mii_write(esw, i, 26, 0x1601); + /* TX100/TX10 AD/DA current bias */ + rt305x_mii_write(esw, i, 29, 0x7015); + /* TX100 slew rate control */ + rt305x_mii_write(esw, i, 30, 0x0038); + } + + /* global registers */ + rt305x_mii_write(esw, 0, 31, 0x0); + /* enlarge agcsel threshold 3 and threshold 2 */ + rt305x_mii_write(esw, 0, 1, 0x4a40); + /* enlarge agcsel threshold 5 and threshold 4 */ + rt305x_mii_write(esw, 0, 2, 0x6254); + /* enlarge agcsel threshold 6 */ + rt305x_mii_write(esw, 0, 3, 0xa17f); + rt305x_mii_write(esw, 0, 12, 0x7eaa); + /* longer TP_IDL tail length */ + rt305x_mii_write(esw, 0, 14, 0x65); + /* increased squelch pulse count threshold. */ + rt305x_mii_write(esw, 0, 16, 0x0684); + /* set TX10 signal amplitude threshold to minimum */ + rt305x_mii_write(esw, 0, 17, 0x0fe0); + /* set squelch amplitude to higher threshold */ + rt305x_mii_write(esw, 0, 18, 0x40ba); + /* tune TP_IDL tail and head waveform, enable power down slew rate control */ + rt305x_mii_write(esw, 0, 22, 0x253f); + /* set PLL/Receive bias current are calibrated */ + rt305x_mii_write(esw, 0, 27, 0x2fda); + /* change PLL/Receive bias current to internal(RT3350) */ + rt305x_mii_write(esw, 0, 28, 0xc410); + /* change PLL bias current to internal(RT3052_MP3) */ + rt305x_mii_write(esw, 0, 29, 0x598b); + /* select local register */ + rt305x_mii_write(esw, 0, 31, 0x8000); + } else if (ralink_soc == MT762X_SOC_MT7628AN) { + int i; +// u32 phy_val; + u32 val; + + /* reset EPHY */ + fe_reset(RT5350_RESET_EPHY); + + rt305x_mii_write(esw, 0, 31, 0x2000); /* change G2 page */ + rt305x_mii_write(esw, 0, 26, 0x0020); + + for (i = 0; i < 5; i++) { + rt305x_mii_write(esw, i, 31, 0x8000); //change L0 page + rt305x_mii_write(esw, i, 0, 0x3100); +// mii_mgr_read(i, 26, &phy_val);// EEE setting +// phy_val |= (1 << 5); +// rt305x_mii_write(esw, i, 26, phy_val); + rt305x_mii_write(esw, i, 30, 0xa000); + rt305x_mii_write(esw, i, 31, 0xa000); // change L2 page + rt305x_mii_write(esw, i, 16, 0x0606); + rt305x_mii_write(esw, i, 23, 0x0f0e); + rt305x_mii_write(esw, i, 24, 0x1610); + rt305x_mii_write(esw, i, 30, 0x1f15); + rt305x_mii_write(esw, i, 28, 0x6111); +// mii_mgr_read(i, 4, &phy_val); +// phy_val |= (1 << 10); +// rt305x_mii_write(esw, i, 4, phy_val); + rt305x_mii_write(esw, i, 31, 0x2000); // change G2 page + rt305x_mii_write(esw, i, 26, 0x0000); + } + + //100Base AOI setting + rt305x_mii_write(esw, 0, 31, 0x5000); //change G5 page + rt305x_mii_write(esw, 0, 19, 0x004a); + rt305x_mii_write(esw, 0, 20, 0x015a); + rt305x_mii_write(esw, 0, 21, 0x00ee); + rt305x_mii_write(esw, 0, 22, 0x0033); + rt305x_mii_write(esw, 0, 23, 0x020a); + rt305x_mii_write(esw, 0, 24, 0x0000); + rt305x_mii_write(esw, 0, 25, 0x024a); + rt305x_mii_write(esw, 0, 26, 0x035a); + rt305x_mii_write(esw, 0, 27, 0x02ee); + rt305x_mii_write(esw, 0, 28, 0x0233); + rt305x_mii_write(esw, 0, 29, 0x000a); + rt305x_mii_write(esw, 0, 30, 0x0000); + } else { + rt305x_mii_write(esw, 0, 31, 0x8000); + for (i = 0; i < 5; i++) { + if (esw->ports[i].disable) { + rt305x_mii_write(esw, i, MII_BMCR, BMCR_PDOWN); + } else { + rt305x_mii_write(esw, i, MII_BMCR, + BMCR_FULLDPLX | + BMCR_ANENABLE | + BMCR_SPEED100); + } + /* TX10 waveform coefficient */ + rt305x_mii_write(esw, i, 26, 0x1601); + /* TX100/TX10 AD/DA current bias */ + rt305x_mii_write(esw, i, 29, 0x7058); + /* TX100 slew rate control */ + rt305x_mii_write(esw, i, 30, 0x0018); + } + + /* PHY IOT */ + /* select global register */ + rt305x_mii_write(esw, 0, 31, 0x0); + /* tune TP_IDL tail and head waveform */ + rt305x_mii_write(esw, 0, 22, 0x052f); + /* set TX10 signal amplitude threshold to minimum */ + rt305x_mii_write(esw, 0, 17, 0x0fe0); + /* set squelch amplitude to higher threshold */ + rt305x_mii_write(esw, 0, 18, 0x40ba); + /* longer TP_IDL tail length */ + rt305x_mii_write(esw, 0, 14, 0x65); + /* select local register */ + rt305x_mii_write(esw, 0, 31, 0x8000); + } + + if (esw->port_map) + port_map = esw->port_map; + else + port_map = RT305X_ESW_PMAP_LLLLLL; + + /* + * Unused HW feature, but still nice to be consistent here... + * This is also exported to userspace ('lan' attribute) so it's + * conveniently usable to decide which ports go into the wan vlan by + * default. + */ + esw_rmw(esw, RT305X_ESW_REG_SGC2, + RT305X_ESW_SGC2_LAN_PMAP_M << RT305X_ESW_SGC2_LAN_PMAP_S, + port_map << RT305X_ESW_SGC2_LAN_PMAP_S); + + /* make the switch leds blink */ + for (i = 0; i < RT305X_ESW_NUM_LEDS; i++) + esw->ports[i].led = 0x05; + + /* Apply the empty config. */ + esw_apply_config(&esw->swdev); + + /* Only unmask the port change interrupt */ + esw_w32(esw, ~RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_IMR); +} + +static irqreturn_t esw_interrupt(int irq, void *_esw) +{ + struct rt305x_esw *esw = (struct rt305x_esw *) _esw; + u32 status; + + status = esw_r32(esw, RT305X_ESW_REG_ISR); + if (status & RT305X_ESW_PORT_ST_CHG) { + u32 link = esw_r32(esw, RT305X_ESW_REG_POA); + link >>= RT305X_ESW_POA_LINK_SHIFT; + link &= RT305X_ESW_POA_LINK_MASK; + dev_info(esw->dev, "link changed 0x%02X\n", link); + } + esw_w32(esw, status, RT305X_ESW_REG_ISR); + + return IRQ_HANDLED; +} + +static int esw_apply_config(struct switch_dev *dev) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + int i; + u8 disable = 0; + u8 doubletag = 0; + u8 en_vlan = 0; + u8 untag = 0; + + for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) { + u32 vid, vmsc; + if (esw->global_vlan_enable) { + vid = esw->vlans[i].vid; + vmsc = esw->vlans[i].ports; + } else { + vid = RT305X_ESW_VLAN_NONE; + vmsc = RT305X_ESW_PORTS_NONE; + } + esw_set_vlan_id(esw, i, vid); + esw_set_vmsc(esw, i, vmsc); + } + + for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) { + u32 pvid; + disable |= esw->ports[i].disable << i; + if (esw->global_vlan_enable) { + doubletag |= esw->ports[i].doubletag << i; + en_vlan |= 1 << i; + untag |= esw->ports[i].untag << i; + pvid = esw->ports[i].pvid; + } else { + int x = esw->alt_vlan_disable ? 0 : 1; + doubletag |= x << i; + en_vlan |= x << i; + untag |= x << i; + pvid = 0; + } + esw_set_pvid(esw, i, pvid); + if (i < RT305X_ESW_NUM_LEDS) + esw_w32(esw, esw->ports[i].led, + RT305X_ESW_REG_P0LED + 4*i); + } + + esw_set_gsc(esw); + esw_set_port_disable(esw, disable); + esw_rmw(esw, RT305X_ESW_REG_SGC2, + (RT305X_ESW_SGC2_DOUBLE_TAG_M << + RT305X_ESW_SGC2_DOUBLE_TAG_S), + doubletag << RT305X_ESW_SGC2_DOUBLE_TAG_S); + esw_rmw(esw, RT305X_ESW_REG_PFC1, + RT305X_ESW_PFC1_EN_VLAN_M << RT305X_ESW_PFC1_EN_VLAN_S, + en_vlan << RT305X_ESW_PFC1_EN_VLAN_S); + esw_rmw(esw, RT305X_ESW_REG_POC2, + RT305X_ESW_POC2_UNTAG_EN_M << RT305X_ESW_POC2_UNTAG_EN_S, + untag << RT305X_ESW_POC2_UNTAG_EN_S); + + if (!esw->global_vlan_enable) { + /* + * Still need to put all ports into vlan 0 or they'll be + * isolated. + * NOTE: vlan 0 is special, no vlan tag is prepended + */ + esw_set_vlan_id(esw, 0, 0); + esw_set_vmsc(esw, 0, RT305X_ESW_PORTS_ALL); + } + + return 0; +} + +static int esw_reset_switch(struct switch_dev *dev) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + esw->global_vlan_enable = 0; + memset(esw->ports, 0, sizeof(esw->ports)); + memset(esw->vlans, 0, sizeof(esw->vlans)); + esw_hw_init(esw); + + return 0; +} + +static int esw_get_vlan_enable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + val->value.i = esw->global_vlan_enable; + + return 0; +} + +static int esw_set_vlan_enable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + esw->global_vlan_enable = val->value.i != 0; + + return 0; +} + +static int esw_get_alt_vlan_disable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + val->value.i = esw->alt_vlan_disable; + + return 0; +} + +static int esw_set_alt_vlan_disable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + esw->alt_vlan_disable = val->value.i != 0; + + return 0; +} + +static int +rt305x_esw_set_bc_status(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + esw->bc_storm_protect = val->value.i & RT305X_ESW_GSC_BC_STROM_MASK; + + return 0; +} + +static int +rt305x_esw_get_bc_status(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + val->value.i = esw->bc_storm_protect; + + return 0; +} + +static int +rt305x_esw_set_led_freq(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + esw->led_frequency = val->value.i & RT305X_ESW_GSC_LED_FREQ_MASK; + + return 0; +} + +static int +rt305x_esw_get_led_freq(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + val->value.i = esw->led_frequency; + + return 0; +} + +static int esw_get_port_link(struct switch_dev *dev, + int port, + struct switch_port_link *link) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + u32 speed, poa; + + if (port < 0 || port >= RT305X_ESW_NUM_PORTS) + return -EINVAL; + + poa = esw_r32(esw, RT305X_ESW_REG_POA) >> port; + + link->link = (poa >> RT305X_ESW_LINK_S) & 1; + link->duplex = (poa >> RT305X_ESW_DUPLEX_S) & 1; + if (port < RT305X_ESW_NUM_LEDS) { + speed = (poa >> RT305X_ESW_SPD_S) & 1; + } else { + if (port == RT305X_ESW_NUM_PORTS - 1) + poa >>= 1; + speed = (poa >> RT305X_ESW_SPD_S) & 3; + } + switch (speed) { + case 0: + link->speed = SWITCH_PORT_SPEED_10; + break; + case 1: + link->speed = SWITCH_PORT_SPEED_100; + break; + case 2: + case 3: /* forced gige speed can be 2 or 3 */ + link->speed = SWITCH_PORT_SPEED_1000; + break; + default: + link->speed = SWITCH_PORT_SPEED_UNKNOWN; + break; + } + + return 0; +} + +static int esw_get_port_bool(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + int idx = val->port_vlan; + u32 x, reg, shift; + + if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS) + return -EINVAL; + + switch (attr->id) { + case RT305X_ESW_ATTR_PORT_DISABLE: + reg = RT305X_ESW_REG_POC0; + shift = RT305X_ESW_POC0_DIS_PORT_S; + break; + case RT305X_ESW_ATTR_PORT_DOUBLETAG: + reg = RT305X_ESW_REG_SGC2; + shift = RT305X_ESW_SGC2_DOUBLE_TAG_S; + break; + case RT305X_ESW_ATTR_PORT_UNTAG: + reg = RT305X_ESW_REG_POC2; + shift = RT305X_ESW_POC2_UNTAG_EN_S; + break; + case RT305X_ESW_ATTR_PORT_LAN: + reg = RT305X_ESW_REG_SGC2; + shift = RT305X_ESW_SGC2_LAN_PMAP_S; + if (idx >= RT305X_ESW_NUM_LANWAN) + return -EINVAL; + break; + default: + return -EINVAL; + } + + x = esw_r32(esw, reg); + val->value.i = (x >> (idx + shift)) & 1; + + return 0; +} + +static int esw_set_port_bool(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + int idx = val->port_vlan; + + if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS || + val->value.i < 0 || val->value.i > 1) + return -EINVAL; + + switch (attr->id) { + case RT305X_ESW_ATTR_PORT_DISABLE: + esw->ports[idx].disable = val->value.i; + break; + case RT305X_ESW_ATTR_PORT_DOUBLETAG: + esw->ports[idx].doubletag = val->value.i; + break; + case RT305X_ESW_ATTR_PORT_UNTAG: + esw->ports[idx].untag = val->value.i; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int esw_get_port_recv_badgood(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + int idx = val->port_vlan; + int shift = attr->id == RT305X_ESW_ATTR_PORT_RECV_GOOD ? 0 : 16; + u32 reg; + + if (idx < 0 || idx >= RT305X_ESW_NUM_LANWAN) + return -EINVAL; + reg = esw_r32(esw, RT305X_ESW_REG_PXPC(idx)); + val->value.i = (reg >> shift) & 0xffff; + + return 0; +} + +static int +esw_get_port_tr_badgood(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + int idx = val->port_vlan; + int shift = attr->id == RT5350_ESW_ATTR_PORT_TR_GOOD ? 0 : 16; + u32 reg; + + if ((ralink_soc != RT305X_SOC_RT5350) && (ralink_soc != MT762X_SOC_MT7628AN)) + return -EINVAL; + + if (idx < 0 || idx >= RT305X_ESW_NUM_LANWAN) + return -EINVAL; + + reg = esw_r32(esw, RT5350_ESW_REG_PXTPC(idx)); + val->value.i = (reg >> shift) & 0xffff; + + return 0; +} + +static int esw_get_port_led(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + int idx = val->port_vlan; + + if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS || + idx >= RT305X_ESW_NUM_LEDS) + return -EINVAL; + + val->value.i = esw_r32(esw, RT305X_ESW_REG_P0LED + 4*idx); + + return 0; +} + +static int esw_set_port_led(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + int idx = val->port_vlan; + + if (idx < 0 || idx >= RT305X_ESW_NUM_LEDS) + return -EINVAL; + + esw->ports[idx].led = val->value.i; + + return 0; +} + +static int esw_get_port_pvid(struct switch_dev *dev, int port, int *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + if (port >= RT305X_ESW_NUM_PORTS) + return -EINVAL; + + *val = esw_get_pvid(esw, port); + + return 0; +} + +static int esw_set_port_pvid(struct switch_dev *dev, int port, int val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + + if (port >= RT305X_ESW_NUM_PORTS) + return -EINVAL; + + esw->ports[port].pvid = val; + + return 0; +} + +static int esw_get_vlan_ports(struct switch_dev *dev, struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + u32 vmsc, poc2; + int vlan_idx = -1; + int i; + + val->len = 0; + + if (val->port_vlan < 0 || val->port_vlan >= RT305X_ESW_NUM_VIDS) + return -EINVAL; + + /* valid vlan? */ + for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) { + if (esw_get_vlan_id(esw, i) == val->port_vlan && + esw_get_vmsc(esw, i) != RT305X_ESW_PORTS_NONE) { + vlan_idx = i; + break; + } + } + + if (vlan_idx == -1) + return -EINVAL; + + vmsc = esw_get_vmsc(esw, vlan_idx); + poc2 = esw_r32(esw, RT305X_ESW_REG_POC2); + + for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) { + struct switch_port *p; + int port_mask = 1 << i; + + if (!(vmsc & port_mask)) + continue; + + p = &val->value.ports[val->len++]; + p->id = i; + if (poc2 & (port_mask << RT305X_ESW_POC2_UNTAG_EN_S)) + p->flags = 0; + else + p->flags = 1 << SWITCH_PORT_FLAG_TAGGED; + } + + return 0; +} + +static int esw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val) +{ + struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); + int ports; + int vlan_idx = -1; + int i; + + if (val->port_vlan < 0 || val->port_vlan >= RT305X_ESW_NUM_VIDS || + val->len > RT305X_ESW_NUM_PORTS) + return -EINVAL; + + /* one of the already defined vlans? */ + for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) { + if (esw->vlans[i].vid == val->port_vlan && + esw->vlans[i].ports != RT305X_ESW_PORTS_NONE) { + vlan_idx = i; + break; + } + } + + /* select a free slot */ + for (i = 0; vlan_idx == -1 && i < RT305X_ESW_NUM_VLANS; i++) { + if (esw->vlans[i].ports == RT305X_ESW_PORTS_NONE) + vlan_idx = i; + } + + /* bail if all slots are in use */ + if (vlan_idx == -1) + return -EINVAL; + + ports = RT305X_ESW_PORTS_NONE; + for (i = 0; i < val->len; i++) { + struct switch_port *p = &val->value.ports[i]; + int port_mask = 1 << p->id; + bool untagged = !(p->flags & (1 << SWITCH_PORT_FLAG_TAGGED)); + + if (p->id >= RT305X_ESW_NUM_PORTS) + return -EINVAL; + + ports |= port_mask; + esw->ports[p->id].untag = untagged; + } + esw->vlans[vlan_idx].ports = ports; + if (ports == RT305X_ESW_PORTS_NONE) + esw->vlans[vlan_idx].vid = RT305X_ESW_VLAN_NONE; + else + esw->vlans[vlan_idx].vid = val->port_vlan; + + return 0; +} + +static const struct switch_attr esw_global[] = { + { + .type = SWITCH_TYPE_INT, + .name = "enable_vlan", + .description = "VLAN mode (1:enabled)", + .max = 1, + .id = RT305X_ESW_ATTR_ENABLE_VLAN, + .get = esw_get_vlan_enable, + .set = esw_set_vlan_enable, + }, + { + .type = SWITCH_TYPE_INT, + .name = "alternate_vlan_disable", + .description = "Use en_vlan instead of doubletag to disable" + " VLAN mode", + .max = 1, + .id = RT305X_ESW_ATTR_ALT_VLAN_DISABLE, + .get = esw_get_alt_vlan_disable, + .set = esw_set_alt_vlan_disable, + }, + { + .type = SWITCH_TYPE_INT, + .name = "bc_storm_protect", + .description = "Global broadcast storm protection (0:Disable, 1:64 blocks, 2:96 blocks, 3:128 blocks)", + .max = 3, + .id = RT305X_ESW_ATTR_BC_STATUS, + .get = rt305x_esw_get_bc_status, + .set = rt305x_esw_set_bc_status, + }, + { + .type = SWITCH_TYPE_INT, + .name = "led_frequency", + .description = "LED Flash frequency (0:30mS, 1:60mS, 2:240mS, 3:480mS)", + .max = 3, + .id = RT305X_ESW_ATTR_LED_FREQ, + .get = rt305x_esw_get_led_freq, + .set = rt305x_esw_set_led_freq, + } +}; + +static const struct switch_attr esw_port[] = { + { + .type = SWITCH_TYPE_INT, + .name = "disable", + .description = "Port state (1:disabled)", + .max = 1, + .id = RT305X_ESW_ATTR_PORT_DISABLE, + .get = esw_get_port_bool, + .set = esw_set_port_bool, + }, + { + .type = SWITCH_TYPE_INT, + .name = "doubletag", + .description = "Double tagging for incoming vlan packets " + "(1:enabled)", + .max = 1, + .id = RT305X_ESW_ATTR_PORT_DOUBLETAG, + .get = esw_get_port_bool, + .set = esw_set_port_bool, + }, + { + .type = SWITCH_TYPE_INT, + .name = "untag", + .description = "Untag (1:strip outgoing vlan tag)", + .max = 1, + .id = RT305X_ESW_ATTR_PORT_UNTAG, + .get = esw_get_port_bool, + .set = esw_set_port_bool, + }, + { + .type = SWITCH_TYPE_INT, + .name = "led", + .description = "LED mode (0:link, 1:100m, 2:duplex, 3:activity," + " 4:collision, 5:linkact, 6:duplcoll, 7:10mact," + " 8:100mact, 10:blink, 11:off, 12:on)", + .max = 15, + .id = RT305X_ESW_ATTR_PORT_LED, + .get = esw_get_port_led, + .set = esw_set_port_led, + }, + { + .type = SWITCH_TYPE_INT, + .name = "lan", + .description = "HW port group (0:wan, 1:lan)", + .max = 1, + .id = RT305X_ESW_ATTR_PORT_LAN, + .get = esw_get_port_bool, + }, + { + .type = SWITCH_TYPE_INT, + .name = "recv_bad", + .description = "Receive bad packet counter", + .id = RT305X_ESW_ATTR_PORT_RECV_BAD, + .get = esw_get_port_recv_badgood, + }, + { + .type = SWITCH_TYPE_INT, + .name = "recv_good", + .description = "Receive good packet counter", + .id = RT305X_ESW_ATTR_PORT_RECV_GOOD, + .get = esw_get_port_recv_badgood, + }, + { + .type = SWITCH_TYPE_INT, + .name = "tr_bad", + + .description = "Transmit bad packet counter. rt5350 only", + .id = RT5350_ESW_ATTR_PORT_TR_BAD, + .get = esw_get_port_tr_badgood, + }, + { + .type = SWITCH_TYPE_INT, + .name = "tr_good", + + .description = "Transmit good packet counter. rt5350 only", + .id = RT5350_ESW_ATTR_PORT_TR_GOOD, + .get = esw_get_port_tr_badgood, + }, +}; + +static const struct switch_attr esw_vlan[] = { +}; + +static const struct switch_dev_ops esw_ops = { + .attr_global = { + .attr = esw_global, + .n_attr = ARRAY_SIZE(esw_global), + }, + .attr_port = { + .attr = esw_port, + .n_attr = ARRAY_SIZE(esw_port), + }, + .attr_vlan = { + .attr = esw_vlan, + .n_attr = ARRAY_SIZE(esw_vlan), + }, + .get_vlan_ports = esw_get_vlan_ports, + .set_vlan_ports = esw_set_vlan_ports, + .get_port_pvid = esw_get_port_pvid, + .set_port_pvid = esw_set_port_pvid, + .get_port_link = esw_get_port_link, + .apply_config = esw_apply_config, + .reset_switch = esw_reset_switch, +}; + +static struct rt305x_esw_platform_data rt3050_esw_data = { + /* All ports are LAN ports. */ + .vlan_config = RT305X_ESW_VLAN_CONFIG_NONE, + .reg_initval_fct2 = 0x00d6500c, + /* + * ext phy base addr 31, enable port 5 polling, rx/tx clock skew 1, + * turbo mii off, rgmi 3.3v off + * port5: disabled + * port6: enabled, gige, full-duplex, rx/tx-flow-control + */ + .reg_initval_fpa2 = 0x3f502b28, +}; + +static const struct of_device_id ralink_esw_match[] = { + { .compatible = "ralink,rt3050-esw", .data = &rt3050_esw_data }, + {}, +}; +MODULE_DEVICE_TABLE(of, ralink_esw_match); + +static int esw_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + const struct rt305x_esw_platform_data *pdata; + const __be32 *port_map, *reg_init; + struct rt305x_esw *esw; + struct switch_dev *swdev; + struct resource *res, *irq; + int err; + + pdata = pdev->dev.platform_data; + if (!pdata) { + const struct of_device_id *match; + match = of_match_device(ralink_esw_match, &pdev->dev); + if (match) + pdata = (struct rt305x_esw_platform_data *) match->data; + } + if (!pdata) + return -EINVAL; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "no memory resource found\n"); + return -ENOMEM; + } + + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!irq) { + dev_err(&pdev->dev, "no irq resource found\n"); + return -ENOMEM; + } + + esw = kzalloc(sizeof(struct rt305x_esw), GFP_KERNEL); + if (!esw) { + dev_err(&pdev->dev, "no memory for private data\n"); + return -ENOMEM; + } + + esw->dev = &pdev->dev; + esw->irq = irq->start; + esw->base = ioremap(res->start, resource_size(res)); + if (!esw->base) { + dev_err(&pdev->dev, "ioremap failed\n"); + err = -ENOMEM; + goto free_esw; + } + + port_map = of_get_property(np, "ralink,portmap", NULL); + if (port_map) + esw->port_map = be32_to_cpu(*port_map); + + reg_init = of_get_property(np, "ralink,fct2", NULL); + if (reg_init) + esw->reg_initval_fct2 = be32_to_cpu(*reg_init); + + reg_init = of_get_property(np, "ralink,fpa2", NULL); + if (reg_init) + esw->reg_initval_fpa2 = be32_to_cpu(*reg_init); + + reg_init = of_get_property(np, "ralink,led_polarity", NULL); + if (reg_init) + esw->reg_led_polarity = be32_to_cpu(*reg_init); + + swdev = &esw->swdev; + swdev->of_node = pdev->dev.of_node; + swdev->name = "rt305x-esw"; + swdev->alias = "rt305x"; + swdev->cpu_port = RT305X_ESW_PORT6; + swdev->ports = RT305X_ESW_NUM_PORTS; + swdev->vlans = RT305X_ESW_NUM_VIDS; + swdev->ops = &esw_ops; + + err = register_switch(swdev, NULL); + if (err < 0) { + dev_err(&pdev->dev, "register_switch failed\n"); + goto unmap_base; + } + + platform_set_drvdata(pdev, esw); + + esw->pdata = pdata; + spin_lock_init(&esw->reg_rw_lock); + + esw_hw_init(esw); + + esw_w32(esw, RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_ISR); + esw_w32(esw, ~RT305X_ESW_PORT_ST_CHG, RT305X_ESW_REG_IMR); + request_irq(esw->irq, esw_interrupt, 0, "esw", esw); + + return 0; + +unmap_base: + iounmap(esw->base); +free_esw: + kfree(esw); + return err; +} + +static int esw_remove(struct platform_device *pdev) +{ + struct rt305x_esw *esw; + + esw = platform_get_drvdata(pdev); + if (esw) { + unregister_switch(&esw->swdev); + platform_set_drvdata(pdev, NULL); + iounmap(esw->base); + kfree(esw); + } + + return 0; +} + +static struct platform_driver esw_driver = { + .probe = esw_probe, + .remove = esw_remove, + .driver = { + .name = "rt305x-esw", + .owner = THIS_MODULE, + .of_match_table = ralink_esw_match, + }, +}; + +int __init rtesw_init(void) +{ + return platform_driver_register(&esw_driver); +} + +void rtesw_exit(void) +{ + platform_driver_unregister(&esw_driver); +} diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3052.h b/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3052.h new file mode 100644 index 0000000..2ced3df --- /dev/null +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/esw_rt3052.h @@ -0,0 +1,32 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2009-2013 John Crispin <blogic@openwrt.org> + */ + +#ifndef _RALINK_ESW_RT3052_H__ +#define _RALINK_ESW_RT3052_H__ + +#ifdef CONFIG_NET_RALINK_ESW_RT3052 + +int __init rtesw_init(void); +void rtesw_exit(void); + +#else + +static inline int __init rtesw_init(void) { return 0; } +static inline void rtesw_exit(void) { } + +#endif +#endif diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620a.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620a.c new file mode 100644 index 0000000..325e243 --- /dev/null +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620a.c @@ -0,0 +1,801 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2009-2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/dma-mapping.h> +#include <linux/init.h> +#include <linux/skbuff.h> +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/platform_device.h> +#include <linux/of_device.h> +#include <linux/clk.h> +#include <linux/of_net.h> +#include <linux/of_mdio.h> +#include <linux/of_irq.h> +#include <linux/of_address.h> +#include <linux/switch.h> + +#include <asm/mach-ralink/ralink_regs.h> + +#include "ralink_soc_eth.h" + +#include <linux/ioport.h> +#include <linux/switch.h> +#include <linux/mii.h> + +#include <ralink_regs.h> +#include <asm/mach-ralink/mt7620.h> + +#include "ralink_soc_eth.h" +#include "gsw_mt7620a.h" +#include "mt7530.h" +#include "mdio.h" + +#define GSW_REG_PHY_TIMEOUT (5 * HZ) + +#ifdef CONFIG_SOC_MT7621 +#define MT7620A_GSW_REG_PIAC 0x0004 +#else +#define MT7620A_GSW_REG_PIAC 0x7004 +#endif + +#define GSW_NUM_VLANS 16 +#define GSW_NUM_VIDS 4096 +#define GSW_NUM_PORTS 7 +#define GSW_PORT6 6 + +#define GSW_MDIO_ACCESS BIT(31) +#define GSW_MDIO_READ BIT(19) +#define GSW_MDIO_WRITE BIT(18) +#define GSW_MDIO_START BIT(16) +#define GSW_MDIO_ADDR_SHIFT 20 +#define GSW_MDIO_REG_SHIFT 25 + +#define GSW_REG_PORT_PMCR(x) (0x3000 + (x * 0x100)) +#define GSW_REG_PORT_STATUS(x) (0x3008 + (x * 0x100)) +#define GSW_REG_SMACCR0 0x3fE4 +#define GSW_REG_SMACCR1 0x3fE8 +#define GSW_REG_CKGCR 0x3ff0 + +#define GSW_REG_IMR 0x7008 +#define GSW_REG_ISR 0x700c +#define GSW_REG_GPC1 0x7014 + +#define SYSC_REG_CHIP_REV_ID 0x0c +#define SYSC_REG_CFG1 0x14 +#define RST_CTRL_MCM BIT(2) +#define SYSC_PAD_RGMII2_MDIO 0x58 +#define SYSC_GPIO_MODE 0x60 + +#define PORT_IRQ_ST_CHG 0x7f + + +#ifdef CONFIG_SOC_MT7621 +#define ESW_PHY_POLLING 0x0000 +#else +#define ESW_PHY_POLLING 0x7000 +#endif + +#define PMCR_IPG BIT(18) +#define PMCR_MAC_MODE BIT(16) +#define PMCR_FORCE BIT(15) +#define PMCR_TX_EN BIT(14) +#define PMCR_RX_EN BIT(13) +#define PMCR_BACKOFF BIT(9) +#define PMCR_BACKPRES BIT(8) +#define PMCR_RX_FC BIT(5) +#define PMCR_TX_FC BIT(4) +#define PMCR_SPEED(_x) (_x << 2) +#define PMCR_DUPLEX BIT(1) +#define PMCR_LINK BIT(0) + +#define PHY_AN_EN BIT(31) +#define PHY_PRE_EN BIT(30) +#define PMY_MDC_CONF(_x) ((_x & 0x3f) << 24) + +enum { + /* Global attributes. */ + GSW_ATTR_ENABLE_VLAN, + /* Port attributes. */ + GSW_ATTR_PORT_UNTAG, +}; + +enum { + PORT4_EPHY = 0, + PORT4_EXT, +}; + +struct mt7620_gsw { + struct device *dev; + void __iomem *base; + int irq; + int port4; + long unsigned int autopoll; +}; + +static inline void gsw_w32(struct mt7620_gsw *gsw, u32 val, unsigned reg) +{ + iowrite32(val, gsw->base + reg); +} + +static inline u32 gsw_r32(struct mt7620_gsw *gsw, unsigned reg) +{ + return ioread32(gsw->base + reg); +} + +static int mt7620_mii_busy_wait(struct mt7620_gsw *gsw) +{ + unsigned long t_start = jiffies; + + while (1) { + if (!(gsw_r32(gsw, MT7620A_GSW_REG_PIAC) & GSW_MDIO_ACCESS)) + return 0; + if (time_after(jiffies, t_start + GSW_REG_PHY_TIMEOUT)) { + break; + } + } + + printk(KERN_ERR "mdio: MDIO timeout\n"); + return -1; +} + +static u32 _mt7620_mii_write(struct mt7620_gsw *gsw, u32 phy_addr, u32 phy_register, + u32 write_data) +{ + if (mt7620_mii_busy_wait(gsw)) + return -1; + + write_data &= 0xffff; + + gsw_w32(gsw, GSW_MDIO_ACCESS | GSW_MDIO_START | GSW_MDIO_WRITE | + (phy_register << GSW_MDIO_REG_SHIFT) | + (phy_addr << GSW_MDIO_ADDR_SHIFT) | write_data, + MT7620A_GSW_REG_PIAC); + + if (mt7620_mii_busy_wait(gsw)) + return -1; + + return 0; +} + +static u32 _mt7620_mii_read(struct mt7620_gsw *gsw, int phy_addr, int phy_reg) +{ + u32 d; + + if (mt7620_mii_busy_wait(gsw)) + return 0xffff; + + gsw_w32(gsw, GSW_MDIO_ACCESS | GSW_MDIO_START | GSW_MDIO_READ | + (phy_reg << GSW_MDIO_REG_SHIFT) | + (phy_addr << GSW_MDIO_ADDR_SHIFT), + MT7620A_GSW_REG_PIAC); + + if (mt7620_mii_busy_wait(gsw)) + return 0xffff; + + d = gsw_r32(gsw, MT7620A_GSW_REG_PIAC) & 0xffff; + + return d; +} + +int mt7620_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val) +{ + struct fe_priv *priv = bus->priv; + struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv; + + return _mt7620_mii_write(gsw, phy_addr, phy_reg, val); +} + +int mt7620_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg) +{ + struct fe_priv *priv = bus->priv; + struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv; + + return _mt7620_mii_read(gsw, phy_addr, phy_reg); +} + +static void +mt7530_mdio_w32(struct mt7620_gsw *gsw, u32 reg, u32 val) +{ + _mt7620_mii_write(gsw, 0x1f, 0x1f, (reg >> 6) & 0x3ff); + _mt7620_mii_write(gsw, 0x1f, (reg >> 2) & 0xf, val & 0xffff); + _mt7620_mii_write(gsw, 0x1f, 0x10, val >> 16); +} + +static u32 +mt7530_mdio_r32(struct mt7620_gsw *gsw, u32 reg) +{ + u16 high, low; + + _mt7620_mii_write(gsw, 0x1f, 0x1f, (reg >> 6) & 0x3ff); + low = _mt7620_mii_read(gsw, 0x1f, (reg >> 2) & 0xf); + high = _mt7620_mii_read(gsw, 0x1f, 0x10); + + return (high << 16) | (low & 0xffff); +} + +static unsigned char *fe_speed_str(int speed) +{ + switch (speed) { + case 2: + case SPEED_1000: + return "1000"; + case 1: + case SPEED_100: + return "100"; + case 0: + case SPEED_10: + return "10"; + } + + return "? "; +} + +int mt7620a_has_carrier(struct fe_priv *priv) +{ + struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv; + int i; + + for (i = 0; i < GSW_PORT6; i++) + if (gsw_r32(gsw, GSW_REG_PORT_STATUS(i)) & 0x1) + return 1; + return 0; +} + +static void mt7620a_handle_carrier(struct fe_priv *priv) +{ + if (!priv->phy) + return; + + if (mt7620a_has_carrier(priv)) + netif_carrier_on(priv->netdev); + else + netif_carrier_off(priv->netdev); +} + +void mt7620_mdio_link_adjust(struct fe_priv *priv, int port) +{ + if (priv->link[port]) + netdev_info(priv->netdev, "port %d link up (%sMbps/%s duplex)\n", + port, fe_speed_str(priv->phy->speed[port]), + (DUPLEX_FULL == priv->phy->duplex[port]) ? "Full" : "Half"); + else + netdev_info(priv->netdev, "port %d link down\n", port); + mt7620a_handle_carrier(priv); +} + +static irqreturn_t gsw_interrupt_mt7620(int irq, void *_priv) +{ + struct fe_priv *priv = (struct fe_priv *) _priv; + struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv; + u32 status; + int i, max = (gsw->port4 == PORT4_EPHY) ? (4) : (3); + + status = gsw_r32(gsw, GSW_REG_ISR); + if (status & PORT_IRQ_ST_CHG) + for (i = 0; i <= max; i++) { + u32 status = gsw_r32(gsw, GSW_REG_PORT_STATUS(i)); + int link = status & 0x1; + + if (link != priv->link[i]) { + if (link) + netdev_info(priv->netdev, "port %d link up (%sMbps/%s duplex)\n", + i, fe_speed_str((status >> 2) & 3), + (status & 0x2) ? "Full" : "Half"); + else + netdev_info(priv->netdev, "port %d link down\n", i); + } + + priv->link[i] = link; + } + mt7620a_handle_carrier(priv); + + gsw_w32(gsw, status, GSW_REG_ISR); + + return IRQ_HANDLED; +} + +static irqreturn_t gsw_interrupt_mt7621(int irq, void *_priv) +{ + struct fe_priv *priv = (struct fe_priv *) _priv; + struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv; + u32 reg, i; + + reg = mt7530_mdio_r32(gsw, 0x700c); + + for (i = 0; i < 5; i++) + if (reg & BIT(i)) { + unsigned int link = mt7530_mdio_r32(gsw, 0x3008 + (i * 0x100)) & 0x1; + + if (link != priv->link[i]) { + priv->link[i] = link; + if (link) + netdev_info(priv->netdev, "port %d link up\n", i); + else + netdev_info(priv->netdev, "port %d link down\n", i); + } + } + + mt7620a_handle_carrier(priv); + mt7530_mdio_w32(gsw, 0x700c, 0x1f); + + return IRQ_HANDLED; +} + +static int mt7620_is_bga(void) +{ + u32 bga = rt_sysc_r32(0x0c); + + return (bga >> 16) & 1; +} + +static void gsw_auto_poll(struct mt7620_gsw *gsw) +{ + int phy; + int lsb = -1, msb = 0; + + for_each_set_bit(phy, &gsw->autopoll, 32) { + if (lsb < 0) + lsb = phy; + msb = phy; + } + + if (lsb == msb) + lsb--; + + gsw_w32(gsw, PHY_AN_EN | PHY_PRE_EN | PMY_MDC_CONF(5) | (msb << 8) | lsb, ESW_PHY_POLLING); +} + +void mt7620_port_init(struct fe_priv *priv, struct device_node *np) +{ + struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv; + const __be32 *_id = of_get_property(np, "reg", NULL); + int phy_mode, size, id; + int shift = 12; + u32 val, mask = 0; + int min = (gsw->port4 == PORT4_EPHY) ? (5) : (4); + + if (!_id || (be32_to_cpu(*_id) < min) || (be32_to_cpu(*_id) > 5)) { + if (_id) + pr_err("%s: invalid port id %d\n", np->name, be32_to_cpu(*_id)); + else + pr_err("%s: invalid port id\n", np->name); + return; + } + + id = be32_to_cpu(*_id); + + if (id == 4) + shift = 14; + + priv->phy->phy_fixed[id] = of_get_property(np, "ralink,fixed-link", &size); + if (priv->phy->phy_fixed[id] && (size != (4 * sizeof(*priv->phy->phy_fixed[id])))) { + pr_err("%s: invalid fixed link property\n", np->name); + priv->phy->phy_fixed[id] = NULL; + return; + } + + phy_mode = of_get_phy_mode(np); + switch (phy_mode) { + case PHY_INTERFACE_MODE_RGMII: + mask = 0; + break; + case PHY_INTERFACE_MODE_MII: + mask = 1; + break; + case PHY_INTERFACE_MODE_RMII: + mask = 2; + break; + default: + dev_err(priv->device, "port %d - invalid phy mode\n", id); + return; + } + + priv->phy->phy_node[id] = of_parse_phandle(np, "phy-handle", 0); + if (!priv->phy->phy_node[id] && !priv->phy->phy_fixed[id]) + return; + + val = rt_sysc_r32(SYSC_REG_CFG1); + val &= ~(3 << shift); + val |= mask << shift; + rt_sysc_w32(val, SYSC_REG_CFG1); + + if (priv->phy->phy_fixed[id]) { + const __be32 *link = priv->phy->phy_fixed[id]; + int tx_fc, rx_fc; + u32 val = 0; + + priv->phy->speed[id] = be32_to_cpup(link++); + tx_fc = be32_to_cpup(link++); + rx_fc = be32_to_cpup(link++); + priv->phy->duplex[id] = be32_to_cpup(link++); + priv->link[id] = 1; + + switch (priv->phy->speed[id]) { + case SPEED_10: + val = 0; + break; + case SPEED_100: + val = 1; + break; + case SPEED_1000: + val = 2; + break; + default: + dev_err(priv->device, "invalid link speed: %d\n", priv->phy->speed[id]); + priv->phy->phy_fixed[id] = 0; + return; + } + val = PMCR_SPEED(val); + val |= PMCR_LINK | PMCR_BACKPRES | PMCR_BACKOFF | PMCR_RX_EN | + PMCR_TX_EN | PMCR_FORCE | PMCR_MAC_MODE | PMCR_IPG; + if (tx_fc) + val |= PMCR_TX_FC; + if (rx_fc) + val |= PMCR_RX_FC; + if (priv->phy->duplex[id]) + val |= PMCR_DUPLEX; + gsw_w32(gsw, val, GSW_REG_PORT_PMCR(id)); + dev_info(priv->device, "using fixed link parameters\n"); + return; + } + + if (priv->phy->phy_node[id] && priv->mii_bus->phy_map[id]) { + u32 val = PMCR_BACKPRES | PMCR_BACKOFF | PMCR_RX_EN | + PMCR_TX_EN | PMCR_MAC_MODE | PMCR_IPG; + + gsw_w32(gsw, val, GSW_REG_PORT_PMCR(id)); + fe_connect_phy_node(priv, priv->phy->phy_node[id]); + gsw->autopoll |= BIT(id); + gsw_auto_poll(gsw); + return; + } +} + +static void gsw_hw_init_mt7620(struct mt7620_gsw *gsw, struct device_node *np) +{ + u32 is_BGA = mt7620_is_bga(); + + rt_sysc_w32(rt_sysc_r32(SYSC_REG_CFG1) | BIT(8), SYSC_REG_CFG1); + gsw_w32(gsw, gsw_r32(gsw, GSW_REG_CKGCR) & ~(0x3 << 4), GSW_REG_CKGCR); + + if (of_property_read_bool(np, "mediatek,mt7530")) { + u32 val; + + /* turn off ephy and set phy base addr to 12 */ + gsw_w32(gsw, gsw_r32(gsw, GSW_REG_GPC1) | (0x1f << 24) | (0xc << 16), GSW_REG_GPC1); + + /* set MT7530 central align */ + val = mt7530_mdio_r32(gsw, 0x7830); + val &= ~1; + val |= 1<<1; + mt7530_mdio_w32(gsw, 0x7830, val); + + val = mt7530_mdio_r32(gsw, 0x7a40); + val &= ~(1<<30); + mt7530_mdio_w32(gsw, 0x7a40, val); + + mt7530_mdio_w32(gsw, 0x7a78, 0x855); + } else { + /* EPHY1 fixup - only run if the ephy is enabled */ + + /*correct PHY setting L3.0 BGA*/ + _mt7620_mii_write(gsw, 1, 31, 0x4000); //global, page 4 + + _mt7620_mii_write(gsw, 1, 17, 0x7444); + if (is_BGA) + _mt7620_mii_write(gsw, 1, 19, 0x0114); + else + _mt7620_mii_write(gsw, 1, 19, 0x0117); + + _mt7620_mii_write(gsw, 1, 22, 0x10cf); + _mt7620_mii_write(gsw, 1, 25, 0x6212); + _mt7620_mii_write(gsw, 1, 26, 0x0777); + _mt7620_mii_write(gsw, 1, 29, 0x4000); + _mt7620_mii_write(gsw, 1, 28, 0xc077); + _mt7620_mii_write(gsw, 1, 24, 0x0000); + + _mt7620_mii_write(gsw, 1, 31, 0x3000); //global, page 3 + _mt7620_mii_write(gsw, 1, 17, 0x4838); + + _mt7620_mii_write(gsw, 1, 31, 0x2000); //global, page 2 + if (is_BGA) { + _mt7620_mii_write(gsw, 1, 21, 0x0515); + _mt7620_mii_write(gsw, 1, 22, 0x0053); + _mt7620_mii_write(gsw, 1, 23, 0x00bf); + _mt7620_mii_write(gsw, 1, 24, 0x0aaf); + _mt7620_mii_write(gsw, 1, 25, 0x0fad); + _mt7620_mii_write(gsw, 1, 26, 0x0fc1); + } else { + _mt7620_mii_write(gsw, 1, 21, 0x0517); + _mt7620_mii_write(gsw, 1, 22, 0x0fd2); + _mt7620_mii_write(gsw, 1, 23, 0x00bf); + _mt7620_mii_write(gsw, 1, 24, 0x0aab); + _mt7620_mii_write(gsw, 1, 25, 0x00ae); + _mt7620_mii_write(gsw, 1, 26, 0x0fff); + } + _mt7620_mii_write(gsw, 1, 31, 0x1000); //global, page 1 + _mt7620_mii_write(gsw, 1, 17, 0xe7f8); + } + + _mt7620_mii_write(gsw, 1, 31, 0x8000); //local, page 0 + _mt7620_mii_write(gsw, 0, 30, 0xa000); + _mt7620_mii_write(gsw, 1, 30, 0xa000); + _mt7620_mii_write(gsw, 2, 30, 0xa000); + _mt7620_mii_write(gsw, 3, 30, 0xa000); + + _mt7620_mii_write(gsw, 0, 4, 0x05e1); + _mt7620_mii_write(gsw, 1, 4, 0x05e1); + _mt7620_mii_write(gsw, 2, 4, 0x05e1); + _mt7620_mii_write(gsw, 3, 4, 0x05e1); + + _mt7620_mii_write(gsw, 1, 31, 0xa000); //local, page 2 + _mt7620_mii_write(gsw, 0, 16, 0x1111); + _mt7620_mii_write(gsw, 1, 16, 0x1010); + _mt7620_mii_write(gsw, 2, 16, 0x1515); + _mt7620_mii_write(gsw, 3, 16, 0x0f0f); + + /* CPU Port6 Force Link 1G, FC ON */ + gsw_w32(gsw, 0x5e33b, GSW_REG_PORT_PMCR(6)); + /* Set Port6 CPU Port */ + gsw_w32(gsw, 0x7f7f7fe0, 0x0010); + + /* setup port 4 */ + if (gsw->port4 == PORT4_EPHY) { + u32 val = rt_sysc_r32(SYSC_REG_CFG1); + val |= 3 << 14; + rt_sysc_w32(val, SYSC_REG_CFG1); + _mt7620_mii_write(gsw, 4, 30, 0xa000); + _mt7620_mii_write(gsw, 4, 4, 0x05e1); + _mt7620_mii_write(gsw, 4, 16, 0x1313); + pr_info("gsw: setting port4 to ephy mode\n"); + } +} + +static void gsw_hw_init_mt7621(struct mt7620_gsw *gsw, struct device_node *np) +{ + u32 i; + u32 val; + + /* Hardware reset Switch */ + fe_reset(RST_CTRL_MCM); + udelay(10000); + + /* reduce RGMII2 PAD driving strength */ + rt_sysc_m32(3 << 4, 0, SYSC_PAD_RGMII2_MDIO); + + /* gpio mux - RGMII1=Normal mode */ + rt_sysc_m32(BIT(14), 0, SYSC_GPIO_MODE); + + //GMAC1= RGMII mode + rt_sysc_m32(3 << 12, 0, SYSC_REG_CFG1); + + /* enable MDIO to control MT7530 */ + rt_sysc_m32(3 << 12, 0, SYSC_GPIO_MODE); + + /* turn off all PHYs */ + for (i = 0; i <= 4; i++) { + val = _mt7620_mii_read(gsw, i, 0x0); + val |= (0x1 << 11); + _mt7620_mii_write(gsw, i, 0x0, val); + } + + /* reset the switch */ + mt7530_mdio_w32(gsw, 0x7000, 0x3); + udelay(10); + + if ((rt_sysc_r32(SYSC_REG_CHIP_REV_ID) & 0xFFFF) == 0x0101) { + /* (GE1, Force 1000M/FD, FC ON, MAX_RX_LENGTH 1536) */ + gsw_w32(gsw, 0x2105e30b, 0x100); + mt7530_mdio_w32(gsw, 0x3600, 0x5e30b); + } else { + /* (GE1, Force 1000M/FD, FC ON, MAX_RX_LENGTH 1536) */ + gsw_w32(gsw, 0x2105e33b, 0x100); + mt7530_mdio_w32(gsw, 0x3600, 0x5e33b); + } + + /* (GE2, Link down) */ + gsw_w32(gsw, 0x8000, 0x200); + + //val = 0x117ccf; //Enable Port 6, P5 as GMAC5, P5 disable + val = mt7530_mdio_r32(gsw, 0x7804); + val &= ~(1<<8); //Enable Port 6 + val |= (1<<6); //Disable Port 5 + val |= (1<<13); //Port 5 as GMAC, no Internal PHY + + val |= (1<<16);//change HW-TRAP + printk("change HW-TRAP to 0x%x\n", val); + mt7530_mdio_w32(gsw, 0x7804, val); + + val = rt_sysc_r32(0x10); + val = (val >> 6) & 0x7; + if (val >= 6) { + /* 25Mhz Xtal - do nothing */ + } else if(val >=3) { + /* 40Mhz */ + + /* disable MT7530 core clock */ + _mt7620_mii_write(gsw, 0, 13, 0x1f); + _mt7620_mii_write(gsw, 0, 14, 0x410); + _mt7620_mii_write(gsw, 0, 13, 0x401f); + _mt7620_mii_write(gsw, 0, 14, 0x0); + + /* disable MT7530 PLL */ + _mt7620_mii_write(gsw, 0, 13, 0x1f); + _mt7620_mii_write(gsw, 0, 14, 0x40d); + _mt7620_mii_write(gsw, 0, 13, 0x401f); + _mt7620_mii_write(gsw, 0, 14, 0x2020); + + /* for MT7530 core clock = 500Mhz */ + _mt7620_mii_write(gsw, 0, 13, 0x1f); + _mt7620_mii_write(gsw, 0, 14, 0x40e); + _mt7620_mii_write(gsw, 0, 13, 0x401f); + _mt7620_mii_write(gsw, 0, 14, 0x119); + + /* enable MT7530 PLL */ + _mt7620_mii_write(gsw, 0, 13, 0x1f); + _mt7620_mii_write(gsw, 0, 14, 0x40d); + _mt7620_mii_write(gsw, 0, 13, 0x401f); + _mt7620_mii_write(gsw, 0, 14, 0x2820); + + udelay(20); + + /* enable MT7530 core clock */ + _mt7620_mii_write(gsw, 0, 13, 0x1f); + _mt7620_mii_write(gsw, 0, 14, 0x410); + _mt7620_mii_write(gsw, 0, 13, 0x401f); + } else { + /* 20Mhz Xtal - TODO */ + } + + /* RGMII */ + _mt7620_mii_write(gsw, 0, 14, 0x1); + + /* set MT7530 central align */ + val = mt7530_mdio_r32(gsw, 0x7830); + val &= ~1; + val |= 1<<1; + mt7530_mdio_w32(gsw, 0x7830, val); + + val = mt7530_mdio_r32(gsw, 0x7a40); + val &= ~(1<<30); + mt7530_mdio_w32(gsw, 0x7a40, val); + + mt7530_mdio_w32(gsw, 0x7a78, 0x855); + mt7530_mdio_w32(gsw, 0x7b00, 0x102); //delay setting for 10/1000M + mt7530_mdio_w32(gsw, 0x7b04, 0x14); //delay setting for 10/1000M + + /*Tx Driving*/ + mt7530_mdio_w32(gsw, 0x7a54, 0x44); //lower driving + mt7530_mdio_w32(gsw, 0x7a5c, 0x44); //lower driving + mt7530_mdio_w32(gsw, 0x7a64, 0x44); //lower driving + mt7530_mdio_w32(gsw, 0x7a6c, 0x44); //lower driving + mt7530_mdio_w32(gsw, 0x7a74, 0x44); //lower driving + mt7530_mdio_w32(gsw, 0x7a7c, 0x44); //lower driving + + //LANWANPartition(); + + /* turn on all PHYs */ + for (i = 0; i <= 4; i++) { + val = _mt7620_mii_read(gsw, i, 0); + val &= ~BIT(11); + _mt7620_mii_write(gsw, i, 0, val); + } + + /* enable irq */ + val = mt7530_mdio_r32(gsw, 0x7808); + val |= 3 << 16; + mt7530_mdio_w32(gsw, 0x7808, val); +} + +void mt7620_set_mac(struct fe_priv *priv, unsigned char *mac) +{ + struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv; + unsigned long flags; + + spin_lock_irqsave(&priv->page_lock, flags); + gsw_w32(gsw, (mac[0] << 8) | mac[1], GSW_REG_SMACCR1); + gsw_w32(gsw, (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5], + GSW_REG_SMACCR0); + spin_unlock_irqrestore(&priv->page_lock, flags); +} + +static struct of_device_id gsw_match[] = { + { .compatible = "ralink,mt7620a-gsw" }, + {} +}; + +int mt7620_gsw_config(struct fe_priv *priv) +{ + struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv; + + /* is the mt7530 internal or external */ + if (priv->mii_bus && priv->mii_bus->phy_map[0x1f]) { + mt7530_probe(priv->device, gsw->base, NULL, 0); + mt7530_probe(priv->device, NULL, priv->mii_bus, 1); + } else { + mt7530_probe(priv->device, gsw->base, NULL, 1); + } + + return 0; +} + +int mt7621_gsw_config(struct fe_priv *priv) +{ + if (priv->mii_bus && priv->mii_bus->phy_map[0x1f]) + mt7530_probe(priv->device, NULL, priv->mii_bus, 1); + + return 0; +} + +int mt7620_gsw_probe(struct fe_priv *priv) +{ + struct mt7620_gsw *gsw; + struct device_node *np; + const char *port4 = NULL; + + np = of_find_matching_node(NULL, gsw_match); + if (!np) { + dev_err(priv->device, "no gsw node found\n"); + return -EINVAL; + } + np = of_node_get(np); + + gsw = devm_kzalloc(priv->device, sizeof(struct mt7620_gsw), GFP_KERNEL); + if (!gsw) { + dev_err(priv->device, "no gsw memory for private data\n"); + return -ENOMEM; + } + + gsw->base = of_iomap(np, 0); + if (!gsw->base) { + dev_err(priv->device, "gsw ioremap failed\n"); + return -ENOMEM; + } + + gsw->dev = priv->device; + priv->soc->swpriv = gsw; + + of_property_read_string(np, "ralink,port4", &port4); + if (port4 && !strcmp(port4, "ephy")) + gsw->port4 = PORT4_EPHY; + else if (port4 && !strcmp(port4, "gmac")) + gsw->port4 = PORT4_EXT; + else + gsw->port4 = PORT4_EPHY; + + if (IS_ENABLED(CONFIG_SOC_MT7620)) + gsw_hw_init_mt7620(gsw, np); + else + gsw_hw_init_mt7621(gsw, np); + + gsw->irq = irq_of_parse_and_map(np, 0); + if (gsw->irq) { + if (IS_ENABLED(CONFIG_SOC_MT7620)) { + request_irq(gsw->irq, gsw_interrupt_mt7620, 0, "gsw", priv); + gsw_w32(gsw, ~PORT_IRQ_ST_CHG, GSW_REG_IMR); + } else { + request_irq(gsw->irq, gsw_interrupt_mt7621, 0, "gsw", priv); + mt7530_mdio_w32(gsw, 0x7008, 0x1f); + } + } + + return 0; +} diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620a.h b/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620a.h new file mode 100644 index 0000000..d75adf9 --- /dev/null +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/gsw_mt7620a.h @@ -0,0 +1,31 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2009-2013 John Crispin <blogic@openwrt.org> + */ + +#ifndef _RALINK_GSW_MT7620_H__ +#define _RALINK_GSW_MT7620_H__ + +extern int mt7620_gsw_config(struct fe_priv *priv); +extern int mt7621_gsw_config(struct fe_priv *priv); +extern int mt7620_gsw_probe(struct fe_priv *priv); +extern void mt7620_set_mac(struct fe_priv *priv, unsigned char *mac); +extern int mt7620_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val); +extern int mt7620_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg); +extern void mt7620_mdio_link_adjust(struct fe_priv *priv, int port); +extern void mt7620_port_init(struct fe_priv *priv, struct device_node *np); +extern int mt7620a_has_carrier(struct fe_priv *priv); + +#endif diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c new file mode 100644 index 0000000..62db11a --- /dev/null +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c @@ -0,0 +1,275 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2009-2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/dma-mapping.h> +#include <linux/init.h> +#include <linux/skbuff.h> +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/platform_device.h> +#include <linux/phy.h> +#include <linux/of_device.h> +#include <linux/clk.h> +#include <linux/of_net.h> +#include <linux/of_mdio.h> + +#include "ralink_soc_eth.h" +#include "mdio.h" + +static int fe_mdio_reset(struct mii_bus *bus) +{ + /* TODO */ + return 0; +} + +static void fe_phy_link_adjust(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + unsigned long flags; + int i; + + spin_lock_irqsave(&priv->phy->lock, flags); + for (i = 0; i < 8; i++) { + if (priv->phy->phy_node[i]) { + struct phy_device *phydev = priv->phy->phy[i]; + int status_change = 0; + + if (phydev->link) + if (priv->phy->duplex[i] != phydev->duplex || + priv->phy->speed[i] != phydev->speed) + status_change = 1; + + if (phydev->link != priv->link[i]) + status_change = 1; + + switch (phydev->speed) { + case SPEED_1000: + case SPEED_100: + case SPEED_10: + priv->link[i] = phydev->link; + priv->phy->duplex[i] = phydev->duplex; + priv->phy->speed[i] = phydev->speed; + + if (status_change && priv->soc->mdio_adjust_link) + priv->soc->mdio_adjust_link(priv, i); + break; + } + } + } +} + +int fe_connect_phy_node(struct fe_priv *priv, struct device_node *phy_node) +{ + const __be32 *_port = NULL; + struct phy_device *phydev; + int phy_mode, port; + + _port = of_get_property(phy_node, "reg", NULL); + + if (!_port || (be32_to_cpu(*_port) >= 0x20)) { + pr_err("%s: invalid port id\n", phy_node->name); + return -EINVAL; + } + port = be32_to_cpu(*_port); + phy_mode = of_get_phy_mode(phy_node); + if (phy_mode < 0) { + dev_err(priv->device, "incorrect phy-mode %d\n", phy_mode); + priv->phy->phy_node[port] = NULL; + return -EINVAL; + } + + phydev = of_phy_connect(priv->netdev, phy_node, fe_phy_link_adjust, + 0, phy_mode); + if (IS_ERR(phydev)) { + dev_err(priv->device, "could not connect to PHY\n"); + priv->phy->phy_node[port] = NULL; + return PTR_ERR(phydev); + } + + phydev->supported &= PHY_GBIT_FEATURES; + phydev->advertising = phydev->supported; + phydev->no_auto_carrier_off = 1; + + dev_info(priv->device, + "connected port %d to PHY at %s [uid=%08x, driver=%s]\n", + port, dev_name(&phydev->dev), phydev->phy_id, + phydev->drv->name); + + priv->phy->phy[port] = phydev; + priv->link[port] = 0; + + return 0; +} + +static void phy_init(struct fe_priv *priv, struct phy_device *phy) +{ + phy_attach(priv->netdev, dev_name(&phy->dev), PHY_INTERFACE_MODE_MII); + + phy->autoneg = AUTONEG_ENABLE; + phy->speed = 0; + phy->duplex = 0; + phy->supported &= PHY_BASIC_FEATURES; + phy->advertising = phy->supported | ADVERTISED_Autoneg; + + phy_start_aneg(phy); +} + +static int fe_phy_connect(struct fe_priv *priv) +{ + int i; + + for (i = 0; i < 8; i++) { + if (priv->phy->phy_node[i]) { + if (!priv->phy_dev) { + priv->phy_dev = priv->phy->phy[i]; + priv->phy_flags = FE_PHY_FLAG_PORT; + } + } else if (priv->mii_bus && priv->mii_bus->phy_map[i]) { + phy_init(priv, priv->mii_bus->phy_map[i]); + if (!priv->phy_dev) { + priv->phy_dev = priv->mii_bus->phy_map[i]; + priv->phy_flags = FE_PHY_FLAG_ATTACH; + } + } + } + + return 0; +} + +static void fe_phy_disconnect(struct fe_priv *priv) +{ + unsigned long flags; + int i; + + for (i = 0; i < 8; i++) + if (priv->phy->phy_fixed[i]) { + spin_lock_irqsave(&priv->phy->lock, flags); + priv->link[i] = 0; + if (priv->soc->mdio_adjust_link) + priv->soc->mdio_adjust_link(priv, i); + spin_unlock_irqrestore(&priv->phy->lock, flags); + } else if (priv->phy->phy[i]) { + phy_disconnect(priv->phy->phy[i]); + } else if (priv->mii_bus && priv->mii_bus->phy_map[i]) { + phy_detach(priv->mii_bus->phy_map[i]); + } +} + +static void fe_phy_start(struct fe_priv *priv) +{ + unsigned long flags; + int i; + + for (i = 0; i < 8; i++) { + if (priv->phy->phy_fixed[i]) { + spin_lock_irqsave(&priv->phy->lock, flags); + priv->link[i] = 1; + if (priv->soc->mdio_adjust_link) + priv->soc->mdio_adjust_link(priv, i); + spin_unlock_irqrestore(&priv->phy->lock, flags); + } else if (priv->phy->phy[i]) { + phy_start(priv->phy->phy[i]); + } + } +} + +static void fe_phy_stop(struct fe_priv *priv) +{ + unsigned long flags; + int i; + + for (i = 0; i < 8; i++) + if (priv->phy->phy_fixed[i]) { + spin_lock_irqsave(&priv->phy->lock, flags); + priv->link[i] = 0; + if (priv->soc->mdio_adjust_link) + priv->soc->mdio_adjust_link(priv, i); + spin_unlock_irqrestore(&priv->phy->lock, flags); + } else if (priv->phy->phy[i]) { + phy_stop(priv->phy->phy[i]); + } +} + +static struct fe_phy phy_ralink = { + .connect = fe_phy_connect, + .disconnect = fe_phy_disconnect, + .start = fe_phy_start, + .stop = fe_phy_stop, +}; + +int fe_mdio_init(struct fe_priv *priv) +{ + struct device_node *mii_np; + int err; + + if (!priv->soc->mdio_read || !priv->soc->mdio_write) + return 0; + + spin_lock_init(&phy_ralink.lock); + priv->phy = &phy_ralink; + + mii_np = of_get_child_by_name(priv->device->of_node, "mdio-bus"); + if (!mii_np) { + dev_err(priv->device, "no %s child node found", "mdio-bus"); + return -ENODEV; + } + + if (!of_device_is_available(mii_np)) { + err = 0; + goto err_put_node; + } + + priv->mii_bus = mdiobus_alloc(); + if (priv->mii_bus == NULL) { + err = -ENOMEM; + goto err_put_node; + } + + priv->mii_bus->name = "mdio"; + priv->mii_bus->read = priv->soc->mdio_read; + priv->mii_bus->write = priv->soc->mdio_write; + priv->mii_bus->reset = fe_mdio_reset; + priv->mii_bus->priv = priv; + priv->mii_bus->parent = priv->device; + + snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s", mii_np->name); + err = of_mdiobus_register(priv->mii_bus, mii_np); + if (err) + goto err_free_bus; + + return 0; + +err_free_bus: + kfree(priv->mii_bus); +err_put_node: + of_node_put(mii_np); + priv->mii_bus = NULL; + return err; +} + +void fe_mdio_cleanup(struct fe_priv *priv) +{ + if (!priv->mii_bus) + return; + + mdiobus_unregister(priv->mii_bus); + of_node_put(priv->mii_bus->dev.of_node); + kfree(priv->mii_bus); +} diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.h b/target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.h new file mode 100644 index 0000000..c3910a0 --- /dev/null +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.h @@ -0,0 +1,29 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2009-2013 John Crispin <blogic@openwrt.org> + */ + +#ifndef _RALINK_MDIO_H__ +#define _RALINK_MDIO_H__ + +#ifdef CONFIG_NET_RALINK_MDIO +extern int fe_mdio_init(struct fe_priv *priv); +extern void fe_mdio_cleanup(struct fe_priv *priv); +extern int fe_connect_phy_node(struct fe_priv *priv, struct device_node *phy_node); +#else +static inline int fe_mdio_init(struct fe_priv *priv) { return 0; } +static inline void fe_mdio_cleanup(struct fe_priv *priv) {} +#endif +#endif diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mdio_rt2880.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/mdio_rt2880.c new file mode 100644 index 0000000..b99eb46 --- /dev/null +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mdio_rt2880.c @@ -0,0 +1,232 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2009-2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/dma-mapping.h> +#include <linux/init.h> +#include <linux/skbuff.h> +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/platform_device.h> +#include <linux/phy.h> +#include <linux/of_device.h> +#include <linux/clk.h> +#include <linux/of_net.h> +#include <linux/of_mdio.h> + +#include "ralink_soc_eth.h" +#include "mdio_rt2880.h" +#include "mdio.h" + +#define FE_MDIO_RETRY 1000 + +static unsigned char *rt2880_speed_str(struct fe_priv *priv) +{ + switch (priv->phy->speed[0]) { + case SPEED_1000: + return "1000"; + case SPEED_100: + return "100"; + case SPEED_10: + return "10"; + } + + return "?"; +} + +void rt2880_mdio_link_adjust(struct fe_priv *priv, int port) +{ + u32 mdio_cfg; + + if (!priv->link[0]) { + netif_carrier_off(priv->netdev); + netdev_info(priv->netdev, "link down\n"); + return; + } + + mdio_cfg = FE_MDIO_CFG_TX_CLK_SKEW_200 | + FE_MDIO_CFG_RX_CLK_SKEW_200 | + FE_MDIO_CFG_GP1_FRC_EN; + + if (priv->phy->duplex[0] == DUPLEX_FULL) + mdio_cfg |= FE_MDIO_CFG_GP1_DUPLEX; + + if (priv->phy->tx_fc[0]) + mdio_cfg |= FE_MDIO_CFG_GP1_FC_TX; + + if (priv->phy->rx_fc[0]) + mdio_cfg |= FE_MDIO_CFG_GP1_FC_RX; + + switch (priv->phy->speed[0]) { + case SPEED_10: + mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_10; + break; + case SPEED_100: + mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_100; + break; + case SPEED_1000: + mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_1000; + break; + default: + BUG(); + } + + fe_w32(mdio_cfg, FE_MDIO_CFG); + + netif_carrier_on(priv->netdev); + netdev_info(priv->netdev, "link up (%sMbps/%s duplex)\n", + rt2880_speed_str(priv), + (DUPLEX_FULL == priv->phy->duplex[0]) ? "Full" : "Half"); +} + +static int rt2880_mdio_wait_ready(struct fe_priv *priv) +{ + int retries; + + retries = FE_MDIO_RETRY; + while (1) { + u32 t; + + t = fe_r32(FE_MDIO_ACCESS); + if ((t & (0x1 << 31)) == 0) + return 0; + + if (retries-- == 0) + break; + + udelay(1); + } + + dev_err(priv->device, "MDIO operation timed out\n"); + return -ETIMEDOUT; +} + +int rt2880_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg) +{ + struct fe_priv *priv = bus->priv; + int err; + u32 t; + + err = rt2880_mdio_wait_ready(priv); + if (err) + return 0xffff; + + t = (phy_addr << 24) | (phy_reg << 16); + fe_w32(t, FE_MDIO_ACCESS); + t |= (1 << 31); + fe_w32(t, FE_MDIO_ACCESS); + + err = rt2880_mdio_wait_ready(priv); + if (err) + return 0xffff; + + pr_debug("%s: addr=%04x, reg=%04x, value=%04x\n", __func__, + phy_addr, phy_reg, fe_r32(FE_MDIO_ACCESS) & 0xffff); + + return fe_r32(FE_MDIO_ACCESS) & 0xffff; +} + +int rt2880_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val) +{ + struct fe_priv *priv = bus->priv; + int err; + u32 t; + + pr_debug("%s: addr=%04x, reg=%04x, value=%04x\n", __func__, + phy_addr, phy_reg, fe_r32(FE_MDIO_ACCESS) & 0xffff); + + err = rt2880_mdio_wait_ready(priv); + if (err) + return err; + + t = (1 << 30) | (phy_addr << 24) | (phy_reg << 16) | val; + fe_w32(t, FE_MDIO_ACCESS); + t |= (1 << 31); + fe_w32(t, FE_MDIO_ACCESS); + + return rt2880_mdio_wait_ready(priv); +} + +void rt2880_port_init(struct fe_priv *priv, struct device_node *np) +{ + const __be32 *id = of_get_property(np, "reg", NULL); + const __be32 *link; + int size; + int phy_mode; + + if (!id || (be32_to_cpu(*id) != 0)) { + pr_err("%s: invalid port id\n", np->name); + return; + } + + priv->phy->phy_fixed[0] = of_get_property(np, "ralink,fixed-link", &size); + if (priv->phy->phy_fixed[0] && (size != (4 * sizeof(*priv->phy->phy_fixed[0])))) { + pr_err("%s: invalid fixed link property\n", np->name); + priv->phy->phy_fixed[0] = NULL; + return; + } + + phy_mode = of_get_phy_mode(np); + switch (phy_mode) { + case PHY_INTERFACE_MODE_RGMII: + break; + case PHY_INTERFACE_MODE_MII: + break; + case PHY_INTERFACE_MODE_RMII: + break; + default: + if (!priv->phy->phy_fixed[0]) + dev_err(priv->device, "port %d - invalid phy mode\n", priv->phy->speed[0]); + break; + } + + priv->phy->phy_node[0] = of_parse_phandle(np, "phy-handle", 0); + if (!priv->phy->phy_node[0] && !priv->phy->phy_fixed[0]) + return; + + if (priv->phy->phy_fixed[0]) { + link = priv->phy->phy_fixed[0]; + priv->phy->speed[0] = be32_to_cpup(link++); + priv->phy->duplex[0] = be32_to_cpup(link++); + priv->phy->tx_fc[0] = be32_to_cpup(link++); + priv->phy->rx_fc[0] = be32_to_cpup(link++); + + priv->link[0] = 1; + switch (priv->phy->speed[0]) { + case SPEED_10: + break; + case SPEED_100: + break; + case SPEED_1000: + break; + default: + dev_err(priv->device, "invalid link speed: %d\n", priv->phy->speed[0]); + priv->phy->phy_fixed[0] = 0; + return; + } + dev_info(priv->device, "using fixed link parameters\n"); + rt2880_mdio_link_adjust(priv, 0); + return; + } + if (priv->phy->phy_node[0] && priv->mii_bus->phy_map[0]) { + fe_connect_phy_node(priv, priv->phy->phy_node[0]); + } + + return; +} diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mdio_rt2880.h b/target/linux/ramips/files/drivers/net/ethernet/ralink/mdio_rt2880.h new file mode 100644 index 0000000..51e3633 --- /dev/null +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mdio_rt2880.h @@ -0,0 +1,26 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2009-2013 John Crispin <blogic@openwrt.org> + */ + +#ifndef _RALINK_MDIO_RT2880_H__ +#define _RALINK_MDIO_RT2880_H__ + +void rt2880_mdio_link_adjust(struct fe_priv *priv, int port); +int rt2880_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg); +int rt2880_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val); +void rt2880_port_init(struct fe_priv *priv, struct device_node *np); + +#endif diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.c new file mode 100644 index 0000000..4e00315 --- /dev/null +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.c @@ -0,0 +1,804 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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. + * + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/if.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/list.h> +#include <linux/if_ether.h> +#include <linux/skbuff.h> +#include <linux/netdevice.h> +#include <linux/netlink.h> +#include <linux/bitops.h> +#include <net/genetlink.h> +#include <linux/switch.h> +#include <linux/delay.h> +#include <linux/phy.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/lockdep.h> +#include <linux/workqueue.h> +#include <linux/of_device.h> + +#include "mt7530.h" + +#define MT7530_CPU_PORT 6 +#define MT7530_NUM_PORTS 8 +#define MT7530_NUM_VLANS 16 +#define MT7530_MAX_VID 4095 +#define MT7530_MIN_VID 0 + +/* registers */ +#define REG_ESW_VLAN_VTCR 0x90 +#define REG_ESW_VLAN_VAWD1 0x94 +#define REG_ESW_VLAN_VAWD2 0x98 +#define REG_ESW_VLAN_VTIM(x) (0x100 + 4 * ((x) / 2)) + +#define REG_ESW_VLAN_VAWD1_IVL_MAC BIT(30) +#define REG_ESW_VLAN_VAWD1_VTAG_EN BIT(28) +#define REG_ESW_VLAN_VAWD1_VALID BIT(0) + +/* vlan egress mode */ +enum { + ETAG_CTRL_UNTAG = 0, + ETAG_CTRL_TAG = 2, + ETAG_CTRL_SWAP = 1, + ETAG_CTRL_STACK = 3, +}; + +#define REG_ESW_PORT_PCR(x) (0x2004 | ((x) << 8)) +#define REG_ESW_PORT_PVC(x) (0x2010 | ((x) << 8)) +#define REG_ESW_PORT_PPBV1(x) (0x2014 | ((x) << 8)) + +#define REG_HWTRAP 0x7804 + +#define MIB_DESC(_s , _o, _n) \ + { \ + .size = (_s), \ + .offset = (_o), \ + .name = (_n), \ + } + +struct mt7xxx_mib_desc { + unsigned int size; + unsigned int offset; + const char *name; +}; + +#define MT7621_MIB_COUNTER_BASE 0x4000 +#define MT7621_MIB_COUNTER_PORT_OFFSET 0x100 +#define MT7621_STATS_TDPC 0x00 +#define MT7621_STATS_TCRC 0x04 +#define MT7621_STATS_TUPC 0x08 +#define MT7621_STATS_TMPC 0x0C +#define MT7621_STATS_TBPC 0x10 +#define MT7621_STATS_TCEC 0x14 +#define MT7621_STATS_TSCEC 0x18 +#define MT7621_STATS_TMCEC 0x1C +#define MT7621_STATS_TDEC 0x20 +#define MT7621_STATS_TLCEC 0x24 +#define MT7621_STATS_TXCEC 0x28 +#define MT7621_STATS_TPPC 0x2C +#define MT7621_STATS_TL64PC 0x30 +#define MT7621_STATS_TL65PC 0x34 +#define MT7621_STATS_TL128PC 0x38 +#define MT7621_STATS_TL256PC 0x3C +#define MT7621_STATS_TL512PC 0x40 +#define MT7621_STATS_TL1024PC 0x44 +#define MT7621_STATS_TOC 0x48 +#define MT7621_STATS_RDPC 0x60 +#define MT7621_STATS_RFPC 0x64 +#define MT7621_STATS_RUPC 0x68 +#define MT7621_STATS_RMPC 0x6C +#define MT7621_STATS_RBPC 0x70 +#define MT7621_STATS_RAEPC 0x74 +#define MT7621_STATS_RCEPC 0x78 +#define MT7621_STATS_RUSPC 0x7C +#define MT7621_STATS_RFEPC 0x80 +#define MT7621_STATS_ROSPC 0x84 +#define MT7621_STATS_RJEPC 0x88 +#define MT7621_STATS_RPPC 0x8C +#define MT7621_STATS_RL64PC 0x90 +#define MT7621_STATS_RL65PC 0x94 +#define MT7621_STATS_RL128PC 0x98 +#define MT7621_STATS_RL256PC 0x9C +#define MT7621_STATS_RL512PC 0xA0 +#define MT7621_STATS_RL1024PC 0xA4 +#define MT7621_STATS_ROC 0xA8 +#define MT7621_STATS_RDPC_CTRL 0xB0 +#define MT7621_STATS_RDPC_ING 0xB4 +#define MT7621_STATS_RDPC_ARL 0xB8 + +static const struct mt7xxx_mib_desc mt7621_mibs[] = { + MIB_DESC(1, MT7621_STATS_TDPC, "TxDrop"), + MIB_DESC(1, MT7621_STATS_TCRC, "TxCRC"), + MIB_DESC(1, MT7621_STATS_TUPC, "TxUni"), + MIB_DESC(1, MT7621_STATS_TMPC, "TxMulti"), + MIB_DESC(1, MT7621_STATS_TBPC, "TxBroad"), + MIB_DESC(1, MT7621_STATS_TCEC, "TxCollision"), + MIB_DESC(1, MT7621_STATS_TSCEC, "TxSingleCol"), + MIB_DESC(1, MT7621_STATS_TMCEC, "TxMultiCol"), + MIB_DESC(1, MT7621_STATS_TDEC, "TxDefer"), + MIB_DESC(1, MT7621_STATS_TLCEC, "TxLateCol"), + MIB_DESC(1, MT7621_STATS_TXCEC, "TxExcCol"), + MIB_DESC(1, MT7621_STATS_TPPC, "TxPause"), + MIB_DESC(1, MT7621_STATS_TL64PC, "Tx64Byte"), + MIB_DESC(1, MT7621_STATS_TL65PC, "Tx65Byte"), + MIB_DESC(1, MT7621_STATS_TL128PC, "Tx128Byte"), + MIB_DESC(1, MT7621_STATS_TL256PC, "Tx256Byte"), + MIB_DESC(1, MT7621_STATS_TL512PC, "Tx512Byte"), + MIB_DESC(1, MT7621_STATS_TL1024PC, "Tx1024Byte"), + MIB_DESC(2, MT7621_STATS_TOC, "TxByte"), + MIB_DESC(1, MT7621_STATS_RDPC, "RxDrop"), + MIB_DESC(1, MT7621_STATS_RFPC, "RxFiltered"), + MIB_DESC(1, MT7621_STATS_RUPC, "RxUni"), + MIB_DESC(1, MT7621_STATS_RMPC, "RxMulti"), + MIB_DESC(1, MT7621_STATS_RBPC, "RxBroad"), + MIB_DESC(1, MT7621_STATS_RAEPC, "RxAlignErr"), + MIB_DESC(1, MT7621_STATS_RCEPC, "RxCRC"), + MIB_DESC(1, MT7621_STATS_RUSPC, "RxUnderSize"), + MIB_DESC(1, MT7621_STATS_RFEPC, "RxFragment"), + MIB_DESC(1, MT7621_STATS_ROSPC, "RxOverSize"), + MIB_DESC(1, MT7621_STATS_RJEPC, "RxJabber"), + MIB_DESC(1, MT7621_STATS_RPPC, "RxPause"), + MIB_DESC(1, MT7621_STATS_RL64PC, "Rx64Byte"), + MIB_DESC(1, MT7621_STATS_RL65PC, "Rx65Byte"), + MIB_DESC(1, MT7621_STATS_RL128PC, "Rx128Byte"), + MIB_DESC(1, MT7621_STATS_RL256PC, "Rx256Byte"), + MIB_DESC(1, MT7621_STATS_RL512PC, "Rx512Byte"), + MIB_DESC(1, MT7621_STATS_RL1024PC, "Rx1024Byte"), + MIB_DESC(2, MT7621_STATS_ROC, "RxByte"), + MIB_DESC(1, MT7621_STATS_RDPC_CTRL, "RxCtrlDrop"), + MIB_DESC(1, MT7621_STATS_RDPC_ING, "RxIngDrop"), + MIB_DESC(1, MT7621_STATS_RDPC_ARL, "RxARLDrop") +}; + +enum { + /* Global attributes. */ + MT7530_ATTR_ENABLE_VLAN, +}; + +struct mt7530_port_entry { + u16 pvid; +}; + +struct mt7530_vlan_entry { + u16 vid; + u8 member; + u8 etags; +}; + +struct mt7530_priv { + void __iomem *base; + struct mii_bus *bus; + struct switch_dev swdev; + + bool global_vlan_enable; + struct mt7530_vlan_entry vlan_entries[MT7530_NUM_VLANS]; + struct mt7530_port_entry port_entries[MT7530_NUM_PORTS]; +}; + +struct mt7530_mapping { + char *name; + u16 pvids[MT7530_NUM_PORTS]; + u8 members[MT7530_NUM_VLANS]; + u8 etags[MT7530_NUM_VLANS]; + u16 vids[MT7530_NUM_VLANS]; +} mt7530_defaults[] = { + { + .name = "llllw", + .pvids = { 1, 1, 1, 1, 2, 1, 1 }, + .members = { 0, 0x6f, 0x50 }, + .etags = { 0, 0x40, 0x40 }, + .vids = { 0, 1, 2 }, + }, { + .name = "wllll", + .pvids = { 2, 1, 1, 1, 1, 1, 1 }, + .members = { 0, 0x7e, 0x41 }, + .etags = { 0, 0x40, 0x40 }, + .vids = { 0, 1, 2 }, + }, +}; + +struct mt7530_mapping* +mt7530_find_mapping(struct device_node *np) +{ + const char *map; + int i; + + if (of_property_read_string(np, "ralink,port-map", &map)) + return NULL; + + for (i = 0; i < ARRAY_SIZE(mt7530_defaults); i++) + if (!strcmp(map, mt7530_defaults[i].name)) + return &mt7530_defaults[i]; + + return NULL; +} + +static void +mt7530_apply_mapping(struct mt7530_priv *mt7530, struct mt7530_mapping *map) +{ + int i = 0; + + for (i = 0; i < MT7530_NUM_PORTS; i++) + mt7530->port_entries[i].pvid = map->pvids[i]; + + for (i = 0; i < MT7530_NUM_VLANS; i++) { + mt7530->vlan_entries[i].member = map->members[i]; + mt7530->vlan_entries[i].etags = map->etags[i]; + mt7530->vlan_entries[i].vid = map->vids[i]; + } +} + +static int +mt7530_reset_switch(struct switch_dev *dev) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + int i; + + memset(priv->port_entries, 0, sizeof(priv->port_entries)); + memset(priv->vlan_entries, 0, sizeof(priv->vlan_entries)); + + /* set default vid of each vlan to the same number of vlan, so the vid + * won't need be set explicitly. + */ + for (i = 0; i < MT7530_NUM_VLANS; i++) { + priv->vlan_entries[i].vid = i; + } + + return 0; +} + +static int +mt7530_get_vlan_enable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + + val->value.i = priv->global_vlan_enable; + + return 0; +} + +static int +mt7530_set_vlan_enable(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + + priv->global_vlan_enable = val->value.i != 0; + + return 0; +} + +static u32 +mt7530_r32(struct mt7530_priv *priv, u32 reg) +{ + u32 val; + if (priv->bus) { + u16 high, low; + + mdiobus_write(priv->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff); + low = mdiobus_read(priv->bus, 0x1f, (reg >> 2) & 0xf); + high = mdiobus_read(priv->bus, 0x1f, 0x10); + + return (high << 16) | (low & 0xffff); + } + + val = ioread32(priv->base + reg); + pr_debug("MT7530 MDIO Read [%04x]=%08x\n", reg, val); + + return val; +} + +static void +mt7530_w32(struct mt7530_priv *priv, u32 reg, u32 val) +{ + if (priv->bus) { + mdiobus_write(priv->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff); + mdiobus_write(priv->bus, 0x1f, (reg >> 2) & 0xf, val & 0xffff); + mdiobus_write(priv->bus, 0x1f, 0x10, val >> 16); + return; + } + + pr_debug("MT7530 MDIO Write[%04x]=%08x\n", reg, val); + iowrite32(val, priv->base + reg); +} + +static void +mt7530_vtcr(struct mt7530_priv *priv, u32 cmd, u32 val) +{ + int i; + + mt7530_w32(priv, REG_ESW_VLAN_VTCR, BIT(31) | (cmd << 12) | val); + + for (i = 0; i < 20; i++) { + u32 val = mt7530_r32(priv, REG_ESW_VLAN_VTCR); + + if ((val & BIT(31)) == 0) + break; + + udelay(1000); + } + if (i == 20) + printk("mt7530: vtcr timeout\n"); +} + +static int +mt7530_get_port_pvid(struct switch_dev *dev, int port, int *val) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + + if (port >= MT7530_NUM_PORTS) + return -EINVAL; + + *val = mt7530_r32(priv, REG_ESW_PORT_PPBV1(port)); + *val &= 0xfff; + + return 0; +} + +static int +mt7530_set_port_pvid(struct switch_dev *dev, int port, int pvid) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + + if (port >= MT7530_NUM_PORTS) + return -EINVAL; + + if (pvid < MT7530_MIN_VID || pvid > MT7530_MAX_VID) + return -EINVAL; + + priv->port_entries[port].pvid = pvid; + + return 0; +} + +static int +mt7530_get_vlan_ports(struct switch_dev *dev, struct switch_val *val) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + u32 member; + u32 etags; + int i; + + val->len = 0; + + if (val->port_vlan < 0 || val->port_vlan >= MT7530_NUM_VLANS) + return -EINVAL; + + mt7530_vtcr(priv, 0, val->port_vlan); + + member = mt7530_r32(priv, REG_ESW_VLAN_VAWD1); + member >>= 16; + member &= 0xff; + + etags = mt7530_r32(priv, REG_ESW_VLAN_VAWD2); + + for (i = 0; i < MT7530_NUM_PORTS; i++) { + struct switch_port *p; + int etag; + + if (!(member & BIT(i))) + continue; + + p = &val->value.ports[val->len++]; + p->id = i; + + etag = (etags >> (i * 2)) & 0x3; + + if (etag == ETAG_CTRL_TAG) + p->flags |= BIT(SWITCH_PORT_FLAG_TAGGED); + else if (etag != ETAG_CTRL_UNTAG) + printk("vlan egress tag control neither untag nor tag.\n"); + } + + return 0; +} + +static int +mt7530_set_vlan_ports(struct switch_dev *dev, struct switch_val *val) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + u8 member = 0; + u8 etags = 0; + int i; + + if (val->port_vlan < 0 || val->port_vlan >= MT7530_NUM_VLANS || + val->len > MT7530_NUM_PORTS) + return -EINVAL; + + for (i = 0; i < val->len; i++) { + struct switch_port *p = &val->value.ports[i]; + + if (p->id >= MT7530_NUM_PORTS) + return -EINVAL; + + member |= BIT(p->id); + + if (p->flags & BIT(SWITCH_PORT_FLAG_TAGGED)) + etags |= BIT(p->id); + } + priv->vlan_entries[val->port_vlan].member = member; + priv->vlan_entries[val->port_vlan].etags = etags; + + return 0; +} + +static int +mt7530_set_vid(struct switch_dev *dev, const struct switch_attr *attr, + struct switch_val *val) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + int vlan; + u16 vid; + + vlan = val->port_vlan; + vid = (u16)val->value.i; + + if (vlan < 0 || vlan >= MT7530_NUM_VLANS) + return -EINVAL; + + if (vid < MT7530_MIN_VID || vid > MT7530_MAX_VID) + return -EINVAL; + + priv->vlan_entries[vlan].vid = vid; + return 0; +} + +static int +mt7530_get_vid(struct switch_dev *dev, const struct switch_attr *attr, + struct switch_val *val) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + u32 vid; + int vlan; + + vlan = val->port_vlan; + + vid = mt7530_r32(priv, REG_ESW_VLAN_VTIM(vlan)); + if (vlan & 1) + vid = vid >> 12; + vid &= 0xfff; + + val->value.i = vid; + return 0; +} + +static int +mt7530_apply_config(struct switch_dev *dev) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + int i, j; + u8 tag_ports; + u8 untag_ports; + + if (!priv->global_vlan_enable) { + for (i = 0; i < MT7530_NUM_PORTS; i++) + mt7530_w32(priv, REG_ESW_PORT_PCR(i), 0x00ff0000); + + for (i = 0; i < MT7530_NUM_PORTS; i++) + mt7530_w32(priv, REG_ESW_PORT_PVC(i), 0x810000c0); + + return 0; + } + + /* set all ports as security mode */ + for (i = 0; i < MT7530_NUM_PORTS; i++) + mt7530_w32(priv, REG_ESW_PORT_PCR(i), 0x00ff0003); + + /* check if a port is used in tag/untag vlan egress mode */ + tag_ports = 0; + untag_ports = 0; + + for (i = 0; i < MT7530_NUM_VLANS; i++) { + u8 member = priv->vlan_entries[i].member; + u8 etags = priv->vlan_entries[i].etags; + + if (!member) + continue; + + for (j = 0; j < MT7530_NUM_PORTS; j++) { + if (!(member & BIT(j))) + continue; + + if (etags & BIT(j)) + tag_ports |= 1u << j; + else + untag_ports |= 1u << j; + } + } + + /* set all untag-only ports as transparent and the rest as user port */ + for (i = 0; i < MT7530_NUM_PORTS; i++) { + u32 pvc_mode = 0x81000000; + + if (untag_ports & BIT(i) && !(tag_ports & BIT(i))) + pvc_mode = 0x810000c0; + + mt7530_w32(priv, REG_ESW_PORT_PVC(i), pvc_mode); + } + + for (i = 0; i < MT7530_NUM_VLANS; i++) { + u16 vid = priv->vlan_entries[i].vid; + u8 member = priv->vlan_entries[i].member; + u8 etags = priv->vlan_entries[i].etags; + u32 val; + + /* vid of vlan */ + val = mt7530_r32(priv, REG_ESW_VLAN_VTIM(i)); + if (i % 2 == 0) { + val &= 0xfff000; + val |= vid; + } else { + val &= 0xfff; + val |= (vid << 12); + } + mt7530_w32(priv, REG_ESW_VLAN_VTIM(i), val); + + /* vlan port membership */ + if (member) + mt7530_w32(priv, REG_ESW_VLAN_VAWD1, REG_ESW_VLAN_VAWD1_IVL_MAC | + REG_ESW_VLAN_VAWD1_VTAG_EN | (member << 16) | + REG_ESW_VLAN_VAWD1_VALID); + else + mt7530_w32(priv, REG_ESW_VLAN_VAWD1, 0); + + /* egress mode */ + val = 0; + for (j = 0; j < MT7530_NUM_PORTS; j++) { + if (etags & BIT(j)) + val |= ETAG_CTRL_TAG << (j * 2); + else + val |= ETAG_CTRL_UNTAG << (j * 2); + } + mt7530_w32(priv, REG_ESW_VLAN_VAWD2, val); + + /* write to vlan table */ + mt7530_vtcr(priv, 1, i); + } + + /* Port Default PVID */ + for (i = 0; i < MT7530_NUM_PORTS; i++) { + u32 val; + val = mt7530_r32(priv, REG_ESW_PORT_PPBV1(i)); + val &= ~0xfff; + val |= priv->port_entries[i].pvid; + mt7530_w32(priv, REG_ESW_PORT_PPBV1(i), val); + } + + return 0; +} + +static int +mt7530_get_port_link(struct switch_dev *dev, int port, + struct switch_port_link *link) +{ + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + u32 speed, pmsr; + + if (port < 0 || port >= MT7530_NUM_PORTS) + return -EINVAL; + + pmsr = mt7530_r32(priv, 0x3008 + (0x100 * port)); + + link->link = pmsr & 1; + link->duplex = (pmsr >> 1) & 1; + speed = (pmsr >> 2) & 3; + + switch (speed) { + case 0: + link->speed = SWITCH_PORT_SPEED_10; + break; + case 1: + link->speed = SWITCH_PORT_SPEED_100; + break; + case 2: + case 3: /* forced gige speed can be 2 or 3 */ + link->speed = SWITCH_PORT_SPEED_1000; + break; + default: + link->speed = SWITCH_PORT_SPEED_UNKNOWN; + break; + } + + return 0; +} + +static const struct switch_attr mt7530_global[] = { + { + .type = SWITCH_TYPE_INT, + .name = "enable_vlan", + .description = "VLAN mode (1:enabled)", + .max = 1, + .id = MT7530_ATTR_ENABLE_VLAN, + .get = mt7530_get_vlan_enable, + .set = mt7530_set_vlan_enable, + }, +}; + +static u64 get_mib_counter(struct mt7530_priv *priv, int i, int port) +{ + unsigned int port_base; + u64 t; + + port_base = MT7621_MIB_COUNTER_BASE + + MT7621_MIB_COUNTER_PORT_OFFSET * port; + + t = mt7530_r32(priv, port_base + mt7621_mibs[i].offset); + if (mt7621_mibs[i].size == 2) { + u64 hi; + + hi = mt7530_r32(priv, port_base + mt7621_mibs[i].offset + 4); + t |= hi << 32; + } + + return t; +} + +static int mt7621_sw_get_port_mib(struct switch_dev *dev, + const struct switch_attr *attr, + struct switch_val *val) +{ + static char buf[4096]; + struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); + int i, len = 0; + + if (val->port_vlan >= MT7530_NUM_PORTS) + return -EINVAL; + + len += snprintf(buf + len, sizeof(buf) - len, + "Port %d MIB counters\n", val->port_vlan); + + for (i = 0; i < sizeof(mt7621_mibs) / sizeof(*mt7621_mibs); ++i) { + u64 counter; + len += snprintf(buf + len, sizeof(buf) - len, + "%-11s: ", mt7621_mibs[i].name); + counter = get_mib_counter(priv, i, val->port_vlan); + len += snprintf(buf + len, sizeof(buf) - len, "%llu\n", + counter); + } + + val->value.s = buf; + val->len = len; + return 0; +} + +static const struct switch_attr mt7621_port[] = { + { + .type = SWITCH_TYPE_STRING, + .name = "mib", + .description = "Get MIB counters for port", + .get = mt7621_sw_get_port_mib, + .set = NULL, + }, +}; + +static const struct switch_attr mt7530_port[] = { +}; + +static const struct switch_attr mt7530_vlan[] = { + { + .type = SWITCH_TYPE_INT, + .name = "vid", + .description = "VLAN ID (0-4094)", + .set = mt7530_set_vid, + .get = mt7530_get_vid, + .max = 4094, + }, +}; + +static const struct switch_dev_ops mt7621_ops = { + .attr_global = { + .attr = mt7530_global, + .n_attr = ARRAY_SIZE(mt7530_global), + }, + .attr_port = { + .attr = mt7621_port, + .n_attr = ARRAY_SIZE(mt7621_port), + }, + .attr_vlan = { + .attr = mt7530_vlan, + .n_attr = ARRAY_SIZE(mt7530_vlan), + }, + .get_vlan_ports = mt7530_get_vlan_ports, + .set_vlan_ports = mt7530_set_vlan_ports, + .get_port_pvid = mt7530_get_port_pvid, + .set_port_pvid = mt7530_set_port_pvid, + .get_port_link = mt7530_get_port_link, + .apply_config = mt7530_apply_config, + .reset_switch = mt7530_reset_switch, +}; + +static const struct switch_dev_ops mt7530_ops = { + .attr_global = { + .attr = mt7530_global, + .n_attr = ARRAY_SIZE(mt7530_global), + }, + .attr_port = { + .attr = mt7530_port, + .n_attr = ARRAY_SIZE(mt7530_port), + }, + .attr_vlan = { + .attr = mt7530_vlan, + .n_attr = ARRAY_SIZE(mt7530_vlan), + }, + .get_vlan_ports = mt7530_get_vlan_ports, + .set_vlan_ports = mt7530_set_vlan_ports, + .get_port_pvid = mt7530_get_port_pvid, + .set_port_pvid = mt7530_set_port_pvid, + .get_port_link = mt7530_get_port_link, + .apply_config = mt7530_apply_config, + .reset_switch = mt7530_reset_switch, +}; + +int +mt7530_probe(struct device *dev, void __iomem *base, struct mii_bus *bus, int vlan) +{ + struct switch_dev *swdev; + struct mt7530_priv *mt7530; + struct mt7530_mapping *map; + int ret; + + mt7530 = devm_kzalloc(dev, sizeof(struct mt7530_priv), GFP_KERNEL); + if (!mt7530) + return -ENOMEM; + + mt7530->base = base; + mt7530->bus = bus; + mt7530->global_vlan_enable = vlan; + + swdev = &mt7530->swdev; + if (bus) { + swdev->alias = "mt7530"; + swdev->name = "mt7530"; + } else if (IS_ENABLED(CONFIG_SOC_MT7621)) { + swdev->alias = "mt7621"; + swdev->name = "mt7621"; + } else { + swdev->alias = "mt7620"; + swdev->name = "mt7620"; + } + swdev->cpu_port = MT7530_CPU_PORT; + swdev->ports = MT7530_NUM_PORTS; + swdev->vlans = MT7530_NUM_VLANS; + if (IS_ENABLED(CONFIG_SOC_MT7621)) + swdev->ops = &mt7621_ops; + else + swdev->ops = &mt7530_ops; + + ret = register_switch(swdev, NULL); + if (ret) { + dev_err(dev, "failed to register mt7530\n"); + return ret; + } + + + map = mt7530_find_mapping(dev->of_node); + if (map) + mt7530_apply_mapping(mt7530, map); + mt7530_apply_config(swdev); + + /* magic vodoo */ + if (!IS_ENABLED(CONFIG_SOC_MT7621) && bus && mt7530_r32(mt7530, REG_HWTRAP) != 0x1117edf) { + dev_info(dev, "fixing up MHWTRAP register - bootloader probably played with it\n"); + mt7530_w32(mt7530, REG_HWTRAP, 0x1117edf); + } + dev_info(dev, "loaded %s driver\n", swdev->name); + + return 0; +} diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.h b/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.h new file mode 100644 index 0000000..1fc8c62 --- /dev/null +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/mt7530.h @@ -0,0 +1,20 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * 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. + * + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> + */ + +#ifndef _MT7530_H__ +#define _MT7530_H__ + +int mt7530_probe(struct device *dev, void __iomem *base, struct mii_bus *bus, int vlan); + +#endif diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_ethtool.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_ethtool.c new file mode 100644 index 0000000..e95a173 --- /dev/null +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_ethtool.c @@ -0,0 +1,236 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2009-2013 Michael Lee <igvtee@gmail.com> + */ + +#include "ralink_soc_eth.h" + +static const char fe_gdma_str[][ETH_GSTRING_LEN] = { +#define _FE(x...) # x, +FE_STAT_REG_DECLARE +#undef _FE +}; + +static int fe_get_settings(struct net_device *dev, + struct ethtool_cmd *cmd) +{ + struct fe_priv *priv = netdev_priv(dev); + int err; + + if (!priv->phy_dev) + goto out_gset; + + if (priv->phy_flags == FE_PHY_FLAG_ATTACH) { + err = phy_read_status(priv->phy_dev); + if (err) + goto out_gset; + } + + return phy_ethtool_gset(priv->phy_dev, cmd); + +out_gset: + return -ENODEV; +} + +static int fe_set_settings(struct net_device *dev, + struct ethtool_cmd *cmd) +{ + struct fe_priv *priv = netdev_priv(dev); + + if (!priv->phy_dev) + goto out_sset; + + if (cmd->phy_address != priv->phy_dev->addr) { + if (priv->phy->phy_node[cmd->phy_address]) { + priv->phy_dev = priv->phy->phy[cmd->phy_address]; + priv->phy_flags = FE_PHY_FLAG_PORT; + } else if (priv->mii_bus && + priv->mii_bus->phy_map[cmd->phy_address]) { + priv->phy_dev = priv->mii_bus->phy_map[cmd->phy_address]; + priv->phy_flags = FE_PHY_FLAG_ATTACH; + } else + goto out_sset; + } + + return phy_ethtool_sset(priv->phy_dev, cmd); + +out_sset: + return -ENODEV; +} + +static void fe_get_drvinfo (struct net_device *dev, + struct ethtool_drvinfo *info) +{ + struct fe_priv *priv = netdev_priv(dev); + struct fe_soc_data *soc = priv->soc; + + strlcpy(info->driver, priv->device->driver->name, sizeof(info->driver)); + strlcpy(info->version, FE_DRV_VERSION, sizeof(info->version)); + strlcpy(info->bus_info, dev_name(priv->device), sizeof(info->bus_info)); + + if (soc->reg_table[FE_REG_FE_COUNTER_BASE]) + info->n_stats = ARRAY_SIZE(fe_gdma_str); +} + +static u32 fe_get_msglevel(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + + return priv->msg_enable; +} + +static void fe_set_msglevel(struct net_device *dev, u32 value) +{ + struct fe_priv *priv = netdev_priv(dev); + + priv->msg_enable = value; +} + +static int fe_nway_reset(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + + if (!priv->phy_dev) + goto out_nway_reset; + + return genphy_restart_aneg(priv->phy_dev); + +out_nway_reset: + return -EOPNOTSUPP; +} + +static u32 fe_get_link(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + int err; + + if (!priv->phy_dev) + goto out_get_link; + + if (priv->phy_flags == FE_PHY_FLAG_ATTACH) { + err = genphy_update_link(priv->phy_dev); + if (err) + goto out_get_link; + } + + return priv->phy_dev->link; + +out_get_link: + return ethtool_op_get_link(dev); +} + +static int fe_set_ringparam(struct net_device *dev, + struct ethtool_ringparam *ring) +{ + struct fe_priv *priv = netdev_priv(dev); + + if ((ring->tx_pending < 2) || + (ring->rx_pending < 2) || + (ring->rx_pending > MAX_DMA_DESC) || + (ring->tx_pending > MAX_DMA_DESC)) + return -EINVAL; + + dev->netdev_ops->ndo_stop(dev); + + priv->tx_ring.tx_ring_size = BIT(fls(ring->tx_pending) - 1); + priv->rx_ring.rx_ring_size = BIT(fls(ring->rx_pending) - 1); + + dev->netdev_ops->ndo_open(dev); + + return 0; +} + +static void fe_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *ring) +{ + struct fe_priv *priv = netdev_priv(dev); + + ring->rx_max_pending = MAX_DMA_DESC; + ring->tx_max_pending = MAX_DMA_DESC; + ring->rx_pending = priv->rx_ring.rx_ring_size; + ring->tx_pending = priv->tx_ring.tx_ring_size; +} + +static void fe_get_strings(struct net_device *dev, u32 stringset, u8 *data) +{ + switch (stringset) { + case ETH_SS_STATS: + memcpy(data, *fe_gdma_str, sizeof(fe_gdma_str)); + break; + } +} + +static int fe_get_sset_count(struct net_device *dev, int sset) +{ + switch (sset) { + case ETH_SS_STATS: + return ARRAY_SIZE(fe_gdma_str); + default: + return -EOPNOTSUPP; + } +} + +static void fe_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 *data) +{ + struct fe_priv *priv = netdev_priv(dev); + struct fe_hw_stats *hwstats = priv->hw_stats; + u64 *data_src, *data_dst; + unsigned int start; + int i; + + if (netif_running(dev) && netif_device_present(dev)) { + if (spin_trylock(&hwstats->stats_lock)) { + fe_stats_update(priv); + spin_unlock(&hwstats->stats_lock); + } + } + + do { + data_src = &hwstats->tx_bytes; + data_dst = data; + start = u64_stats_fetch_begin_irq(&hwstats->syncp); + + for (i = 0; i < ARRAY_SIZE(fe_gdma_str); i++) + *data_dst++ = *data_src++; + + } while (u64_stats_fetch_retry_irq(&hwstats->syncp, start)); +} + +static struct ethtool_ops fe_ethtool_ops = { + .get_settings = fe_get_settings, + .set_settings = fe_set_settings, + .get_drvinfo = fe_get_drvinfo, + .get_msglevel = fe_get_msglevel, + .set_msglevel = fe_set_msglevel, + .nway_reset = fe_nway_reset, + .get_link = fe_get_link, + .set_ringparam = fe_set_ringparam, + .get_ringparam = fe_get_ringparam, +}; + +void fe_set_ethtool_ops(struct net_device *netdev) +{ + struct fe_priv *priv = netdev_priv(netdev); + struct fe_soc_data *soc = priv->soc; + + if (soc->reg_table[FE_REG_FE_COUNTER_BASE]) { + fe_ethtool_ops.get_strings = fe_get_strings; + fe_ethtool_ops.get_sset_count = fe_get_sset_count; + fe_ethtool_ops.get_ethtool_stats = fe_get_ethtool_stats; + } + + netdev->ethtool_ops = &fe_ethtool_ops; +} diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_ethtool.h b/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_ethtool.h new file mode 100644 index 0000000..550f413 --- /dev/null +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_ethtool.h @@ -0,0 +1,25 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2009-2013 Michael Lee <igvtee@gmail.com> + */ + +#ifndef FE_ETHTOOL_H +#define FE_ETHTOOL_H + +#include <linux/ethtool.h> + +void fe_set_ethtool_ops(struct net_device *netdev); + +#endif /* FE_ETHTOOL_H */ diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.c new file mode 100644 index 0000000..0f3009c --- /dev/null +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.c @@ -0,0 +1,1606 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2009-2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/dma-mapping.h> +#include <linux/init.h> +#include <linux/skbuff.h> +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/platform_device.h> +#include <linux/of_device.h> +#include <linux/clk.h> +#include <linux/of_net.h> +#include <linux/of_mdio.h> +#include <linux/if_vlan.h> +#include <linux/reset.h> +#include <linux/tcp.h> +#include <linux/io.h> +#include <linux/bug.h> + +#include <asm/mach-ralink/ralink_regs.h> + +#include "ralink_soc_eth.h" +#include "esw_rt3052.h" +#include "mdio.h" +#include "ralink_ethtool.h" + +#define MAX_RX_LENGTH 1536 +#define FE_RX_ETH_HLEN (VLAN_ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN) +#define FE_RX_HLEN (NET_SKB_PAD + FE_RX_ETH_HLEN + NET_IP_ALIGN) +#define DMA_DUMMY_DESC 0xffffffff +#define FE_DEFAULT_MSG_ENABLE \ + (NETIF_MSG_DRV | \ + NETIF_MSG_PROBE | \ + NETIF_MSG_LINK | \ + NETIF_MSG_TIMER | \ + NETIF_MSG_IFDOWN | \ + NETIF_MSG_IFUP | \ + NETIF_MSG_RX_ERR | \ + NETIF_MSG_TX_ERR) + +#define TX_DMA_DESP2_DEF (TX_DMA_LS0 | TX_DMA_DONE) +#define TX_DMA_DESP4_DEF (TX_DMA_QN(3) | TX_DMA_PN(1)) +#define NEXT_TX_DESP_IDX(X) (((X) + 1) & (ring->tx_ring_size - 1)) +#define NEXT_RX_DESP_IDX(X) (((X) + 1) & (ring->rx_ring_size - 1)) + +#define SYSC_REG_RSTCTRL 0x34 + +static int fe_msg_level = -1; +module_param_named(msg_level, fe_msg_level, int, 0); +MODULE_PARM_DESC(msg_level, "Message level (-1=defaults,0=none,...,16=all)"); + +static const u16 fe_reg_table_default[FE_REG_COUNT] = { + [FE_REG_PDMA_GLO_CFG] = FE_PDMA_GLO_CFG, + [FE_REG_PDMA_RST_CFG] = FE_PDMA_RST_CFG, + [FE_REG_DLY_INT_CFG] = FE_DLY_INT_CFG, + [FE_REG_TX_BASE_PTR0] = FE_TX_BASE_PTR0, + [FE_REG_TX_MAX_CNT0] = FE_TX_MAX_CNT0, + [FE_REG_TX_CTX_IDX0] = FE_TX_CTX_IDX0, + [FE_REG_TX_DTX_IDX0] = FE_TX_DTX_IDX0, + [FE_REG_RX_BASE_PTR0] = FE_RX_BASE_PTR0, + [FE_REG_RX_MAX_CNT0] = FE_RX_MAX_CNT0, + [FE_REG_RX_CALC_IDX0] = FE_RX_CALC_IDX0, + [FE_REG_RX_DRX_IDX0] = FE_RX_DRX_IDX0, + [FE_REG_FE_INT_ENABLE] = FE_FE_INT_ENABLE, + [FE_REG_FE_INT_STATUS] = FE_FE_INT_STATUS, + [FE_REG_FE_DMA_VID_BASE] = FE_DMA_VID0, + [FE_REG_FE_COUNTER_BASE] = FE_GDMA1_TX_GBCNT, + [FE_REG_FE_RST_GL] = FE_FE_RST_GL, +}; + +static const u16 *fe_reg_table = fe_reg_table_default; + +struct fe_work_t { + int bitnr; + void (*action)(struct fe_priv *); +}; + +static void __iomem *fe_base = 0; + +void fe_w32(u32 val, unsigned reg) +{ + __raw_writel(val, fe_base + reg); +} + +u32 fe_r32(unsigned reg) +{ + return __raw_readl(fe_base + reg); +} + +void fe_reg_w32(u32 val, enum fe_reg reg) +{ + fe_w32(val, fe_reg_table[reg]); +} + +u32 fe_reg_r32(enum fe_reg reg) +{ + return fe_r32(fe_reg_table[reg]); +} + +void fe_reset(u32 reset_bits) +{ + u32 t; + + t = rt_sysc_r32(SYSC_REG_RSTCTRL); + t |= reset_bits; + rt_sysc_w32(t , SYSC_REG_RSTCTRL); + udelay(10); + + t &= ~reset_bits; + rt_sysc_w32(t, SYSC_REG_RSTCTRL); + udelay(10); +} + +static inline void fe_int_disable(u32 mask) +{ + fe_reg_w32(fe_reg_r32(FE_REG_FE_INT_ENABLE) & ~mask, + FE_REG_FE_INT_ENABLE); + /* flush write */ + fe_reg_r32(FE_REG_FE_INT_ENABLE); +} + +static inline void fe_int_enable(u32 mask) +{ + fe_reg_w32(fe_reg_r32(FE_REG_FE_INT_ENABLE) | mask, + FE_REG_FE_INT_ENABLE); + /* flush write */ + fe_reg_r32(FE_REG_FE_INT_ENABLE); +} + +static inline void fe_hw_set_macaddr(struct fe_priv *priv, unsigned char *mac) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->page_lock, flags); + fe_w32((mac[0] << 8) | mac[1], FE_GDMA1_MAC_ADRH); + fe_w32((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5], + FE_GDMA1_MAC_ADRL); + spin_unlock_irqrestore(&priv->page_lock, flags); +} + +static int fe_set_mac_address(struct net_device *dev, void *p) +{ + int ret = eth_mac_addr(dev, p); + + if (!ret) { + struct fe_priv *priv = netdev_priv(dev); + + if (priv->soc->set_mac) + priv->soc->set_mac(priv, dev->dev_addr); + else + fe_hw_set_macaddr(priv, p); + } + + return ret; +} + +static inline int fe_max_frag_size(int mtu) +{ + /* make sure buf_size will be at least MAX_RX_LENGTH */ + if (mtu + FE_RX_ETH_HLEN < MAX_RX_LENGTH) + mtu = MAX_RX_LENGTH - FE_RX_ETH_HLEN; + + return SKB_DATA_ALIGN(FE_RX_HLEN + mtu) + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); +} + +static inline int fe_max_buf_size(int frag_size) +{ + int buf_size = frag_size - NET_SKB_PAD - NET_IP_ALIGN - + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + + BUG_ON(buf_size < MAX_RX_LENGTH); + return buf_size; +} + +static inline void fe_get_rxd(struct fe_rx_dma *rxd, struct fe_rx_dma *dma_rxd) +{ + rxd->rxd1 = dma_rxd->rxd1; + rxd->rxd2 = dma_rxd->rxd2; + rxd->rxd3 = dma_rxd->rxd3; + rxd->rxd4 = dma_rxd->rxd4; +} + +static inline void fe_set_txd(struct fe_tx_dma *txd, struct fe_tx_dma *dma_txd) +{ + dma_txd->txd1 = txd->txd1; + dma_txd->txd3 = txd->txd3; + dma_txd->txd4 = txd->txd4; + /* clean dma done flag last */ + dma_txd->txd2 = txd->txd2; +} + +static void fe_clean_rx(struct fe_priv *priv) +{ + int i; + struct fe_rx_ring *ring = &priv->rx_ring; + + if (ring->rx_data) { + for (i = 0; i < ring->rx_ring_size; i++) + if (ring->rx_data[i]) { + if (ring->rx_dma && ring->rx_dma[i].rxd1) + dma_unmap_single(&priv->netdev->dev, + ring->rx_dma[i].rxd1, + ring->rx_buf_size, + DMA_FROM_DEVICE); + put_page(virt_to_head_page(ring->rx_data[i])); + } + + kfree(ring->rx_data); + ring->rx_data = NULL; + } + + if (ring->rx_dma) { + dma_free_coherent(&priv->netdev->dev, + ring->rx_ring_size * sizeof(*ring->rx_dma), + ring->rx_dma, + ring->rx_phys); + ring->rx_dma = NULL; + } +} + +static int fe_alloc_rx(struct fe_priv *priv) +{ + struct net_device *netdev = priv->netdev; + struct fe_rx_ring *ring = &priv->rx_ring; + int i, pad; + + ring->rx_data = kcalloc(ring->rx_ring_size, sizeof(*ring->rx_data), + GFP_KERNEL); + if (!ring->rx_data) + goto no_rx_mem; + + for (i = 0; i < ring->rx_ring_size; i++) { + ring->rx_data[i] = netdev_alloc_frag(ring->frag_size); + if (!ring->rx_data[i]) + goto no_rx_mem; + } + + ring->rx_dma = dma_alloc_coherent(&netdev->dev, + ring->rx_ring_size * sizeof(*ring->rx_dma), + &ring->rx_phys, + GFP_ATOMIC | __GFP_ZERO); + if (!ring->rx_dma) + goto no_rx_mem; + + if (priv->flags & FE_FLAG_RX_2B_OFFSET) + pad = 0; + else + pad = NET_IP_ALIGN; + for (i = 0; i < ring->rx_ring_size; i++) { + dma_addr_t dma_addr = dma_map_single(&netdev->dev, + ring->rx_data[i] + NET_SKB_PAD + pad, + ring->rx_buf_size, + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(&netdev->dev, dma_addr))) + goto no_rx_mem; + ring->rx_dma[i].rxd1 = (unsigned int) dma_addr; + + if (priv->flags & FE_FLAG_RX_SG_DMA) + ring->rx_dma[i].rxd2 = RX_DMA_PLEN0(ring->rx_buf_size); + else + ring->rx_dma[i].rxd2 = RX_DMA_LSO; + } + ring->rx_calc_idx = ring->rx_ring_size - 1; + wmb(); + + fe_reg_w32(ring->rx_phys, FE_REG_RX_BASE_PTR0); + fe_reg_w32(ring->rx_ring_size, FE_REG_RX_MAX_CNT0); + fe_reg_w32(ring->rx_calc_idx, FE_REG_RX_CALC_IDX0); + fe_reg_w32(FE_PST_DRX_IDX0, FE_REG_PDMA_RST_CFG); + + return 0; + +no_rx_mem: + return -ENOMEM; +} + +static void fe_txd_unmap(struct device *dev, struct fe_tx_buf *tx_buf) +{ + if (tx_buf->flags & FE_TX_FLAGS_SINGLE0) { + dma_unmap_single(dev, + dma_unmap_addr(tx_buf, dma_addr0), + dma_unmap_len(tx_buf, dma_len0), + DMA_TO_DEVICE); + } else if (tx_buf->flags & FE_TX_FLAGS_PAGE0) { + dma_unmap_page(dev, + dma_unmap_addr(tx_buf, dma_addr0), + dma_unmap_len(tx_buf, dma_len0), + DMA_TO_DEVICE); + } + if (tx_buf->flags & FE_TX_FLAGS_PAGE1) + dma_unmap_page(dev, + dma_unmap_addr(tx_buf, dma_addr1), + dma_unmap_len(tx_buf, dma_len1), + DMA_TO_DEVICE); + + tx_buf->flags = 0; + if (tx_buf->skb && (tx_buf->skb != (struct sk_buff *) DMA_DUMMY_DESC)) { + dev_kfree_skb_any(tx_buf->skb); + } + tx_buf->skb = NULL; +} + +static void fe_clean_tx(struct fe_priv *priv) +{ + int i; + struct device *dev = &priv->netdev->dev; + struct fe_tx_ring *ring = &priv->tx_ring; + + if (ring->tx_buf) { + for (i = 0; i < ring->tx_ring_size; i++) + fe_txd_unmap(dev, &ring->tx_buf[i]); + kfree(ring->tx_buf); + ring->tx_buf = NULL; + } + + if (ring->tx_dma) { + dma_free_coherent(dev, + ring->tx_ring_size * sizeof(*ring->tx_dma), + ring->tx_dma, + ring->tx_phys); + ring->tx_dma = NULL; + } + + netdev_reset_queue(priv->netdev); +} + +static int fe_alloc_tx(struct fe_priv *priv) +{ + int i; + struct fe_tx_ring *ring = &priv->tx_ring; + + ring->tx_free_idx = 0; + ring->tx_next_idx = 0; + ring->tx_thresh = max((unsigned long)ring->tx_ring_size >> 2, MAX_SKB_FRAGS); + + ring->tx_buf = kcalloc(ring->tx_ring_size, sizeof(*ring->tx_buf), + GFP_KERNEL); + if (!ring->tx_buf) + goto no_tx_mem; + + ring->tx_dma = dma_alloc_coherent(&priv->netdev->dev, + ring->tx_ring_size * sizeof(*ring->tx_dma), + &ring->tx_phys, + GFP_ATOMIC | __GFP_ZERO); + if (!ring->tx_dma) + goto no_tx_mem; + + for (i = 0; i < ring->tx_ring_size; i++) { + if (priv->soc->tx_dma) { + priv->soc->tx_dma(&ring->tx_dma[i]); + } + ring->tx_dma[i].txd2 = TX_DMA_DESP2_DEF; + } + wmb(); + + fe_reg_w32(ring->tx_phys, FE_REG_TX_BASE_PTR0); + fe_reg_w32(ring->tx_ring_size, FE_REG_TX_MAX_CNT0); + fe_reg_w32(0, FE_REG_TX_CTX_IDX0); + fe_reg_w32(FE_PST_DTX_IDX0, FE_REG_PDMA_RST_CFG); + + return 0; + +no_tx_mem: + return -ENOMEM; +} + +static int fe_init_dma(struct fe_priv *priv) +{ + int err; + + err = fe_alloc_tx(priv); + if (err) + return err; + + err = fe_alloc_rx(priv); + if (err) + return err; + + return 0; +} + +static void fe_free_dma(struct fe_priv *priv) +{ + fe_clean_tx(priv); + fe_clean_rx(priv); +} + +void fe_stats_update(struct fe_priv *priv) +{ + struct fe_hw_stats *hwstats = priv->hw_stats; + unsigned int base = fe_reg_table[FE_REG_FE_COUNTER_BASE]; + u64 stats; + + u64_stats_update_begin(&hwstats->syncp); + + if (IS_ENABLED(CONFIG_SOC_MT7621)) { + hwstats->rx_bytes += fe_r32(base); + stats = fe_r32(base + 0x04); + if (stats) + hwstats->rx_bytes += (stats << 32); + hwstats->rx_packets += fe_r32(base + 0x08); + hwstats->rx_overflow += fe_r32(base + 0x10); + hwstats->rx_fcs_errors += fe_r32(base + 0x14); + hwstats->rx_short_errors += fe_r32(base + 0x18); + hwstats->rx_long_errors += fe_r32(base + 0x1c); + hwstats->rx_checksum_errors += fe_r32(base + 0x20); + hwstats->rx_flow_control_packets += fe_r32(base + 0x24); + hwstats->tx_skip += fe_r32(base + 0x28); + hwstats->tx_collisions += fe_r32(base + 0x2c); + hwstats->tx_bytes += fe_r32(base + 0x30); + stats = fe_r32(base + 0x34); + if (stats) + hwstats->tx_bytes += (stats << 32); + hwstats->tx_packets += fe_r32(base + 0x38); + } else { + hwstats->tx_bytes += fe_r32(base); + hwstats->tx_packets += fe_r32(base + 0x04); + hwstats->tx_skip += fe_r32(base + 0x08); + hwstats->tx_collisions += fe_r32(base + 0x0c); + hwstats->rx_bytes += fe_r32(base + 0x20); + hwstats->rx_packets += fe_r32(base + 0x24); + hwstats->rx_overflow += fe_r32(base + 0x28); + hwstats->rx_fcs_errors += fe_r32(base + 0x2c); + hwstats->rx_short_errors += fe_r32(base + 0x30); + hwstats->rx_long_errors += fe_r32(base + 0x34); + hwstats->rx_checksum_errors += fe_r32(base + 0x38); + hwstats->rx_flow_control_packets += fe_r32(base + 0x3c); + } + + u64_stats_update_end(&hwstats->syncp); +} + +static struct rtnl_link_stats64 *fe_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *storage) +{ + struct fe_priv *priv = netdev_priv(dev); + struct fe_hw_stats *hwstats = priv->hw_stats; + unsigned int base = fe_reg_table[FE_REG_FE_COUNTER_BASE]; + unsigned int start; + + if (!base) { + netdev_stats_to_stats64(storage, &dev->stats); + return storage; + } + + if (netif_running(dev) && netif_device_present(dev)) { + if (spin_trylock(&hwstats->stats_lock)) { + fe_stats_update(priv); + spin_unlock(&hwstats->stats_lock); + } + } + + do { + start = u64_stats_fetch_begin_irq(&hwstats->syncp); + storage->rx_packets = hwstats->rx_packets; + storage->tx_packets = hwstats->tx_packets; + storage->rx_bytes = hwstats->rx_bytes; + storage->tx_bytes = hwstats->tx_bytes; + storage->collisions = hwstats->tx_collisions; + storage->rx_length_errors = hwstats->rx_short_errors + + hwstats->rx_long_errors; + storage->rx_over_errors = hwstats->rx_overflow; + storage->rx_crc_errors = hwstats->rx_fcs_errors; + storage->rx_errors = hwstats->rx_checksum_errors; + storage->tx_aborted_errors = hwstats->tx_skip; + } while (u64_stats_fetch_retry_irq(&hwstats->syncp, start)); + + storage->tx_errors = priv->netdev->stats.tx_errors; + storage->rx_dropped = priv->netdev->stats.rx_dropped; + storage->tx_dropped = priv->netdev->stats.tx_dropped; + + return storage; +} + +static int fe_vlan_rx_add_vid(struct net_device *dev, + __be16 proto, u16 vid) +{ + struct fe_priv *priv = netdev_priv(dev); + u32 idx = (vid & 0xf); + u32 vlan_cfg; + + if (!((fe_reg_table[FE_REG_FE_DMA_VID_BASE]) && + (dev->features & NETIF_F_HW_VLAN_CTAG_TX))) + return 0; + + if (test_bit(idx, &priv->vlan_map)) { + netdev_warn(dev, "disable tx vlan offload\n"); + dev->wanted_features &= ~NETIF_F_HW_VLAN_CTAG_TX; + netdev_update_features(dev); + } else { + vlan_cfg = fe_r32(fe_reg_table[FE_REG_FE_DMA_VID_BASE] + + ((idx >> 1) << 2)); + if (idx & 0x1) { + vlan_cfg &= 0xffff; + vlan_cfg |= (vid << 16); + } else { + vlan_cfg &= 0xffff0000; + vlan_cfg |= vid; + } + fe_w32(vlan_cfg, fe_reg_table[FE_REG_FE_DMA_VID_BASE] + + ((idx >> 1) << 2)); + set_bit(idx, &priv->vlan_map); + } + + return 0; +} + +static int fe_vlan_rx_kill_vid(struct net_device *dev, + __be16 proto, u16 vid) +{ + struct fe_priv *priv = netdev_priv(dev); + u32 idx = (vid & 0xf); + + if (!((fe_reg_table[FE_REG_FE_DMA_VID_BASE]) && + (dev->features & NETIF_F_HW_VLAN_CTAG_TX))) + return 0; + + clear_bit(idx, &priv->vlan_map); + + return 0; +} + +static inline u32 fe_empty_txd(struct fe_tx_ring *ring) +{ + barrier(); + return (u32)(ring->tx_ring_size - + ((ring->tx_next_idx - ring->tx_free_idx) & + (ring->tx_ring_size - 1))); +} + +static int fe_tx_map_dma(struct sk_buff *skb, struct net_device *dev, + int tx_num, struct fe_tx_ring *ring) +{ + struct fe_priv *priv = netdev_priv(dev); + struct skb_frag_struct *frag; + struct fe_tx_dma txd, *ptxd; + struct fe_tx_buf *tx_buf; + dma_addr_t mapped_addr; + unsigned int nr_frags; + u32 def_txd4; + int i, j, k, frag_size, frag_map_size, offset; + + tx_buf = &ring->tx_buf[ring->tx_next_idx]; + memset(tx_buf, 0, sizeof(*tx_buf)); + memset(&txd, 0, sizeof(txd)); + nr_frags = skb_shinfo(skb)->nr_frags; + + /* init tx descriptor */ + if (priv->soc->tx_dma) + priv->soc->tx_dma(&txd); + else + txd.txd4 = TX_DMA_DESP4_DEF; + def_txd4 = txd.txd4; + + /* TX Checksum offload */ + if (skb->ip_summed == CHECKSUM_PARTIAL) + txd.txd4 |= TX_DMA_CHKSUM; + + /* VLAN header offload */ + if (vlan_tx_tag_present(skb)) { + if (IS_ENABLED(CONFIG_SOC_MT7621)) + txd.txd4 |= TX_DMA_INS_VLAN_MT7621 | vlan_tx_tag_get(skb); + else + txd.txd4 |= TX_DMA_INS_VLAN | + ((vlan_tx_tag_get(skb) >> VLAN_PRIO_SHIFT) << 4) | + (vlan_tx_tag_get(skb) & 0xF); + } + + /* TSO: fill MSS info in tcp checksum field */ + if (skb_is_gso(skb)) { + if (skb_cow_head(skb, 0)) { + netif_warn(priv, tx_err, dev, + "GSO expand head fail.\n"); + goto err_out; + } + if (skb_shinfo(skb)->gso_type & + (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { + txd.txd4 |= TX_DMA_TSO; + tcp_hdr(skb)->check = htons(skb_shinfo(skb)->gso_size); + } + } + + mapped_addr = dma_map_single(&dev->dev, skb->data, + skb_headlen(skb), DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(&dev->dev, mapped_addr))) + goto err_out; + txd.txd1 = mapped_addr; + txd.txd2 = TX_DMA_PLEN0(skb_headlen(skb)); + + tx_buf->flags |= FE_TX_FLAGS_SINGLE0; + dma_unmap_addr_set(tx_buf, dma_addr0, mapped_addr); + dma_unmap_len_set(tx_buf, dma_len0, skb_headlen(skb)); + + /* TX SG offload */ + j = ring->tx_next_idx; + k = 0; + for (i = 0; i < nr_frags; i++) { + offset = 0; + frag = &skb_shinfo(skb)->frags[i]; + frag_size = skb_frag_size(frag); + + while (frag_size > 0) { + frag_map_size = min(frag_size, TX_DMA_BUF_LEN); + mapped_addr = skb_frag_dma_map(&dev->dev, frag, offset, + frag_map_size, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(&dev->dev, mapped_addr))) + goto err_dma; + + if (k & 0x1) { + j = NEXT_TX_DESP_IDX(j); + txd.txd1 = mapped_addr; + txd.txd2 = TX_DMA_PLEN0(frag_map_size); + txd.txd4 = def_txd4; + + tx_buf = &ring->tx_buf[j]; + memset(tx_buf, 0, sizeof(*tx_buf)); + + tx_buf->flags |= FE_TX_FLAGS_PAGE0; + dma_unmap_addr_set(tx_buf, dma_addr0, mapped_addr); + dma_unmap_len_set(tx_buf, dma_len0, frag_map_size); + } else { + txd.txd3 = mapped_addr; + txd.txd2 |= TX_DMA_PLEN1(frag_map_size); + + tx_buf->skb = (struct sk_buff *) DMA_DUMMY_DESC; + tx_buf->flags |= FE_TX_FLAGS_PAGE1; + dma_unmap_addr_set(tx_buf, dma_addr1, mapped_addr); + dma_unmap_len_set(tx_buf, dma_len1, frag_map_size); + + if (!((i == (nr_frags -1)) && + (frag_map_size == frag_size))) { + fe_set_txd(&txd, &ring->tx_dma[j]); + memset(&txd, 0, sizeof(txd)); + } + } + frag_size -= frag_map_size; + offset += frag_map_size; + k++; + } + } + + /* set last segment */ + if (k & 0x1) + txd.txd2 |= TX_DMA_LS1; + else + txd.txd2 |= TX_DMA_LS0; + fe_set_txd(&txd, &ring->tx_dma[j]); + + /* store skb to cleanup */ + tx_buf->skb = skb; + + netdev_sent_queue(dev, skb->len); + skb_tx_timestamp(skb); + + ring->tx_next_idx = NEXT_TX_DESP_IDX(j); + wmb(); + if (unlikely(fe_empty_txd(ring) <= ring->tx_thresh)) { + netif_stop_queue(dev); + smp_mb(); + if (unlikely(fe_empty_txd(ring) > ring->tx_thresh)) + netif_wake_queue(dev); + } + + if (netif_xmit_stopped(netdev_get_tx_queue(dev, 0)) || !skb->xmit_more) + fe_reg_w32(ring->tx_next_idx, FE_REG_TX_CTX_IDX0); + + return 0; + +err_dma: + j = ring->tx_next_idx; + for (i = 0; i < tx_num; i++) { + ptxd = &ring->tx_dma[j]; + tx_buf = &ring->tx_buf[j]; + + /* unmap dma */ + fe_txd_unmap(&dev->dev, tx_buf); + + ptxd->txd2 = TX_DMA_DESP2_DEF; + j = NEXT_TX_DESP_IDX(j); + } + wmb(); + +err_out: + return -1; +} + +static inline int fe_skb_padto(struct sk_buff *skb, struct fe_priv *priv) { + unsigned int len; + int ret; + + ret = 0; + if (unlikely(skb->len < VLAN_ETH_ZLEN)) { + if ((priv->flags & FE_FLAG_PADDING_64B) && + !(priv->flags & FE_FLAG_PADDING_BUG)) + return ret; + + if (vlan_tx_tag_present(skb)) + len = ETH_ZLEN; + else if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) + len = VLAN_ETH_ZLEN; + else if(!(priv->flags & FE_FLAG_PADDING_64B)) + len = ETH_ZLEN; + else + return ret; + + if (skb->len < len) { + if ((ret = skb_pad(skb, len - skb->len)) < 0) + return ret; + skb->len = len; + skb_set_tail_pointer(skb, len); + } + } + + return ret; +} + +static inline int fe_cal_txd_req(struct sk_buff *skb) +{ + int i, nfrags; + struct skb_frag_struct *frag; + + nfrags = 1; + if (skb_is_gso(skb)) { + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + frag = &skb_shinfo(skb)->frags[i]; + nfrags += DIV_ROUND_UP(frag->size, TX_DMA_BUF_LEN); + } + } else { + nfrags += skb_shinfo(skb)->nr_frags; + } + + return DIV_ROUND_UP(nfrags, 2); +} + +static int fe_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + struct fe_tx_ring *ring = &priv->tx_ring; + struct net_device_stats *stats = &dev->stats; + int tx_num; + int len = skb->len; + + if (fe_skb_padto(skb, priv)) { + netif_warn(priv, tx_err, dev, "tx padding failed!\n"); + return NETDEV_TX_OK; + } + + tx_num = fe_cal_txd_req(skb); + if (unlikely(fe_empty_txd(ring) <= tx_num)) + { + netif_stop_queue(dev); + netif_err(priv, tx_queued,dev, + "Tx Ring full when queue awake!\n"); + return NETDEV_TX_BUSY; + } + + if (fe_tx_map_dma(skb, dev, tx_num, ring) < 0) { + stats->tx_dropped++; + } else { + stats->tx_packets++; + stats->tx_bytes += len; + } + + return NETDEV_TX_OK; +} + +static inline void fe_rx_vlan(struct sk_buff *skb) +{ + struct ethhdr *ehdr; + u16 vlanid; + + if (!__vlan_get_tag(skb, &vlanid)) { + /* pop the vlan tag */ + ehdr = (struct ethhdr *)skb->data; + memmove(skb->data + VLAN_HLEN, ehdr, ETH_ALEN * 2); + skb_pull(skb, VLAN_HLEN); + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlanid); + } +} + +static int fe_poll_rx(struct napi_struct *napi, int budget, + struct fe_priv *priv, u32 rx_intr) +{ + struct net_device *netdev = priv->netdev; + struct net_device_stats *stats = &netdev->stats; + struct fe_soc_data *soc = priv->soc; + struct fe_rx_ring *ring = &priv->rx_ring; + int idx = ring->rx_calc_idx; + u32 checksum_bit; + struct sk_buff *skb; + u8 *data, *new_data; + struct fe_rx_dma *rxd, trxd; + int done = 0, pad; + bool rx_vlan = netdev->features & NETIF_F_HW_VLAN_CTAG_RX; + + if (netdev->features & NETIF_F_RXCSUM) + checksum_bit = soc->checksum_bit; + else + checksum_bit = 0; + + if (priv->flags & FE_FLAG_RX_2B_OFFSET) + pad = 0; + else + pad = NET_IP_ALIGN; + + while (done < budget) { + unsigned int pktlen; + dma_addr_t dma_addr; + idx = NEXT_RX_DESP_IDX(idx); + rxd = &ring->rx_dma[idx]; + data = ring->rx_data[idx]; + + fe_get_rxd(&trxd, rxd); + if (!(trxd.rxd2 & RX_DMA_DONE)) + break; + + /* alloc new buffer */ + new_data = netdev_alloc_frag(ring->frag_size); + if (unlikely(!new_data)) { + stats->rx_dropped++; + goto release_desc; + } + dma_addr = dma_map_single(&netdev->dev, + new_data + NET_SKB_PAD + pad, + ring->rx_buf_size, + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(&netdev->dev, dma_addr))) { + put_page(virt_to_head_page(new_data)); + goto release_desc; + } + + /* receive data */ + skb = build_skb(data, ring->frag_size); + if (unlikely(!skb)) { + put_page(virt_to_head_page(new_data)); + goto release_desc; + } + skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN); + + dma_unmap_single(&netdev->dev, trxd.rxd1, + ring->rx_buf_size, DMA_FROM_DEVICE); + pktlen = RX_DMA_GET_PLEN0(trxd.rxd2); + skb->dev = netdev; + skb_put(skb, pktlen); + if (trxd.rxd4 & checksum_bit) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else { + skb_checksum_none_assert(skb); + } + if (rx_vlan) + fe_rx_vlan(skb); + skb->protocol = eth_type_trans(skb, netdev); + + stats->rx_packets++; + stats->rx_bytes += pktlen; + + napi_gro_receive(napi, skb); + + ring->rx_data[idx] = new_data; + rxd->rxd1 = (unsigned int) dma_addr; + +release_desc: + if (priv->flags & FE_FLAG_RX_SG_DMA) + rxd->rxd2 = RX_DMA_PLEN0(ring->rx_buf_size); + else + rxd->rxd2 = RX_DMA_LSO; + + ring->rx_calc_idx = idx; + wmb(); + fe_reg_w32(ring->rx_calc_idx, FE_REG_RX_CALC_IDX0); + done++; + } + + if (done < budget) + fe_reg_w32(rx_intr, FE_REG_FE_INT_STATUS); + + return done; +} + +static int fe_poll_tx(struct fe_priv *priv, int budget, u32 tx_intr, + int *tx_again) +{ + struct net_device *netdev = priv->netdev; + struct device *dev = &netdev->dev; + unsigned int bytes_compl = 0; + struct sk_buff *skb; + struct fe_tx_buf *tx_buf; + int done = 0; + u32 idx, hwidx; + struct fe_tx_ring *ring = &priv->tx_ring; + + idx = ring->tx_free_idx; + hwidx = fe_reg_r32(FE_REG_TX_DTX_IDX0); + + while ((idx != hwidx) && budget) { + tx_buf = &ring->tx_buf[idx]; + skb = tx_buf->skb; + + if (!skb) + break; + + if (skb != (struct sk_buff *) DMA_DUMMY_DESC) { + bytes_compl += skb->len; + done++; + budget--; + } + fe_txd_unmap(dev, tx_buf); + idx = NEXT_TX_DESP_IDX(idx); + } + ring->tx_free_idx = idx; + + if (idx == hwidx) { + /* read hw index again make sure no new tx packet */ + hwidx = fe_reg_r32(FE_REG_TX_DTX_IDX0); + if (idx == hwidx) + fe_reg_w32(tx_intr, FE_REG_FE_INT_STATUS); + else + *tx_again = 1; + } else + *tx_again = 1; + + if (done) { + netdev_completed_queue(netdev, done, bytes_compl); + smp_mb(); + if (unlikely(netif_queue_stopped(netdev) && + (fe_empty_txd(ring) > ring->tx_thresh))) + netif_wake_queue(netdev); + } + + return done; +} + +static int fe_poll(struct napi_struct *napi, int budget) +{ + struct fe_priv *priv = container_of(napi, struct fe_priv, rx_napi); + struct fe_hw_stats *hwstat = priv->hw_stats; + int tx_done, rx_done, tx_again; + u32 status, fe_status, status_reg, mask; + u32 tx_intr, rx_intr, status_intr; + + fe_status = status = fe_reg_r32(FE_REG_FE_INT_STATUS); + tx_intr = priv->soc->tx_int; + rx_intr = priv->soc->rx_int; + status_intr = priv->soc->status_int; + tx_done = rx_done = tx_again = 0; + + if (fe_reg_table[FE_REG_FE_INT_STATUS2]) { + fe_status = fe_reg_r32(FE_REG_FE_INT_STATUS2); + status_reg = FE_REG_FE_INT_STATUS2; + } else + status_reg = FE_REG_FE_INT_STATUS; + + if (status & tx_intr) + tx_done = fe_poll_tx(priv, budget, tx_intr, &tx_again); + + if (status & rx_intr) + rx_done = fe_poll_rx(napi, budget, priv, rx_intr); + + if (unlikely(fe_status & status_intr)) { + if (hwstat && spin_trylock(&hwstat->stats_lock)) { + fe_stats_update(priv); + spin_unlock(&hwstat->stats_lock); + } + fe_reg_w32(status_intr, status_reg); + } + + if (unlikely(netif_msg_intr(priv))) { + mask = fe_reg_r32(FE_REG_FE_INT_ENABLE); + netdev_info(priv->netdev, + "done tx %d, rx %d, intr 0x%08x/0x%x\n", + tx_done, rx_done, status, mask); + } + + if (!tx_again && (rx_done < budget)) { + status = fe_reg_r32(FE_REG_FE_INT_STATUS); + if (status & (tx_intr | rx_intr)) { + /* let napi poll again */ + rx_done = budget; + goto poll_again; + } + + napi_complete(napi); + fe_int_enable(tx_intr | rx_intr); + } + +poll_again: + return rx_done; +} + +static void fe_tx_timeout(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + struct fe_tx_ring *ring = &priv->tx_ring; + + priv->netdev->stats.tx_errors++; + netif_err(priv, tx_err, dev, + "transmit timed out\n"); + netif_info(priv, drv, dev, "dma_cfg:%08x\n", + fe_reg_r32(FE_REG_PDMA_GLO_CFG)); + netif_info(priv, drv, dev, "tx_ring=%d, " \ + "base=%08x, max=%u, ctx=%u, dtx=%u, fdx=%hu, next=%hu\n", 0, + fe_reg_r32(FE_REG_TX_BASE_PTR0), + fe_reg_r32(FE_REG_TX_MAX_CNT0), + fe_reg_r32(FE_REG_TX_CTX_IDX0), + fe_reg_r32(FE_REG_TX_DTX_IDX0), + ring->tx_free_idx, + ring->tx_next_idx + ); + netif_info(priv, drv, dev, "rx_ring=%d, " \ + "base=%08x, max=%u, calc=%u, drx=%u\n", 0, + fe_reg_r32(FE_REG_RX_BASE_PTR0), + fe_reg_r32(FE_REG_RX_MAX_CNT0), + fe_reg_r32(FE_REG_RX_CALC_IDX0), + fe_reg_r32(FE_REG_RX_DRX_IDX0) + ); + + if (!test_and_set_bit(FE_FLAG_RESET_PENDING, priv->pending_flags)) + schedule_work(&priv->pending_work); +} + +static irqreturn_t fe_handle_irq(int irq, void *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + u32 status, int_mask; + + status = fe_reg_r32(FE_REG_FE_INT_STATUS); + + if (unlikely(!status)) + return IRQ_NONE; + + int_mask = (priv->soc->rx_int | priv->soc->tx_int); + if (likely(status & int_mask)) { + if (likely(napi_schedule_prep(&priv->rx_napi))) { + fe_int_disable(int_mask); + __napi_schedule(&priv->rx_napi); + } + } else { + fe_reg_w32(status, FE_REG_FE_INT_STATUS); + } + + return IRQ_HANDLED; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void fe_poll_controller(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + u32 int_mask = priv->soc->tx_int | priv->soc->rx_int; + + fe_int_disable(int_mask); + fe_handle_irq(dev->irq, dev); + fe_int_enable(int_mask); +} +#endif + +int fe_set_clock_cycle(struct fe_priv *priv) +{ + unsigned long sysclk = priv->sysclk; + + if (!sysclk) { + return -EINVAL; + } + + sysclk /= FE_US_CYC_CNT_DIVISOR; + sysclk <<= FE_US_CYC_CNT_SHIFT; + + fe_w32((fe_r32(FE_FE_GLO_CFG) & + ~(FE_US_CYC_CNT_MASK << FE_US_CYC_CNT_SHIFT)) | + sysclk, + FE_FE_GLO_CFG); + return 0; +} + +void fe_fwd_config(struct fe_priv *priv) +{ + u32 fwd_cfg; + + fwd_cfg = fe_r32(FE_GDMA1_FWD_CFG); + + /* disable jumbo frame */ + if (priv->flags & FE_FLAG_JUMBO_FRAME) + fwd_cfg &= ~FE_GDM1_JMB_EN; + + /* set unicast/multicast/broadcast frame to cpu */ + fwd_cfg &= ~0xffff; + + fe_w32(fwd_cfg, FE_GDMA1_FWD_CFG); +} + +static void fe_rxcsum_config(bool enable) +{ + if (enable) + fe_w32(fe_r32(FE_GDMA1_FWD_CFG) | (FE_GDM1_ICS_EN | + FE_GDM1_TCS_EN | FE_GDM1_UCS_EN), + FE_GDMA1_FWD_CFG); + else + fe_w32(fe_r32(FE_GDMA1_FWD_CFG) & ~(FE_GDM1_ICS_EN | + FE_GDM1_TCS_EN | FE_GDM1_UCS_EN), + FE_GDMA1_FWD_CFG); +} + +static void fe_txcsum_config(bool enable) +{ + if (enable) + fe_w32(fe_r32(FE_CDMA_CSG_CFG) | (FE_ICS_GEN_EN | + FE_TCS_GEN_EN | FE_UCS_GEN_EN), + FE_CDMA_CSG_CFG); + else + fe_w32(fe_r32(FE_CDMA_CSG_CFG) & ~(FE_ICS_GEN_EN | + FE_TCS_GEN_EN | FE_UCS_GEN_EN), + FE_CDMA_CSG_CFG); +} + +void fe_csum_config(struct fe_priv *priv) +{ + struct net_device *dev = priv_netdev(priv); + + fe_txcsum_config((dev->features & NETIF_F_IP_CSUM)); + fe_rxcsum_config((dev->features & NETIF_F_RXCSUM)); +} + +static int fe_hw_init(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + int i, err; + + err = devm_request_irq(priv->device, dev->irq, fe_handle_irq, 0, + dev_name(priv->device), dev); + if (err) + return err; + + if (priv->soc->set_mac) + priv->soc->set_mac(priv, dev->dev_addr); + else + fe_hw_set_macaddr(priv, dev->dev_addr); + + /* disable delay interrupt */ + fe_reg_w32(0, FE_REG_DLY_INT_CFG); + + fe_int_disable(priv->soc->tx_int | priv->soc->rx_int); + + /* frame engine will push VLAN tag regarding to VIDX feild in Tx desc. */ + if (fe_reg_table[FE_REG_FE_DMA_VID_BASE]) + for (i = 0; i < 16; i += 2) + fe_w32(((i + 1) << 16) + i, + fe_reg_table[FE_REG_FE_DMA_VID_BASE] + + (i * 2)); + + BUG_ON(!priv->soc->fwd_config); + if (priv->soc->fwd_config(priv)) + netdev_err(dev, "unable to get clock\n"); + + if (fe_reg_table[FE_REG_FE_RST_GL]) { + fe_reg_w32(1, FE_REG_FE_RST_GL); + fe_reg_w32(0, FE_REG_FE_RST_GL); + } + + return 0; +} + +static int fe_open(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + unsigned long flags; + u32 val; + int err; + + err = fe_init_dma(priv); + if (err) + goto err_out; + + spin_lock_irqsave(&priv->page_lock, flags); + + val = FE_TX_WB_DDONE | FE_RX_DMA_EN | FE_TX_DMA_EN; + if (priv->flags & FE_FLAG_RX_2B_OFFSET) + val |= FE_RX_2B_OFFSET; + val |= priv->soc->pdma_glo_cfg; + fe_reg_w32(val, FE_REG_PDMA_GLO_CFG); + + spin_unlock_irqrestore(&priv->page_lock, flags); + + if (priv->phy) + priv->phy->start(priv); + + if (priv->soc->has_carrier && priv->soc->has_carrier(priv)) + netif_carrier_on(dev); + + napi_enable(&priv->rx_napi); + fe_int_enable(priv->soc->tx_int | priv->soc->rx_int); + netif_start_queue(dev); + + return 0; + +err_out: + fe_free_dma(priv); + return err; +} + +static int fe_stop(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + unsigned long flags; + int i; + + netif_tx_disable(dev); + fe_int_disable(priv->soc->tx_int | priv->soc->rx_int); + napi_disable(&priv->rx_napi); + + if (priv->phy) + priv->phy->stop(priv); + + spin_lock_irqsave(&priv->page_lock, flags); + + fe_reg_w32(fe_reg_r32(FE_REG_PDMA_GLO_CFG) & + ~(FE_TX_WB_DDONE | FE_RX_DMA_EN | FE_TX_DMA_EN), + FE_REG_PDMA_GLO_CFG); + spin_unlock_irqrestore(&priv->page_lock, flags); + + /* wait dma stop */ + for (i = 0; i < 10; i++) { + if (fe_reg_r32(FE_REG_PDMA_GLO_CFG) & + (FE_TX_DMA_BUSY | FE_RX_DMA_BUSY)) { + msleep(10); + continue; + } + break; + } + + fe_free_dma(priv); + + return 0; +} + +static int __init fe_init(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + struct device_node *port; + int err; + + BUG_ON(!priv->soc->reset_fe); + priv->soc->reset_fe(); + + if (priv->soc->switch_init) + priv->soc->switch_init(priv); + + of_get_mac_address_mtd(priv->device->of_node, dev->dev_addr); + /*If the mac address is invalid, use random mac address */ + if (!is_valid_ether_addr(dev->dev_addr)) { + random_ether_addr(dev->dev_addr); + dev_err(priv->device, "generated random MAC address %pM\n", + dev->dev_addr); + } + + err = fe_mdio_init(priv); + if (err) + return err; + + if (priv->soc->port_init) + for_each_child_of_node(priv->device->of_node, port) + if (of_device_is_compatible(port, "ralink,eth-port") && of_device_is_available(port)) + priv->soc->port_init(priv, port); + + if (priv->phy) { + err = priv->phy->connect(priv); + if (err) + goto err_phy_disconnect; + } + + err = fe_hw_init(dev); + if (err) + goto err_phy_disconnect; + + if (priv->soc->switch_config) + priv->soc->switch_config(priv); + + return 0; + +err_phy_disconnect: + if (priv->phy) + priv->phy->disconnect(priv); + fe_mdio_cleanup(priv); + + return err; +} + +static void fe_uninit(struct net_device *dev) +{ + struct fe_priv *priv = netdev_priv(dev); + + if (priv->phy) + priv->phy->disconnect(priv); + fe_mdio_cleanup(priv); + + fe_reg_w32(0, FE_REG_FE_INT_ENABLE); + free_irq(dev->irq, dev); +} + +static int fe_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + struct fe_priv *priv = netdev_priv(dev); + + if (!priv->phy_dev) + return -ENODEV; + + switch (cmd) { + case SIOCETHTOOL: + return phy_ethtool_ioctl(priv->phy_dev, + (void *) ifr->ifr_data); + case SIOCGMIIPHY: + case SIOCGMIIREG: + case SIOCSMIIREG: + return phy_mii_ioctl(priv->phy_dev, ifr, cmd); + default: + break; + } + + return -EOPNOTSUPP; +} + +static int fe_change_mtu(struct net_device *dev, int new_mtu) +{ + struct fe_priv *priv = netdev_priv(dev); + int frag_size, old_mtu; + u32 fwd_cfg; + + if (!(priv->flags & FE_FLAG_JUMBO_FRAME)) + return eth_change_mtu(dev, new_mtu); + + frag_size = fe_max_frag_size(new_mtu); + if (new_mtu < 68 || frag_size > PAGE_SIZE) + return -EINVAL; + + old_mtu = dev->mtu; + dev->mtu = new_mtu; + + /* return early if the buffer sizes will not change */ + if (old_mtu <= ETH_DATA_LEN && new_mtu <= ETH_DATA_LEN) + return 0; + if (old_mtu > ETH_DATA_LEN && new_mtu > ETH_DATA_LEN) + return 0; + + if (new_mtu <= ETH_DATA_LEN) + priv->rx_ring.frag_size = fe_max_frag_size(ETH_DATA_LEN); + else + priv->rx_ring.frag_size = PAGE_SIZE; + priv->rx_ring.rx_buf_size = fe_max_buf_size(priv->rx_ring.frag_size); + + if (!netif_running(dev)) + return 0; + + fe_stop(dev); + fwd_cfg = fe_r32(FE_GDMA1_FWD_CFG); + if (new_mtu <= ETH_DATA_LEN) + fwd_cfg &= ~FE_GDM1_JMB_EN; + else { + fwd_cfg &= ~(FE_GDM1_JMB_LEN_MASK << FE_GDM1_JMB_LEN_SHIFT); + fwd_cfg |= (DIV_ROUND_UP(frag_size, 1024) << + FE_GDM1_JMB_LEN_SHIFT) | FE_GDM1_JMB_EN; + } + fe_w32(fwd_cfg, FE_GDMA1_FWD_CFG); + + return fe_open(dev); +} + +static const struct net_device_ops fe_netdev_ops = { + .ndo_init = fe_init, + .ndo_uninit = fe_uninit, + .ndo_open = fe_open, + .ndo_stop = fe_stop, + .ndo_start_xmit = fe_start_xmit, + .ndo_set_mac_address = fe_set_mac_address, + .ndo_validate_addr = eth_validate_addr, + .ndo_do_ioctl = fe_do_ioctl, + .ndo_change_mtu = fe_change_mtu, + .ndo_tx_timeout = fe_tx_timeout, + .ndo_get_stats64 = fe_get_stats64, + .ndo_vlan_rx_add_vid = fe_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = fe_vlan_rx_kill_vid, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = fe_poll_controller, +#endif +}; + +static void fe_reset_pending(struct fe_priv *priv) +{ + struct net_device *dev = priv->netdev; + int err; + + rtnl_lock(); + fe_stop(dev); + + err = fe_open(dev); + if (err) + goto error; + rtnl_unlock(); + + return; +error: + netif_alert(priv, ifup, dev, + "Driver up/down cycle failed, closing device.\n"); + dev_close(dev); + rtnl_unlock(); +} + +static const struct fe_work_t fe_work[] = { + {FE_FLAG_RESET_PENDING, fe_reset_pending}, +}; + +static void fe_pending_work(struct work_struct *work) +{ + struct fe_priv *priv = container_of(work, struct fe_priv, pending_work); + int i; + bool pending; + + for (i = 0; i < ARRAY_SIZE(fe_work); i++) { + pending = test_and_clear_bit(fe_work[i].bitnr, + priv->pending_flags); + if (pending) + fe_work[i].action(priv); + } +} + +static int fe_probe(struct platform_device *pdev) +{ + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + const struct of_device_id *match; + struct fe_soc_data *soc; + struct net_device *netdev; + struct fe_priv *priv; + struct clk *sysclk; + int err, napi_weight; + + device_reset(&pdev->dev); + + match = of_match_device(of_fe_match, &pdev->dev); + soc = (struct fe_soc_data *) match->data; + + if (soc->reg_table) + fe_reg_table = soc->reg_table; + else + soc->reg_table = fe_reg_table; + + fe_base = devm_ioremap_resource(&pdev->dev, res); + if (!fe_base) { + err = -EADDRNOTAVAIL; + goto err_out; + } + + netdev = alloc_etherdev(sizeof(*priv)); + if (!netdev) { + dev_err(&pdev->dev, "alloc_etherdev failed\n"); + err = -ENOMEM; + goto err_iounmap; + } + + SET_NETDEV_DEV(netdev, &pdev->dev); + netdev->netdev_ops = &fe_netdev_ops; + netdev->base_addr = (unsigned long) fe_base; + + netdev->irq = platform_get_irq(pdev, 0); + if (netdev->irq < 0) { + dev_err(&pdev->dev, "no IRQ resource found\n"); + err = -ENXIO; + goto err_free_dev; + } + + if (soc->init_data) + soc->init_data(soc, netdev); + /* fake NETIF_F_HW_VLAN_CTAG_RX for good GRO performance */ + netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX; + netdev->vlan_features = netdev->hw_features & + ~(NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX); + netdev->features |= netdev->hw_features; + + /* fake rx vlan filter func. to support tx vlan offload func */ + if (fe_reg_table[FE_REG_FE_DMA_VID_BASE]) + netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; + + priv = netdev_priv(netdev); + spin_lock_init(&priv->page_lock); + if (fe_reg_table[FE_REG_FE_COUNTER_BASE]) { + priv->hw_stats = kzalloc(sizeof(*priv->hw_stats), GFP_KERNEL); + if (!priv->hw_stats) { + err = -ENOMEM; + goto err_free_dev; + } + spin_lock_init(&priv->hw_stats->stats_lock); + } + + sysclk = devm_clk_get(&pdev->dev, NULL); + if (!IS_ERR(sysclk)) + priv->sysclk = clk_get_rate(sysclk); + + priv->netdev = netdev; + priv->device = &pdev->dev; + priv->soc = soc; + priv->msg_enable = netif_msg_init(fe_msg_level, FE_DEFAULT_MSG_ENABLE); + priv->rx_ring.frag_size = fe_max_frag_size(ETH_DATA_LEN); + priv->rx_ring.rx_buf_size = fe_max_buf_size(priv->rx_ring.frag_size); + priv->tx_ring.tx_ring_size = priv->rx_ring.rx_ring_size = NUM_DMA_DESC; + INIT_WORK(&priv->pending_work, fe_pending_work); + + napi_weight = 32; + if (priv->flags & FE_FLAG_NAPI_WEIGHT) { + napi_weight *= 4; + priv->tx_ring.tx_ring_size *= 4; + priv->rx_ring.rx_ring_size *= 4; + } + netif_napi_add(netdev, &priv->rx_napi, fe_poll, napi_weight); + fe_set_ethtool_ops(netdev); + + err = register_netdev(netdev); + if (err) { + dev_err(&pdev->dev, "error bringing up device\n"); + goto err_free_dev; + } + + platform_set_drvdata(pdev, netdev); + + netif_info(priv, probe, netdev, "ralink at 0x%08lx, irq %d\n", + netdev->base_addr, netdev->irq); + + return 0; + +err_free_dev: + free_netdev(netdev); +err_iounmap: + devm_iounmap(&pdev->dev, fe_base); +err_out: + return err; +} + +static int fe_remove(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata(pdev); + struct fe_priv *priv = netdev_priv(dev); + + netif_napi_del(&priv->rx_napi); + if (priv->hw_stats) + kfree(priv->hw_stats); + + cancel_work_sync(&priv->pending_work); + + unregister_netdev(dev); + free_netdev(dev); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver fe_driver = { + .probe = fe_probe, + .remove = fe_remove, + .driver = { + .name = "ralink_soc_eth", + .owner = THIS_MODULE, + .of_match_table = of_fe_match, + }, +}; + +static int __init init_rtfe(void) +{ + int ret; + + ret = rtesw_init(); + if (ret) + return ret; + + ret = platform_driver_register(&fe_driver); + if (ret) + rtesw_exit(); + + return ret; +} + +static void __exit exit_rtfe(void) +{ + platform_driver_unregister(&fe_driver); + rtesw_exit(); +} + +module_init(init_rtfe); +module_exit(exit_rtfe); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); +MODULE_DESCRIPTION("Ethernet driver for Ralink SoC"); +MODULE_VERSION(FE_DRV_VERSION); diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.h b/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.h new file mode 100644 index 0000000..51b087c --- /dev/null +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.h @@ -0,0 +1,529 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * based on Ralink SDK3.3 + * Copyright (C) 2009-2013 John Crispin <blogic@openwrt.org> + */ + +#ifndef FE_ETH_H +#define FE_ETH_H + +#include <linux/mii.h> +#include <linux/interrupt.h> +#include <linux/netdevice.h> +#include <linux/dma-mapping.h> +#include <linux/phy.h> +#include <linux/ethtool.h> +#include <linux/version.h> + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0) +#define u64_stats_fetch_retry_irq u64_stats_fetch_retry_bh +#define u64_stats_fetch_begin_irq u64_stats_fetch_begin_bh +#endif + +enum fe_reg { + FE_REG_PDMA_GLO_CFG = 0, + FE_REG_PDMA_RST_CFG, + FE_REG_DLY_INT_CFG, + FE_REG_TX_BASE_PTR0, + FE_REG_TX_MAX_CNT0, + FE_REG_TX_CTX_IDX0, + FE_REG_TX_DTX_IDX0, + FE_REG_RX_BASE_PTR0, + FE_REG_RX_MAX_CNT0, + FE_REG_RX_CALC_IDX0, + FE_REG_RX_DRX_IDX0, + FE_REG_FE_INT_ENABLE, + FE_REG_FE_INT_STATUS, + FE_REG_FE_DMA_VID_BASE, + FE_REG_FE_COUNTER_BASE, + FE_REG_FE_RST_GL, + FE_REG_FE_INT_STATUS2, + FE_REG_COUNT +}; + +enum fe_work_flag { + FE_FLAG_RESET_PENDING, + FE_FLAG_MAX +}; + +#define FE_DRV_VERSION "0.1.2" + +/* power of 2 to let NEXT_TX_DESP_IDX work */ +#define NUM_DMA_DESC (1 << 7) +#define MAX_DMA_DESC 0xfff + +#define FE_DELAY_EN_INT 0x80 +#define FE_DELAY_MAX_INT 0x04 +#define FE_DELAY_MAX_TOUT 0x04 +#define FE_DELAY_TIME 20 +#define FE_DELAY_CHAN (((FE_DELAY_EN_INT | FE_DELAY_MAX_INT) << 8) | FE_DELAY_MAX_TOUT) +#define FE_DELAY_INIT ((FE_DELAY_CHAN << 16) | FE_DELAY_CHAN) +#define FE_PSE_FQFC_CFG_INIT 0x80504000 +#define FE_PSE_FQFC_CFG_256Q 0xff908000 + +/* interrupt bits */ +#define FE_CNT_PPE_AF BIT(31) +#define FE_CNT_GDM_AF BIT(29) +#define FE_PSE_P2_FC BIT(26) +#define FE_PSE_BUF_DROP BIT(24) +#define FE_GDM_OTHER_DROP BIT(23) +#define FE_PSE_P1_FC BIT(22) +#define FE_PSE_P0_FC BIT(21) +#define FE_PSE_FQ_EMPTY BIT(20) +#define FE_GE1_STA_CHG BIT(18) +#define FE_TX_COHERENT BIT(17) +#define FE_RX_COHERENT BIT(16) +#define FE_TX_DONE_INT3 BIT(11) +#define FE_TX_DONE_INT2 BIT(10) +#define FE_TX_DONE_INT1 BIT(9) +#define FE_TX_DONE_INT0 BIT(8) +#define FE_RX_DONE_INT0 BIT(2) +#define FE_TX_DLY_INT BIT(1) +#define FE_RX_DLY_INT BIT(0) + +#define FE_RX_DONE_INT FE_RX_DONE_INT0 +#define FE_TX_DONE_INT (FE_TX_DONE_INT0 | FE_TX_DONE_INT1 | \ + FE_TX_DONE_INT2 | FE_TX_DONE_INT3) + +#define RT5350_RX_DLY_INT BIT(30) +#define RT5350_TX_DLY_INT BIT(28) +#define RT5350_RX_DONE_INT1 BIT(17) +#define RT5350_RX_DONE_INT0 BIT(16) +#define RT5350_TX_DONE_INT3 BIT(3) +#define RT5350_TX_DONE_INT2 BIT(2) +#define RT5350_TX_DONE_INT1 BIT(1) +#define RT5350_TX_DONE_INT0 BIT(0) + +#define RT5350_RX_DONE_INT (RT5350_RX_DONE_INT0 | RT5350_RX_DONE_INT1) +#define RT5350_TX_DONE_INT (RT5350_TX_DONE_INT0 | RT5350_TX_DONE_INT1 | \ + RT5350_TX_DONE_INT2 | RT5350_TX_DONE_INT3) + +/* registers */ +#define FE_FE_OFFSET 0x0000 +#define FE_GDMA_OFFSET 0x0020 +#define FE_PSE_OFFSET 0x0040 +#define FE_GDMA2_OFFSET 0x0060 +#define FE_CDMA_OFFSET 0x0080 +#define FE_DMA_VID0 0x00a8 +#define FE_PDMA_OFFSET 0x0100 +#define FE_PPE_OFFSET 0x0200 +#define FE_CMTABLE_OFFSET 0x0400 +#define FE_POLICYTABLE_OFFSET 0x1000 + +#define RT5350_PDMA_OFFSET 0x0800 +#define RT5350_SDM_OFFSET 0x0c00 + +#define FE_MDIO_ACCESS (FE_FE_OFFSET + 0x00) +#define FE_MDIO_CFG (FE_FE_OFFSET + 0x04) +#define FE_FE_GLO_CFG (FE_FE_OFFSET + 0x08) +#define FE_FE_RST_GL (FE_FE_OFFSET + 0x0C) +#define FE_FE_INT_STATUS (FE_FE_OFFSET + 0x10) +#define FE_FE_INT_ENABLE (FE_FE_OFFSET + 0x14) +#define FE_MDIO_CFG2 (FE_FE_OFFSET + 0x18) +#define FE_FOC_TS_T (FE_FE_OFFSET + 0x1C) + +#define FE_GDMA1_FWD_CFG (FE_GDMA_OFFSET + 0x00) +#define FE_GDMA1_SCH_CFG (FE_GDMA_OFFSET + 0x04) +#define FE_GDMA1_SHPR_CFG (FE_GDMA_OFFSET + 0x08) +#define FE_GDMA1_MAC_ADRL (FE_GDMA_OFFSET + 0x0C) +#define FE_GDMA1_MAC_ADRH (FE_GDMA_OFFSET + 0x10) + +#define FE_GDMA2_FWD_CFG (FE_GDMA2_OFFSET + 0x00) +#define FE_GDMA2_SCH_CFG (FE_GDMA2_OFFSET + 0x04) +#define FE_GDMA2_SHPR_CFG (FE_GDMA2_OFFSET + 0x08) +#define FE_GDMA2_MAC_ADRL (FE_GDMA2_OFFSET + 0x0C) +#define FE_GDMA2_MAC_ADRH (FE_GDMA2_OFFSET + 0x10) + +#define FE_PSE_FQ_CFG (FE_PSE_OFFSET + 0x00) +#define FE_CDMA_FC_CFG (FE_PSE_OFFSET + 0x04) +#define FE_GDMA1_FC_CFG (FE_PSE_OFFSET + 0x08) +#define FE_GDMA2_FC_CFG (FE_PSE_OFFSET + 0x0C) + +#define FE_CDMA_CSG_CFG (FE_CDMA_OFFSET + 0x00) +#define FE_CDMA_SCH_CFG (FE_CDMA_OFFSET + 0x04) + +#ifdef CONFIG_SOC_MT7621 +#define MT7620A_GDMA_OFFSET 0x0500 +#else +#define MT7620A_GDMA_OFFSET 0x0600 +#endif +#define MT7620A_GDMA1_FWD_CFG (MT7620A_GDMA_OFFSET + 0x00) +#define MT7620A_FE_GDMA1_SCH_CFG (MT7620A_GDMA_OFFSET + 0x04) +#define MT7620A_FE_GDMA1_SHPR_CFG (MT7620A_GDMA_OFFSET + 0x08) +#define MT7620A_FE_GDMA1_MAC_ADRL (MT7620A_GDMA_OFFSET + 0x0C) +#define MT7620A_FE_GDMA1_MAC_ADRH (MT7620A_GDMA_OFFSET + 0x10) + +#define RT5350_TX_BASE_PTR0 (RT5350_PDMA_OFFSET + 0x00) +#define RT5350_TX_MAX_CNT0 (RT5350_PDMA_OFFSET + 0x04) +#define RT5350_TX_CTX_IDX0 (RT5350_PDMA_OFFSET + 0x08) +#define RT5350_TX_DTX_IDX0 (RT5350_PDMA_OFFSET + 0x0C) +#define RT5350_TX_BASE_PTR1 (RT5350_PDMA_OFFSET + 0x10) +#define RT5350_TX_MAX_CNT1 (RT5350_PDMA_OFFSET + 0x14) +#define RT5350_TX_CTX_IDX1 (RT5350_PDMA_OFFSET + 0x18) +#define RT5350_TX_DTX_IDX1 (RT5350_PDMA_OFFSET + 0x1C) +#define RT5350_TX_BASE_PTR2 (RT5350_PDMA_OFFSET + 0x20) +#define RT5350_TX_MAX_CNT2 (RT5350_PDMA_OFFSET + 0x24) +#define RT5350_TX_CTX_IDX2 (RT5350_PDMA_OFFSET + 0x28) +#define RT5350_TX_DTX_IDX2 (RT5350_PDMA_OFFSET + 0x2C) +#define RT5350_TX_BASE_PTR3 (RT5350_PDMA_OFFSET + 0x30) +#define RT5350_TX_MAX_CNT3 (RT5350_PDMA_OFFSET + 0x34) +#define RT5350_TX_CTX_IDX3 (RT5350_PDMA_OFFSET + 0x38) +#define RT5350_TX_DTX_IDX3 (RT5350_PDMA_OFFSET + 0x3C) +#define RT5350_RX_BASE_PTR0 (RT5350_PDMA_OFFSET + 0x100) +#define RT5350_RX_MAX_CNT0 (RT5350_PDMA_OFFSET + 0x104) +#define RT5350_RX_CALC_IDX0 (RT5350_PDMA_OFFSET + 0x108) +#define RT5350_RX_DRX_IDX0 (RT5350_PDMA_OFFSET + 0x10C) +#define RT5350_RX_BASE_PTR1 (RT5350_PDMA_OFFSET + 0x110) +#define RT5350_RX_MAX_CNT1 (RT5350_PDMA_OFFSET + 0x114) +#define RT5350_RX_CALC_IDX1 (RT5350_PDMA_OFFSET + 0x118) +#define RT5350_RX_DRX_IDX1 (RT5350_PDMA_OFFSET + 0x11C) +#define RT5350_PDMA_GLO_CFG (RT5350_PDMA_OFFSET + 0x204) +#define RT5350_PDMA_RST_CFG (RT5350_PDMA_OFFSET + 0x208) +#define RT5350_DLY_INT_CFG (RT5350_PDMA_OFFSET + 0x20c) +#define RT5350_FE_INT_STATUS (RT5350_PDMA_OFFSET + 0x220) +#define RT5350_FE_INT_ENABLE (RT5350_PDMA_OFFSET + 0x228) +#define RT5350_PDMA_SCH_CFG (RT5350_PDMA_OFFSET + 0x280) + +#define FE_PDMA_GLO_CFG (FE_PDMA_OFFSET + 0x00) +#define FE_PDMA_RST_CFG (FE_PDMA_OFFSET + 0x04) +#define FE_PDMA_SCH_CFG (FE_PDMA_OFFSET + 0x08) +#define FE_DLY_INT_CFG (FE_PDMA_OFFSET + 0x0C) +#define FE_TX_BASE_PTR0 (FE_PDMA_OFFSET + 0x10) +#define FE_TX_MAX_CNT0 (FE_PDMA_OFFSET + 0x14) +#define FE_TX_CTX_IDX0 (FE_PDMA_OFFSET + 0x18) +#define FE_TX_DTX_IDX0 (FE_PDMA_OFFSET + 0x1C) +#define FE_TX_BASE_PTR1 (FE_PDMA_OFFSET + 0x20) +#define FE_TX_MAX_CNT1 (FE_PDMA_OFFSET + 0x24) +#define FE_TX_CTX_IDX1 (FE_PDMA_OFFSET + 0x28) +#define FE_TX_DTX_IDX1 (FE_PDMA_OFFSET + 0x2C) +#define FE_RX_BASE_PTR0 (FE_PDMA_OFFSET + 0x30) +#define FE_RX_MAX_CNT0 (FE_PDMA_OFFSET + 0x34) +#define FE_RX_CALC_IDX0 (FE_PDMA_OFFSET + 0x38) +#define FE_RX_DRX_IDX0 (FE_PDMA_OFFSET + 0x3C) +#define FE_TX_BASE_PTR2 (FE_PDMA_OFFSET + 0x40) +#define FE_TX_MAX_CNT2 (FE_PDMA_OFFSET + 0x44) +#define FE_TX_CTX_IDX2 (FE_PDMA_OFFSET + 0x48) +#define FE_TX_DTX_IDX2 (FE_PDMA_OFFSET + 0x4C) +#define FE_TX_BASE_PTR3 (FE_PDMA_OFFSET + 0x50) +#define FE_TX_MAX_CNT3 (FE_PDMA_OFFSET + 0x54) +#define FE_TX_CTX_IDX3 (FE_PDMA_OFFSET + 0x58) +#define FE_TX_DTX_IDX3 (FE_PDMA_OFFSET + 0x5C) +#define FE_RX_BASE_PTR1 (FE_PDMA_OFFSET + 0x60) +#define FE_RX_MAX_CNT1 (FE_PDMA_OFFSET + 0x64) +#define FE_RX_CALC_IDX1 (FE_PDMA_OFFSET + 0x68) +#define FE_RX_DRX_IDX1 (FE_PDMA_OFFSET + 0x6C) + +#define RT5350_SDM_CFG (RT5350_SDM_OFFSET + 0x00) //Switch DMA configuration +#define RT5350_SDM_RRING (RT5350_SDM_OFFSET + 0x04) //Switch DMA Rx Ring +#define RT5350_SDM_TRING (RT5350_SDM_OFFSET + 0x08) //Switch DMA Tx Ring +#define RT5350_SDM_MAC_ADRL (RT5350_SDM_OFFSET + 0x0C) //Switch MAC address LSB +#define RT5350_SDM_MAC_ADRH (RT5350_SDM_OFFSET + 0x10) //Switch MAC Address MSB +#define RT5350_SDM_TPCNT (RT5350_SDM_OFFSET + 0x100) //Switch DMA Tx packet count +#define RT5350_SDM_TBCNT (RT5350_SDM_OFFSET + 0x104) //Switch DMA Tx byte count +#define RT5350_SDM_RPCNT (RT5350_SDM_OFFSET + 0x108) //Switch DMA rx packet count +#define RT5350_SDM_RBCNT (RT5350_SDM_OFFSET + 0x10C) //Switch DMA rx byte count +#define RT5350_SDM_CS_ERR (RT5350_SDM_OFFSET + 0x110) //Switch DMA rx checksum error count + +#define RT5350_SDM_ICS_EN BIT(16) +#define RT5350_SDM_TCS_EN BIT(17) +#define RT5350_SDM_UCS_EN BIT(18) + + +/* MDIO_CFG register bits */ +#define FE_MDIO_CFG_AUTO_POLL_EN BIT(29) +#define FE_MDIO_CFG_GP1_BP_EN BIT(16) +#define FE_MDIO_CFG_GP1_FRC_EN BIT(15) +#define FE_MDIO_CFG_GP1_SPEED_10 (0 << 13) +#define FE_MDIO_CFG_GP1_SPEED_100 (1 << 13) +#define FE_MDIO_CFG_GP1_SPEED_1000 (2 << 13) +#define FE_MDIO_CFG_GP1_DUPLEX BIT(12) +#define FE_MDIO_CFG_GP1_FC_TX BIT(11) +#define FE_MDIO_CFG_GP1_FC_RX BIT(10) +#define FE_MDIO_CFG_GP1_LNK_DWN BIT(9) +#define FE_MDIO_CFG_GP1_AN_FAIL BIT(8) +#define FE_MDIO_CFG_MDC_CLK_DIV_1 (0 << 6) +#define FE_MDIO_CFG_MDC_CLK_DIV_2 (1 << 6) +#define FE_MDIO_CFG_MDC_CLK_DIV_4 (2 << 6) +#define FE_MDIO_CFG_MDC_CLK_DIV_8 (3 << 6) +#define FE_MDIO_CFG_TURBO_MII_FREQ BIT(5) +#define FE_MDIO_CFG_TURBO_MII_MODE BIT(4) +#define FE_MDIO_CFG_RX_CLK_SKEW_0 (0 << 2) +#define FE_MDIO_CFG_RX_CLK_SKEW_200 (1 << 2) +#define FE_MDIO_CFG_RX_CLK_SKEW_400 (2 << 2) +#define FE_MDIO_CFG_RX_CLK_SKEW_INV (3 << 2) +#define FE_MDIO_CFG_TX_CLK_SKEW_0 0 +#define FE_MDIO_CFG_TX_CLK_SKEW_200 1 +#define FE_MDIO_CFG_TX_CLK_SKEW_400 2 +#define FE_MDIO_CFG_TX_CLK_SKEW_INV 3 + +/* uni-cast port */ +#define FE_GDM1_JMB_LEN_MASK 0xf +#define FE_GDM1_JMB_LEN_SHIFT 28 +#define FE_GDM1_ICS_EN BIT(22) +#define FE_GDM1_TCS_EN BIT(21) +#define FE_GDM1_UCS_EN BIT(20) +#define FE_GDM1_JMB_EN BIT(19) +#define FE_GDM1_STRPCRC BIT(16) +#define FE_GDM1_UFRC_P_CPU (0 << 12) +#define FE_GDM1_UFRC_P_GDMA1 (1 << 12) +#define FE_GDM1_UFRC_P_PPE (6 << 12) + +/* checksums */ +#define FE_ICS_GEN_EN BIT(2) +#define FE_UCS_GEN_EN BIT(1) +#define FE_TCS_GEN_EN BIT(0) + +/* dma ring */ +#define FE_PST_DRX_IDX0 BIT(16) +#define FE_PST_DTX_IDX3 BIT(3) +#define FE_PST_DTX_IDX2 BIT(2) +#define FE_PST_DTX_IDX1 BIT(1) +#define FE_PST_DTX_IDX0 BIT(0) + +#define FE_RX_2B_OFFSET BIT(31) +#define FE_TX_WB_DDONE BIT(6) +#define FE_RX_DMA_BUSY BIT(3) +#define FE_TX_DMA_BUSY BIT(1) +#define FE_RX_DMA_EN BIT(2) +#define FE_TX_DMA_EN BIT(0) + +#define FE_PDMA_SIZE_4DWORDS (0 << 4) +#define FE_PDMA_SIZE_8DWORDS (1 << 4) +#define FE_PDMA_SIZE_16DWORDS (2 << 4) + +#define FE_US_CYC_CNT_MASK 0xff +#define FE_US_CYC_CNT_SHIFT 0x8 +#define FE_US_CYC_CNT_DIVISOR 1000000 + +/* rxd2 */ +#define RX_DMA_DONE BIT(31) +#define RX_DMA_LSO BIT(30) +#define RX_DMA_PLEN0(_x) (((_x) & 0x3fff) << 16) +#define RX_DMA_GET_PLEN0(_x) (((_x) >> 16) & 0x3fff) +#define RX_DMA_TAG BIT(15) +/* rxd3 */ +#define RX_DMA_TPID(_x) (((_x) >> 16) & 0xffff) +#define RX_DMA_VID(_x) ((_x) & 0xffff) +/* rxd4 */ +#define RX_DMA_L4VALID BIT(30) + +struct fe_rx_dma { + unsigned int rxd1; + unsigned int rxd2; + unsigned int rxd3; + unsigned int rxd4; +} __packed __aligned(4); + +#define TX_DMA_BUF_LEN 0x3fff +#define TX_DMA_PLEN0_MASK (TX_DMA_BUF_LEN << 16) +#define TX_DMA_PLEN0(_x) (((_x) & TX_DMA_BUF_LEN) << 16) +#define TX_DMA_PLEN1(_x) ((_x) & TX_DMA_BUF_LEN) +#define TX_DMA_GET_PLEN0(_x) (((_x) >> 16 ) & TX_DMA_BUF_LEN) +#define TX_DMA_GET_PLEN1(_x) ((_x) & TX_DMA_BUF_LEN) +#define TX_DMA_LS1 BIT(14) +#define TX_DMA_LS0 BIT(30) +#define TX_DMA_DONE BIT(31) + +#define TX_DMA_INS_VLAN_MT7621 BIT(16) +#define TX_DMA_INS_VLAN BIT(7) +#define TX_DMA_INS_PPPOE BIT(12) +#define TX_DMA_QN(_x) ((_x) << 16) +#define TX_DMA_PN(_x) ((_x) << 24) +#define TX_DMA_QN_MASK TX_DMA_QN(0x7) +#define TX_DMA_PN_MASK TX_DMA_PN(0x7) +#define TX_DMA_UDF BIT(20) +#define TX_DMA_CHKSUM (0x7 << 29) +#define TX_DMA_TSO BIT(28) + +/* frame engine counters */ +#define FE_PPE_AC_BCNT0 (FE_CMTABLE_OFFSET + 0x00) +#define FE_GDMA1_TX_GBCNT (FE_CMTABLE_OFFSET + 0x300) +#define FE_GDMA2_TX_GBCNT (FE_GDMA1_TX_GBCNT + 0x40) + +/* phy device flags */ +#define FE_PHY_FLAG_PORT BIT(0) +#define FE_PHY_FLAG_ATTACH BIT(1) + +struct fe_tx_dma { + unsigned int txd1; + unsigned int txd2; + unsigned int txd3; + unsigned int txd4; +} __packed __aligned(4); + +struct fe_priv; + +struct fe_phy { + struct phy_device *phy[8]; + struct device_node *phy_node[8]; + const __be32 *phy_fixed[8]; + int duplex[8]; + int speed[8]; + int tx_fc[8]; + int rx_fc[8]; + spinlock_t lock; + + int (*connect)(struct fe_priv *priv); + void (*disconnect)(struct fe_priv *priv); + void (*start)(struct fe_priv *priv); + void (*stop)(struct fe_priv *priv); +}; + +struct fe_soc_data +{ + const u16 *reg_table; + + void (*init_data)(struct fe_soc_data *data, struct net_device *netdev); + void (*reset_fe)(void); + void (*set_mac)(struct fe_priv *priv, unsigned char *mac); + int (*fwd_config)(struct fe_priv *priv); + void (*tx_dma)(struct fe_tx_dma *txd); + int (*switch_init)(struct fe_priv *priv); + int (*switch_config)(struct fe_priv *priv); + void (*port_init)(struct fe_priv *priv, struct device_node *port); + int (*has_carrier)(struct fe_priv *priv); + int (*mdio_init)(struct fe_priv *priv); + void (*mdio_cleanup)(struct fe_priv *priv); + int (*mdio_write)(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val); + int (*mdio_read)(struct mii_bus *bus, int phy_addr, int phy_reg); + void (*mdio_adjust_link)(struct fe_priv *priv, int port); + + void *swpriv; + u32 pdma_glo_cfg; + u32 rx_int; + u32 tx_int; + u32 status_int; + u32 checksum_bit; +}; + +#define FE_FLAG_PADDING_64B BIT(0) +#define FE_FLAG_PADDING_BUG BIT(1) +#define FE_FLAG_JUMBO_FRAME BIT(2) +#define FE_FLAG_RX_2B_OFFSET BIT(3) +#define FE_FLAG_RX_SG_DMA BIT(4) +#define FE_FLAG_RX_VLAN_CTAG BIT(5) +#define FE_FLAG_NAPI_WEIGHT BIT(6) + +#define FE_STAT_REG_DECLARE \ + _FE(tx_bytes) \ + _FE(tx_packets) \ + _FE(tx_skip) \ + _FE(tx_collisions) \ + _FE(rx_bytes) \ + _FE(rx_packets) \ + _FE(rx_overflow) \ + _FE(rx_fcs_errors) \ + _FE(rx_short_errors) \ + _FE(rx_long_errors) \ + _FE(rx_checksum_errors) \ + _FE(rx_flow_control_packets) + +struct fe_hw_stats +{ + spinlock_t stats_lock; + struct u64_stats_sync syncp; +#define _FE(x) u64 x; +FE_STAT_REG_DECLARE +#undef _FE +}; + +enum fe_tx_flags { + FE_TX_FLAGS_SINGLE0 = 0x01, + FE_TX_FLAGS_PAGE0 = 0x02, + FE_TX_FLAGS_PAGE1 = 0x04, +}; + +struct fe_tx_buf +{ + struct sk_buff *skb; + u32 flags; + DEFINE_DMA_UNMAP_ADDR(dma_addr0); + DEFINE_DMA_UNMAP_LEN(dma_len0); + DEFINE_DMA_UNMAP_ADDR(dma_addr1); + DEFINE_DMA_UNMAP_LEN(dma_len1); +}; + +struct fe_tx_ring +{ + struct fe_tx_dma *tx_dma; + struct fe_tx_buf *tx_buf; + dma_addr_t tx_phys; + u16 tx_ring_size; + u16 tx_free_idx; + u16 tx_next_idx; + u16 tx_thresh; +}; + +struct fe_rx_ring +{ + struct fe_rx_dma *rx_dma; + u8 **rx_data; + dma_addr_t rx_phys; + u16 rx_ring_size; + u16 frag_size; + u16 rx_buf_size; + u16 rx_calc_idx; +}; + +struct fe_priv +{ + spinlock_t page_lock; + + struct fe_soc_data *soc; + struct net_device *netdev; + u32 msg_enable; + u32 flags; + + struct device *device; + unsigned long sysclk; + + struct fe_rx_ring rx_ring; + struct napi_struct rx_napi; + + struct fe_tx_ring tx_ring; + + struct fe_phy *phy; + struct mii_bus *mii_bus; + struct phy_device *phy_dev; + u32 phy_flags; + + int link[8]; + + struct fe_hw_stats *hw_stats; + unsigned long vlan_map; + struct work_struct pending_work; + DECLARE_BITMAP(pending_flags, FE_FLAG_MAX); +}; + +extern const struct of_device_id of_fe_match[]; + +void fe_w32(u32 val, unsigned reg); +u32 fe_r32(unsigned reg); + +int fe_set_clock_cycle(struct fe_priv *priv); +void fe_csum_config(struct fe_priv *priv); +void fe_stats_update(struct fe_priv *priv); +void fe_fwd_config(struct fe_priv *priv); +void fe_reg_w32(u32 val, enum fe_reg reg); +u32 fe_reg_r32(enum fe_reg reg); + +void fe_reset(u32 reset_bits); + +static inline void *priv_netdev(struct fe_priv *priv) +{ + return (char *)priv - ALIGN(sizeof(struct net_device), NETDEV_ALIGN); +} + +#endif /* FE_ETH_H */ diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_mt7620.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_mt7620.c new file mode 100644 index 0000000..a18c1c9 --- /dev/null +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_mt7620.c @@ -0,0 +1,278 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2009-2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/if_vlan.h> + +#include <asm/mach-ralink/ralink_regs.h> + +#include <mt7620.h> +#include "ralink_soc_eth.h" +#include "gsw_mt7620a.h" + +#define MT7620A_CDMA_CSG_CFG 0x400 +#define MT7620_DMA_VID (MT7620A_CDMA_CSG_CFG | 0x30) +#define MT7621_CDMP_IG_CTRL (MT7620A_CDMA_CSG_CFG + 0x00) +#define MT7621_CDMP_EG_CTRL (MT7620A_CDMA_CSG_CFG + 0x04) +#define MT7620A_RESET_FE BIT(21) +#define MT7621_RESET_FE BIT(6) +#define MT7620A_RESET_ESW BIT(23) +#define MT7620_L4_VALID BIT(23) +#define MT7621_L4_VALID BIT(24) + +#define MT7620_TX_DMA_UDF BIT(15) +#define MT7621_TX_DMA_UDF BIT(19) +#define TX_DMA_FP_BMAP ((0xff) << 19) + +#define CDMA_ICS_EN BIT(2) +#define CDMA_UCS_EN BIT(1) +#define CDMA_TCS_EN BIT(0) + +#define GDMA_ICS_EN BIT(22) +#define GDMA_TCS_EN BIT(21) +#define GDMA_UCS_EN BIT(20) + +/* frame engine counters */ +#define MT7620_REG_MIB_OFFSET 0x1000 +#define MT7620_PPE_AC_BCNT0 (MT7620_REG_MIB_OFFSET + 0x00) +#define MT7620_GDM1_TX_GBCNT (MT7620_REG_MIB_OFFSET + 0x300) +#define MT7620_GDM2_TX_GBCNT (MT7620_GDM1_TX_GBCNT + 0x40) + +#define MT7621_REG_MIB_OFFSET 0x2000 +#define MT7621_PPE_AC_BCNT0 (MT7621_REG_MIB_OFFSET + 0x00) +#define MT7621_GDM1_TX_GBCNT (MT7621_REG_MIB_OFFSET + 0x400) +#define MT7621_GDM2_TX_GBCNT (MT7621_GDM1_TX_GBCNT + 0x40) + +#define GSW_REG_GDMA1_MAC_ADRL 0x508 +#define GSW_REG_GDMA1_MAC_ADRH 0x50C + +#define MT7621_FE_RST_GL (FE_FE_OFFSET + 0x04) +#define MT7620_FE_INT_STATUS2 (FE_FE_OFFSET + 0x08) + +/* + * FE_INT_STATUS reg on mt7620 define CNT_GDM1_AF at BIT(29) + * but after test it should be BIT(13). + */ +#define MT7620_FE_GDM1_AF BIT(13) +#define MT7621_FE_GDM1_AF BIT(28) +#define MT7621_FE_GDM2_AF BIT(29) + +static const u16 mt7620_reg_table[FE_REG_COUNT] = { + [FE_REG_PDMA_GLO_CFG] = RT5350_PDMA_GLO_CFG, + [FE_REG_PDMA_RST_CFG] = RT5350_PDMA_RST_CFG, + [FE_REG_DLY_INT_CFG] = RT5350_DLY_INT_CFG, + [FE_REG_TX_BASE_PTR0] = RT5350_TX_BASE_PTR0, + [FE_REG_TX_MAX_CNT0] = RT5350_TX_MAX_CNT0, + [FE_REG_TX_CTX_IDX0] = RT5350_TX_CTX_IDX0, + [FE_REG_TX_DTX_IDX0] = RT5350_TX_DTX_IDX0, + [FE_REG_RX_BASE_PTR0] = RT5350_RX_BASE_PTR0, + [FE_REG_RX_MAX_CNT0] = RT5350_RX_MAX_CNT0, + [FE_REG_RX_CALC_IDX0] = RT5350_RX_CALC_IDX0, + [FE_REG_RX_DRX_IDX0] = RT5350_RX_DRX_IDX0, + [FE_REG_FE_INT_ENABLE] = RT5350_FE_INT_ENABLE, + [FE_REG_FE_INT_STATUS] = RT5350_FE_INT_STATUS, + [FE_REG_FE_DMA_VID_BASE] = MT7620_DMA_VID, + [FE_REG_FE_COUNTER_BASE] = MT7620_GDM1_TX_GBCNT, + [FE_REG_FE_RST_GL] = MT7621_FE_RST_GL, + [FE_REG_FE_INT_STATUS2] = MT7620_FE_INT_STATUS2, +}; + +static const u16 mt7621_reg_table[FE_REG_COUNT] = { + [FE_REG_PDMA_GLO_CFG] = RT5350_PDMA_GLO_CFG, + [FE_REG_PDMA_RST_CFG] = RT5350_PDMA_RST_CFG, + [FE_REG_DLY_INT_CFG] = RT5350_DLY_INT_CFG, + [FE_REG_TX_BASE_PTR0] = RT5350_TX_BASE_PTR0, + [FE_REG_TX_MAX_CNT0] = RT5350_TX_MAX_CNT0, + [FE_REG_TX_CTX_IDX0] = RT5350_TX_CTX_IDX0, + [FE_REG_TX_DTX_IDX0] = RT5350_TX_DTX_IDX0, + [FE_REG_RX_BASE_PTR0] = RT5350_RX_BASE_PTR0, + [FE_REG_RX_MAX_CNT0] = RT5350_RX_MAX_CNT0, + [FE_REG_RX_CALC_IDX0] = RT5350_RX_CALC_IDX0, + [FE_REG_RX_DRX_IDX0] = RT5350_RX_DRX_IDX0, + [FE_REG_FE_INT_ENABLE] = RT5350_FE_INT_ENABLE, + [FE_REG_FE_INT_STATUS] = RT5350_FE_INT_STATUS, + [FE_REG_FE_DMA_VID_BASE] = 0, + [FE_REG_FE_COUNTER_BASE] = MT7621_GDM1_TX_GBCNT, + [FE_REG_FE_RST_GL] = MT7621_FE_RST_GL, + [FE_REG_FE_INT_STATUS2] = MT7620_FE_INT_STATUS2, +}; + +static void mt7620_fe_reset(void) +{ + fe_reset(MT7620A_RESET_FE | MT7620A_RESET_ESW); +} + +static void mt7621_fe_reset(void) +{ + fe_reset(MT7621_RESET_FE); +} + +static void mt7620_rxcsum_config(bool enable) +{ + if (enable) + fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) | (GDMA_ICS_EN | + GDMA_TCS_EN | GDMA_UCS_EN), + MT7620A_GDMA1_FWD_CFG); + else + fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) & ~(GDMA_ICS_EN | + GDMA_TCS_EN | GDMA_UCS_EN), + MT7620A_GDMA1_FWD_CFG); +} + +static void mt7620_txcsum_config(bool enable) +{ + if (enable) + fe_w32(fe_r32(MT7620A_CDMA_CSG_CFG) | (CDMA_ICS_EN | + CDMA_UCS_EN | CDMA_TCS_EN), + MT7620A_CDMA_CSG_CFG); + else + fe_w32(fe_r32(MT7620A_CDMA_CSG_CFG) & ~(CDMA_ICS_EN | + CDMA_UCS_EN | CDMA_TCS_EN), + MT7620A_CDMA_CSG_CFG); +} + +static void mt7621_rxvlan_config(bool enable) +{ + if (enable) + fe_w32(1, MT7621_CDMP_EG_CTRL); + else + fe_w32(0, MT7621_CDMP_EG_CTRL); +} + +static int mt7620_fwd_config(struct fe_priv *priv) +{ + struct net_device *dev = priv_netdev(priv); + + fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) & ~7, MT7620A_GDMA1_FWD_CFG); + + mt7620_txcsum_config((dev->features & NETIF_F_IP_CSUM)); + mt7620_rxcsum_config((dev->features & NETIF_F_RXCSUM)); + + return 0; +} + +static int mt7621_fwd_config(struct fe_priv *priv) +{ + struct net_device *dev = priv_netdev(priv); + + fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) & ~0xffff, MT7620A_GDMA1_FWD_CFG); + + /* mt7621 don't have txcsum config */ + mt7620_rxcsum_config((dev->features & NETIF_F_RXCSUM)); + mt7621_rxvlan_config((dev->features & NETIF_F_HW_VLAN_CTAG_RX) && + (priv->flags & FE_FLAG_RX_VLAN_CTAG)); + + return 0; +} + +static void mt7620_tx_dma(struct fe_tx_dma *txd) +{ +} + +static void mt7621_tx_dma(struct fe_tx_dma *txd) +{ + txd->txd4 = BIT(25); +} + +static void mt7620_init_data(struct fe_soc_data *data, + struct net_device *netdev) +{ + struct fe_priv *priv = netdev_priv(netdev); + + priv->flags = FE_FLAG_PADDING_64B | FE_FLAG_RX_2B_OFFSET | + FE_FLAG_RX_SG_DMA; + + netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | + NETIF_F_HW_VLAN_CTAG_TX; + if (mt7620_get_eco() >= 5) + netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | + NETIF_F_IPV6_CSUM; +} + +static void mt7621_init_data(struct fe_soc_data *data, + struct net_device *netdev) +{ + struct fe_priv *priv = netdev_priv(netdev); + + priv->flags = FE_FLAG_PADDING_64B | FE_FLAG_RX_2B_OFFSET | + FE_FLAG_RX_SG_DMA | FE_FLAG_NAPI_WEIGHT; + + netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | + NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG | NETIF_F_TSO | + NETIF_F_TSO6 | NETIF_F_IPV6_CSUM; +} + +static void mt7621_set_mac(struct fe_priv *priv, unsigned char *mac) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->page_lock, flags); + fe_w32((mac[0] << 8) | mac[1], GSW_REG_GDMA1_MAC_ADRH); + fe_w32((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5], + GSW_REG_GDMA1_MAC_ADRL); + spin_unlock_irqrestore(&priv->page_lock, flags); +} + +static struct fe_soc_data mt7620_data = { + .init_data = mt7620_init_data, + .reset_fe = mt7620_fe_reset, + .set_mac = mt7620_set_mac, + .fwd_config = mt7620_fwd_config, + .tx_dma = mt7620_tx_dma, + .switch_init = mt7620_gsw_probe, + .switch_config = mt7620_gsw_config, + .port_init = mt7620_port_init, + .reg_table = mt7620_reg_table, + .pdma_glo_cfg = FE_PDMA_SIZE_16DWORDS, + .rx_int = RT5350_RX_DONE_INT, + .tx_int = RT5350_TX_DONE_INT, + .status_int = MT7620_FE_GDM1_AF, + .checksum_bit = MT7620_L4_VALID, + .has_carrier = mt7620a_has_carrier, + .mdio_read = mt7620_mdio_read, + .mdio_write = mt7620_mdio_write, + .mdio_adjust_link = mt7620_mdio_link_adjust, +}; + +static struct fe_soc_data mt7621_data = { + .init_data = mt7621_init_data, + .reset_fe = mt7621_fe_reset, + .set_mac = mt7621_set_mac, + .fwd_config = mt7621_fwd_config, + .tx_dma = mt7621_tx_dma, + .switch_init = mt7620_gsw_probe, + .switch_config = mt7621_gsw_config, + .reg_table = mt7621_reg_table, + .pdma_glo_cfg = FE_PDMA_SIZE_16DWORDS, + .rx_int = RT5350_RX_DONE_INT, + .tx_int = RT5350_TX_DONE_INT, + .status_int = (MT7621_FE_GDM1_AF | MT7621_FE_GDM2_AF), + .checksum_bit = MT7621_L4_VALID, + .has_carrier = mt7620a_has_carrier, + .mdio_read = mt7620_mdio_read, + .mdio_write = mt7620_mdio_write, + .mdio_adjust_link = mt7620_mdio_link_adjust, +}; + +const struct of_device_id of_fe_match[] = { + { .compatible = "ralink,mt7620a-eth", .data = &mt7620_data }, + { .compatible = "ralink,mt7621-eth", .data = &mt7621_data }, + {}, +}; + +MODULE_DEVICE_TABLE(of, of_fe_match); diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt2880.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt2880.c new file mode 100644 index 0000000..147687b --- /dev/null +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt2880.c @@ -0,0 +1,79 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2009-2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/module.h> + +#include <asm/mach-ralink/ralink_regs.h> + +#include "ralink_soc_eth.h" +#include "mdio_rt2880.h" + +#define RT2880_RESET_FE BIT(18) + +static void rt2880_init_data(struct fe_soc_data *data, + struct net_device *netdev) +{ + struct fe_priv *priv = netdev_priv(netdev); + + priv->flags = FE_FLAG_PADDING_64B | FE_FLAG_PADDING_BUG | + FE_FLAG_JUMBO_FRAME; + netdev->hw_features = NETIF_F_SG | NETIF_F_HW_VLAN_CTAG_TX; + /* maybe have hardware bug. */ + //netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; +} + +void rt2880_fe_reset(void) +{ + fe_reset(RT2880_RESET_FE); +} + +static int rt2880_fwd_config(struct fe_priv *priv) +{ + int ret; + + ret = fe_set_clock_cycle(priv); + if (ret) + return ret; + + fe_fwd_config(priv); + fe_w32(FE_PSE_FQFC_CFG_INIT, FE_PSE_FQ_CFG); + fe_csum_config(priv); + + return ret; +} + +struct fe_soc_data rt2880_data = { + .init_data = rt2880_init_data, + .reset_fe = rt2880_fe_reset, + .fwd_config = rt2880_fwd_config, + .pdma_glo_cfg = FE_PDMA_SIZE_8DWORDS, + .checksum_bit = RX_DMA_L4VALID, + .rx_int = FE_RX_DONE_INT, + .tx_int = FE_TX_DONE_INT, + .status_int = FE_CNT_GDM_AF, + .mdio_read = rt2880_mdio_read, + .mdio_write = rt2880_mdio_write, + .mdio_adjust_link = rt2880_mdio_link_adjust, + .port_init = rt2880_port_init, +}; + +const struct of_device_id of_fe_match[] = { + { .compatible = "ralink,rt2880-eth", .data = &rt2880_data }, + {}, +}; + +MODULE_DEVICE_TABLE(of, of_fe_match); diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt305x.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt305x.c new file mode 100644 index 0000000..c1baa40 --- /dev/null +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt305x.c @@ -0,0 +1,157 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2009-2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/module.h> + +#include <asm/mach-ralink/ralink_regs.h> + +#include "ralink_soc_eth.h" +#include "mdio_rt2880.h" + +#define RT305X_RESET_FE BIT(21) +#define RT305X_RESET_ESW BIT(23) + +static const u16 rt5350_reg_table[FE_REG_COUNT] = { + [FE_REG_PDMA_GLO_CFG] = RT5350_PDMA_GLO_CFG, + [FE_REG_PDMA_RST_CFG] = RT5350_PDMA_RST_CFG, + [FE_REG_DLY_INT_CFG] = RT5350_DLY_INT_CFG, + [FE_REG_TX_BASE_PTR0] = RT5350_TX_BASE_PTR0, + [FE_REG_TX_MAX_CNT0] = RT5350_TX_MAX_CNT0, + [FE_REG_TX_CTX_IDX0] = RT5350_TX_CTX_IDX0, + [FE_REG_TX_DTX_IDX0] = RT5350_TX_DTX_IDX0, + [FE_REG_RX_BASE_PTR0] = RT5350_RX_BASE_PTR0, + [FE_REG_RX_MAX_CNT0] = RT5350_RX_MAX_CNT0, + [FE_REG_RX_CALC_IDX0] = RT5350_RX_CALC_IDX0, + [FE_REG_RX_DRX_IDX0] = RT5350_RX_DRX_IDX0, + [FE_REG_FE_INT_ENABLE] = RT5350_FE_INT_ENABLE, + [FE_REG_FE_INT_STATUS] = RT5350_FE_INT_STATUS, + [FE_REG_FE_RST_GL] = 0, + [FE_REG_FE_DMA_VID_BASE] = 0, +}; + +static void rt305x_init_data(struct fe_soc_data *data, + struct net_device *netdev) +{ + struct fe_priv *priv = netdev_priv(netdev); + + priv->flags = FE_FLAG_PADDING_64B | FE_FLAG_PADDING_BUG; + netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX; +} + +static int rt3050_fwd_config(struct fe_priv *priv) +{ + int ret; + + if (ralink_soc != RT305X_SOC_RT3052) { + ret = fe_set_clock_cycle(priv); + if (ret) + return ret; + } + + fe_fwd_config(priv); + if (ralink_soc != RT305X_SOC_RT3352) + fe_w32(FE_PSE_FQFC_CFG_INIT, FE_PSE_FQ_CFG); + fe_csum_config(priv); + + return 0; +} + +static void rt305x_fe_reset(void) +{ + fe_reset(RT305X_RESET_FE); +} + +static void rt5350_init_data(struct fe_soc_data *data, + struct net_device *netdev) +{ + netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM; +} + +static void rt5350_set_mac(struct fe_priv *priv, unsigned char *mac) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->page_lock, flags); + fe_w32((mac[0] << 8) | mac[1], RT5350_SDM_MAC_ADRH); + fe_w32((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5], + RT5350_SDM_MAC_ADRL); + spin_unlock_irqrestore(&priv->page_lock, flags); +} + +static void rt5350_rxcsum_config(bool enable) +{ + if (enable) + fe_w32(fe_r32(RT5350_SDM_CFG) | (RT5350_SDM_ICS_EN | + RT5350_SDM_TCS_EN | RT5350_SDM_UCS_EN), + RT5350_SDM_CFG); + else + fe_w32(fe_r32(RT5350_SDM_CFG) & ~(RT5350_SDM_ICS_EN | + RT5350_SDM_TCS_EN | RT5350_SDM_UCS_EN), + RT5350_SDM_CFG); +} + +static int rt5350_fwd_config(struct fe_priv *priv) +{ + struct net_device *dev = priv_netdev(priv); + + rt5350_rxcsum_config((dev->features & NETIF_F_RXCSUM)); + + return 0; +} + +static void rt5350_tx_dma(struct fe_tx_dma *txd) +{ + txd->txd4 = 0; +} + +static void rt5350_fe_reset(void) +{ + fe_reset(RT305X_RESET_FE | RT305X_RESET_ESW); +} + +static struct fe_soc_data rt3050_data = { + .init_data = rt305x_init_data, + .reset_fe = rt305x_fe_reset, + .fwd_config = rt3050_fwd_config, + .pdma_glo_cfg = FE_PDMA_SIZE_8DWORDS, + .checksum_bit = RX_DMA_L4VALID, + .rx_int = FE_RX_DONE_INT, + .tx_int = FE_TX_DONE_INT, + .status_int = FE_CNT_GDM_AF, +}; + +static struct fe_soc_data rt5350_data = { + .init_data = rt5350_init_data, + .reg_table = rt5350_reg_table, + .reset_fe = rt5350_fe_reset, + .set_mac = rt5350_set_mac, + .fwd_config = rt5350_fwd_config, + .tx_dma = rt5350_tx_dma, + .pdma_glo_cfg = FE_PDMA_SIZE_8DWORDS, + .checksum_bit = RX_DMA_L4VALID, + .rx_int = RT5350_RX_DONE_INT, + .tx_int = RT5350_TX_DONE_INT, +}; + +const struct of_device_id of_fe_match[] = { + { .compatible = "ralink,rt3050-eth", .data = &rt3050_data }, + { .compatible = "ralink,rt5350-eth", .data = &rt5350_data }, + {}, +}; + +MODULE_DEVICE_TABLE(of, of_fe_match); diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt3883.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt3883.c new file mode 100644 index 0000000..82499fe --- /dev/null +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/soc_rt3883.c @@ -0,0 +1,79 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2009-2013 John Crispin <blogic@openwrt.org> + */ + +#include <linux/module.h> + +#include <asm/mach-ralink/ralink_regs.h> + +#include "ralink_soc_eth.h" +#include "mdio_rt2880.h" + +#define RT3883_RSTCTRL_FE BIT(21) + +static void rt3883_fe_reset(void) +{ + fe_reset(RT3883_RSTCTRL_FE); +} + +static int rt3883_fwd_config(struct fe_priv *priv) +{ + int ret; + + ret = fe_set_clock_cycle(priv); + if (ret) + return ret; + + fe_fwd_config(priv); + fe_w32(FE_PSE_FQFC_CFG_256Q, FE_PSE_FQ_CFG); + fe_csum_config(priv); + + return ret; +} + +static void rt3883_init_data(struct fe_soc_data *data, + struct net_device *netdev) +{ + struct fe_priv *priv = netdev_priv(netdev); + + priv->flags = FE_FLAG_PADDING_64B | FE_FLAG_PADDING_BUG | + FE_FLAG_JUMBO_FRAME; + netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX; +} + +static struct fe_soc_data rt3883_data = { + .init_data = rt3883_init_data, + .reset_fe = rt3883_fe_reset, + .fwd_config = rt3883_fwd_config, + .pdma_glo_cfg = FE_PDMA_SIZE_8DWORDS, + .rx_int = FE_RX_DONE_INT, + .tx_int = FE_TX_DONE_INT, + .status_int = FE_CNT_GDM_AF, + .checksum_bit = RX_DMA_L4VALID, + .mdio_read = rt2880_mdio_read, + .mdio_write = rt2880_mdio_write, + .mdio_adjust_link = rt2880_mdio_link_adjust, + .port_init = rt2880_port_init, +}; + +const struct of_device_id of_fe_match[] = { + { .compatible = "ralink,rt3883-eth", .data = &rt3883_data }, + {}, +}; + +MODULE_DEVICE_TABLE(of, of_fe_match); + diff --git a/target/linux/ramips/image/Makefile b/target/linux/ramips/image/Makefile new file mode 100644 index 0000000..5e19c3f --- /dev/null +++ b/target/linux/ramips/image/Makefile @@ -0,0 +1,1076 @@ +# +# Copyright (C) 2008-2011 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/image.mk + +define imgname +$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1) +endef + +define sysupname +$(call imgname,$(1),$(2))-sysupgrade.bin +endef + +VMLINUX:=$(IMG_PREFIX)-vmlinux +UIMAGE:=$(IMG_PREFIX)-uImage + +define Image/Build/Initramfs + $(call Image/Build/Profile/$(PROFILE),initramfs) +endef + +DEVICE_VARS += DTS + +loadaddr-y := 0x80000000 +loadaddr-$(CONFIG_TARGET_ramips_rt288x) := 0x88000000 +loadaddr-$(CONFIG_TARGET_ramips_mt7621) := 0x80001000 + +KERNEL_LOADADDR := $(loadaddr-y) + +KERNEL_DTB = kernel-bin | patch-dtb | lzma +define Device/Default + KERNEL := $(KERNEL_DTB) | uImage lzma + IMAGES := sysupgrade.bin + IMAGE_SIZE := $(ralink_default_fw_size_8M) + IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | check-size $$$$(IMAGE_SIZE) +endef + +define Build/patch-dtb + $(LINUX_DIR)/scripts/dtc/dtc -O dtb -o $@.dtb ../dts/$(DTS).dts + $(STAGING_DIR_HOST)/bin/patch-dtb $@ $@.dtb +endef + +define Build/trx + $(STAGING_DIR_HOST)/bin/trx \ + -o $@ \ + -m $(IMAGE_SIZE) \ + -f $(word 1,$^) \ + -a 4 -f $(word 2,$^) +endef + +define Build/seama + $(STAGING_DIR_HOST)/bin/seama -i $@ $(1) + mv $@.seama $@ +endef + +define Build/seama-seal + $(call Build/seama,-s $@.seama $(1)) +endef + +define Build/relocate-kernel + ( \ + dd if=$(KDIR)/loader.bin bs=32 conv=sync && \ + perl -e '@s = stat("$@"); print pack("V", @s[7])' && \ + cat $@ \ + ) > $@.new + mv $@.new $@ +endef + +define MkCombineduImage + $(call PatchKernelLzma,$(2),$(3)) + if [ `stat -c%s "$(KDIR)/vmlinux-$(2).bin.lzma"` -gt `expr $(4) - 64` ]; then \ + echo "Warning: $(KDIR)/vmlinux-$(2).bin.lzma is too big" >&2; \ + else if [ `stat -c%s "$(KDIR)/root.$(1)"` -gt $(5) ]; then \ + echo "Warning: $(KDIR)/root.$(1) is too big" >&2; \ + else \ + ( dd if=$(KDIR)/vmlinux-$(2).bin.lzma bs=`expr $(4) - 64` conv=sync ; dd if=$(KDIR)/root.$(1) ) > $(KDIR)/vmlinux-$(2).bin.lzma.combined ; \ + fi ; fi + $(call MkImage,lzma,$(KDIR)/vmlinux-$(2).bin.lzma.combined,$(call sysupname,$(1),$(2)),$(6)) +endef + + +# +# The real magic happens inside these templates +# +# $(1), compression method +# $(2), filename of image data +# $(3), output filename +define MkImage + $(eval imagename=$(if $(4),$(4),MIPS OpenWrt Linux-$(LINUX_VERSION))) + -mkimage -A mips -O linux -T kernel -C $(1) -a $(loadaddr-y) -e $(loadaddr-y) \ + -n "$(imagename)" \ + -d $(2) $(3) +endef + +define CompressLzma + $(STAGING_DIR_HOST)/bin/lzma e $(1) -lc1 -lp2 -pb2 $(2) +endef + +define MkImageSysupgrade/squashfs + $(eval output_name=$(IMG_PREFIX)-$(2)-$(1)-$(if $(4),$(4),sysupgrade).bin) + cat $(KDIR)/vmlinux-$(2).uImage $(KDIR)/root.$(1) > $(KDIR)/$(output_name) + $(call prepare_generic_squashfs,$(KDIR)/$(output_name)) + if [ `stat -c%s "$(KDIR)/$(output_name)"` -gt $(3) ]; then \ + echo "Warning: $(KDIR)/$(output_name) is too big" >&2; \ + else \ + $(CP) $(KDIR)/$(output_name) $(BIN_DIR)/$(output_name); \ + fi +endef + +define MkImageTpl/squashfs + $(eval output_name=$(IMG_PREFIX)-$(2)-$(1)-$(if $(4),$(4),sysupgrade).bin) + $(STAGING_DIR_HOST)/bin/mktplinkfw2 -V "ver. 2.0" -B "$(2)" -j \ + -o $(KDIR)/$(output_name) \ + -k $(KDIR)/vmlinux-$(1)$(4).bin.lzma \ + -r $(KDIR)/root.$(1) + $(CP) $(KDIR)/$(output_name) $(BIN_DIR)/$(output_name) +endef + +define MkImageTpl/initramfs + $(eval output_name=$(IMG_PREFIX)-$(2)-$(1).bin) + $(STAGING_DIR_HOST)/bin/mktplinkfw2 -V "ver. 2.0" -B "$(2)" -c \ + -o $(KDIR)/$(output_name) \ + -k $(KDIR)/vmlinux-$(1).bin.lzma + $(CP) $(KDIR)/$(output_name) $(BIN_DIR)/$(output_name) +endef + +# $(1), lowercase board name like "mt7620a_v22sg" +# $(2), DTS filename without .dts extension +# $(3), optional filename suffix, e.g. "-initramfs" +define PatchKernelLzmaDtb + cp $(KDIR)/vmlinux$(3) $(KDIR)/vmlinux-$(1)$(3) + $(LINUX_DIR)/scripts/dtc/dtc -O dtb -o $(KDIR)/$(2).dtb ../dts/$(2).dts + $(STAGING_DIR_HOST)/bin/patch-dtb $(KDIR)/vmlinux-$(1)$(3) $(KDIR)/$(2).dtb + $(call CompressLzma,$(KDIR)/vmlinux-$(1)$(3),$(KDIR)/vmlinux-$(1)$(3).bin.lzma) +endef + +# $(1), lowercase board name +# $(2), DTS filename without .dts extension +# $(3), ih_name field of uImage header +# $(4), optional filename suffix, e.g. "-initramfs" +define MkImageLzmaDtb + $(call PatchKernelLzmaDtb,$(1),$(2),$(4)) + $(call MkImage,lzma,$(KDIR)/vmlinux-$(1)$(4).bin.lzma,$(KDIR)/vmlinux-$(1)$(4).uImage,$(3)) +endef + +# $(1), Rootfs type, e.g. squashfs +# $(2), lowercase board name +# $(3), DTS filename without .dts extension +# $(4), maximum size of sysupgrade image +# $(5), uImage header's ih_name field +define BuildFirmware/OF + $(call MkImageLzmaDtb,$(2),$(3),$(5)) + $(call MkImageSysupgrade/$(1),$(1),$(2),$(4),$(6)) +endef + +define BuildFirmware/OF/tplink + $(call PatchKernelLzmaDtb,$(1),$(2),$(4)) + $(call MkImageTpl/$(1),$(1),$(2),$(4),$(5)) +endef + +define BuildFirmware/OF/tplink/initramfs + $(call PatchKernelLzmaDtb,$(2),$(3),-initramfs) + $(call MkImageTpl/$(1),$(1),$(2),$(4),$(5)) +endef + +# $(1), squashfs/initramfs +# $(2), lowercase board name +# $(3), DTS filename without .dts extension +# $(4), ih_name field of uImage header +define BuildFirmware/OF/initramfs + $(call MkImageLzmaDtb,$(2),$(3),$(4),-initramfs) + $(CP) $(KDIR)/vmlinux-$(2)-initramfs.uImage $(call imgname,$(1),$(2))-uImage.bin +endef + + +# Build images for default ralink layout for 4MB flash +# kernel + roots = 0x3b0000 +# $(1) = squashfs/initramfs +# $(2) = lowercase board name +# $(3) = dts file +ralink_default_fw_size_4M=3866624 +BuildFirmware/Default4M/squashfs=$(call BuildFirmware/OF,$(1),$(2),$(3),$(ralink_default_fw_size_4M),$(4)) +BuildFirmware/Default4M/initramfs=$(call BuildFirmware/OF/initramfs,$(1),$(2),$(3),$(4)) + +# Build images for default ralink layout for 8MB flash +# kernel + roots = 0x7b0000 +# $(1) = squashfs/initramfs +# $(2) = lowercase board name +# $(3) = dts file +# $(4) = uImage header name field +ralink_default_fw_size_8M=8060928 +BuildFirmware/Default8M/squashfs=$(call BuildFirmware/OF,$(1),$(2),$(3),$(ralink_default_fw_size_8M),$(4)) +BuildFirmware/Default8M/initramfs=$(call BuildFirmware/OF/initramfs,$(1),$(2),$(3),$(4)) +BuildFirmware/Tplink/squashfs=$(call BuildFirmware/OF/tplink,$(1),$(2),$(3),$(4)) +BuildFirmware/Tplink/initramfs=$(call BuildFirmware/OF/tplink/initramfs,$(1),$(2),$(3),$(4)) + +ralink_default_fw_size_16M=16121856 +BuildFirmware/Default16M/squashfs=$(call BuildFirmware/OF,$(1),$(2),$(3),$(ralink_default_fw_size_16M),$(4)) +BuildFirmware/Default16M/initramfs=$(call BuildFirmware/OF/initramfs,$(1),$(2),$(3),$(4)) + +ralink_default_fw_size_32M=33226752 +BuildFirmware/Default32M/squashfs=$(call BuildFirmware/OF,$(1),$(2),$(3),$(ralink_default_fw_size_32M),$(4)) +BuildFirmware/Default32M/initramfs=$(call BuildFirmware/OF/initramfs,$(1),$(2),$(3),$(4)) + +# Build images for a custom sized flash layout +# $(1) = squashfs/initramfs +# $(2) = lowercase board name +# $(3) = dts file +# $(4) = kernel + rootfs size +BuildFirmware/CustomFlash/squashfs=$(call BuildFirmware/OF,$(1),$(2),$(3),$(4),$(5),$(6)) +BuildFirmware/CustomFlash/initramfs=$(call BuildFirmware/OF/initramfs,$(1),$(2),$(3)) + +# wrappers for boards that have 4MB and 8MB versions +define BuildFirmware/DefaultDualSize/squashfs + $(call BuildFirmware/Default4M/$(1),$(1),$(2)-4M,$(3)-4M) + $(call BuildFirmware/Default8M/$(1),$(1),$(2)-8M,$(3)-8M) +endef +define BuildFirmware/DefaultDualSize/initramfs + $(call BuildFirmware/OF/initramfs,$(1),$(2)-4M,$(3)-4M) + $(call BuildFirmware/OF/initramfs,$(1),$(2)-8M,$(3)-8M) +endef + +# Some boards need a special header inside the uImage to make them bootable +define BuildFirmware/CustomFlashFactory/squashfs + $(call BuildFirmware/CustomFlash/$(1),$(1),$(2),$(3),$(4)) + $(call BuildFirmware/CustomFlash/$(1),$(1),$(2),$(3),$(4),$(5),$(6)) +endef +BuildFirmware/CustomFlashFactory/initramfs=$(call BuildFirmware/OF/initramfs,$(1),$(2),$(3)) + +# sign an image to make it work with edimax tftp recovery +define BuildFirmware/Edimax/squashfs + $(call BuildFirmware/OF,$(1),$(2),$(3),$(4)) + if [ -e "$(call sysupname,$(1),$(2))" ]; then \ + mkedimaximg -i $(call sysupname,$(1),$(2)) \ + -o $(call imgname,$(1),$(2))-factory.bin \ + -s $(5) -m $(6) -f $(7) -S $(8); \ + fi +endef +BuildFirmware/Edimax/initramfs=$(call BuildFirmware/OF/initramfs,$(1),$(2),$(3)) + +# build Seama header images +define BuildFirmware/Seama/squashfs + $(call MkImageLzmaDtb,$(2),$(3),$(5)) + $(eval output_name=$(IMG_PREFIX)-$(2)-$(1)-sysupgrade.bin) + cat $(KDIR)/vmlinux-$(2).bin.lzma $(KDIR)/root.$(1) > $(KDIR)/img_$(2).$(1).tmp + if [ `stat -c%s "$(KDIR)/img_$(2).$(1).tmp"` -gt $$$$(($(5) - 64)) ]; then \ + echo "Warning: $(KDIR)/img_$(2).$(1).tmp is too big" >&2; \ + else \ + dd if=$(KDIR)/vmlinux-$(2).bin.lzma of=$(KDIR)/vmlinux-$(2).bin.lzma.padded bs=64k conv=sync; \ + ( \ + dd if=$(KDIR)/vmlinux-$(2).bin.lzma.padded bs=1 count=`expr \`stat -c%s $(KDIR)/vmlinux-$(2).bin.lzma.padded\` - 64`; \ + dd if=$(KDIR)/root.$(1) bs=64k conv=sync; \ + ) > $(KDIR)/vmlinux-$(2).tmp; \ + $(STAGING_DIR_HOST)/bin/seama \ + -i $(KDIR)/vmlinux-$(2).tmp \ + -m "dev=/dev/mtdblock/2" -m "type=firmware"; \ + $(STAGING_DIR_HOST)/bin/seama \ + -s $(call imgname,$(1),$(2))-factory.bin \ + -m "signature=$(4)" \ + -i $(KDIR)/vmlinux-$(2).tmp.seama; \ + dd if=$(KDIR)/vmlinux-$(2).bin.lzma.padded bs=1 count=`expr \`stat -c%s $(KDIR)/vmlinux-$(2).bin.lzma.padded\` - 64` of=$(KDIR)/vmlinux-$(2)-sysupgrade.tmp; \ + $(STAGING_DIR_HOST)/bin/seama \ + -i $(KDIR)/vmlinux-$(2)-sysupgrade.tmp \ + -m "dev=/dev/mtdblock/2" -m "type=firmware"; \ + ( \ + dd if=$(KDIR)/vmlinux-$(2)-sysupgrade.tmp.seama; \ + dd if=$(KDIR)/root.$(1) bs=64k conv=sync; \ + ) > $(BIN_DIR)/$(output_name); \ + fi +endef +BuildFirmware/Seama/initramfs=$(call BuildFirmware/OF/initramfs,$(1),$(2),$(3)) + +# sign Buffalo images +define BuildFirmware/Buffalo + if [ -e "$(call sysupname,$(1),$(2))" ]; then \ + buffalo-enc -p $(3) -v 1.76 \ + -i $(KDIR)/vmlinux-$(2).uImage \ + -o $(KDIR)/vmlinux-$(2).uImage.enc; \ + buffalo-enc -p $(3) -v 1.76 \ + -i $(KDIR)/root.$(1) \ + -o $(KDIR)/root.$(2).enc; \ + buffalo-tag -b $(3) -p $(3) -a ram -v 1.76 -m 1.01 \ + -l mlang8 -f 1 -r EU \ + -i $(KDIR)/vmlinux-$(2).uImage.enc \ + -i $(KDIR)/root.$(2).enc \ + -o $(call imgname,$(1),$(2))-factory-EU.bin; \ + fi +endef + +# sign trednet / UMedia images +define BuildFirmware/UMedia/squashfs + $(call BuildFirmware/Default8M/$(1),$(1),$(2),$(3)) + if [ -e "$(call sysupname,$(1),$(2))" ]; then \ + fix-u-media-header -T 0x46 -B $(4) \ + -i $(call sysupname,$(1),$(2)) \ + -o $(call imgname,$(1),$(2))-factory.bin; \ + fi +endef +BuildFirmware/UMedia/initramfs=$(call BuildFirmware/OF/initramfs,$(1),$(2),$(3)) + +# sign dap 1350 based images +dap1350_mtd_size=7667712 +define BuildFirmware/dap1350/squashfs + $(call BuildFirmware/CustomFlash/$(1),$(1),$(2),$(3),$(dap1350_mtd_size)) + -mkdapimg -s $(4) \ + -i $(call sysupname,$(1),$(2)) \ + -o $(call imgname,$(1),$(2))-factory.bin +endef +BuildFirmware/dap1350/initramfs=$(call BuildFirmware/OF/initramfs,$(1),$(2),$(3)) + +# Sign Poray images +define BuildFirmware/Poray4M/squashfs + $(call BuildFirmware/Default4M/$(1),$(1),$(2),$(3)) + if [ -e "$(call sysupname,$(1),$(2))" ]; then \ + mkporayfw -B $(3) -F 4M \ + -f $(call sysupname,$(1),$(2)) \ + -o $(call imgname,$(1),$(2))-factory.bin; \ + fi +endef +BuildFirmware/Poray4M/initramfs=$(call BuildFirmware/OF/initramfs,$(1),$(2),$(3)) + +define BuildFirmware/Poray8M/squashfs + $(call BuildFirmware/Default8M/$(1),$(1),$(2),$(3)) + if [ -e "$(call sysupname,$(1),$(2))" ]; then \ + mkporayfw -B $(3) -F 8M \ + -f $(call sysupname,$(1),$(2)) \ + -o $(call imgname,$(1),$(2))-factory.bin; \ + fi +endef +BuildFirmware/Poray8M/initramfs=$(call BuildFirmware/OF/initramfs,$(1),$(2),$(3)) + +define BuildFirmware/PorayDualSize/squashfs + $(call BuildFirmware/DefaultDualSize/$(1),$(1),$(2),$(3)) + if [ -e "$(call sysupname,$(1),$(2)-4M)" ]; then \ + mkporayfw -B $(3) -F 4M \ + -f $(call sysupname,$(1),$(2)-4M) \ + -o $(call imgname,$(1),$(2)-4M)-factory.bin; \ + fi + if [ -e "$(call sysupname,$(1),$(2)-8M)" ]; then \ + mkporayfw -B $(3) -F 8M \ + -f $(call sysupname,$(1),$(2)-8M) \ + -o $(call imgname,$(1),$(2)-8M)-factory.bin; \ + fi +endef +BuildFirmware/PorayDualSize/initramfs=$(call BuildFirmware/DefaultDualSize/initramfs,$(1),$(2),$(3)) + +define BuildFirmware/Gemtek/squashfs + $(call BuildFirmware/Default4M/$(1),$(1),$(2),$(3)) + if [ -e "$(call sysupname,$(1),$(2))" ]; then \ + mkheader_gemtek "$(call sysupname,$(1),$(2))" \ + "$(call imgname,$(1),$(2))-factory.bin" $(2) || \ + rm -f "$(call imgname,$(1),$(2))-factory.bin"; \ + fi +endef +BuildFirmware/Gemtek/initramfs=$(call BuildFirmware/OF/initramfs,$(1),$(2),$(3)) + +# Airlink101 AR670W -- LZMA without uImage header +define BuildFirmware/AR670W/squashfs + $(call PatchKernelLzmaDtb,$(2),$(3),$(5)) + + $(eval output_name=$(IMG_PREFIX)-$(2)-$(1)-$(if $(4),$(4),sysupgrade).bin) + $(eval factory_name=$(IMG_PREFIX)-$(2)-$(1)-factory.bin) + + ( dd if=$(KDIR)/vmlinux-$(2).bin.lzma bs=65536 \ + conv=sync; dd if=$(KDIR)/root.$(1) ) > $(KDIR)/$(output_name) + + $(call prepare_generic_squashfs,$(KDIR)/$(output_name)) + + if [ `stat -c%s "$(KDIR)/$(output_name)"` \ + -gt $(ralink_default_fw_size_4M) ]; then \ + echo "Warning: $(KDIR)/$(output_name) is too big" >&2; \ + else \ + mkwrgimg -i $(KDIR)/$(output_name) \ + -d "/dev/mtdblock/2" \ + -s "wrgn16a_airlink_ar670w" \ + -o $(BIN_DIR)/$(factory_name); \ + $(CP) $(KDIR)/$(output_name) $(BIN_DIR)/$(output_name); \ + fi +endef + +# +# RT288X Profiles +# + +Image/Build/Profile/AR670W=$(call BuildFirmware/AR670W/$(1),$(1),ar670w,AR670W) + +Image/Build/Profile/AR725W=$(call BuildFirmware/Gemtek/$(1),$(1),ar725w,AR725W) + +# 0x790000 +belkin_f5d8235v1_mtd_size=7929856 +Image/Build/Profile/F5D8235V1=$(call BuildFirmware/CustomFlash/$(1),$(1),f5d8235v1,F5D8235_V1,$(belkin_f5d8235v1_mtd_size)) + +Image/Build/Profile/RTN15=$(call BuildFirmware/Default4M/$(1),$(1),rt-n15,RT-N15) + +Image/Build/Profile/V11STFE=$(call BuildFirmware/Default4M/$(1),$(1),v11st-fe,V11STFE) + +Image/Build/Profile/WLITX4AG300N=$(call BuildFirmware/Default4M/$(1),$(1),wli-tx4-ag300n,WLI-TX4-AG300N) + +Image/Build/Profile/WZRAGL300NH=$(call BuildFirmware/Default4M/$(1),$(1),wzr-agl300nh,WZR-AGL300NH) + +ifeq ($(SUBTARGET),rt288x) +define Image/Build/Profile/Default + $(call Image/Build/Profile/AR670W,$(1)) + $(call Image/Build/Profile/AR725W,$(1)) + $(call Image/Build/Profile/F5D8235V1,$(1)) + $(call Image/Build/Profile/RTN15,$(1)) + $(call Image/Build/Profile/V11STFE,$(1)) + $(call Image/Build/Profile/WLITX4AG300N,$(1)) + $(call Image/Build/Profile/WZRAGL300NH,$(1)) +endef +endif + + + +# +# RT305X Profiles +# + +Image/Build/Profile/DIR610A1=$(call BuildFirmware/Seama/$(1),$(1),dir-610-a1,DIR-610-A1,wrgn59_dlob.hans_dir610,$(ralink_default_fw_size_4M)) + +edimax_3g6200n_mtd_size=3735552 +Image/Build/Profile/3G6200N=$(call BuildFirmware/Edimax/$(1),$(1),3g-6200n,3G-6200N,$(edimax_3g6200n_mtd_size),CSYS,3G62,0x50000,0xc0000) + +Image/Build/Profile/3G6200NL=$(call BuildFirmware/Edimax/$(1),$(1),3g-6200nl,3G-6200NL,$(edimax_3g6200n_mtd_size),CSYS,3G62,0x50000,0xc0000) + +Image/Build/Profile/3G300M=$(call BuildFirmware/CustomFlashFactory/$(1),$(1),3g300m,3G300M,$(ralink_default_fw_size_4M),3G150M_SPI Kernel Image,factory) + +Image/Build/Profile/A5-V11=$(call BuildFirmware/Poray4M/$(1),$(1),a5-v11,A5-V11) + +Image/Build/Profile/AIR3GII=$(call BuildFirmware/Default4M/$(1),$(1),air3gii,AIR3GII) + +define BuildFirmware/UIMAGE_8M + $(call MkCombineduImage,$(1),$(2),$(call mkcmdline,$(3),$(4),$(5)) $(call mkmtd/$(6),$(mtdlayout_8M)),$(kernel_size_8M),$(rootfs_size_8M),$(7)) +endef +define Image/Build/Profile/ALL02393G + $(call Image/Build/Template/$(image_type)/$(1),UIMAGE_8M,all0239-3g,ALL0239-3G,ttyS1,57600,phys) +endef + +Image/Build/Profile/ALL0256N=$(call BuildFirmware/DefaultDualSize/$(1),$(1),all0256n,ALL0256N) + +allnet_all5002_mtd_size=33226752 +Image/Build/Profile/ALL5002=$(call BuildFirmware/CustomFlash/$(1),$(1),all5002,ALL5002,$(allnet_all5002_mtd_size)) +Image/Build/Profile/ALL5003=$(call BuildFirmware/CustomFlash/$(1),$(1),all5003,ALL5003,$(allnet_all5002_mtd_size)) + +argus_atp52b_mtd_size=7995392 +Image/Build/Profile/ATP-52B=$(call BuildFirmware/CustomFlash/$(1),$(1),atp-52b,ATP-52B,$(argus_atp52b_mtd_size)) + +asl26555_8mb_mtd_size=7929856 +asl26555_16mb_mtd_size=16252928 +define BuildFirmware/ASL26555/squashfs + $(call BuildFirmware/CustomFlash/$(1),$(1),$(2)-8M,$(3)-8M,$(asl26555_8mb_mtd_size)) + $(call BuildFirmware/CustomFlash/$(1),$(1),$(2)-16M,$(3)-16M,$(asl26555_16mb_mtd_size)) +endef +define BuildFirmware/ASL26555/initramfs + $(call BuildFirmware/OF/initramfs,$(1),$(2)-8M,$(3)-8M) + $(call BuildFirmware/OF/initramfs,$(1),$(2)-16M,$(3)-16M) +endef +Image/Build/Profile/ASL26555=$(call BuildFirmware/ASL26555/$(1),$(1),asl26555,ASL26555) + +Image/Build/Profile/AWM002EVB=$(call BuildFirmware/DefaultDualSize/$(1),$(1),awm002-evb,AWM002-EVB) +Image/Build/Profile/AWM003EVB=$(call BuildFirmware/Default8M/$(1),$(1),awm003-evb,AWM003-EVB) +Image/Build/Profile/AWAPN2403=$(call BuildFirmware/Default4M/$(1),$(1),awmapn2403,AWAPN2403) + +Image/Build/Profile/BC2=$(call BuildFirmware/Default8M/$(1),$(1),bc2,BC2) + +broadway_mtd_size=7929856 +Image/Build/Profile/BROADWAY=$(call BuildFirmware/CustomFlashFactory/$(1),$(1),broadway,BROADWAY,$(broadway_mtd_size),Broadway Kernel Image,factory) + +Image/Build/Profile/CARAMBOLA=$(call BuildFirmware/Default8M/$(1),$(1),carambola,CARAMBOLA) + +Image/Build/Profile/D105=$(call BuildFirmware/Default4M/$(1),$(1),d105,D105) + +define BuildFirmware/DIR300B1/squashfs + $(call BuildFirmware/Default4M/$(1),$(1),$(2),$(3)) + -mkwrgimg -s $(4) -d /dev/mtdblock/2 \ + -i $(call sysupname,$(1),$(2)) \ + -o $(call imgname,$(1),$(2))-factory.bin +endef +BuildFirmware/DIR300B1/initramfs=$(call BuildFirmware/OF/initramfs,$(1),$(2),$(3)) +Image/Build/Profile/DIR-300-B1=$(call BuildFirmware/DIR300B1/$(1),$(1),dir-300-b1,DIR-300-B1,wrgn23_dlwbr_dir300b) +Image/Build/Profile/DIR-600-B1=$(call BuildFirmware/DIR300B1/$(1),$(1),dir-600-b1,DIR-600-B1,wrgn23_dlwbr_dir600b) +Image/Build/Profile/DIR-600-B2=$(call BuildFirmware/DIR300B1/$(1),$(1),dir-600-b2,DIR-600-B2,wrgn23_dlwbr_dir600b) +Image/Build/Profile/DIR-615-D=$(call BuildFirmware/DIR300B1/$(1),$(1),dir-615-d,DIR-615-D,wrgn23_dlwbr_dir615d) + +Image/Build/Profile/DIR-620-A1=$(call BuildFirmware/Default8M/$(1),$(1),dir-620-a1,DIR-620-A1) +Image/Build/Profile/DIR-620-D1=$(call BuildFirmware/Default8M/$(1),$(1),dir-620-d1,DIR-620-D1) + +define BuildFirmware/DIR615H1/squashfs + $(call BuildFirmware/Default4M/$(1),$(1),dir-615-h1,DIR-615-H1) + -mksenaofw -e $(call sysupname,$(1),dir-615-h1) \ + -o $(call imgname,$(1),dir-615-h1)-factory.bin \ + -r 0x218 -p 0x30 -t 3 +endef +BuildFirmware/DIR615H1/initramfs=$(call BuildFirmware/OF/initramfs,$(1),dir-615-h1,DIR-615-H1) +Image/Build/Profile/DIR615H1=$(call BuildFirmware/DIR615H1/$(1),$(1)) + +Image/Build/Profile/DAP1350=$(call BuildFirmware/dap1350/$(1),$(1),dap-1350,DAP-1350,RT3052-AP-DAP1350-3) + +Image/Build/Profile/DAP1350WW=$(call BuildFirmware/dap1350/$(1),$(1),dap-1350WW,DAP-1350,RT3052-AP-DAP1350WW-3) + +define BuildFirmware/DCS930/squashfs + $(call BuildFirmware/Default4M/squashfs,squashfs,$(2),$(3)) + dd if=$(KDIR)/vmlinux-$(2).bin.lzma of=$(KDIR)/image.$(2).combined bs=1048512 count=1 conv=sync + cat $(KDIR)/root.squashfs >> $(KDIR)/image.$(2).combined + $(call MkImage,lzma,$(KDIR)/image.$(2).combined,$(KDIR)/image.$(2)) + $(call prepare_generic_squashfs,$(KDIR)/image.$(2)) + if [ `stat -c%s "$(KDIR)/image.$(2)"` -gt $(ralink_default_fw_size_4M) ]; then \ + echo "Warning: $(KDIR)/image.$(2) is too big" >&2; \ + else \ + dd if=$(KDIR)/image.$(2) of=$(KDIR)/dcs.tmp bs=64K count=5 conv=sync ;\ + cat $(KDIR)/image.$(2) >> $(KDIR)/dcs.tmp ; \ + dd if=$(KDIR)/dcs.tmp of=$(call imgname,$(1),$(2))-factory.bin bs=4096k count=1 conv=sync ;\ + $(STAGING_DIR_HOST)/bin/mkdcs932 $(call imgname,$(1),$(2))-factory.bin ; \ + fi +endef +BuildFirmware/DCS930/initramfs=$(call BuildFirmware/OF/initramfs,$(1),$(2),$(3)) +Image/Build/Profile/DCS930=$(call BuildFirmware/DCS930/$(1),$(1),dcs-930,DCS-930) +Image/Build/Profile/DCS930LB1=$(call BuildFirmware/DCS930/$(1),$(1),dcs-930l-b1,DCS-930L-B1) + +Image/Build/Profile/ESR-9753=$(call BuildFirmware/Default4M/$(1),$(1),esr-9753,ESR-9753) + +Image/Build/Profile/HW550-3G=$(call BuildFirmware/Default8M/$(1),$(1),hw550-3g,HW550-3G) + +belkin_f5d8235v2_mtd_size=7929856 +Image/Build/Profile/F5D8235V2=$(call BuildFirmware/CustomFlash/$(1),$(1),f5d8235v2,F5D8235_V2,$(belkin_f5d8235v2_mtd_size)) + +# 0x770000 +belkin_f7c027_mtd_size=7798784 +Image/Build/Profile/F7C027=$(call BuildFirmware/CustomFlash/$(1),$(1),f7c027,F7C027,$(belkin_f7c027_mtd_size)) + +Image/Build/Profile/FONERA20N=$(call BuildFirmware/Edimax/$(1),$(1),fonera20n,FONERA20N,$(ralink_default_fw_size_8M),RSDK,NL1T,0x50000,0xc0000) + +Image/Build/Profile/RT-N13U=$(call BuildFirmware/Default8M/$(1),$(1),rt-n13u,RT-N13U) + +#Image/Build/Profile/HG255D=$(call BuildFirmware/Default16M/$(1),$(1),hg255d,HG255D) + +Image/Build/Profile/FREESTATION5=$(call BuildFirmware/Default8M/$(1),$(1),freestation5,FREESTATION5) + +Image/Build/Profile/IP2202=$(call BuildFirmware/Default8M/$(1),$(1),ip2202,IP2202) + +BuildFirmware/HLKRM04/squashfs=$(call BuildFirmware/Default4M/squashfs,$(1),$(2),$(3),$(4)) +define BuildFirmware/HLKRM04/initramfs + $(call BuildFirmware/OF/initramfs,$(1),$(2),$(3),$(4)) + mkhilinkfw -e -i$(call imgname,$(1),$(2))-uImage.bin -o $(call imgname,$(1),$(2))-factory.bin; +endef +Image/Build/Profile/HLKRM04=$(call BuildFirmware/HLKRM04/$(1),$(1),hlk-rm04,HLKRM04,HLK-RM02) + +Image/Build/Profile/HT-TM02=$(call BuildFirmware/Default8M/$(1),$(1),ht-tm02,HT-TM02) + +Image/Build/Profile/M3=$(call BuildFirmware/Poray4M/$(1),$(1),m3,M3) + +Image/Build/Profile/M4=$(call BuildFirmware/PorayDualSize/$(1),$(1),m4,M4) + +Image/Build/Profile/MOFI3500-3GN=$(call BuildFirmware/Default8M/$(1),$(1),mofi3500-3gn,MOFI3500-3GN) + +# Kernel name should be "Linux Kernel Image" to make the OpenWrt image installable from factory Web UI +Image/Build/Profile/3G150B=$(call BuildFirmware/Default4M/$(1),$(1),3g150b,3G150B,Linux Kernel Image) + +Image/Build/Profile/MR102N=$(call BuildFirmware/Default8M/$(1),$(1),mr-102n,MR-102N) + +Image/Build/Profile/MPRA1=$(call BuildFirmware/Default4M/$(1),$(1),mpr-a1,MPRA1,Linux Kernel Image) +Image/Build/Profile/MPRA2=$(call BuildFirmware/Default8M/$(1),$(1),mpr-a2,MPRA2,Linux Kernel Image) + +Image/Build/Profile/DIR-300-B7=$(call BuildFirmware/Default4M/$(1),$(1),dir-300-b7,DIR-300-B7) +Image/Build/Profile/DIR-320-B1=$(call BuildFirmware/Default8M/$(1),$(1),dir-320-b1,DIR-320-B1) + +Image/Build/Profile/NBG-419N=$(call BuildFirmware/Default4M/$(1),$(1),nbg-419n,NBG-419N) + +Image/Build/Profile/MZKW300NH2=$(call BuildFirmware/Edimax/$(1),$(1),mzk-w300nh2,MZK-W300NH2,$(mzkw300nh2_mtd_size),CSYS,RN52,0x50000,0xc0000) + +Image/Build/Profile/NCS601W=$(call BuildFirmware/Default8M/$(1),$(1),ncs601W,NCS601W) + +nw718_mtd_size=3801088 +Image/Build/Profile/NW718=$(call BuildFirmware/CustomFlashFactory/$(1),$(1),nw718m,NW718,$(nw718_mtd_size),ARA1B4NCRNW718;1,factory) + +Image/Build/Profile/M2M=$(call BuildFirmware/Default8M/$(1),$(1),m2m,M2M,Linux Kernel Image) + +Image/Build/Profile/MINIEMBPLUG=$(call BuildFirmware/Default8M/$(1),$(1),miniembplug,MINIEMBPLUG) + +Image/Build/Profile/MINIEMBWIFI=$(call BuildFirmware/Default8M/$(1),$(1),miniembwifi,MINIEMBWIFI) + +Image/Build/Profile/PSR-680W=$(call BuildFirmware/Default4M/$(1),$(1),psr-680w,PSR-680W) + +Image/Build/Profile/PWH2004=$(call BuildFirmware/Default8M/$(1),$(1),pwh2004,PWH2004) + +Image/Build/Profile/PX-4885=$(call BuildFirmware/DefaultDualSize/$(1),$(1),px-4885,PX-4885) + +Image/Build/Profile/RT5350F-OLINUXINO=$(call BuildFirmware/Default8M/$(1),$(1),rt5350f-olinuxino,RT5350F-OLINUXINO) + +Image/Build/Profile/RT5350F-OLINUXINO-EVB=$(call BuildFirmware/Default8M/$(1),$(1),rt5350f-olinuxino-evb,RT5350F-OLINUXINO-EVB) + +Image/Build/Profile/RTG32B1=$(call BuildFirmware/Default4M/$(1),$(1),rt-g32-b1,RT-G32-B1) + +Image/Build/Profile/RTN10PLUS=$(call BuildFirmware/Default4M/$(1),$(1),rt-n10-plus,RT-N10-PLUS) + +Image/Build/Profile/RUT5XX=$(call BuildFirmware/Default8M/$(1),$(1),rut5xx,RUT5XX) + +Image/Build/Profile/SL-R7205=$(call BuildFirmware/Default4M/$(1),$(1),sl-r7205,SL-R7205) + +Image/Build/Profile/V22RW-2X2=$(call BuildFirmware/Default4M/$(1),$(1),v22rw-2x2,V22RW-2X2) + +vocore_8mb_mtd_size=8060928 +vocore_16mb_mtd_size=16449536 +define BuildFirmware/VOCORE/squashfs + $(call BuildFirmware/CustomFlash/$(1),$(1),$(2)-8M,$(3)-8M,$(vocore_8mb_mtd_size)) + $(call BuildFirmware/CustomFlash/$(1),$(1),$(2)-16M,$(3)-16M,$(vocore_16mb_mtd_size)) +endef +define BuildFirmware/VOCORE/initramfs + $(call BuildFirmware/OF/initramfs,$(1),$(2)-8M,$(3)-8M) + $(call BuildFirmware/OF/initramfs,$(1),$(2)-16M,$(3)-16M) +endef +Image/Build/Profile/VOCORE=$(call BuildFirmware/VOCORE/$(1),$(1),vocore,VOCORE) + +Image/Build/Profile/W150M=$(call BuildFirmware/CustomFlashFactory/$(1),$(1),w150m,W150M,$(ralink_default_fw_size_4M),W150M Kernel Image,factory) + +Image/Build/Profile/W306R_V20=$(call BuildFirmware/CustomFlashFactory/$(1),$(1),w306r-v20,W306R_V20,$(ralink_default_fw_size_4M),linkn Kernel Image,factory) + +Image/Build/Profile/W502U=$(call BuildFirmware/Default8M/$(1),$(1),w502u,W502U) + +Image/Build/Profile/WCR150GN=$(call BuildFirmware/Default4M/$(1),$(1),wcr150gn,WCR150GN) + +Image/Build/Profile/MZK-DP150N=$(call BuildFirmware/Default4M/$(1),$(1),mzk-dp150n,MZK-DP150N) + +buffalo_whrg300n_mtd_size=3801088 +define BuildFirmware/WHRG300N/squashfs + $(call BuildFirmware/Default4M/$(1),$(1),whr-g300n,WHR-G300N) + # the following line has a bad argument 3 ... the old Makefile was already broken + $(call BuildFirmware/Buffalo,$(1),whr-g300n,whr-g300n) + if [ -e "$(call sysupname,$(1),$(2))" ]; then \ + ( \ + echo -n -e "# Airstation FirmWare\nrun u_fw\nreset\n\n" | \ + dd bs=512 count=1 conv=sync; \ + dd if=$(call sysupname,$(1),whr-g300n); \ + ) > $(KDIR)/whr-g300n-tftp.tmp && \ + buffalo-tftp -i $(KDIR)/whr-g300n-tftp.tmp \ + -o $(call imgname,$(1),whr-g300n)-tftp.bin; \ + fi +endef +BuildFirmware/WHRG300N/initramfs=$(call BuildFirmware/OF/initramfs,$(1),whr-g300n,WHR-G300N) +Image/Build/Profile/WHRG300N=$(call BuildFirmware/WHRG300N/$(1),$(1)) + +Image/Build/Profile/WIZARD8800=$(call BuildFirmware/Default8M/$(1),$(1),wizard-8800,WIZARD8800,Linux Kernel Image) + +Image/Build/Profile/WIZFI630A=$(call BuildFirmware/Default16M/$(1),$(1),wizfi630a,WIZFI630A) + +Image/Build/Profile/WL-330N=$(call BuildFirmware/Default4M/$(1),$(1),wl-330n,WL-330N) + +Image/Build/Profile/WL-330N3G=$(call BuildFirmware/Default4M/$(1),$(1),wl-330n3g,WL-330N3G) + +kernel_size_wl341v3=917504 +rootfs_size_wl341v3=2949120 +define BuildFirmware/WL-341V3/squashfs + $(call BuildFirmware/Default4M/$(1),$(1),wl-341v3,WL-341V3) + # This code looks broken and really needs to be converted to C + if [ -e "$(call sysupname,$(1),$(2))" ]; then \ + ( \ + dd if=/dev/zero bs=195936 count=1; \ + echo "1.01"; \ + dd if=/dev/zero bs=581 count=1; \ + echo -n -e "\x73\x45\x72\x43\x6F\x4D\x6D\x00\x01\x00\x00\x59\x4E\x37\x95\x58\x10\x00\x20\x00\x28\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x03\x00\x00\x80\x00\x00\x00\x00\x03\x00\x00\x10\x12\x00\x00\x00\x10\x73\x45\x72\x43\x6F\x4D\x6D"; \ + dd if=/dev/zero bs=65552 count=1; \ + dd if=$(KDIR)/vmlinux-$(2).uImage bs=$(kernel_size_wl341v3) conv=sync; \ + dd if=$(KDIR)/root.$(1) bs=64k conv=sync; \ + dd if=/dev/zero bs=`expr 4194304 - 262144 - 16 - $(kernel_size_wl341v3) - \( \( \( \`stat -c%s $(KDIR)/root.$(1)\` / 65536 \) + 1 \) \* 65536 \)` count=1; \ + echo -n -e "\x11\x03\x80\x00\x10\x12\x90\xF7\x65\x52\x63\x4F\x6D\x4D\x00\x00"; \ + ) > $(call imgname,$(1),$(2))-factory.bin; \ + fi +endef +BuildFirmware/WL-341V3/initramfs=$(call BuildFirmware/OF/initramfs,$(1),wl-341v3,WL-341V3) +Image/Build/Profile/WL-341V3=$(call BuildFirmware/WL-341V3/$(1),$(1)) + +Image/Build/Profile/WL-351=$(call BuildFirmware/Default4M/$(1),$(1),wl-351,WL-351) + +define BuildFirmware/WNCE2001/squashfs + $(call BuildFirmware/Default4M/$(1),$(1),$(2),$(3)) + -mkdapimg -s RT3052-AP-WNCE2001-3 -r WW -v 1.0.0.99 \ + -i $(call sysupname,$(1),$(2)) \ + -o $(call imgname,$(1),$(2))-factory-worldwide.bin + -mkdapimg -s RT3052-AP-WNCE2001-3 -r NA -v 1.0.0.99 \ + -i $(call sysupname,$(1),$(2)) \ + -o $(call imgname,$(1),$(2))-factory-northamerica.bin +endef +BuildFirmware/WNCE2001/initramfs=$(call BuildFirmware/OF/initramfs,$(1),$(2),$(3)) +Image/Build/Profile/WNCE2001=$(call BuildFirmware/WNCE2001/$(1),$(1),wnce2001,WNCE2001) + +Image/Build/Profile/WR512-3GN=$(call BuildFirmware/DefaultDualSize/$(1),$(1),wr512-3ng,WR512-3GN) + +Image/Build/Profile/WT1520=$(call BuildFirmware/PorayDualSize/$(1),$(1),wt1520,WT1520) + +Image/Build/Profile/UR-326N4G=$(call BuildFirmware/Default4M/$(1),$(1),ur-326n4g,UR-326N4G) + +Image/Build/Profile/UR-336UN=$(call BuildFirmware/Default8M/$(1),$(1),ur-336un,UR-336UN) + +Image/Build/Profile/WR6202=$(call BuildFirmware/Default8M/$(1),$(1),wr6202,WR6202) + +Image/Build/Profile/X5=$(call BuildFirmware/Poray8M/$(1),$(1),x5,X5) + +Image/Build/Profile/X8=$(call BuildFirmware/Poray8M/$(1),$(1),x8,X8) + +Image/Build/Profile/XDXRN502J=$(call BuildFirmware/Default4M/$(1),$(1),xdxrn502j,XDXRN502J) + +ifeq ($(SUBTARGET),rt305x) +define Image/Build/Profile/Default + $(call Image/Build/Profile/3G6200N,$(1)) + $(call Image/Build/Profile/3G6200NL,$(1)) + $(call Image/Build/Profile/3G150B,$(1)) + $(call Image/Build/Profile/3G300M,$(1)) + $(call Image/Build/Profile/A5-11,$(1)) + $(call Image/Build/Profile/AIR3GII,$(1)) + $(call Image/Build/Profile/ALL02393G,$(1)) + $(call Image/Build/Profile/ALL0256N,$(1)) + $(call Image/Build/Profile/ALL5002,$(1)) + $(call Image/Build/Profile/ALL5003,$(1)) + $(call Image/Build/Profile/ASL26555,$(1)) + $(call Image/Build/Profile/ATP-52B,$(1)) + $(call Image/Build/Profile/AWM002EVB,$(1)) + $(call Image/Build/Profile/AWAPN2403,$(1)) + $(call Image/Build/Profile/BC2,$(1)) + $(call Image/Build/Profile/BROADWAY,$(1)) + $(call Image/Build/Profile/CARAMBOLA,$(1)) + $(call Image/Build/Profile/D105,$(1)) + $(call Image/Build/Profile/DIR-300-B1,$(1)) + $(call Image/Build/Profile/DIR-600-B1,$(1)) + $(call Image/Build/Profile/DIR-300-B7,$(1)) + $(call Image/Build/Profile/DIR-320-B1,$(1)) + $(call Image/Build/Profile/DIR-600-B2,$(1)) + $(call Image/Build/Profile/DIR610A1,$(1)) + $(call Image/Build/Profile/DIR-615-D,$(1)) + $(call Image/Build/Profile/DIR-620-A1,$(1)) + $(call Image/Build/Profile/DIR-620-D1,$(1)) + $(call Image/Build/Profile/DIR615H1,$(1)) + $(call Image/Build/Profile/DAP1350,$(1)) + $(call Image/Build/Profile/DAP1350WW,$(1)) + $(call Image/Build/Profile/DCS930,$(1)) + $(call Image/Build/Profile/DCS930LB1,$(1)) + $(call Image/Build/Profile/ESR-9753,$(1)) + $(call Image/Build/Profile/F7C027,$(1)) + $(call Image/Build/Profile/F5D8235V2,$(1)) + $(call Image/Build/Profile/FONERA20N,$(1)) + $(call Image/Build/Profile/FREESTATION5,$(1)) +# $(call Image/Build/Profile/HG255D,$(1)) + $(call Image/Build/Profile/HLKRM04,$(1)) + $(call Image/Build/Profile/HT-TM02,$(1)) + $(call Image/Build/Profile/HW550-3G,$(1)) + $(call Image/Build/Profile/IP2202,$(1)) + $(call Image/Build/Profile/M2M,$(1)) + $(call Image/Build/Profile/M3,$(1)) + $(call Image/Build/Profile/M4,$(1)) + $(call Image/Build/Profile/MOFI3500-3GN,$(1)) + $(call Image/Build/Profile/MR102N,$(1)) + $(call Image/Build/Profile/MPRA1,$(1)) + $(call Image/Build/Profile/MPRA2,$(1)) + $(call Image/Build/Profile/MZKW300NH2,$(1)) + $(call Image/Build/Profile/NBG-419N,$(1)) + $(call Image/Build/Profile/NCS601W,$(1)) + $(call Image/Build/Profile/NW718,$(1)) + $(call Image/Build/Profile/MINIEMBWIFI,$(1)) + $(call Image/Build/Profile/MINIEMBPLUG,$(1)) + $(call Image/Build/Profile/PSR-680W,$(1)) + $(call Image/Build/Profile/PWH2004,$(1)) + $(call Image/Build/Profile/PX-4885,$(1)) + $(call Image/Build/Profile/RT5350F-OLINUXINO,$(1)) + $(call Image/Build/Profile/RT5350F-OLINUXINO-EVB,$(1)) + $(call Image/Build/Profile/RTG32B1,$(1)) + $(call Image/Build/Profile/RTN10PLUS,$(1)) + $(call Image/Build/Profile/RT-N13U,$(1)) + $(call Image/Build/Profile/RUT5XX,$(1)) + $(call Image/Build/Profile/SL-R7205,$(1)) + $(call Image/Build/Profile/UR-326N4G,$(1)) + $(call Image/Build/Profile/V22RW-2X2,$(1)) + $(call Image/Build/Profile/VOCORE,$(1)) + $(call Image/Build/Profile/W150M,$(1)) + $(call Image/Build/Profile/W306R_V20,$(1)) + $(call Image/Build/Profile/W502U,$(1)) + $(call Image/Build/Profile/WCR150GN,$(1)) + $(call Image/Build/Profile/WHRG300N,$(1)) + $(call Image/Build/Profile/WIZARD8800,$(1)) + $(call Image/Build/Profile/WIZFI630A,$(1)) + $(call Image/Build/Profile/WL-330N,$(1)) + $(call Image/Build/Profile/WL-330N3G,$(1)) + $(call Image/Build/Profile/WL-341V3,$(1)) + $(call Image/Build/Profile/WL-351,$(1)) + $(call Image/Build/Profile/WNCE2001,$(1)) + $(call Image/Build/Profile/WR512-3GN,$(1)) + $(call Image/Build/Profile/WR6202,$(1)) + $(call Image/Build/Profile/WT1520,$(1)) + $(call Image/Build/Profile/X5,$(1)) + $(call Image/Build/Profile/X8,$(1)) + $(call Image/Build/Profile/XDXRN502J,$(1)) + $(call Image/Build/Profile/MZK-DP150N,$(1)) + +endef +endif + + + +# +# RT3662/RT3883 Profiles +# + +# $(1) = squashfs/initramfs +# $(2) = lowercase board name +# $(3) = dts file +# $(4) = kernel size +# $(5) = rootfs size +# $(6) = signature +# $(7) = model +# $(8) = flash address +# $(9) = start address +define BuildFirmware/EdimaxCombined/squashfs + $(call PatchKernelLzmaDtb,$(2),$(3)) + $(call MkImage,lzma,$(KDIR)/vmlinux-$(2).bin.lzma,$(KDIR)/vmlinux-$(2).bin.uImage) + if [ `stat -c%s "$(KDIR)/vmlinux-$(2).bin.uImage"` -gt `expr $(4) - 20` ]; then \ + echo "Warning: $(KDIR)/vmlinux-$(2).bin.uImage is too big" >&2; \ + exit 1; \ + else if [ `stat -c%s "$(KDIR)/root.$(1)"` -gt $(5) ]; then \ + echo "Warning: $(KDIR)/root.$(1) is too big" >&2; \ + exit 1; \ + else \ + ( dd if=$(KDIR)/vmlinux-$(2).bin.uImage bs=`expr $(4) - 20` conv=sync ; dd if=$(KDIR)/root.$(1) ) > $(KDIR)/vmlinux-$(2).bin.uImage.combined ; \ + fi ; fi + mkedimaximg -i "$(KDIR)/vmlinux-$(2).bin.uImage.combined" \ + -o $(call imgname,$(1),$(2)).bin \ + -s $(6) -m $(7) -f $(8) -S $(9) +endef + +Image/Build/Profile/CYSWR1100=$(call BuildFirmware/Seama/$(1),$(1),cy-swr1100,CY-SWR1100,wrgnd10_samsung_ss815,$(ralink_default_fw_size_8M)) + +Image/Build/Profile/DIR645=$(call BuildFirmware/Seama/$(1),$(1),dir-645,DIR-645,wrgn39_dlob.hans_dir645,$(ralink_default_fw_size_8M)) + +hpm_mtd_size=16449536 +Image/Build/Profile/HPM=$(call BuildFirmware/CustomFlash/$(1),$(1),hpm,HPM,$(hpm_mtd_size)) + +define BuildFirmware/RTN56U/squashfs + $(call BuildFirmware/Default8M/$(1),$(1),rt-n56u,RT-N56U) + -mkrtn56uimg -s $(call sysupname,$(1),rt-n56u) + -cp $(call sysupname,$(1),rt-n56u) $(call imgname,$(1),rt-n56u)-factory.bin + -mkrtn56uimg -f $(call imgname,$(1),rt-n56u)-factory.bin +endef +Image/Build/Profile/RTN56U=$(call BuildFirmware/RTN56U/$(1),$(1),rt-n56u,RT-N56U) + +Image/Build/Profile/TEW691GR=$(call BuildFirmware/UMedia/$(1),$(1),tew-691gr,TEW-691GR,0x026910) + +Image/Build/Profile/TEW692GR=$(call BuildFirmware/UMedia/$(1),$(1),tew-692gr,TEW-692GR,0x026920) + +kernel_size_BR6475ND:=2097152 +rootfs_size_BR6475ND:=5832704 +Image/Build/Profile/BR6475ND=$(call BuildFirmware/EdimaxCombined/$(1),$(1),br-6475nd,BR-6475ND,$(kernel_size_BR6475ND),$(rootfs_size_BR6475ND),CSYS,RN54,0x70000,0x01100000) + +ifeq ($(SUBTARGET),rt3883) +define Image/Build/Profile/Default + $(call Image/Build/Profile/CYSWR1100,$(1)) + $(call Image/Build/Profile/DIR645,$(1)) + $(call Image/Build/Profile/HPM,$(1)) + $(call Image/Build/Profile/RTN56U,$(1)) + $(call Image/Build/Profile/BR6475ND,$(1)) + $(call Image/Build/Profile/TEW691GR,$(1)) + $(call Image/Build/Profile/TEW692GR,$(1)) +endef +endif + +# +# MT7620A Profiles +# + +Image/Build/Profile/E1700=$(call BuildFirmware/UMedia/$(1),$(1),e1700,E1700,0x013326) +Image/Build/Profile/MT7620a=$(call BuildFirmware/Default8M/$(1),$(1),mt7620a,MT7620a) +Image/Build/Profile/MT7620a_MT7610e=$(call BuildFirmware/Default8M/$(1),$(1),mt7620a_mt7610e,MT7620a_MT7610e) +Image/Build/Profile/MT7620a_MT7530=$(call BuildFirmware/Default8M/$(1),$(1),mt7620a_mt7530,MT7620a_MT7530) +Image/Build/Profile/MT7620a_V22SG=$(call BuildFirmware/Default8M/$(1),$(1),mt7620a_v22sg,MT7620a_V22SG) +br100_mtd_size=8126464 +Image/Build/Profile/AI-BR100=$(call BuildFirmware/CustomFlash/$(1),$(1),ai-br100,AI-BR100,$(br100_mtd_size),Ai-BR) +Image/Build/Profile/RP-N53=$(call BuildFirmware/Default8M/$(1),$(1),rp-n53,RP-N53) +whr_300hp2_mtd_size=7012352 +Image/Build/Profile/WHR300HP2=$(call BuildFirmware/CustomFlash/$(1),$(1),whr-300hp2,WHR-300HP2,$(whr_300hp2_mtd_size)) +Image/Build/Profile/WHR600D=$(call BuildFirmware/CustomFlash/$(1),$(1),whr-600d,WHR-600D,$(whr_300hp2_mtd_size)) +whr_1166d_mtd_size=15400960 +Image/Build/Profile/WHR1166D=$(call BuildFirmware/CustomFlash/$(1),$(1),whr-1166d,WHR-1166D,$(whr_1166d_mtd_size)) +dlink810l_mtd_size=6881280 +Image/Build/Profile/CF-WR800N=$(call BuildFirmware/Default8M/$(1),$(1),cf-wr800n,CF-WR800N) +Image/Build/Profile/DIR-810L=$(call BuildFirmware/CustomFlash/$(1),$(1),dir-810l,DIR-810L,$(dlink810l_mtd_size)) +na930_mtd_size=20971520 +Image/Build/Profile/NA930=$(call BuildFirmware/CustomFlash/$(1),$(1),na930,NA930,$(na930_mtd_size)) +Image/Build/Profile/DB-WRT01=$(call BuildFirmware/Default8M/$(1),$(1),db-wrt01,DB-WRT01) +Image/Build/Profile/MZK-750DHP=$(call BuildFirmware/Default8M/$(1),$(1),mzk-750dhp,MZK-750DHP) +Image/Build/Profile/HC5661=$(call BuildFirmware/Default16M/$(1),$(1),hc5661,HC5661) +Image/Build/Profile/HC5761=$(call BuildFirmware/Default16M/$(1),$(1),hc5761,HC5761) +Image/Build/Profile/HC5861=$(call BuildFirmware/Default16M/$(1),$(1),hc5861,HC5861) +Image/Build/Profile/OY-0001=$(call BuildFirmware/Default16M/$(1),$(1),oy-0001,OY-0001) +Image/Build/Profile/Y1=$(call BuildFirmware/Default16M/$(1),$(1),y1,Y1) +Image/Build/Profile/Y1S=$(call BuildFirmware/Default16M/$(1),$(1),y1s,Y1S) +Image/Build/Profile/MLW221=$(call BuildFirmware/Default16M/$(1),$(1),mlw221,MLW221) +Image/Build/Profile/MLWG2=$(call BuildFirmware/Default16M/$(1),$(1),mlwg2,MLWG2) +Image/Build/Profile/WMR-300=$(call BuildFirmware/Default8M/$(1),$(1),wmr-300,WMR-300) +Image/Build/Profile/RT-N14U=$(call BuildFirmware/Default8M/$(1),$(1),rt-n14u,RT-N14U) +Image/Build/Profile/WRTNODE=$(call BuildFirmware/Default16M/$(1),$(1),wrtnode,WRTNODE) +Image/Build/Profile/WT3020=$(call BuildFirmware/PorayDualSize/$(1),$(1),wt3020,WT3020) +Image/Build/Profile/MIWIFI-MINI=$(call BuildFirmware/Default16M/$(1),$(1),miwifi-mini,MIWIFI-MINI) +Image/Build/Profile/ZTE-Q7=$(call BuildFirmware/Default8M/$(1),$(1),zte-q7,ZTE-Q7) +Image/Build/Profile/ZBT-WA05=$(call BuildFirmware/Default8M/$(1),$(1),zbt-wa05,ZBT-WA05) +Image/Build/Profile/ZBT-WR8305RT=$(call BuildFirmware/Default8M/$(1),$(1),zbt-wr8305rt,ZBT-WR8305RT) +Image/Build/Profile/ArcherC20i=$(call BuildFirmware/Tplink/$(1),$(1),ArcherC20i,ArcherC20i) +microwrt_mtd_size=16515072 +Image/Build/Profile/MicroWRT=$(call BuildFirmware/CustomFlash/$(1),$(1),microwrt,MicroWRT,$(microwrt_mtd_size)) +Image/Build/Profile/TINY-AC=$(call BuildFirmware/Default8M/$(1),$(1),tiny-ac,TINY-AC) + + +ifeq ($(SUBTARGET),mt7620) +define Image/Build/Profile/Default + $(call Image/Build/Profile/E1700,$(1)) + $(call Image/Build/Profile/MT7620a,$(1)) + $(call Image/Build/Profile/MT7620a_MT7610e,$(1)) + $(call Image/Build/Profile/MT7620a_MT7530,$(1)) + $(call Image/Build/Profile/MT7620a_V22SG,$(1)) + $(call Image/Build/Profile/AI-BR100,$(1)) + $(call Image/Build/Profile/CF-WR800N,$(1)) + $(call Image/Build/Profile/RP-N53,$(1)) + $(call Image/Build/Profile/DIR-810L,$(1)) + $(call Image/Build/Profile/WHR300HP2,$(1)) + $(call Image/Build/Profile/WHR600D,$(1)) + $(call Image/Build/Profile/WHR1166D,$(1)) + $(call Image/Build/Profile/DB-WRT01,$(1)) + $(call Image/Build/Profile/MZK-750DHP,$(1)) + $(call Image/Build/Profile/NA930,$(1)) + $(call Image/Build/Profile/HC5661,$(1)) + $(call Image/Build/Profile/HC5761,$(1)) + $(call Image/Build/Profile/HC5861,$(1)) + $(call Image/Build/Profile/OY-0001,$(1)) + $(call Image/Build/Profile/Y1,$(1)) + $(call Image/Build/Profile/Y1S,$(1)) + $(call Image/Build/Profile/MLW221,$(1)) + $(call Image/Build/Profile/MLWG2,$(1)) + $(call Image/Build/Profile/WMR-300,$(1)) + $(call Image/Build/Profile/RT-N14U,$(1)) + $(call Image/Build/Profile/WRTNODE,$(1)) + $(call Image/Build/Profile/WT3020,$(1)) + $(call Image/Build/Profile/MIWIFI-MINI,$(1)) + $(call Image/Build/Profile/ZTE-Q7,$(1)) + $(call Image/Build/Profile/ZBT-WA05,$(1)) + $(call Image/Build/Profile/ZBT-WR8305RT,$(1)) + $(call Image/Build/Profile/ArcherC20i,$(1)) + $(call Image/Build/Profile/MicroWRT,$(1)) + $(call Image/Build/Profile/TINY-AC,$(1)) +endef +endif + +# +# MT7621 Profiles +# + +ifeq ($(SUBTARGET),mt7621) + TARGET_DEVICES += mt7621 wsr-600 wsr-1166 dir-860l-b1 firewrt pbr-m1 re6500 sap-g3200u3 zbt-wg2626 +endif + +define Device/mt7621 + DTS := MT7621 + IMAGE_SIZE := $(ralink_default_fw_size_4M) +endef + +define Device/wsr-600 + DTS := WSR-600 +endef + +define Device/re6500 + DTS := RE6500 +endef + +define Device/wsr-1166 + DTS := WSR-1166 + IMAGE/sysupgrade.bin := trx | pad-rootfs +endef + +define Device/dir-860l-b1 + DTS := DIR-860L-B1 + IMAGES += factory.bin + KERNEL := kernel-bin | patch-dtb | relocate-kernel | lzma | uImage lzma + IMAGE/sysupgrade.bin := \ + append-kernel | pad-offset 65536 64 | append-rootfs | \ + seama -m "dev=/dev/mtdblock/2" -m "type=firmware" | \ + pad-rootfs | check-size $$$$(IMAGE_SIZE) + IMAGE/factory.bin := \ + append-kernel | pad-offset 65536 64 | append-rootfs | pad-rootfs -x 64 | \ + seama -m "dev=/dev/mtdblock/2" -m "type=firmware" | \ + check-size $$$$(IMAGE_SIZE) | \ + seama-seal -m "signature=wrgac13_dlink.2013gui_dir860lb" +endef + +define Device/firewrt + DTS := FIREWRT + IMAGE_SIZE := $(ralink_default_fw_size_16M) +endef + +define Device/pbr-m1 + DTS := PBR-M1 + IMAGE_SIZE := $(ralink_default_fw_size_16M) +endef + +define Device/sap-g3200u3 + DTS := SAP-G3200U3 +endef + +define Device/zbt-wg2626 + DTS := ZBT-WG2626 + IMAGE_SIZE := $(ralink_default_fw_size_16M) +endef + +# +# MT7628 Profiles +# + +Image/Build/Profile/MT7628=$(call BuildFirmware/Default4M/$(1),$(1),mt7628,MT7628) + +ifeq ($(SUBTARGET),mt7628) +define Image/Build/Profile/Default + $(call Image/Build/Profile/MT7628,$(1)) +endef +endif + + +# +# MT7688 Profiles +# + +Image/Build/Profile/mt7688=$(call BuildFirmware/Default16M/$(1),$(1),mt7688,MT7688) +Image/Build/Profile/LinkIt7688=$(call BuildFirmware/Default32M/$(1),$(1),LinkIt7688,LINKIT7688) + +ifeq ($(SUBTARGET),mt7688) +define Image/Build/Profile/Default + $(call Image/Build/Profile/mt7688,$(1)) + $(call Image/Build/Profile/LinkIt7688,$(1)) +endef +endif + + +ifndef TARGET_DEVICES +# +# Generic Targets - only needed for legacy image building code +# +define Image/BuildKernel + cp $(KDIR)/vmlinux.elf $(BIN_DIR)/$(VMLINUX).elf + cp $(KDIR)/vmlinux $(BIN_DIR)/$(VMLINUX).bin + $(call CompressLzma,$(KDIR)/vmlinux,$(KDIR)/vmlinux.bin.lzma) + $(call MkImage,lzma,$(KDIR)/vmlinux.bin.lzma,$(KDIR)/uImage.lzma) + cp $(KDIR)/uImage.lzma $(BIN_DIR)/$(UIMAGE).bin +endef + +define Image/BuildKernel/Initramfs + cp $(KDIR)/vmlinux-initramfs.elf $(BIN_DIR)/$(VMLINUX)-initramfs.elf + cp $(KDIR)/vmlinux-initramfs $(BIN_DIR)/$(VMLINUX)-initramfs.bin + $(call CompressLzma,$(KDIR)/vmlinux-initramfs,$(KDIR)/vmlinux-initramfs.bin.lzma) + $(call MkImage,lzma,$(KDIR)/vmlinux-initramfs.bin.lzma,$(KDIR)/uImage-initramfs.lzma) + cp $(KDIR)/uImage-initramfs.lzma $(BIN_DIR)/$(UIMAGE)-initramfs.bin + $(call Image/Build/Initramfs) +endef + +define Image/Build + $(call Image/Build/$(1)) + dd if=$(KDIR)/root.$(1) of=$(BIN_DIR)/$(IMG_PREFIX)-root.$(1) bs=128k conv=sync + $(call Image/Build/Profile/$(PROFILE),$(1)) +endef +endif + +ifeq ($(SUBTARGET),mt7621) +define Image/Prepare +#define Build/Compile + rm -rf $(KDIR)/relocate + $(CP) ../../generic/image/relocate $(KDIR) + $(MAKE) -C $(KDIR)/relocate KERNEL_ADDR=$(KERNEL_LOADADDR) CROSS_COMPILE=$(TARGET_CROSS) + $(CP) $(KDIR)/relocate/loader.bin $(KDIR)/loader.bin +endef +endif + +$(eval $(call BuildImage)) diff --git a/target/linux/ramips/image/lzma-loader/Makefile b/target/linux/ramips/image/lzma-loader/Makefile new file mode 100644 index 0000000..7833016 --- /dev/null +++ b/target/linux/ramips/image/lzma-loader/Makefile @@ -0,0 +1,65 @@ +# +# Copyright (C) 2011 OpenWrt.org +# Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +LZMA_TEXT_START := 0x80a00000 +LOADER := loader.bin +LOADER_NAME := $(basename $(notdir $(LOADER))) +LOADER_DATA := +TARGET_DIR := +FLASH_OFFS := +FLASH_MAX := +BOARD := + +ifeq ($(TARGET_DIR),) +TARGET_DIR := $(KDIR) +endif + +LOADER_BIN := $(TARGET_DIR)/$(LOADER_NAME).bin +LOADER_GZ := $(TARGET_DIR)/$(LOADER_NAME).gz +LOADER_ELF := $(TARGET_DIR)/$(LOADER_NAME).elf + +PKG_NAME := lzma-loader +PKG_BUILD_DIR := $(KDIR)/$(PKG_NAME) + +.PHONY : loader-compile loader.bin loader.elf loader.gz + +$(PKG_BUILD_DIR)/.prepared: + mkdir $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ + touch $@ + +loader-compile: $(PKG_BUILD_DIR)/.prepared + $(MAKE) -C $(PKG_BUILD_DIR) CROSS_COMPILE="$(TARGET_CROSS)" \ + LZMA_TEXT_START=$(LZMA_TEXT_START) \ + LOADER_DATA=$(LOADER_DATA) \ + FLASH_OFFS=$(FLASH_OFFS) \ + FLASH_MAX=$(FLASH_MAX) \ + BOARD="$(BOARD)" \ + PLATFORM="ralink" \ + clean all + +loader.gz: $(PKG_BUILD_DIR)/loader.bin + gzip -nc9 $< > $(LOADER_GZ) + +loader.elf: $(PKG_BUILD_DIR)/loader.elf + $(CP) $< $(LOADER_ELF) + +loader.bin: $(PKG_BUILD_DIR)/loader.bin + $(CP) $< $(LOADER_BIN) + +download: +prepare: $(PKG_BUILD_DIR)/.prepared +compile: loader-compile + +install: + +clean: + rm -rf $(PKG_BUILD_DIR) + diff --git a/target/linux/ramips/image/lzma-loader/src/LzmaDecode.c b/target/linux/ramips/image/lzma-loader/src/LzmaDecode.c new file mode 100644 index 0000000..cb83453 --- /dev/null +++ b/target/linux/ramips/image/lzma-loader/src/LzmaDecode.c @@ -0,0 +1,584 @@ +/* + LzmaDecode.c + LZMA Decoder (optimized for Speed version) + + LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) + http://www.7-zip.org/ + + LZMA SDK is licensed under two licenses: + 1) GNU Lesser General Public License (GNU LGPL) + 2) Common Public License (CPL) + It means that you can select one of these two licenses and + follow rules of that license. + + SPECIAL EXCEPTION: + Igor Pavlov, as the author of this Code, expressly permits you to + statically or dynamically link your Code (or bind by name) to the + interfaces of this file without subjecting your linked Code to the + terms of the CPL or GNU LGPL. Any modifications or additions + to this file, however, are subject to the LGPL or CPL terms. +*/ + +#include "LzmaDecode.h" + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_READ_BYTE (*Buffer++) + +#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \ + { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }} + +#ifdef _LZMA_IN_CB + +#define RC_TEST { if (Buffer == BufferLim) \ + { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \ + BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }} + +#define RC_INIT Buffer = BufferLim = 0; RC_INIT2 + +#else + +#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; } + +#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2 + +#endif + +#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; } + +#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound) +#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits; +#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits; + +#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \ + { UpdateBit0(p); mi <<= 1; A0; } else \ + { UpdateBit1(p); mi = (mi + mi) + 1; A1; } + +#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;) + +#define RangeDecoderBitTreeDecode(probs, numLevels, res) \ + { int i = numLevels; res = 1; \ + do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \ + res -= (1 << numLevels); } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + + +#define kNumStates 12 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size) +{ + unsigned char prop0; + if (size < LZMA_PROPERTIES_SIZE) + return LZMA_RESULT_DATA_ERROR; + prop0 = propsData[0]; + if (prop0 >= (9 * 5 * 5)) + return LZMA_RESULT_DATA_ERROR; + { + for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5)); + for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9); + propsRes->lc = prop0; + /* + unsigned char remainder = (unsigned char)(prop0 / 9); + propsRes->lc = prop0 % 9; + propsRes->pb = remainder / 5; + propsRes->lp = remainder % 5; + */ + } + + #ifdef _LZMA_OUT_READ + { + int i; + propsRes->DictionarySize = 0; + for (i = 0; i < 4; i++) + propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8); + if (propsRes->DictionarySize == 0) + propsRes->DictionarySize = 1; + } + #endif + return LZMA_RESULT_OK; +} + +#define kLzmaStreamWasFinishedId (-1) + +int LzmaDecode(CLzmaDecoderState *vs, + #ifdef _LZMA_IN_CB + ILzmaInCallback *InCallback, + #else + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, + #endif + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed) +{ + CProb *p = vs->Probs; + SizeT nowPos = 0; + Byte previousByte = 0; + UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; + UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; + int lc = vs->Properties.lc; + + #ifdef _LZMA_OUT_READ + + UInt32 Range = vs->Range; + UInt32 Code = vs->Code; + #ifdef _LZMA_IN_CB + const Byte *Buffer = vs->Buffer; + const Byte *BufferLim = vs->BufferLim; + #else + const Byte *Buffer = inStream; + const Byte *BufferLim = inStream + inSize; + #endif + int state = vs->State; + UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; + int len = vs->RemainLen; + UInt32 globalPos = vs->GlobalPos; + UInt32 distanceLimit = vs->DistanceLimit; + + Byte *dictionary = vs->Dictionary; + UInt32 dictionarySize = vs->Properties.DictionarySize; + UInt32 dictionaryPos = vs->DictionaryPos; + + Byte tempDictionary[4]; + + #ifndef _LZMA_IN_CB + *inSizeProcessed = 0; + #endif + *outSizeProcessed = 0; + if (len == kLzmaStreamWasFinishedId) + return LZMA_RESULT_OK; + + if (dictionarySize == 0) + { + dictionary = tempDictionary; + dictionarySize = 1; + tempDictionary[0] = vs->TempDictionary[0]; + } + + if (len == kLzmaNeedInitId) + { + { + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); + UInt32 i; + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + rep0 = rep1 = rep2 = rep3 = 1; + state = 0; + globalPos = 0; + distanceLimit = 0; + dictionaryPos = 0; + dictionary[dictionarySize - 1] = 0; + #ifdef _LZMA_IN_CB + RC_INIT; + #else + RC_INIT(inStream, inSize); + #endif + } + len = 0; + } + while(len != 0 && nowPos < outSize) + { + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos]; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + len--; + } + if (dictionaryPos == 0) + previousByte = dictionary[dictionarySize - 1]; + else + previousByte = dictionary[dictionaryPos - 1]; + + #else /* if !_LZMA_OUT_READ */ + + int state = 0; + UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; + int len = 0; + const Byte *Buffer; + const Byte *BufferLim; + UInt32 Range; + UInt32 Code; + + #ifndef _LZMA_IN_CB + *inSizeProcessed = 0; + #endif + *outSizeProcessed = 0; + + { + UInt32 i; + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + } + + #ifdef _LZMA_IN_CB + RC_INIT; + #else + RC_INIT(inStream, inSize); + #endif + + #endif /* _LZMA_OUT_READ */ + + while(nowPos < outSize) + { + CProb *prob; + UInt32 bound; + int posState = (int)( + (nowPos + #ifdef _LZMA_OUT_READ + + globalPos + #endif + ) + & posStateMask); + + prob = p + IsMatch + (state << kNumPosBitsMax) + posState; + IfBit0(prob) + { + int symbol = 1; + UpdateBit0(prob) + prob = p + Literal + (LZMA_LIT_SIZE * + ((( + (nowPos + #ifdef _LZMA_OUT_READ + + globalPos + #endif + ) + & literalPosMask) << lc) + (previousByte >> (8 - lc)))); + + if (state >= kNumLitStates) + { + int matchByte; + #ifdef _LZMA_OUT_READ + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + matchByte = dictionary[pos]; + #else + matchByte = outStream[nowPos - rep0]; + #endif + do + { + int bit; + CProb *probLit; + matchByte <<= 1; + bit = (matchByte & 0x100); + probLit = prob + 0x100 + bit + symbol; + RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break) + } + while (symbol < 0x100); + } + while (symbol < 0x100) + { + CProb *probLit = prob + symbol; + RC_GET_BIT(probLit, symbol) + } + previousByte = (Byte)symbol; + + outStream[nowPos++] = previousByte; + #ifdef _LZMA_OUT_READ + if (distanceLimit < dictionarySize) + distanceLimit++; + + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #endif + if (state < 4) state = 0; + else if (state < 10) state -= 3; + else state -= 6; + } + else + { + UpdateBit1(prob); + prob = p + IsRep + state; + IfBit0(prob) + { + UpdateBit0(prob); + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + state = state < kNumLitStates ? 0 : 3; + prob = p + LenCoder; + } + else + { + UpdateBit1(prob); + prob = p + IsRepG0 + state; + IfBit0(prob) + { + UpdateBit0(prob); + prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState; + IfBit0(prob) + { + #ifdef _LZMA_OUT_READ + UInt32 pos; + #endif + UpdateBit0(prob); + + #ifdef _LZMA_OUT_READ + if (distanceLimit == 0) + #else + if (nowPos == 0) + #endif + return LZMA_RESULT_DATA_ERROR; + + state = state < kNumLitStates ? 9 : 11; + #ifdef _LZMA_OUT_READ + pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #else + previousByte = outStream[nowPos - rep0]; + #endif + outStream[nowPos++] = previousByte; + #ifdef _LZMA_OUT_READ + if (distanceLimit < dictionarySize) + distanceLimit++; + #endif + + continue; + } + else + { + UpdateBit1(prob); + } + } + else + { + UInt32 distance; + UpdateBit1(prob); + prob = p + IsRepG1 + state; + IfBit0(prob) + { + UpdateBit0(prob); + distance = rep1; + } + else + { + UpdateBit1(prob); + prob = p + IsRepG2 + state; + IfBit0(prob) + { + UpdateBit0(prob); + distance = rep2; + } + else + { + UpdateBit1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = p + RepLenCoder; + } + { + int numBits, offset; + CProb *probLen = prob + LenChoice; + IfBit0(probLen) + { + UpdateBit0(probLen); + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + numBits = kLenNumLowBits; + } + else + { + UpdateBit1(probLen); + probLen = prob + LenChoice2; + IfBit0(probLen) + { + UpdateBit0(probLen); + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + numBits = kLenNumMidBits; + } + else + { + UpdateBit1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + numBits = kLenNumHighBits; + } + } + RangeDecoderBitTreeDecode(probLen, numBits, len); + len += offset; + } + + if (state < 4) + { + int posSlot; + state += kNumLitStates; + prob = p + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + rep0 = (2 | ((UInt32)posSlot & 1)); + if (posSlot < kEndPosModelIndex) + { + rep0 <<= numDirectBits; + prob = p + SpecPos + rep0 - posSlot - 1; + } + else + { + numDirectBits -= kNumAlignBits; + do + { + RC_NORMALIZE + Range >>= 1; + rep0 <<= 1; + if (Code >= Range) + { + Code -= Range; + rep0 |= 1; + } + } + while (--numDirectBits != 0); + prob = p + Align; + rep0 <<= kNumAlignBits; + numDirectBits = kNumAlignBits; + } + { + int i = 1; + int mi = 1; + do + { + CProb *prob3 = prob + mi; + RC_GET_BIT2(prob3, mi, ; , rep0 |= i); + i <<= 1; + } + while(--numDirectBits != 0); + } + } + else + rep0 = posSlot; + if (++rep0 == (UInt32)(0)) + { + /* it's for stream version */ + len = kLzmaStreamWasFinishedId; + break; + } + } + + len += kMatchMinLen; + #ifdef _LZMA_OUT_READ + if (rep0 > distanceLimit) + #else + if (rep0 > nowPos) + #endif + return LZMA_RESULT_DATA_ERROR; + + #ifdef _LZMA_OUT_READ + if (dictionarySize - distanceLimit > (UInt32)len) + distanceLimit += len; + else + distanceLimit = dictionarySize; + #endif + + do + { + #ifdef _LZMA_OUT_READ + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #else + previousByte = outStream[nowPos - rep0]; + #endif + len--; + outStream[nowPos++] = previousByte; + } + while(len != 0 && nowPos < outSize); + } + } + RC_NORMALIZE; + + #ifdef _LZMA_OUT_READ + vs->Range = Range; + vs->Code = Code; + vs->DictionaryPos = dictionaryPos; + vs->GlobalPos = globalPos + (UInt32)nowPos; + vs->DistanceLimit = distanceLimit; + vs->Reps[0] = rep0; + vs->Reps[1] = rep1; + vs->Reps[2] = rep2; + vs->Reps[3] = rep3; + vs->State = state; + vs->RemainLen = len; + vs->TempDictionary[0] = tempDictionary[0]; + #endif + + #ifdef _LZMA_IN_CB + vs->Buffer = Buffer; + vs->BufferLim = BufferLim; + #else + *inSizeProcessed = (SizeT)(Buffer - inStream); + #endif + *outSizeProcessed = nowPos; + return LZMA_RESULT_OK; +} diff --git a/target/linux/ramips/image/lzma-loader/src/LzmaDecode.h b/target/linux/ramips/image/lzma-loader/src/LzmaDecode.h new file mode 100644 index 0000000..2870eeb --- /dev/null +++ b/target/linux/ramips/image/lzma-loader/src/LzmaDecode.h @@ -0,0 +1,113 @@ +/* + LzmaDecode.h + LZMA Decoder interface + + LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) + http://www.7-zip.org/ + + LZMA SDK is licensed under two licenses: + 1) GNU Lesser General Public License (GNU LGPL) + 2) Common Public License (CPL) + It means that you can select one of these two licenses and + follow rules of that license. + + SPECIAL EXCEPTION: + Igor Pavlov, as the author of this code, expressly permits you to + statically or dynamically link your code (or bind by name) to the + interfaces of this file without subjecting your linked code to the + terms of the CPL or GNU LGPL. Any modifications or additions + to this file, however, are subject to the LGPL or CPL terms. +*/ + +#ifndef __LZMADECODE_H +#define __LZMADECODE_H + +#include "LzmaTypes.h" + +/* #define _LZMA_IN_CB */ +/* Use callback for input data */ + +/* #define _LZMA_OUT_READ */ +/* Use read function for output data */ + +/* #define _LZMA_PROB32 */ +/* It can increase speed on some 32-bit CPUs, + but memory usage will be doubled in that case */ + +/* #define _LZMA_LOC_OPT */ +/* Enable local speed optimizations inside code */ + +#ifdef _LZMA_PROB32 +#define CProb UInt32 +#else +#define CProb UInt16 +#endif + +#define LZMA_RESULT_OK 0 +#define LZMA_RESULT_DATA_ERROR 1 + +#ifdef _LZMA_IN_CB +typedef struct _ILzmaInCallback +{ + int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize); +} ILzmaInCallback; +#endif + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +#define LZMA_PROPERTIES_SIZE 5 + +typedef struct _CLzmaProperties +{ + int lc; + int lp; + int pb; + #ifdef _LZMA_OUT_READ + UInt32 DictionarySize; + #endif +}CLzmaProperties; + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); + +#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp))) + +#define kLzmaNeedInitId (-2) + +typedef struct _CLzmaDecoderState +{ + CLzmaProperties Properties; + CProb *Probs; + + #ifdef _LZMA_IN_CB + const unsigned char *Buffer; + const unsigned char *BufferLim; + #endif + + #ifdef _LZMA_OUT_READ + unsigned char *Dictionary; + UInt32 Range; + UInt32 Code; + UInt32 DictionaryPos; + UInt32 GlobalPos; + UInt32 DistanceLimit; + UInt32 Reps[4]; + int State; + int RemainLen; + unsigned char TempDictionary[4]; + #endif +} CLzmaDecoderState; + +#ifdef _LZMA_OUT_READ +#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; } +#endif + +int LzmaDecode(CLzmaDecoderState *vs, + #ifdef _LZMA_IN_CB + ILzmaInCallback *inCallback, + #else + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, + #endif + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed); + +#endif diff --git a/target/linux/ramips/image/lzma-loader/src/LzmaTypes.h b/target/linux/ramips/image/lzma-loader/src/LzmaTypes.h new file mode 100644 index 0000000..9c27290 --- /dev/null +++ b/target/linux/ramips/image/lzma-loader/src/LzmaTypes.h @@ -0,0 +1,45 @@ +/* +LzmaTypes.h + +Types for LZMA Decoder + +This file written and distributed to public domain by Igor Pavlov. +This file is part of LZMA SDK 4.40 (2006-05-01) +*/ + +#ifndef __LZMATYPES_H +#define __LZMATYPES_H + +#ifndef _7ZIP_BYTE_DEFINED +#define _7ZIP_BYTE_DEFINED +typedef unsigned char Byte; +#endif + +#ifndef _7ZIP_UINT16_DEFINED +#define _7ZIP_UINT16_DEFINED +typedef unsigned short UInt16; +#endif + +#ifndef _7ZIP_UINT32_DEFINED +#define _7ZIP_UINT32_DEFINED +#ifdef _LZMA_UINT32_IS_ULONG +typedef unsigned long UInt32; +#else +typedef unsigned int UInt32; +#endif +#endif + +/* #define _LZMA_NO_SYSTEM_SIZE_T */ +/* You can use it, if you don't want <stddef.h> */ + +#ifndef _7ZIP_SIZET_DEFINED +#define _7ZIP_SIZET_DEFINED +#ifdef _LZMA_NO_SYSTEM_SIZE_T +typedef UInt32 SizeT; +#else +#include <stddef.h> +typedef size_t SizeT; +#endif +#endif + +#endif diff --git a/target/linux/ramips/image/lzma-loader/src/Makefile b/target/linux/ramips/image/lzma-loader/src/Makefile new file mode 100644 index 0000000..f861666 --- /dev/null +++ b/target/linux/ramips/image/lzma-loader/src/Makefile @@ -0,0 +1,110 @@ +# +# Makefile for the LZMA compressed kernel loader for +# Atheros AR7XXX/AR9XXX based boards +# +# Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> +# +# Some parts of this file was based on the OpenWrt specific lzma-loader +# for the BCM47xx and ADM5120 based boards: +# Copyright (C) 2004 Manuel Novoa III (mjn3@codepoet.org) +# Copyright (C) 2005 Mineharu Takahara <mtakahar@yahoo.com> +# Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su> +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# + +LOADADDR := +LZMA_TEXT_START := 0x80a00000 +LOADER_DATA := +BOARD := +FLASH_OFFS := +FLASH_MAX := +PLATFORM := + +CC := $(CROSS_COMPILE)gcc +LD := $(CROSS_COMPILE)ld +OBJCOPY := $(CROSS_COMPILE)objcopy +OBJDUMP := $(CROSS_COMPILE)objdump + +BIN_FLAGS := -O binary -R .reginfo -R .note -R .comment -R .mdebug -S + +CFLAGS = -D__KERNEL__ -Wall -Wstrict-prototypes -Wno-trigraphs -Os \ + -fno-strict-aliasing -fno-common -fomit-frame-pointer -G 0 \ + -mno-abicalls -fno-pic -ffunction-sections -pipe -mlong-calls \ + -fno-common -ffreestanding -fhonour-copts \ + -mabi=32 -march=mips32r2 \ + -Wa,-32 -Wa,-march=mips32r2 -Wa,-mips32r2 -Wa,--trap +CFLAGS += -D_LZMA_PROB32 -DARCH=$(PLATFORM) + +ASFLAGS = $(CFLAGS) -D__ASSEMBLY__ + +LDFLAGS = -static --gc-sections -no-warn-mismatch +LDFLAGS += -e startup -T loader.lds -Ttext $(LZMA_TEXT_START) + +O_FORMAT = $(shell $(OBJDUMP) -i | head -2 | grep elf32) + +OBJECTS := head.o loader.o cache.o board-$(PLATFORM).o printf.o LzmaDecode.o + +include $(PLATFORM).mk +CFLAGS+=$(CACHE_FLAGS) +ASFLAGS+=$(CACHE_FLAGS) + +ifneq ($(strip $(LOADER_DATA)),) +OBJECTS += data.o +CFLAGS += -DLZMA_WRAPPER=1 -DLOADADDR=$(LOADADDR) +endif + +ifneq ($(strip $(KERNEL_CMDLINE)),) +CFLAGS += -DCONFIG_KERNEL_CMDLINE='"$(KERNEL_CMDLINE)"' +endif + +ifneq ($(strip $(FLASH_OFFS)),) +CFLAGS += -DCONFIG_FLASH_OFFS=$(FLASH_OFFS) +endif + +ifneq ($(strip $(FLASH_MAX)),) +CFLAGS += -DCONFIG_FLASH_MAX=$(FLASH_MAX) +endif + +BOARD_DEF := $(shell echo $(strip $(BOARD)) | tr a-z A-Z | tr - _) +ifneq ($(BOARD_DEF),) +CFLAGS += -DCONFIG_BOARD_$(BOARD_DEF) +endif + +all: loader.elf + +# Don't build dependencies, this may die if $(CC) isn't gcc +dep: + +install: + +%.o : %.c + $(CC) $(CFLAGS) -c -o $@ $< + +%.o : %.S + $(CC) $(ASFLAGS) -c -o $@ $< + +data.o: $(LOADER_DATA) + $(LD) -r -b binary --oformat $(O_FORMAT) -T lzma-data.lds -o $@ $< + +loader: $(OBJECTS) + $(LD) $(LDFLAGS) -o $@ $(OBJECTS) + +loader.bin: loader + $(OBJCOPY) $(BIN_FLAGS) $< $@ + +loader2.o: loader.bin + $(LD) -r -b binary --oformat $(O_FORMAT) -o $@ $< + +loader.elf: loader2.o + $(LD) -e startup -T loader2.lds -Ttext $(LOADADDR) -o $@ $< + +mrproper: clean + +clean: + rm -f loader *.elf *.bin *.o + + + diff --git a/target/linux/ramips/image/lzma-loader/src/board-ralink.c b/target/linux/ramips/image/lzma-loader/src/board-ralink.c new file mode 100644 index 0000000..7c947ec --- /dev/null +++ b/target/linux/ramips/image/lzma-loader/src/board-ralink.c @@ -0,0 +1,42 @@ +/* + * Arch specific code for Ralink based boards + * + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <stddef.h> +#include "config.h" + +#define READREG(r) *(volatile unsigned int *)(r) +#define WRITEREG(r,v) *(volatile unsigned int *)(r) = v + +#define KSEG1ADDR(_x) (((_x) & 0x1fffffff) | 0xa0000000) + +#ifdef CONFIG_SOC_RT288X +#define UART_BASE 0xb0300c00 +#else +#define UART_BASE 0xb0000c00 +#endif + +#define UART_TX 1 +#define UART_LSR 7 + +#define UART_LSR_THRE 0x20 + +#define UART_READ(r) READREG(UART_BASE + 4 * (r)) +#define UART_WRITE(r,v) WRITEREG(UART_BASE + 4 * (r), (v)) + +void board_putc(int ch) +{ + while (((UART_READ(UART_LSR)) & UART_LSR_THRE) == 0); + UART_WRITE(UART_TX, ch); + while (((UART_READ(UART_LSR)) & UART_LSR_THRE) == 0); +} + +void board_init(void) +{ +} diff --git a/target/linux/ramips/image/lzma-loader/src/cache.c b/target/linux/ramips/image/lzma-loader/src/cache.c new file mode 100644 index 0000000..28cc848 --- /dev/null +++ b/target/linux/ramips/image/lzma-loader/src/cache.c @@ -0,0 +1,43 @@ +/* + * LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards + * + * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> + * + * The cache manipulation routine has been taken from the U-Boot project. + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, <wd@denx.de> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + */ + +#include "cache.h" +#include "cacheops.h" +#include "config.h" + +#define cache_op(op,addr) \ + __asm__ __volatile__( \ + " .set push \n" \ + " .set noreorder \n" \ + " .set mips3\n\t \n" \ + " cache %0, %1 \n" \ + " .set pop \n" \ + : \ + : "i" (op), "R" (*(unsigned char *)(addr))) + +void flush_cache(unsigned long start_addr, unsigned long size) +{ + unsigned long lsize = CONFIG_CACHELINE_SIZE; + unsigned long addr = start_addr & ~(lsize - 1); + unsigned long aend = (start_addr + size - 1) & ~(lsize - 1); + + while (1) { + cache_op(Hit_Writeback_Inv_D, addr); + cache_op(Hit_Invalidate_I, addr); + if (addr == aend) + break; + addr += lsize; + } +} diff --git a/target/linux/ramips/image/lzma-loader/src/cache.h b/target/linux/ramips/image/lzma-loader/src/cache.h new file mode 100644 index 0000000..506a235 --- /dev/null +++ b/target/linux/ramips/image/lzma-loader/src/cache.h @@ -0,0 +1,17 @@ +/* + * LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards + * + * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + */ + +#ifndef __CACHE_H +#define __CACHE_H + +void flush_cache(unsigned long start_addr, unsigned long size); + +#endif /* __CACHE_H */ diff --git a/target/linux/ramips/image/lzma-loader/src/cacheops.h b/target/linux/ramips/image/lzma-loader/src/cacheops.h new file mode 100644 index 0000000..70bcad7 --- /dev/null +++ b/target/linux/ramips/image/lzma-loader/src/cacheops.h @@ -0,0 +1,85 @@ +/* + * Cache operations for the cache instruction. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * (C) Copyright 1996, 97, 99, 2002, 03 Ralf Baechle + * (C) Copyright 1999 Silicon Graphics, Inc. + */ +#ifndef __ASM_CACHEOPS_H +#define __ASM_CACHEOPS_H + +/* + * Cache Operations available on all MIPS processors with R4000-style caches + */ +#define Index_Invalidate_I 0x00 +#define Index_Writeback_Inv_D 0x01 +#define Index_Load_Tag_I 0x04 +#define Index_Load_Tag_D 0x05 +#define Index_Store_Tag_I 0x08 +#define Index_Store_Tag_D 0x09 +#if defined(CONFIG_CPU_LOONGSON2) +#define Hit_Invalidate_I 0x00 +#else +#define Hit_Invalidate_I 0x10 +#endif +#define Hit_Invalidate_D 0x11 +#define Hit_Writeback_Inv_D 0x15 + +/* + * R4000-specific cacheops + */ +#define Create_Dirty_Excl_D 0x0d +#define Fill 0x14 +#define Hit_Writeback_I 0x18 +#define Hit_Writeback_D 0x19 + +/* + * R4000SC and R4400SC-specific cacheops + */ +#define Index_Invalidate_SI 0x02 +#define Index_Writeback_Inv_SD 0x03 +#define Index_Load_Tag_SI 0x06 +#define Index_Load_Tag_SD 0x07 +#define Index_Store_Tag_SI 0x0A +#define Index_Store_Tag_SD 0x0B +#define Create_Dirty_Excl_SD 0x0f +#define Hit_Invalidate_SI 0x12 +#define Hit_Invalidate_SD 0x13 +#define Hit_Writeback_Inv_SD 0x17 +#define Hit_Writeback_SD 0x1b +#define Hit_Set_Virtual_SI 0x1e +#define Hit_Set_Virtual_SD 0x1f + +/* + * R5000-specific cacheops + */ +#define R5K_Page_Invalidate_S 0x17 + +/* + * RM7000-specific cacheops + */ +#define Page_Invalidate_T 0x16 + +/* + * R10000-specific cacheops + * + * Cacheops 0x02, 0x06, 0x0a, 0x0c-0x0e, 0x16, 0x1a and 0x1e are unused. + * Most of the _S cacheops are identical to the R4000SC _SD cacheops. + */ +#define Index_Writeback_Inv_S 0x03 +#define Index_Load_Tag_S 0x07 +#define Index_Store_Tag_S 0x0B +#define Hit_Invalidate_S 0x13 +#define Cache_Barrier 0x14 +#define Hit_Writeback_Inv_S 0x17 +#define Index_Load_Data_I 0x18 +#define Index_Load_Data_D 0x19 +#define Index_Load_Data_S 0x1b +#define Index_Store_Data_I 0x1c +#define Index_Store_Data_D 0x1d +#define Index_Store_Data_S 0x1f + +#endif /* __ASM_CACHEOPS_H */ diff --git a/target/linux/ramips/image/lzma-loader/src/config.h b/target/linux/ramips/image/lzma-loader/src/config.h new file mode 100644 index 0000000..b7719e9 --- /dev/null +++ b/target/linux/ramips/image/lzma-loader/src/config.h @@ -0,0 +1,27 @@ +/* + * LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards + * + * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + */ + +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +#ifndef CONFIG_FLASH_OFFS +#define CONFIG_FLASH_OFFS 0 +#endif + +#ifndef CONFIG_FLASH_MAX +#define CONFIG_FLASH_MAX 0 +#endif + +#ifndef CONFIG_FLASH_STEP +#define CONFIG_FLASH_STEP 0x1000 +#endif + +#endif /* _CONFIG_H_ */ diff --git a/target/linux/ramips/image/lzma-loader/src/cp0regdef.h b/target/linux/ramips/image/lzma-loader/src/cp0regdef.h new file mode 100644 index 0000000..c1188ad --- /dev/null +++ b/target/linux/ramips/image/lzma-loader/src/cp0regdef.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 1994, 1995, 1996, 1997, 2000, 2001 by Ralf Baechle + * + * Copyright (C) 2001, Monta Vista Software + * Author: jsun@mvista.com or jsun@junsun.net + */ +#ifndef _cp0regdef_h_ +#define _cp0regdef_h_ + +#define CP0_INDEX $0 +#define CP0_RANDOM $1 +#define CP0_ENTRYLO0 $2 +#define CP0_ENTRYLO1 $3 +#define CP0_CONTEXT $4 +#define CP0_PAGEMASK $5 +#define CP0_WIRED $6 +#define CP0_BADVADDR $8 +#define CP0_COUNT $9 +#define CP0_ENTRYHI $10 +#define CP0_COMPARE $11 +#define CP0_STATUS $12 +#define CP0_CAUSE $13 +#define CP0_EPC $14 +#define CP0_PRID $15 +#define CP0_CONFIG $16 +#define CP0_LLADDR $17 +#define CP0_WATCHLO $18 +#define CP0_WATCHHI $19 +#define CP0_XCONTEXT $20 +#define CP0_FRAMEMASK $21 +#define CP0_DIAGNOSTIC $22 +#define CP0_PERFORMANCE $25 +#define CP0_ECC $26 +#define CP0_CACHEERR $27 +#define CP0_TAGLO $28 +#define CP0_TAGHI $29 +#define CP0_ERROREPC $30 + +#endif diff --git a/target/linux/ramips/image/lzma-loader/src/head.S b/target/linux/ramips/image/lzma-loader/src/head.S new file mode 100644 index 0000000..543996a --- /dev/null +++ b/target/linux/ramips/image/lzma-loader/src/head.S @@ -0,0 +1,118 @@ +/* + * LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards + * + * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> + * + * Some parts of this code was based on the OpenWrt specific lzma-loader + * for the BCM47xx and ADM5120 based boards: + * Copyright (C) 2004 Manuel Novoa III (mjn3@codepoet.org) + * Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <asm/asm.h> +#include <asm/regdef.h> +#include "cp0regdef.h" +#include "cacheops.h" +#include "config.h" + +#define KSEG0 0x80000000 + + .macro ehb + sll zero, 3 + .endm + + .text + +LEAF(startup) + .set noreorder + .set mips32 + + mtc0 zero, CP0_WATCHLO # clear watch registers + mtc0 zero, CP0_WATCHHI + mtc0 zero, CP0_CAUSE # clear before writing status register + + mfc0 t0, CP0_STATUS + li t1, 0x1000001f + or t0, t1 + xori t0, 0x1f + mtc0 t0, CP0_STATUS + ehb + + mtc0 zero, CP0_COUNT + mtc0 zero, CP0_COMPARE + ehb + + la t0, __reloc_label # get linked address of label + bal __reloc_label # branch and link to label to + nop # get actual address +__reloc_label: + subu t0, ra, t0 # get reloc_delta + + beqz t0, __reloc_done # if delta is 0 we are in the right place + nop + + /* Copy our code to the right place */ + la t1, _code_start # get linked address of _code_start + la t2, _code_end # get linked address of _code_end + addu t0, t0, t1 # calculate actual address of _code_start + +__reloc_copy: + lw t3, 0(t0) + sw t3, 0(t1) + add t1, 4 + blt t1, t2, __reloc_copy + add t0, 4 + + /* flush cache */ + la t0, _code_start + la t1, _code_end + + li t2, ~(CONFIG_CACHELINE_SIZE - 1) + and t0, t2 + and t1, t2 + li t2, CONFIG_CACHELINE_SIZE + + b __flush_check + nop + +__flush_line: + cache Hit_Writeback_Inv_D, 0(t0) + cache Hit_Invalidate_I, 0(t0) + add t0, t2 + +__flush_check: + bne t0, t1, __flush_line + nop + + sync + +__reloc_done: + + /* clear bss */ + la t0, _bss_start + la t1, _bss_end + b __bss_check + nop + +__bss_fill: + sw zero, 0(t0) + addi t0, 4 + +__bss_check: + bne t0, t1, __bss_fill + nop + + /* Setup new "C" stack */ + la sp, _stack + + /* jump to the decompressor routine */ + la t0, loader_main + jr t0 + nop + + .set reorder +END(startup) diff --git a/target/linux/ramips/image/lzma-loader/src/lantiq.mk b/target/linux/ramips/image/lzma-loader/src/lantiq.mk new file mode 100644 index 0000000..4137645 --- /dev/null +++ b/target/linux/ramips/image/lzma-loader/src/lantiq.mk @@ -0,0 +1 @@ +CACHE_FLAGS+=-DCONFIG_ICACHE_SIZE="(32 * 1024)" -DCONFIG_DCACHE_SIZE="(32 * 1024)" -DCONFIG_CACHELINE_SIZE=32 diff --git a/target/linux/ramips/image/lzma-loader/src/loader.c b/target/linux/ramips/image/lzma-loader/src/loader.c new file mode 100644 index 0000000..1d42bfa --- /dev/null +++ b/target/linux/ramips/image/lzma-loader/src/loader.c @@ -0,0 +1,263 @@ +/* + * LZMA compressed kernel loader for Atheros AR7XXX/AR9XXX based boards + * + * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> + * + * Some parts of this code was based on the OpenWrt specific lzma-loader + * for the BCM47xx and ADM5120 based boards: + * Copyright (C) 2004 Manuel Novoa III (mjn3@codepoet.org) + * Copyright (C) 2005 Mineharu Takahara <mtakahar@yahoo.com> + * Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su> + * + * The image_header structure has been taken from the U-Boot project. + * (C) Copyright 2008 Semihalf + * (C) Copyright 2000-2005 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <stddef.h> +#include <stdint.h> + +#include "config.h" +#include "cache.h" +#include "printf.h" +#include "LzmaDecode.h" + +#define AR71XX_FLASH_START 0x1f000000 +#define AR71XX_FLASH_END 0x1fe00000 + +#define KSEG0 0x80000000 +#define KSEG1 0xa0000000 + +#define KSEG1ADDR(a) ((((unsigned)(a)) & 0x1fffffffU) | KSEG1) + +#undef LZMA_DEBUG + +#ifdef LZMA_DEBUG +# define DBG(f, a...) printf(f, ## a) +#else +# define DBG(f, a...) do {} while (0) +#endif + +#define IH_MAGIC_OKLI 0x4f4b4c49 /* 'OKLI' */ + +#define IH_NMLEN 32 /* Image Name Length */ + +typedef struct image_header { + uint32_t ih_magic; /* Image Header Magic Number */ + uint32_t ih_hcrc; /* Image Header CRC Checksum */ + uint32_t ih_time; /* Image Creation Timestamp */ + uint32_t ih_size; /* Image Data Size */ + uint32_t ih_load; /* Data Load Address */ + uint32_t ih_ep; /* Entry Point Address */ + uint32_t ih_dcrc; /* Image Data CRC Checksum */ + uint8_t ih_os; /* Operating System */ + uint8_t ih_arch; /* CPU architecture */ + uint8_t ih_type; /* Image Type */ + uint8_t ih_comp; /* Compression Type */ + uint8_t ih_name[IH_NMLEN]; /* Image Name */ +} image_header_t; + +/* beyond the image end, size not known in advance */ +extern unsigned char workspace[]; +extern void board_init(void); + +static CLzmaDecoderState lzma_state; +static unsigned char *lzma_data; +static unsigned long lzma_datasize; +static unsigned long lzma_outsize; +static unsigned long kernel_la; + +#ifdef CONFIG_KERNEL_CMDLINE +#define kernel_argc 1 +static const char kernel_cmdline[] = CONFIG_KERNEL_CMDLINE; +static const char *kernel_argv[] = { + kernel_cmdline, + NULL, +}; +#endif /* CONFIG_KERNEL_CMDLINE */ + +static void halt(void) +{ + printf("\nSystem halted!\n"); + for(;;); +} + +static __inline__ unsigned long get_be32(void *buf) +{ + unsigned char *p = buf; + + return (((unsigned long) p[0] << 24) + + ((unsigned long) p[1] << 16) + + ((unsigned long) p[2] << 8) + + (unsigned long) p[3]); +} + +static __inline__ unsigned char lzma_get_byte(void) +{ + unsigned char c; + + lzma_datasize--; + c = *lzma_data++; + + return c; +} + +static int lzma_init_props(void) +{ + unsigned char props[LZMA_PROPERTIES_SIZE]; + int res; + int i; + + /* read lzma properties */ + for (i = 0; i < LZMA_PROPERTIES_SIZE; i++) + props[i] = lzma_get_byte(); + + /* read the lower half of uncompressed size in the header */ + lzma_outsize = ((SizeT) lzma_get_byte()) + + ((SizeT) lzma_get_byte() << 8) + + ((SizeT) lzma_get_byte() << 16) + + ((SizeT) lzma_get_byte() << 24); + + /* skip rest of the header (upper half of uncompressed size) */ + for (i = 0; i < 4; i++) + lzma_get_byte(); + + res = LzmaDecodeProperties(&lzma_state.Properties, props, + LZMA_PROPERTIES_SIZE); + return res; +} + +static int lzma_decompress(unsigned char *outStream) +{ + SizeT ip, op; + int ret; + + lzma_state.Probs = (CProb *) workspace; + + ret = LzmaDecode(&lzma_state, lzma_data, lzma_datasize, &ip, outStream, + lzma_outsize, &op); + + if (ret != LZMA_RESULT_OK) { + int i; + + DBG("LzmaDecode error %d at %08x, osize:%d ip:%d op:%d\n", + ret, lzma_data + ip, lzma_outsize, ip, op); + + for (i = 0; i < 16; i++) + DBG("%02x ", lzma_data[ip + i]); + + DBG("\n"); + } + + return ret; +} + +#if (LZMA_WRAPPER) +static void lzma_init_data(void) +{ + extern unsigned char _lzma_data_start[]; + extern unsigned char _lzma_data_end[]; + + kernel_la = LOADADDR; + lzma_data = _lzma_data_start; + lzma_datasize = _lzma_data_end - _lzma_data_start; +} +#else +static void lzma_init_data(void) +{ + struct image_header *hdr = NULL; + unsigned char *flash_base; + unsigned long flash_ofs; + unsigned long kernel_ofs; + unsigned long kernel_size; + + flash_base = (unsigned char *) KSEG1ADDR(AR71XX_FLASH_START); + + printf("Looking for OpenWrt image... "); + + for (flash_ofs = CONFIG_FLASH_OFFS; + flash_ofs <= (CONFIG_FLASH_OFFS + CONFIG_FLASH_MAX); + flash_ofs += CONFIG_FLASH_STEP) { + unsigned long magic; + unsigned char *p; + + p = flash_base + flash_ofs; + magic = get_be32(p); + if (magic == IH_MAGIC_OKLI) { + hdr = (struct image_header *) p; + break; + } + } + + if (hdr == NULL) { + printf("not found!\n"); + halt(); + } + + printf("found at 0x%08x\n", flash_base + flash_ofs); + + kernel_ofs = sizeof(struct image_header); + kernel_size = get_be32(&hdr->ih_size); + kernel_la = get_be32(&hdr->ih_load); + + lzma_data = flash_base + flash_ofs + kernel_ofs; + lzma_datasize = kernel_size; +} +#endif /* (LZMA_WRAPPER) */ + +void loader_main(unsigned long reg_a0, unsigned long reg_a1, + unsigned long reg_a2, unsigned long reg_a3) +{ + void (*kernel_entry) (unsigned long, unsigned long, unsigned long, + unsigned long); + int res; + + board_init(); + + printf("\n\nOpenWrt kernel loader for MIPS based SoC\n"); + printf("Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>\n"); + + lzma_init_data(); + + res = lzma_init_props(); + if (res != LZMA_RESULT_OK) { + printf("Incorrect LZMA stream properties!\n"); + halt(); + } + + printf("Decompressing kernel... "); + + res = lzma_decompress((unsigned char *) kernel_la); + if (res != LZMA_RESULT_OK) { + printf("failed, "); + switch (res) { + case LZMA_RESULT_DATA_ERROR: + printf("data error!\n"); + break; + default: + printf("unknown error %d!\n", res); + } + halt(); + } else { + printf("done!\n"); + } + + flush_cache(kernel_la, lzma_outsize); + + printf("Starting kernel at %08x...\n\n", kernel_la); + +#ifdef CONFIG_KERNEL_CMDLINE + reg_a0 = kernel_argc; + reg_a1 = (unsigned long) kernel_argv; + reg_a2 = 0; + reg_a3 = 0; +#endif + + kernel_entry = (void *) kernel_la; + kernel_entry(reg_a0, reg_a1, reg_a2, reg_a3); +} diff --git a/target/linux/ramips/image/lzma-loader/src/loader.lds b/target/linux/ramips/image/lzma-loader/src/loader.lds new file mode 100644 index 0000000..80cc7ca --- /dev/null +++ b/target/linux/ramips/image/lzma-loader/src/loader.lds @@ -0,0 +1,35 @@ +OUTPUT_ARCH(mips) +SECTIONS { + .text : { + _code_start = .; + *(.text) + *(.text.*) + *(.rodata) + *(.rodata.*) + *(.data.lzma) + } + + . = ALIGN(32); + .data : { + *(.data) + *(.data.*) + . = . + 524288; /* workaround for buggy bootloaders */ + } + + . = ALIGN(32); + _code_end = .; + + _bss_start = .; + .bss : { + *(.bss) + *(.bss.*) + } + + . = ALIGN(32); + _bss_end = .; + + . = . + 8192; + _stack = .; + + workspace = .; +} diff --git a/target/linux/ramips/image/lzma-loader/src/loader2.lds b/target/linux/ramips/image/lzma-loader/src/loader2.lds new file mode 100644 index 0000000..db0bb46 --- /dev/null +++ b/target/linux/ramips/image/lzma-loader/src/loader2.lds @@ -0,0 +1,10 @@ +OUTPUT_ARCH(mips) +SECTIONS { + .text : { + startup = .; + *(.text) + *(.text.*) + *(.data) + *(.data.*) + } +} diff --git a/target/linux/ramips/image/lzma-loader/src/lzma-data.lds b/target/linux/ramips/image/lzma-loader/src/lzma-data.lds new file mode 100644 index 0000000..abf756b --- /dev/null +++ b/target/linux/ramips/image/lzma-loader/src/lzma-data.lds @@ -0,0 +1,8 @@ +OUTPUT_ARCH(mips) +SECTIONS { + .data.lzma : { + _lzma_data_start = .; + *(.data) + _lzma_data_end = .; + } +} diff --git a/target/linux/ramips/image/lzma-loader/src/printf.c b/target/linux/ramips/image/lzma-loader/src/printf.c new file mode 100644 index 0000000..7bb5a86 --- /dev/null +++ b/target/linux/ramips/image/lzma-loader/src/printf.c @@ -0,0 +1,350 @@ +/* + * Copyright (C) 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include "printf.h" + +extern void board_putc(int ch); + +/* this is the maximum width for a variable */ +#define LP_MAX_BUF 256 + +/* macros */ +#define IsDigit(x) ( ((x) >= '0') && ((x) <= '9') ) +#define Ctod(x) ( (x) - '0') + +/* forward declaration */ +static int PrintChar(char *, char, int, int); +static int PrintString(char *, char *, int, int); +static int PrintNum(char *, unsigned long, int, int, int, int, char, int); + +/* private variable */ +static const char theFatalMsg[] = "fatal error in lp_Print!"; + +/* -*- + * A low level printf() function. + */ +static void +lp_Print(void (*output)(void *, char *, int), + void * arg, + char *fmt, + va_list ap) +{ + +#define OUTPUT(arg, s, l) \ + { if (((l) < 0) || ((l) > LP_MAX_BUF)) { \ + (*output)(arg, (char*)theFatalMsg, sizeof(theFatalMsg)-1); for(;;); \ + } else { \ + (*output)(arg, s, l); \ + } \ + } + + char buf[LP_MAX_BUF]; + + char c; + char *s; + long int num; + + int longFlag; + int negFlag; + int width; + int prec; + int ladjust; + char padc; + + int length; + + for(;;) { + { + /* scan for the next '%' */ + char *fmtStart = fmt; + while ( (*fmt != '\0') && (*fmt != '%')) { + fmt ++; + } + + /* flush the string found so far */ + OUTPUT(arg, fmtStart, fmt-fmtStart); + + /* are we hitting the end? */ + if (*fmt == '\0') break; + } + + /* we found a '%' */ + fmt ++; + + /* check for long */ + if (*fmt == 'l') { + longFlag = 1; + fmt ++; + } else { + longFlag = 0; + } + + /* check for other prefixes */ + width = 0; + prec = -1; + ladjust = 0; + padc = ' '; + + if (*fmt == '-') { + ladjust = 1; + fmt ++; + } + + if (*fmt == '0') { + padc = '0'; + fmt++; + } + + if (IsDigit(*fmt)) { + while (IsDigit(*fmt)) { + width = 10 * width + Ctod(*fmt++); + } + } + + if (*fmt == '.') { + fmt ++; + if (IsDigit(*fmt)) { + prec = 0; + while (IsDigit(*fmt)) { + prec = prec*10 + Ctod(*fmt++); + } + } + } + + + /* check format flag */ + negFlag = 0; + switch (*fmt) { + case 'b': + if (longFlag) { + num = va_arg(ap, long int); + } else { + num = va_arg(ap, int); + } + length = PrintNum(buf, num, 2, 0, width, ladjust, padc, 0); + OUTPUT(arg, buf, length); + break; + + case 'd': + case 'D': + if (longFlag) { + num = va_arg(ap, long int); + } else { + num = va_arg(ap, int); + } + if (num < 0) { + num = - num; + negFlag = 1; + } + length = PrintNum(buf, num, 10, negFlag, width, ladjust, padc, 0); + OUTPUT(arg, buf, length); + break; + + case 'o': + case 'O': + if (longFlag) { + num = va_arg(ap, long int); + } else { + num = va_arg(ap, int); + } + length = PrintNum(buf, num, 8, 0, width, ladjust, padc, 0); + OUTPUT(arg, buf, length); + break; + + case 'u': + case 'U': + if (longFlag) { + num = va_arg(ap, long int); + } else { + num = va_arg(ap, int); + } + length = PrintNum(buf, num, 10, 0, width, ladjust, padc, 0); + OUTPUT(arg, buf, length); + break; + + case 'x': + if (longFlag) { + num = va_arg(ap, long int); + } else { + num = va_arg(ap, int); + } + length = PrintNum(buf, num, 16, 0, width, ladjust, padc, 0); + OUTPUT(arg, buf, length); + break; + + case 'X': + if (longFlag) { + num = va_arg(ap, long int); + } else { + num = va_arg(ap, int); + } + length = PrintNum(buf, num, 16, 0, width, ladjust, padc, 1); + OUTPUT(arg, buf, length); + break; + + case 'c': + c = (char)va_arg(ap, int); + length = PrintChar(buf, c, width, ladjust); + OUTPUT(arg, buf, length); + break; + + case 's': + s = (char*)va_arg(ap, char *); + length = PrintString(buf, s, width, ladjust); + OUTPUT(arg, buf, length); + break; + + case '\0': + fmt --; + break; + + default: + /* output this char as it is */ + OUTPUT(arg, fmt, 1); + } /* switch (*fmt) */ + + fmt ++; + } /* for(;;) */ + + /* special termination call */ + OUTPUT(arg, "\0", 1); +} + + +/* --------------- local help functions --------------------- */ +static int +PrintChar(char * buf, char c, int length, int ladjust) +{ + int i; + + if (length < 1) length = 1; + if (ladjust) { + *buf = c; + for (i=1; i< length; i++) buf[i] = ' '; + } else { + for (i=0; i< length-1; i++) buf[i] = ' '; + buf[length - 1] = c; + } + return length; +} + +static int +PrintString(char * buf, char* s, int length, int ladjust) +{ + int i; + int len=0; + char* s1 = s; + while (*s1++) len++; + if (length < len) length = len; + + if (ladjust) { + for (i=0; i< len; i++) buf[i] = s[i]; + for (i=len; i< length; i++) buf[i] = ' '; + } else { + for (i=0; i< length-len; i++) buf[i] = ' '; + for (i=length-len; i < length; i++) buf[i] = s[i-length+len]; + } + return length; +} + +static int +PrintNum(char * buf, unsigned long u, int base, int negFlag, + int length, int ladjust, char padc, int upcase) +{ + /* algorithm : + * 1. prints the number from left to right in reverse form. + * 2. fill the remaining spaces with padc if length is longer than + * the actual length + * TRICKY : if left adjusted, no "0" padding. + * if negtive, insert "0" padding between "0" and number. + * 3. if (!ladjust) we reverse the whole string including paddings + * 4. otherwise we only reverse the actual string representing the num. + */ + + int actualLength =0; + char *p = buf; + int i; + + do { + int tmp = u %base; + if (tmp <= 9) { + *p++ = '0' + tmp; + } else if (upcase) { + *p++ = 'A' + tmp - 10; + } else { + *p++ = 'a' + tmp - 10; + } + u /= base; + } while (u != 0); + + if (negFlag) { + *p++ = '-'; + } + + /* figure out actual length and adjust the maximum length */ + actualLength = p - buf; + if (length < actualLength) length = actualLength; + + /* add padding */ + if (ladjust) { + padc = ' '; + } + if (negFlag && !ladjust && (padc == '0')) { + for (i = actualLength-1; i< length-1; i++) buf[i] = padc; + buf[length -1] = '-'; + } else { + for (i = actualLength; i< length; i++) buf[i] = padc; + } + + + /* prepare to reverse the string */ + { + int begin = 0; + int end; + if (ladjust) { + end = actualLength - 1; + } else { + end = length -1; + } + + while (end > begin) { + char tmp = buf[begin]; + buf[begin] = buf[end]; + buf[end] = tmp; + begin ++; + end --; + } + } + + /* adjust the string pointer */ + return length; +} + +static void printf_output(void *arg, char *s, int l) +{ + int i; + + // special termination call + if ((l==1) && (s[0] == '\0')) return; + + for (i=0; i< l; i++) { + board_putc(s[i]); + if (s[i] == '\n') board_putc('\r'); + } +} + +void printf(char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + lp_Print(printf_output, 0, fmt, ap); + va_end(ap); +} diff --git a/target/linux/ramips/image/lzma-loader/src/printf.h b/target/linux/ramips/image/lzma-loader/src/printf.h new file mode 100644 index 0000000..9b1c1df --- /dev/null +++ b/target/linux/ramips/image/lzma-loader/src/printf.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef _printf_h_ +#define _printf_h_ + +#include <stdarg.h> +void printf(char *fmt, ...); + +#endif /* _printf_h_ */ diff --git a/target/linux/ramips/image/lzma-loader/src/ralink.mk b/target/linux/ramips/image/lzma-loader/src/ralink.mk new file mode 100644 index 0000000..3ff5fdd --- /dev/null +++ b/target/linux/ramips/image/lzma-loader/src/ralink.mk @@ -0,0 +1 @@ +CACHE_FLAGS+=-DCONFIG_ICACHE_SIZE="(32 * 1024)" -DCONFIG_DCACHE_SIZE="(16 * 1024)" -DCONFIG_CACHELINE_SIZE=32 diff --git a/target/linux/ramips/modules.mk b/target/linux/ramips/modules.mk new file mode 100644 index 0000000..bfb9bcd --- /dev/null +++ b/target/linux/ramips/modules.mk @@ -0,0 +1,102 @@ +# +# Copyright (C) 2006-2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +OTHER_MENU:=Other modules +define KernelPackage/sdhci-mt7620 + SUBMENU:=Other modules + TITLE:=MT7620 SDCI + DEPENDS:=@(TARGET_ramips_mt7620||TARGET_ramips_mt7628||TARGET_ramips_mt7621||TARGET_ramips_mt7688) +kmod-sdhci + KCONFIG:= \ + CONFIG_MTK_MMC \ + CONFIG_MTK_AEE_KDUMP=n \ + CONFIG_MTK_MMC_CD_POLL=n + FILES:= \ + $(LINUX_DIR)/drivers/mmc/host/mtk-mmc/mtk_sd.ko + AUTOLOAD:=$(call AutoProbe,mtk_sd,1) +endef + +$(eval $(call KernelPackage,sdhci-mt7620)) + +I2C_RALINK_MODULES:= \ + CONFIG_I2C_RALINK:drivers/i2c/busses/i2c-ralink + +define KernelPackage/i2c-ralink + $(call i2c_defaults,$(I2C_RALINK_MODULES),59) + TITLE:=Ralink I2C Controller + DEPENDS:=@TARGET_ramips @(!TARGET_ramips_mt7621) kmod-i2c-core +endef + +define KernelPackage/i2c-ralink/description + Kernel modules for enable ralink i2c controller. +endef + +$(eval $(call KernelPackage,i2c-ralink)) + + +I2C_MT7621_MODULES:= \ + CONFIG_I2C_MT7621:drivers/i2c/busses/i2c-mt7621 + +define KernelPackage/i2c-mt7621 + $(call i2c_defaults,$(I2C_MT7621_MODULES),59) + TITLE:=MT7621 I2C Controller + DEPENDS:=@TARGET_ramips @TARGET_ramips_mt7621 kmod-i2c-core +endef + +define KernelPackage/i2c-mt7621/description + Kernel modules for enable mt7621 i2c controller. +endef + +$(eval $(call KernelPackage,i2c-mt7621)) + + + +define KernelPackage/sound-mt7620 + TITLE:=MT7620 PCM/I2S Alsa Driver + DEPENDS:=@TARGET_ramips_mt7620 +kmod-sound-soc-core +kmod-regmap @BROKEN + KCONFIG:= \ + CONFIG_SND_MT7620_SOC_I2S \ + CONFIG_SND_MT7620_SOC_WM8960 + FILES:= \ + $(LINUX_DIR)/sound/soc/ralink/snd-soc-mt7620-i2s.ko \ + $(LINUX_DIR)/sound/soc/ralink/snd-soc-mt7620-wm8960.ko \ + $(LINUX_DIR)/sound/soc/codecs/snd-soc-wm8960.ko + AUTOLOAD:=$(call AutoLoad,90,snd-soc-wm8960 snd-soc-mt7620-i2s snd-soc-mt7620-wm8960) + $(call AddDepends/sound) +endef + +define KernelPackage/sound-mt7620/description + Alsa modules for ralink i2s controller. +endef + +$(eval $(call KernelPackage,sound-mt7620)) + + +define KernelPackage/sound-mtk + TITLE:=Mediatek I2S Alsa Driver + DEPENDS:= +kmod-sound-soc-core +kmod-regmap +kmod-i2c-ralink @(TARGET_ramips_mt7628||TARGET_ramips_mt7688||TARGET_ramips_mt7620) + KCONFIG:= \ + CONFIG_SND_MT76XX_SOC \ + CONFIG_SND_MT76XX_I2S \ + CONFIG_SND_MT76XX_PCM \ + CONFIG_SND_SOC_WM8960 + FILES:= \ + $(LINUX_DIR)/sound/soc/mtk/ralink_gdma.ko \ + $(LINUX_DIR)/sound/soc/mtk/snd-soc-mt76xx-i2s-ctl.ko \ + $(LINUX_DIR)/sound/soc/mtk/snd-soc-mt76xx-i2s.ko \ + $(LINUX_DIR)/sound/soc/mtk/snd-soc-mt76xx-pcm.ko \ + $(LINUX_DIR)/sound/soc/mtk/snd-soc-mt76xx-machine.ko \ + $(LINUX_DIR)/sound/soc/mtk/i2c_wm8960.ko \ + $(LINUX_DIR)/sound/soc/codecs/snd-soc-wm8960.ko + AUTOLOAD:=$(call AutoLoad,90,ralink_gdma snd-soc-wm8960 i2c_wm8960 snd-soc-mt76xx-i2s-ctl snd-soc-mt76xx-i2s snd-soc-mt76xx-pcm snd-soc-mt76xx-machine) + $(call AddDepends/sound) +endef + +define KernelPackage/sound-mtk/description + Alsa modules for ralink i2s controller. +endef + +$(eval $(call KernelPackage,sound-mtk)) diff --git a/target/linux/ramips/mt7620/config-3.18 b/target/linux/ramips/mt7620/config-3.18 new file mode 100644 index 0000000..5dbfaa2 --- /dev/null +++ b/target/linux/ramips/mt7620/config-3.18 @@ -0,0 +1,189 @@ +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_ARCH_DISCARD_MEMBLOCK=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +# CONFIG_ARCH_HAS_SG_CHAIN is not set +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_AT803X_PHY=y +CONFIG_ICPLUS_PHY=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_CEVT_R4K=y +CONFIG_CLKDEV_LOOKUP=y +CONFIG_CLKEVT_RT3352=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLKSRC_OF=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMDLINE="rootfstype=squashfs,jffs2" +CONFIG_CMDLINE_BOOL=y +# CONFIG_CMDLINE_OVERRIDE is not set +CONFIG_CPU_GENERIC_DUMP_TLB=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS32_R1 is not set +CONFIG_CPU_MIPS32_R2=y +CONFIG_CPU_MIPSR2=y +CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y +CONFIG_CPU_R4K_CACHE_TLB=y +CONFIG_CPU_R4K_FPU=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_CPU_SUPPORTS_MSA=y +CONFIG_CSRC_R4K=y +CONFIG_DEBUG_PINCTRL=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_DTB_MT7620A_EVAL is not set +# CONFIG_DTB_MT7628AN_EVAL is not set +CONFIG_DTB_RT_NONE=y +CONFIG_DTC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_ATOMIC64=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_IO=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +# CONFIG_GPIO_MT7621 is not set +CONFIG_GPIO_RALINK=y +CONFIG_GPIO_SYSFS=y +CONFIG_HARDWARE_WATCHPOINTS=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_HAVE_BPF_JIT=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_HAVE_DEBUG_KMEMLEAK=y +CONFIG_HAVE_DEBUG_STACKOVERFLOW=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_IDE=y +CONFIG_HAVE_KVM=y +CONFIG_HAVE_MACH_CLKDEV=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MEMBLOCK_NODE_MAP=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_HAVE_NET_DSA=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HW_HAS_PCI=y +CONFIG_HZ_PERIODIC=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQCHIP=y +CONFIG_IRQ_CPU=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_INTC=y +CONFIG_IRQ_WORK=y +CONFIG_LIBFDT=y +CONFIG_MDIO_BOARDINFO=y +CONFIG_MIPS=y +# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_MIPS_MACHINE is not set +CONFIG_MODULES_USE_ELF_REL=y +# CONFIG_MT7621_WDT is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_M25P80=y +CONFIG_MTD_NAND_MT7620=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_TPLINK_FW=y +CONFIG_MTD_SPLIT_UIMAGE_FW=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_PER_CPU_KM=y +CONFIG_NET_RALINK=y +CONFIG_NET_RALINK_GSW_MT7620=y +CONFIG_NET_RALINK_MDIO=y +CONFIG_NET_RALINK_MT7620=y +# CONFIG_NET_RALINK_RT305X is not set +CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y +# CONFIG_NO_IOPORT_MAP is not set +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_ADDRESS_PCI=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y +CONFIG_OF_NET=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PHYLIB=y +CONFIG_PHY_RALINK_USB=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_RT2880=y +# CONFIG_PINCTRL_SINGLE is not set +# CONFIG_PREEMPT_RCU is not set +CONFIG_RALINK=y +# CONFIG_RALINK_ILL_ACC is not set +CONFIG_RALINK_USBPHY=y +CONFIG_RALINK_WDT=y +# CONFIG_RCU_STALL_COMMON is not set +CONFIG_RESET_CONTROLLER=y +# CONFIG_SCSI_DMA is not set +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RT288X=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +CONFIG_SOC_MT7620=y +# CONFIG_SOC_MT7621 is not set +# CONFIG_SOC_RT288X is not set +# CONFIG_SOC_RT305X is not set +# CONFIG_SOC_RT3883 is not set +CONFIG_SND_MT76XX_SOC_MT7620=y +# CONFIG_SND_MT76XX_SOC_MT7628 is not set +CONFIG_SPI=y +CONFIG_SPI_MASTER=y +# CONFIG_SPI_MT7621 is not set +CONFIG_SPI_RT2880=y +CONFIG_SWCONFIG=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_SYS_HAS_CPU_MIPS32_R2=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_MIPS16=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_USB_PHY=y +CONFIG_USB_SUPPORT=y +CONFIG_USE_OF=y +CONFIG_WATCHDOG_CORE=y +CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/ramips/mt7620/profiles/00-default.mk b/target/linux/ramips/mt7620/profiles/00-default.mk new file mode 100644 index 0000000..6c7d721 --- /dev/null +++ b/target/linux/ramips/mt7620/profiles/00-default.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2011 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 + PACKAGES:=\ + kmod-usb-core kmod-usb2 kmod-usb-ohci \ + kmod-ledtrig-usbdev +endef + +define Profile/Default/Description + Default package set compatible with most boards. +endef +$(eval $(call Profile,Default)) diff --git a/target/linux/ramips/mt7620/profiles/aigale.mk b/target/linux/ramips/mt7620/profiles/aigale.mk new file mode 100644 index 0000000..629a378 --- /dev/null +++ b/target/linux/ramips/mt7620/profiles/aigale.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/AI-BR100 + NAME:=Aigale Ai-BR100 + PACKAGES:=kmod-usb-ohci kmod-usb2 +endef + +define Profile/AI-BR100/Description + Default package set for Aigale Ai-BR100. +endef +$(eval $(call Profile,AI-BR100)) diff --git a/target/linux/ramips/mt7620/profiles/dovado.mk b/target/linux/ramips/mt7620/profiles/dovado.mk new file mode 100644 index 0000000..34bc74a --- /dev/null +++ b/target/linux/ramips/mt7620/profiles/dovado.mk @@ -0,0 +1,17 @@ +# +# Copyright (C) 2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/TINY-AC + NAME:=Dovado Tiny AC + PACKAGES:=\ + kmod-usb-core kmod-usb2 kmod-usb-ohci +endef + +define Profile/TINY-AC/Description + Support for Dovado Tiny AC router +endef +$(eval $(call Profile,TINY-AC)) diff --git a/target/linux/ramips/mt7620/profiles/hiwifi.mk b/target/linux/ramips/mt7620/profiles/hiwifi.mk new file mode 100644 index 0000000..5baa85a --- /dev/null +++ b/target/linux/ramips/mt7620/profiles/hiwifi.mk @@ -0,0 +1,47 @@ +# +# Copyright (C) 2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/HC5661 + NAME:=HiWiFi HC5661 + PACKAGES:=\ + kmod-usb-core kmod-usb-dwc2 kmod-usb2 \ + kmod-mmc-spi kmod-sdhci kmod-sdhci-mt7620 \ + kmod-ledtrig-usbdev +endef + +define Profile/HC5661/Description + Support HiWiFi HC5661 model(J1S) +endef +$(eval $(call Profile,HC5661)) + + +define Profile/HC5761 + NAME:=HiWiFi HC5761 + PACKAGES:=\ + kmod-usb-core kmod-usb-dwc2 kmod-usb2 \ + kmod-mmc-spi kmod-sdhci kmod-sdhci-mt7620 \ + kmod-ledtrig-usbdev +endef + +define Profile/HC5761/Description + Support HiWiFi HC5761 model(J2) +endef +$(eval $(call Profile,HC5761)) + + +define Profile/HC5861 + NAME:=HiWiFi HC5861 + PACKAGES:=\ + kmod-usb-core kmod-usb-dwc2 kmod-usb2 \ + kmod-mmc-spi kmod-sdhci kmod-sdhci-mt7620 \ + kmod-ledtrig-usbdev +endef + +define Profile/HC5861/Description + Support HiWiFi HC5861 model(J3) +endef +$(eval $(call Profile,HC5861)) diff --git a/target/linux/ramips/mt7620/profiles/linksys.mk b/target/linux/ramips/mt7620/profiles/linksys.mk new file mode 100644 index 0000000..d8a2df4 --- /dev/null +++ b/target/linux/ramips/mt7620/profiles/linksys.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/E1700 + NAME:=Linksys E1700 + PACKAGES:=swconfig +endef + +define Profile/E1700/Description + Package set compatible with the Linksys E1700. +endef +$(eval $(call Profile,E1700)) diff --git a/target/linux/ramips/mt7620/profiles/mediatek.mk b/target/linux/ramips/mt7620/profiles/mediatek.mk new file mode 100644 index 0000000..4f6703e --- /dev/null +++ b/target/linux/ramips/mt7620/profiles/mediatek.mk @@ -0,0 +1,15 @@ +# +# Copyright (C) 2011 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/MT7620a + NAME:=MT7620a EVB +endef + +define Profile/MT7620a/Description + Default package set compatible with MT7620a eval board +endef +$(eval $(call Profile,MT7620a)) diff --git a/target/linux/ramips/mt7620/profiles/microduino.mk b/target/linux/ramips/mt7620/profiles/microduino.mk new file mode 100644 index 0000000..b68a269 --- /dev/null +++ b/target/linux/ramips/mt7620/profiles/microduino.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/MicroWRT + NAME:=Microduino MicroWRT + PACKAGES:= kmod-usb-core kmod-usb2 kmod-usb-ohci +endef + +define Profile/MicroWRT/Description + Package set compatible with MicroWRT +endef +$(eval $(call Profile,MicroWRT)) diff --git a/target/linux/ramips/mt7620/profiles/xiaomi.mk b/target/linux/ramips/mt7620/profiles/xiaomi.mk new file mode 100644 index 0000000..8483578 --- /dev/null +++ b/target/linux/ramips/mt7620/profiles/xiaomi.mk @@ -0,0 +1,17 @@ +# +# Copyright (C) 2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/MIWIFI-MINI + NAME:=Xiaomi MiWiFi Mini + PACKAGES:=\ + kmod-usb-core kmod-usb-dwc2 kmod-usb2 kmod-usb-ohci +endef + +define Profile/MIWIFI-MINI/Description + Support for Xiaomi MiWiFi Mini routers +endef +$(eval $(call Profile,MIWIFI-MINI)) diff --git a/target/linux/ramips/mt7620/target.mk b/target/linux/ramips/mt7620/target.mk new file mode 100644 index 0000000..99763b0 --- /dev/null +++ b/target/linux/ramips/mt7620/target.mk @@ -0,0 +1,17 @@ +# +# Copyright (C) 2009 OpenWrt.org +# + +SUBTARGET:=mt7620 +BOARDNAME:=MT7620 based boards +ARCH_PACKAGES:=ramips_24kec +FEATURES+=usb +CPU_TYPE:=24kec +CPU_SUBTYPE:=dsp + +DEFAULT_PACKAGES += kmod-rt2800-pci kmod-rt2800-soc kmod-mt76 + +define Target/Description + Build firmware images for Ralink MT7620 based boards. +endef + diff --git a/target/linux/ramips/mt7621/config-3.18 b/target/linux/ramips/mt7621/config-3.18 new file mode 100644 index 0000000..fb05d1e --- /dev/null +++ b/target/linux/ramips/mt7621/config-3.18 @@ -0,0 +1,217 @@ +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_ARCH_DISCARD_MEMBLOCK=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +# CONFIG_ARCH_HAS_SG_CHAIN is not set +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_BOARD_SCACHE=y +CONFIG_BOUNCE=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_CEVT_GIC is not set +CONFIG_CEVT_R4K=y +# CONFIG_CEVT_SYSTICK_QUIRK is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMDLINE="rootfstype=squashfs,jffs2" +CONFIG_CMDLINE_BOOL=y +# CONFIG_CMDLINE_OVERRIDE is not set +CONFIG_CPU_GENERIC_DUMP_TLB=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS32_R1 is not set +CONFIG_CPU_MIPS32_R2=y +CONFIG_CPU_MIPSR2=y +CONFIG_CPU_MIPSR2_IRQ_EI=y +CONFIG_CPU_MIPSR2_IRQ_VI=y +CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y +CONFIG_CPU_R4K_CACHE_TLB=y +CONFIG_CPU_R4K_FPU=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_CPU_SUPPORTS_MSA=y +CONFIG_CSRC_R4K=y +CONFIG_DEBUG_PINCTRL=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_DTB_MT7621_EVAL is not set +CONFIG_DTB_RT_NONE=y +CONFIG_DTC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_ATOMIC64=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_IO=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_GPIO_MT7621=y +# CONFIG_GPIO_RALINK is not set +CONFIG_GPIO_SYSFS=y +CONFIG_HARDWARE_WATCHPOINTS=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_HAVE_BPF_JIT=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_HAVE_DEBUG_KMEMLEAK=y +CONFIG_HAVE_DEBUG_STACKOVERFLOW=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_IDE=y +CONFIG_HAVE_KVM=y +CONFIG_HAVE_MACH_CLKDEV=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MEMBLOCK_NODE_MAP=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_HAVE_NET_DSA=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HIGHMEM=y +CONFIG_HW_HAS_PCI=y +CONFIG_HZ_PERIODIC=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQCHIP=y +CONFIG_IRQ_CPU=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_GIC=y +CONFIG_IRQ_WORK=y +CONFIG_LIBFDT=y +CONFIG_MDIO_BOARDINFO=y +CONFIG_MIPS=y +CONFIG_MIPS_CM=y +CONFIG_MIPS_CMP=y +CONFIG_MIPS_CPU_SCACHE=y +CONFIG_MIPS_GIC_IPI=y +# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set +CONFIG_MIPS_L1_CACHE_SHIFT=6 +CONFIG_MIPS_L1_CACHE_SHIFT_6=y +# CONFIG_MIPS_MACHINE is not set +CONFIG_MIPS_MT=y +CONFIG_MIPS_MT_FPAFF=y +CONFIG_MIPS_MT_SMP=y +CONFIG_MIPS_PERF_SHARED_TC_COUNTERS=y +# CONFIG_MIPS_VPE_LOADER is not set +# CONFIG_MTK_MTD_NAND is not set +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MT7621_WDT=y +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_M25P80=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_SEAMA_FW=y +CONFIG_MTD_SPLIT_TRX_FW=y +CONFIG_MTD_SPLIT_UIMAGE_FW=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_RALINK=y +CONFIG_NET_RALINK_GSW_MT7620=y +CONFIG_NET_RALINK_MDIO=y +CONFIG_NET_RALINK_MT7620=y +CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y +# CONFIG_NO_IOPORT_MAP is not set +CONFIG_NR_CPUS=4 +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_ADDRESS_PCI=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y +CONFIG_OF_NET=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_PCI=y +CONFIG_PCI_DISABLE_COMMON_QUIRKS=y +CONFIG_PCI_DOMAINS=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PHYLIB=y +# CONFIG_PHY_RALINK_USB is not set +CONFIG_PINCTRL=y +CONFIG_PINCTRL_RT2880=y +# CONFIG_PINCTRL_SINGLE is not set +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO=y +# CONFIG_POWER_RESET_GPIO_RESTART is not set +# CONFIG_POWER_RESET_LTC2952 is not set +# CONFIG_POWER_RESET_SYSCON is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_PREEMPT_RCU is not set +CONFIG_RALINK=y +# CONFIG_RALINK_WDT is not set +CONFIG_RCU_STALL_COMMON=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RFS_ACCEL=y +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +CONFIG_SCHED_SMT=y +# CONFIG_SCSI_DMA is not set +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +CONFIG_SLUB_CPU_PARTIAL=y +CONFIG_SMP=y +CONFIG_SMP_UP=y +# CONFIG_SOC_MT7620 is not set +CONFIG_SOC_MT7621=y +# CONFIG_SOC_RT288X is not set +# CONFIG_SOC_RT305X is not set +# CONFIG_SOC_RT3883 is not set +CONFIG_SPI=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MT7621=y +# CONFIG_SPI_RT2880 is not set +CONFIG_STOP_MACHINE=y +CONFIG_SWCONFIG=y +CONFIG_SYNC_R4K=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_SYS_HAS_CPU_MIPS32_R2=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_SYS_SUPPORTS_HIGHMEM=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_MIPS16=y +CONFIG_SYS_SUPPORTS_MIPS_CMP=y +CONFIG_SYS_SUPPORTS_MULTITHREADING=y +CONFIG_SYS_SUPPORTS_SCHED_SMT=y +CONFIG_SYS_SUPPORTS_SMP=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TREE_RCU=y +CONFIG_USB_SUPPORT=y +CONFIG_USE_OF=y +CONFIG_WATCHDOG_CORE=y +CONFIG_WEAK_ORDERING=y +CONFIG_XPS=y +CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/ramips/mt7621/profiles/00-default.mk b/target/linux/ramips/mt7621/profiles/00-default.mk new file mode 100644 index 0000000..fb04ba7 --- /dev/null +++ b/target/linux/ramips/mt7621/profiles/00-default.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2011 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 + PACKAGES:=\ + kmod-usb-core kmod-usb3 \ + kmod-ledtrig-usbdev +endef + +define Profile/Default/Description + Default package set compatible with most boards. +endef +$(eval $(call Profile,Default)) diff --git a/target/linux/ramips/mt7621/profiles/firefly.mk b/target/linux/ramips/mt7621/profiles/firefly.mk new file mode 100644 index 0000000..bc50ab4 --- /dev/null +++ b/target/linux/ramips/mt7621/profiles/firefly.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/FIREWRT + NAME:=Firefly FireWRT + PACKAGES:=\ + kmod-usb-core kmod-usb3 kmod-usb-hid kmod-sdhci-mt7620 \ + kmod-ledtrig-usbdev +endef + +define Profile/FIREWRT/Description + Package set compatible with the Firefly FireWRT board. +endef +$(eval $(call Profile,FIREWRT)) diff --git a/target/linux/ramips/mt7621/profiles/linksys.mk b/target/linux/ramips/mt7621/profiles/linksys.mk new file mode 100644 index 0000000..fb447c9 --- /dev/null +++ b/target/linux/ramips/mt7621/profiles/linksys.mk @@ -0,0 +1,15 @@ +# +# Copyright (C) 2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/RE6500 + NAME:=Linksys RE6500 +endef + +define Profile/RE6500/Description + Package set compatible with the Linksys RE6500 board. +endef +$(eval $(call Profile,RE6500)) diff --git a/target/linux/ramips/mt7621/profiles/misc.mk b/target/linux/ramips/mt7621/profiles/misc.mk new file mode 100644 index 0000000..9db0cd5 --- /dev/null +++ b/target/linux/ramips/mt7621/profiles/misc.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/PBR-M1 + NAME:=PBR-M1 Device + FEATURES+=rtc + PACKAGES:=\ + kmod-usb-core kmod-usb3 kmod-usb-hid kmod-sdhci-mt7620 \ + kmod-ledtrig-usbdev kmod-ata-core kmod-ata-ahci \ + kmod-usb3-mt7621 kmod-rtc-pcf8563 +endef + +define Profile/PBR-M1/Description + Default package set compatible with most boards. +endef +$(eval $(call Profile,PBR-M1)) diff --git a/target/linux/ramips/mt7621/profiles/storylink.mk b/target/linux/ramips/mt7621/profiles/storylink.mk new file mode 100644 index 0000000..9ca4a2f --- /dev/null +++ b/target/linux/ramips/mt7621/profiles/storylink.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/SAP-G3200U3 + NAME:=STORYLiNK SAP-G3200U3 + PACKAGES:=\ + kmod-usb-core kmod-usb3 kmod-usb-hid \ + kmod-ledtrig-usbdev +endef + +define Profile/SAP-G3200U3/Description + Package set compatible with the STORYLiNK SAP-G3200U3 board. +endef +$(eval $(call Profile,SAP-G3200U3)) diff --git a/target/linux/ramips/mt7621/profiles/zbt.mk b/target/linux/ramips/mt7621/profiles/zbt.mk new file mode 100644 index 0000000..0134bb5 --- /dev/null +++ b/target/linux/ramips/mt7621/profiles/zbt.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/ZBT-WG2626 + NAME:=ZBT-WG2626 Device + FEATURES+=rtc + PACKAGES:=\ + kmod-usb-core kmod-usb3 kmod-sdhci-mt7620 \ + kmod-ledtrig-usbdev kmod-ata-core kmod-ata-ahci \ + kmod-usb3-mt7621 +endef + +define Profile/ZBT-WG2626/Description + Package set for ZBT-WG2626 device +endef +$(eval $(call Profile,ZBT-WG2626)) diff --git a/target/linux/ramips/mt7621/target.mk b/target/linux/ramips/mt7621/target.mk new file mode 100644 index 0000000..4e38dbd --- /dev/null +++ b/target/linux/ramips/mt7621/target.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2009 OpenWrt.org +# + +SUBTARGET:=mt7621 +BOARDNAME:=MT7621 based boards +ARCH_PACKAGES:=ramips_1004kc +FEATURES+=usb +CPU_TYPE:=1004kc +CPU_SUBTYPE:=dsp +CFLAGS:=-Os -pipe -mmt -mips32r2 -mtune=1004kc + +DEFAULT_PACKAGES += kmod-mt76 + +define Target/Description + Build firmware images for Ralink MT7621 based boards. +endef + diff --git a/target/linux/ramips/mt7628/config-3.18 b/target/linux/ramips/mt7628/config-3.18 new file mode 100644 index 0000000..9ab31ac --- /dev/null +++ b/target/linux/ramips/mt7628/config-3.18 @@ -0,0 +1,186 @@ +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_ARCH_DISCARD_MEMBLOCK=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +# CONFIG_ARCH_HAS_SG_CHAIN is not set +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_AT803X_PHY=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_CEVT_R4K=y +CONFIG_CLKDEV_LOOKUP=y +CONFIG_CLKEVT_RT3352=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLKSRC_OF=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMDLINE="rootfstype=squashfs,jffs2" +CONFIG_CMDLINE_BOOL=y +# CONFIG_CMDLINE_OVERRIDE is not set +CONFIG_CPU_GENERIC_DUMP_TLB=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS32_R1 is not set +CONFIG_CPU_MIPS32_R2=y +CONFIG_CPU_MIPSR2=y +CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y +CONFIG_CPU_R4K_CACHE_TLB=y +CONFIG_CPU_R4K_FPU=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_CPU_SUPPORTS_MSA=y +CONFIG_CSRC_R4K=y +CONFIG_DEBUG_PINCTRL=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_DTB_MT7620A_EVAL is not set +CONFIG_DTB_RT_NONE=y +CONFIG_DTC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_ATOMIC64=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_IO=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_GPIO_MT7621=y +# CONFIG_GPIO_RALINK is not set +CONFIG_GPIO_SYSFS=y +CONFIG_HARDWARE_WATCHPOINTS=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_HAVE_BPF_JIT=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_HAVE_DEBUG_KMEMLEAK=y +CONFIG_HAVE_DEBUG_STACKOVERFLOW=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_IDE=y +CONFIG_HAVE_KVM=y +CONFIG_HAVE_MACH_CLKDEV=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MEMBLOCK_NODE_MAP=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_HAVE_NET_DSA=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HW_HAS_PCI=y +CONFIG_HZ_PERIODIC=y +CONFIG_ICPLUS_PHY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQCHIP=y +CONFIG_IRQ_CPU=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_INTC=y +CONFIG_IRQ_WORK=y +CONFIG_LIBFDT=y +CONFIG_MDIO_BOARDINFO=y +CONFIG_MIPS=y +# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_MIPS_MACHINE is not set +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MT7621_WDT=y +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_M25P80=y +CONFIG_MTD_NAND_MT7620=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_UIMAGE_FW=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_PER_CPU_KM=y +CONFIG_NET_RALINK=y +CONFIG_NET_RALINK_ESW_RT3052=y +# CONFIG_NET_RALINK_MT7620 is not set +CONFIG_NET_RALINK_RT305X=y +CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y +# CONFIG_NO_IOPORT_MAP is not set +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_ADDRESS_PCI=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y +CONFIG_OF_NET=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PHYLIB=y +CONFIG_PHY_RALINK_USB=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_RT2880=y +# CONFIG_PINCTRL_SINGLE is not set +# CONFIG_PREEMPT_RCU is not set +CONFIG_RALINK=y +# CONFIG_RALINK_ILL_ACC is not set +CONFIG_RALINK_USBPHY=y +# CONFIG_RALINK_WDT is not set +# CONFIG_RCU_STALL_COMMON is not set +CONFIG_RESET_CONTROLLER=y +# CONFIG_SCSI_DMA is not set +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RT288X=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +CONFIG_SOC_MT7620=y +# CONFIG_SOC_MT7621 is not set +# CONFIG_SOC_RT288X is not set +# CONFIG_SOC_RT305X is not set +# CONFIG_SOC_RT3883 is not set +# CONFIG_SND_MT76XX_SOC_MT7620 is not set +CONFIG_SND_MT76XX_SOC_MT7628=y +CONFIG_SPI=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MT7621=y +# CONFIG_SPI_RT2880 is not set +CONFIG_SWCONFIG=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_SYS_HAS_CPU_MIPS32_R2=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_MIPS16=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_USB_PHY=y +CONFIG_USB_SUPPORT=y +CONFIG_USE_OF=y +CONFIG_WATCHDOG_CORE=y +CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/ramips/mt7628/profiles/00-default.mk b/target/linux/ramips/mt7628/profiles/00-default.mk new file mode 100644 index 0000000..6c7d721 --- /dev/null +++ b/target/linux/ramips/mt7628/profiles/00-default.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2011 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 + PACKAGES:=\ + kmod-usb-core kmod-usb2 kmod-usb-ohci \ + kmod-ledtrig-usbdev +endef + +define Profile/Default/Description + Default package set compatible with most boards. +endef +$(eval $(call Profile,Default)) diff --git a/target/linux/ramips/mt7628/target.mk b/target/linux/ramips/mt7628/target.mk new file mode 100644 index 0000000..2269721 --- /dev/null +++ b/target/linux/ramips/mt7628/target.mk @@ -0,0 +1,15 @@ +# +# Copyright (C) 2009 OpenWrt.org +# + +SUBTARGET:=mt7628 +BOARDNAME:=MT7628 based boards +ARCH_PACKAGES:=ramips_24kec +FEATURES+=usb +CPU_TYPE:=24kec +CPU_SUBTYPE:=dsp + +define Target/Description + Build firmware images for Ralink MT7628 based boards. +endef + diff --git a/target/linux/ramips/mt7688/config-3.18 b/target/linux/ramips/mt7688/config-3.18 new file mode 100644 index 0000000..27eab9a --- /dev/null +++ b/target/linux/ramips/mt7688/config-3.18 @@ -0,0 +1,192 @@ +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_ARCH_DISCARD_MEMBLOCK=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +# CONFIG_ARCH_HAS_SG_CHAIN is not set +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_AT803X_PHY=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_CEVT_R4K=y +CONFIG_CEVT_SYSTICK_QUIRK=y +CONFIG_CLKDEV_LOOKUP=y +CONFIG_CLKEVT_RT3352=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLKSRC_OF=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMDLINE="rootfstype=squashfs,jffs2" +CONFIG_CMDLINE_BOOL=y +# CONFIG_CMDLINE_OVERRIDE is not set +CONFIG_CPU_GENERIC_DUMP_TLB=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS32_R1 is not set +CONFIG_CPU_MIPS32_R2=y +CONFIG_CPU_MIPSR2=y +CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y +CONFIG_CPU_R4K_CACHE_TLB=y +CONFIG_CPU_R4K_FPU=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_CPU_SUPPORTS_MSA=y +CONFIG_CSRC_R4K=y +CONFIG_DEBUG_PINCTRL=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_DTB_MT7620A_EVAL is not set +CONFIG_DTB_RT_NONE=y +CONFIG_DTC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_ATOMIC64=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_IO=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_GPIO_MT7621=y +# CONFIG_GPIO_RALINK is not set +CONFIG_GPIO_SYSFS=y +CONFIG_HARDWARE_WATCHPOINTS=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_HAVE_BPF_JIT=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_HAVE_DEBUG_KMEMLEAK=y +CONFIG_HAVE_DEBUG_STACKOVERFLOW=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_IDE=y +CONFIG_HAVE_KVM=y +CONFIG_HAVE_MACH_CLKDEV=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MEMBLOCK_NODE_MAP=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_HAVE_NET_DSA=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HW_HAS_PCI=y +CONFIG_HZ_PERIODIC=y +CONFIG_ICPLUS_PHY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQCHIP=y +CONFIG_IRQ_CPU=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_INTC=y +CONFIG_IRQ_WORK=y +CONFIG_LIBFDT=y +CONFIG_LINKIT_BOOTSTRAP=y +CONFIG_MDIO_BOARDINFO=y +CONFIG_MIPS=y +CONFIG_MIPS_FPU_EMULATOR=y +# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_MIPS_MACHINE is not set +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MT7621_WDT=y +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_M25P80=y +CONFIG_MTD_NAND_MT7620=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_UIMAGE_FW=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_PER_CPU_KM=y +CONFIG_NET_RALINK=y +CONFIG_NET_RALINK_ESW_RT3052=y +# CONFIG_NET_RALINK_MT7620 is not set +CONFIG_NET_RALINK_RT305X=y +CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y +# CONFIG_NO_IOPORT_MAP is not set +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_ADDRESS_PCI=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y +CONFIG_OF_NET=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PHYLIB=y +CONFIG_PHY_RALINK_USB=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_RT2880=y +# CONFIG_PINCTRL_SINGLE is not set +# CONFIG_PREEMPT_RCU is not set +CONFIG_PWM=y +# CONFIG_PWM_FSL_FTM is not set +CONFIG_PWM_MEDIATEK=y +CONFIG_PWM_SYSFS=y +CONFIG_RALINK=y +# CONFIG_RALINK_WDT is not set +# CONFIG_RCU_STALL_COMMON is not set +CONFIG_RESET_CONTROLLER=y +# CONFIG_SCSI_DMA is not set +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_RT288X is not set +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +CONFIG_SOC_MT7620=y +# CONFIG_SOC_MT7621 is not set +# CONFIG_SOC_RT288X is not set +# CONFIG_SOC_RT305X is not set +# CONFIG_SOC_RT3883 is not set +# CONFIG_SND_MT76XX_SOC_MT7620 is not set +CONFIG_SND_MT76XX_SOC_MT7628=y +CONFIG_SPI=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MT7621=y +# CONFIG_SPI_RT2880 is not set +CONFIG_SPI_SPIDEV=y +CONFIG_SWCONFIG=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_SYS_HAS_CPU_MIPS32_R2=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_MIPS16=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_USB_SUPPORT=y +CONFIG_USE_OF=y +CONFIG_WATCHDOG_CORE=y +CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/ramips/mt7688/profiles/00-default.mk b/target/linux/ramips/mt7688/profiles/00-default.mk new file mode 100644 index 0000000..6c7d721 --- /dev/null +++ b/target/linux/ramips/mt7688/profiles/00-default.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2011 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 + PACKAGES:=\ + kmod-usb-core kmod-usb2 kmod-usb-ohci \ + kmod-ledtrig-usbdev +endef + +define Profile/Default/Description + Default package set compatible with most boards. +endef +$(eval $(call Profile,Default)) diff --git a/target/linux/ramips/mt7688/profiles/01-mediatek.mk b/target/linux/ramips/mt7688/profiles/01-mediatek.mk new file mode 100644 index 0000000..0e24e06 --- /dev/null +++ b/target/linux/ramips/mt7688/profiles/01-mediatek.mk @@ -0,0 +1,30 @@ +# +# Copyright (C) 2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/mt7688 + NAME:=mt7688 + PACKAGES:=\ + kmod-usb-core kmod-usb2 kmod-usb-ohci \ + kmod-ledtrig-usbdev +endef + +define Profile/mt7688/Description + Default package set compatible with most boards. +endef +$(eval $(call Profile,mt7688)) + +define Profile/LinkIt7688 + NAME:=LinkIt7688 + PACKAGES:=\ + kmod-usb-core kmod-usb2 kmod-usb-ohci \ + uboot-envtools kmod-ledtrig-netdev +endef + +define Profile/LinkIt7688/Description + Default package set compatible with LinkIt Smart7688 dev board. +endef +$(eval $(call Profile,LinkIt7688)) diff --git a/target/linux/ramips/mt7688/target.mk b/target/linux/ramips/mt7688/target.mk new file mode 100644 index 0000000..37b5ebc --- /dev/null +++ b/target/linux/ramips/mt7688/target.mk @@ -0,0 +1,15 @@ +# +# Copyright (C) 2015 OpenWrt.org +# + +SUBTARGET:=mt7688 +BOARDNAME:=MT7688 based boards +ARCH_PACKAGES:=ramips_24kec +FEATURES+=usb +CPU_TYPE:=24kec +CPU_SUBTYPE:=dsp + +define Target/Description + Build firmware images for Ralink MT7688 based boards. +endef + diff --git a/target/linux/ramips/patches-3.18/0001-MIPS-ralink-add-verbose-pmu-info.patch b/target/linux/ramips/patches-3.18/0001-MIPS-ralink-add-verbose-pmu-info.patch new file mode 100644 index 0000000..5bf90c6 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0001-MIPS-ralink-add-verbose-pmu-info.patch @@ -0,0 +1,59 @@ +From 453850d315070678245f61202ae343153589e5a6 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 27 Jul 2014 09:16:50 +0100 +Subject: [PATCH 01/57] MIPS: ralink: add verbose pmu info + +Print the PMU and LDO settings on boot. + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/ralink/mt7620.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +--- a/arch/mips/ralink/mt7620.c ++++ b/arch/mips/ralink/mt7620.c +@@ -20,6 +20,22 @@ + + #include "common.h" + ++/* analog */ ++#define PMU0_CFG 0x88 ++#define PMU_SW_SET BIT(28) ++#define A_DCDC_EN BIT(24) ++#define A_SSC_PERI BIT(19) ++#define A_SSC_GEN BIT(18) ++#define A_SSC_M 0x3 ++#define A_SSC_S 16 ++#define A_DLY_M 0x7 ++#define A_DLY_S 8 ++#define A_VTUNE_M 0xff ++ ++/* digital */ ++#define PMU1_CFG 0x8C ++#define DIG_SW_SEL BIT(25) ++ + /* does the board have sdram or ddram */ + static int dram_type; + +@@ -339,6 +355,8 @@ void prom_soc_init(struct ralink_soc_inf + u32 n1; + u32 rev; + u32 cfg0; ++ u32 pmu0; ++ u32 pmu1; + + n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0); + n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1); +@@ -386,4 +404,12 @@ void prom_soc_init(struct ralink_soc_inf + BUG(); + } + soc_info->mem_base = MT7620_DRAM_BASE; ++ ++ pmu0 = __raw_readl(sysc + PMU0_CFG); ++ pmu1 = __raw_readl(sysc + PMU1_CFG); ++ ++ pr_info("Analog PMU set to %s control\n", ++ (pmu0 & PMU_SW_SET) ? ("sw") : ("hw")); ++ pr_info("Digital PMU set to %s control\n", ++ (pmu1 & DIG_SW_SEL) ? ("sw") : ("hw")); + } diff --git a/target/linux/ramips/patches-3.18/0002-MIPS-ralink-add-a-helper-for-reading-the-ECO-version.patch b/target/linux/ramips/patches-3.18/0002-MIPS-ralink-add-a-helper-for-reading-the-ECO-version.patch new file mode 100644 index 0000000..237ba00 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0002-MIPS-ralink-add-a-helper-for-reading-the-ECO-version.patch @@ -0,0 +1,22 @@ +From 1751f28d4779df83cc793c9d7ff75485c0ceaa23 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 16 Mar 2014 04:53:02 +0000 +Subject: [PATCH 02/57] MIPS: ralink: add a helper for reading the ECO version + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/include/asm/mach-ralink/mt7620.h | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/arch/mips/include/asm/mach-ralink/mt7620.h ++++ b/arch/mips/include/asm/mach-ralink/mt7620.h +@@ -105,4 +105,9 @@ + #define MT7620_GPIO_MODE_EPHY BIT(15) + #define MT7620_GPIO_MODE_WDT BIT(22) + ++static inline int mt7620_get_eco(void) ++{ ++ return rt_sysc_r32(SYSC_REG_CHIP_REV) & CHIP_REV_ECO_MASK; ++} ++ + #endif diff --git a/target/linux/ramips/patches-3.18/0003-MIPS-ralink-add-rt_sysc_m32-helper.patch b/target/linux/ramips/patches-3.18/0003-MIPS-ralink-add-rt_sysc_m32-helper.patch new file mode 100644 index 0000000..66126e6 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0003-MIPS-ralink-add-rt_sysc_m32-helper.patch @@ -0,0 +1,26 @@ +From 0f0f041cd6a05eb865e391155d3299bb55ff00e3 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 19 May 2013 00:42:23 +0200 +Subject: [PATCH 03/57] MIPS: ralink: add rt_sysc_m32 helper + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/include/asm/mach-ralink/ralink_regs.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/arch/mips/include/asm/mach-ralink/ralink_regs.h ++++ b/arch/mips/include/asm/mach-ralink/ralink_regs.h +@@ -26,6 +26,13 @@ static inline u32 rt_sysc_r32(unsigned r + return __raw_readl(rt_sysc_membase + reg); + } + ++static inline void rt_sysc_m32(u32 clr, u32 set, unsigned reg) ++{ ++ u32 val = rt_sysc_r32(reg) & ~clr; ++ ++ __raw_writel(val | set, rt_sysc_membase + reg); ++} ++ + static inline void rt_memc_w32(u32 val, unsigned reg) + { + __raw_writel(val, rt_memc_membase + reg); diff --git a/target/linux/ramips/patches-3.18/0004-MIPS-ralink-adds-a-bootrom-dumper-module.patch b/target/linux/ramips/patches-3.18/0004-MIPS-ralink-adds-a-bootrom-dumper-module.patch new file mode 100644 index 0000000..049a876 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0004-MIPS-ralink-adds-a-bootrom-dumper-module.patch @@ -0,0 +1,74 @@ +From af03898c74172ab16d610f3eeaa65f66401eb7db Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Tue, 21 May 2013 15:50:31 +0200 +Subject: [PATCH 04/57] MIPS: ralink: adds a bootrom dumper module + +This patch adds a trivial driver that allows userland to extract the bootrom of +a SoC via debugfs. + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/ralink/Makefile | 2 ++ + arch/mips/ralink/bootrom.c | 48 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 50 insertions(+) + create mode 100644 arch/mips/ralink/bootrom.c + +--- a/arch/mips/ralink/Makefile ++++ b/arch/mips/ralink/Makefile +@@ -16,3 +16,5 @@ obj-$(CONFIG_SOC_RT3883) += rt3883.o + obj-$(CONFIG_SOC_MT7620) += mt7620.o + + obj-$(CONFIG_EARLY_PRINTK) += early_printk.o ++ ++obj-$(CONFIG_DEBUG_FS) += bootrom.o +--- /dev/null ++++ b/arch/mips/ralink/bootrom.c +@@ -0,0 +1,48 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ * Copyright (C) 2013 John Crispin <blogic@openwrt.org> ++ */ ++ ++#include <linux/debugfs.h> ++#include <linux/seq_file.h> ++ ++#define BOOTROM_OFFSET 0x10118000 ++#define BOOTROM_SIZE 0x8000 ++ ++static void __iomem *membase = (void __iomem*) KSEG1ADDR(BOOTROM_OFFSET); ++ ++static int bootrom_show(struct seq_file *s, void *unused) ++{ ++ seq_write(s, membase, BOOTROM_SIZE); ++ ++ return 0; ++} ++ ++static int bootrom_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, bootrom_show, NULL); ++} ++ ++static const struct file_operations bootrom_file_ops = { ++ .open = bootrom_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int bootrom_setup(void) ++{ ++ if (!debugfs_create_file("bootrom", 0444, ++ NULL, NULL, &bootrom_file_ops)) { ++ pr_err("Failed to create bootrom debugfs file\n"); ++ ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++postcore_initcall(bootrom_setup); diff --git a/target/linux/ramips/patches-3.18/0005-MIPS-ralink-add-illegal-access-driver.patch b/target/linux/ramips/patches-3.18/0005-MIPS-ralink-add-illegal-access-driver.patch new file mode 100644 index 0000000..fa9cd21 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0005-MIPS-ralink-add-illegal-access-driver.patch @@ -0,0 +1,115 @@ +From 60999174904c731e55992a4087999bbd4e5f2051 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Thu, 16 May 2013 23:28:23 +0200 +Subject: [PATCH 05/57] MIPS: ralink: add illegal access driver + +these SoCs have a special irq that fires upon an illegal memmory access. + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/ralink/Makefile | 2 + + arch/mips/ralink/ill_acc.c | 87 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 89 insertions(+) + create mode 100644 arch/mips/ralink/ill_acc.c + +--- a/arch/mips/ralink/Makefile ++++ b/arch/mips/ralink/Makefile +@@ -10,6 +10,8 @@ obj-y := prom.o of.o reset.o clk.o irq.o + + obj-$(CONFIG_CLKEVT_RT3352) += cevt-rt3352.o + ++obj-$(CONFIG_RALINK_ILL_ACC) += ill_acc.o ++ + obj-$(CONFIG_SOC_RT288X) += rt288x.o + obj-$(CONFIG_SOC_RT305X) += rt305x.o + obj-$(CONFIG_SOC_RT3883) += rt3883.o +--- /dev/null ++++ b/arch/mips/ralink/ill_acc.c +@@ -0,0 +1,87 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ * Copyright (C) 2013 John Crispin <blogic@openwrt.org> ++ */ ++ ++#include <linux/interrupt.h> ++#include <linux/of_platform.h> ++#include <linux/of_irq.h> ++ ++#include <asm/mach-ralink/ralink_regs.h> ++ ++#define REG_ILL_ACC_ADDR 0x10 ++#define REG_ILL_ACC_TYPE 0x14 ++ ++#define ILL_INT_STATUS BIT(31) ++#define ILL_ACC_WRITE BIT(30) ++#define ILL_ACC_LEN_M 0xff ++#define ILL_ACC_OFF_M 0xf ++#define ILL_ACC_OFF_S 16 ++#define ILL_ACC_ID_M 0x7 ++#define ILL_ACC_ID_S 8 ++ ++#define DRV_NAME "ill_acc" ++ ++static const char *ill_acc_ids[] = { ++ "cpu", "dma", "ppe", "pdma rx","pdma tx", "pci/e", "wmac", "usb", ++}; ++ ++static irqreturn_t ill_acc_irq_handler(int irq, void *_priv) ++{ ++ struct device *dev = (struct device *) _priv; ++ u32 addr = rt_memc_r32(REG_ILL_ACC_ADDR); ++ u32 type = rt_memc_r32(REG_ILL_ACC_TYPE); ++ ++ dev_err(dev, "illegal %s access from %s - addr:0x%08x offset:%d len:%d\n", ++ (type & ILL_ACC_WRITE) ? ("write") : ("read"), ++ ill_acc_ids[(type >> ILL_ACC_ID_S) & ILL_ACC_ID_M], ++ addr, (type >> ILL_ACC_OFF_S) & ILL_ACC_OFF_M, ++ type & ILL_ACC_LEN_M); ++ ++ rt_memc_w32(REG_ILL_ACC_TYPE, REG_ILL_ACC_TYPE); ++ ++ return IRQ_HANDLED; ++} ++ ++static int __init ill_acc_of_setup(void) ++{ ++ struct platform_device *pdev; ++ struct device_node *np; ++ int irq; ++ ++ /* somehow this driver breaks on RT5350 */ ++ if (of_machine_is_compatible("ralink,rt5350-soc")) ++ return -EINVAL; ++ ++ np = of_find_compatible_node(NULL, NULL, "ralink,rt3050-memc"); ++ if (!np) ++ return -EINVAL; ++ ++ pdev = of_find_device_by_node(np); ++ if (!pdev) { ++ pr_err("%s: failed to lookup pdev\n", np->name); ++ return -EINVAL; ++ } ++ ++ irq = irq_of_parse_and_map(np, 0); ++ if (!irq) { ++ dev_err(&pdev->dev, "failed to get irq\n"); ++ return -EINVAL; ++ } ++ ++ if (request_irq(irq, ill_acc_irq_handler, 0, "ill_acc", &pdev->dev)) { ++ dev_err(&pdev->dev, "failed to request irq\n"); ++ return -EINVAL; ++ } ++ ++ rt_memc_w32(ILL_INT_STATUS, REG_ILL_ACC_TYPE); ++ ++ dev_info(&pdev->dev, "irq registered\n"); ++ ++ return 0; ++} ++ ++arch_initcall(ill_acc_of_setup); diff --git a/target/linux/ramips/patches-3.18/0006-MIPS-ralink-add-missing-clk_set_rate-to-clk.c.patch b/target/linux/ramips/patches-3.18/0006-MIPS-ralink-add-missing-clk_set_rate-to-clk.c.patch new file mode 100644 index 0000000..8085e4b --- /dev/null +++ b/target/linux/ramips/patches-3.18/0006-MIPS-ralink-add-missing-clk_set_rate-to-clk.c.patch @@ -0,0 +1,27 @@ +From 979ad9f0324ad8fa5eb4a00b57d9feb061aa3200 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 16 Mar 2014 04:38:07 +0000 +Subject: [PATCH 06/57] MIPS: ralink: add missing clk_set_rate() to clk.c + +This function was missing causing allmod to fail. + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/ralink/clk.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/arch/mips/ralink/clk.c ++++ b/arch/mips/ralink/clk.c +@@ -56,6 +56,12 @@ unsigned long clk_get_rate(struct clk *c + } + EXPORT_SYMBOL_GPL(clk_get_rate); + ++int clk_set_rate(struct clk *clk, unsigned long rate) ++{ ++ return -1; ++} ++EXPORT_SYMBOL_GPL(clk_set_rate); ++ + void __init plat_time_init(void) + { + struct clk *clk; diff --git a/target/linux/ramips/patches-3.18/0007-MIPS-ralink-add-support-for-MT7620n.patch b/target/linux/ramips/patches-3.18/0007-MIPS-ralink-add-support-for-MT7620n.patch new file mode 100644 index 0000000..1d50710 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0007-MIPS-ralink-add-support-for-MT7620n.patch @@ -0,0 +1,66 @@ +From efc0f99cebcab21dbabcc634b9dbb963bbbbcab8 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 27 Jul 2014 09:23:36 +0100 +Subject: [PATCH 07/57] MIPS: ralink: add support for MT7620n + +This is the small version of MT7620a. + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/include/asm/mach-ralink/mt7620.h | 7 ++----- + arch/mips/ralink/mt7620.c | 19 ++++++++++++------- + 2 files changed, 14 insertions(+), 12 deletions(-) + +--- a/arch/mips/include/asm/mach-ralink/mt7620.h ++++ b/arch/mips/include/asm/mach-ralink/mt7620.h +@@ -25,11 +25,8 @@ + #define SYSC_REG_CPLL_CONFIG0 0x54 + #define SYSC_REG_CPLL_CONFIG1 0x58 + +-#define MT7620N_CHIP_NAME0 0x33365452 +-#define MT7620N_CHIP_NAME1 0x20203235 +- +-#define MT7620A_CHIP_NAME0 0x3637544d +-#define MT7620A_CHIP_NAME1 0x20203032 ++#define MT7620_CHIP_NAME0 0x3637544d ++#define MT7620_CHIP_NAME1 0x20203032 + + #define SYSCFG0_XTAL_FREQ_SEL BIT(6) + +--- a/arch/mips/ralink/mt7620.c ++++ b/arch/mips/ralink/mt7620.c +@@ -357,22 +357,27 @@ void prom_soc_init(struct ralink_soc_inf + u32 cfg0; + u32 pmu0; + u32 pmu1; ++ u32 bga; + + n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0); + n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1); ++ rev = __raw_readl(sysc + SYSC_REG_CHIP_REV); ++ bga = (rev >> CHIP_REV_PKG_SHIFT) & CHIP_REV_PKG_MASK; + +- if (n0 == MT7620N_CHIP_NAME0 && n1 == MT7620N_CHIP_NAME1) { +- name = "MT7620N"; +- soc_info->compatible = "ralink,mt7620n-soc"; +- } else if (n0 == MT7620A_CHIP_NAME0 && n1 == MT7620A_CHIP_NAME1) { ++ if (n0 != MT7620_CHIP_NAME0 || n1 != MT7620_CHIP_NAME1) ++ panic("mt7620: unknown SoC, n0:%08x n1:%08x\n", n0, n1); ++ ++ if (bga) { + name = "MT7620A"; + soc_info->compatible = "ralink,mt7620a-soc"; + } else { +- panic("mt7620: unknown SoC, n0:%08x n1:%08x", n0, n1); ++ name = "MT7620N"; ++ soc_info->compatible = "ralink,mt7620n-soc"; ++#ifdef CONFIG_PCI ++ panic("mt7620n is only supported for non pci kernels"); ++#endif + } + +- rev = __raw_readl(sysc + SYSC_REG_CHIP_REV); +- + snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, + "Ralink %s ver:%u eco:%u", + name, diff --git a/target/linux/ramips/patches-3.18/0008-MIPS-ralink-allow-manual-memory-override.patch b/target/linux/ramips/patches-3.18/0008-MIPS-ralink-allow-manual-memory-override.patch new file mode 100644 index 0000000..1870d13 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0008-MIPS-ralink-allow-manual-memory-override.patch @@ -0,0 +1,45 @@ +From 071e97587a291d3a5bbd614a425f46b7f90310aa Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 16 Mar 2014 04:40:48 +0000 +Subject: [PATCH 08/57] MIPS: ralink: allow manual memory override + +RT5350 relies on the bootloader setting up the memc correctly. +On sme boards the setup is incorrect leading to 32 MB being available but only 16 being recognized. Allow these boards to manually override the memory range +. +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/ralink/of.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +--- a/arch/mips/ralink/of.c ++++ b/arch/mips/ralink/of.c +@@ -53,6 +53,17 @@ void __init device_tree_init(void) + unflatten_and_copy_device_tree(); + } + ++static int memory_dtb; ++ ++static int __init early_init_dt_find_memory(unsigned long node, const char *uname, ++ int depth, void *data) ++{ ++ if (depth == 1 && !strcmp(uname, "memory@0")) ++ memory_dtb = 1; ++ ++ return 0; ++} ++ + void __init plat_mem_setup(void) + { + set_io_port_base(KSEG1); +@@ -63,7 +74,10 @@ void __init plat_mem_setup(void) + */ + __dt_setup_arch(__dtb_start); + +- if (soc_info.mem_size) ++ of_scan_flat_dt(early_init_dt_find_memory, NULL); ++ if (memory_dtb) ++ of_scan_flat_dt(early_init_dt_scan_memory, NULL); ++ else if (soc_info.mem_size) + add_memory_region(soc_info.mem_base, soc_info.mem_size * SZ_1M, + BOOT_MEM_RAM); + else diff --git a/target/linux/ramips/patches-3.18/0009-MIPS-ralink-define-the-wmac-clock-on-mt7620.patch b/target/linux/ramips/patches-3.18/0009-MIPS-ralink-define-the-wmac-clock-on-mt7620.patch new file mode 100644 index 0000000..225afd5 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0009-MIPS-ralink-define-the-wmac-clock-on-mt7620.patch @@ -0,0 +1,20 @@ +From 1cb19fe02c830e278b91498edea09fbda37c4a21 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 27 Jul 2014 10:13:43 +0100 +Subject: [PATCH 09/57] MIPS: ralink: define the wmac clock on mt7620 + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/ralink/mt7620.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/mips/ralink/mt7620.c ++++ b/arch/mips/ralink/mt7620.c +@@ -336,6 +336,7 @@ void __init ralink_clk_init(void) + ralink_clk_add("10000500.uart", periph_rate); + ralink_clk_add("10000b00.spi", sys_rate); + ralink_clk_add("10000c00.uartlite", periph_rate); ++ ralink_clk_add("10180000.wmac", xtal_rate); + } + + void __init ralink_of_remap(void) diff --git a/target/linux/ramips/patches-3.18/0010-MIPS-ralink-define-the-wmac-clock-on-rt3883.patch b/target/linux/ramips/patches-3.18/0010-MIPS-ralink-define-the-wmac-clock-on-rt3883.patch new file mode 100644 index 0000000..2de066b --- /dev/null +++ b/target/linux/ramips/patches-3.18/0010-MIPS-ralink-define-the-wmac-clock-on-rt3883.patch @@ -0,0 +1,20 @@ +From 1f17cf131fc2ae7fa2651dbe6a622dd125939718 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 27 Jul 2014 10:14:30 +0100 +Subject: [PATCH 10/57] MIPS: ralink: define the wmac clock on rt3883 + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/ralink/rt3883.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/mips/ralink/rt3883.c ++++ b/arch/mips/ralink/rt3883.c +@@ -204,6 +204,7 @@ void __init ralink_clk_init(void) + ralink_clk_add("10000b00.spi", sys_rate); + ralink_clk_add("10000c00.uartlite", 40000000); + ralink_clk_add("10100000.ethernet", sys_rate); ++ ralink_clk_add("10180000.wmac", 40000000); + } + + void __init ralink_of_remap(void) diff --git a/target/linux/ramips/patches-3.18/0011-MIPS-ralink-add-rt2880-wmac-clock.patch b/target/linux/ramips/patches-3.18/0011-MIPS-ralink-add-rt2880-wmac-clock.patch new file mode 100644 index 0000000..76d2f6a --- /dev/null +++ b/target/linux/ramips/patches-3.18/0011-MIPS-ralink-add-rt2880-wmac-clock.patch @@ -0,0 +1,29 @@ +From bf4f5250117cd65a78903b8ce302499806416ed1 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Mon, 4 Aug 2014 09:52:22 +0200 +Subject: [PATCH 11/57] MIPS: ralink: add rt2880 wmac clock + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/ralink/rt288x.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/mips/ralink/rt288x.c ++++ b/arch/mips/ralink/rt288x.c +@@ -76,7 +76,7 @@ struct ralink_pinmux rt_gpio_pinmux = { + + void __init ralink_clk_init(void) + { +- unsigned long cpu_rate; ++ unsigned long cpu_rate, wmac_rate = 40000000; + u32 t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG); + t = ((t >> SYSTEM_CONFIG_CPUCLK_SHIFT) & SYSTEM_CONFIG_CPUCLK_MASK); + +@@ -101,6 +101,7 @@ void __init ralink_clk_init(void) + ralink_clk_add("300500.uart", cpu_rate / 2); + ralink_clk_add("300c00.uartlite", cpu_rate / 2); + ralink_clk_add("400000.ethernet", cpu_rate / 2); ++ ralink_clk_add("480000.wmac", wmac_rate); + } + + void __init ralink_of_remap(void) diff --git a/target/linux/ramips/patches-3.18/0012-MIPS-ralink-add-MT7621-support.patch b/target/linux/ramips/patches-3.18/0012-MIPS-ralink-add-MT7621-support.patch new file mode 100644 index 0000000..23d3268 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0012-MIPS-ralink-add-MT7621-support.patch @@ -0,0 +1,752 @@ +From c8c69923236f2f3f184ddcc7eb41c113b5cc3223 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 27 Jul 2014 10:57:40 +0100 +Subject: [PATCH 12/57] MIPS: ralink: add MT7621 support + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/include/asm/gic.h | 4 + + arch/mips/include/asm/mach-ralink/irq.h | 9 + + arch/mips/include/asm/mach-ralink/mt7621.h | 39 ++++ + arch/mips/kernel/vmlinux.lds.S | 1 + + arch/mips/ralink/Kconfig | 18 ++ + arch/mips/ralink/Makefile | 7 +- + arch/mips/ralink/Platform | 5 + + arch/mips/ralink/irq-gic.c | 271 ++++++++++++++++++++++++++++ + arch/mips/ralink/malta-amon.c | 81 +++++++++ + arch/mips/ralink/mt7621.c | 183 +++++++++++++++++++ + 10 files changed, 617 insertions(+), 1 deletion(-) + create mode 100644 arch/mips/include/asm/mach-ralink/irq.h + create mode 100644 arch/mips/include/asm/mach-ralink/mt7621.h + create mode 100644 arch/mips/ralink/irq-gic.c + create mode 100644 arch/mips/ralink/malta-amon.c + create mode 100644 arch/mips/ralink/mt7621.c + +--- /dev/null ++++ b/arch/mips/include/asm/mach-ralink/irq.h +@@ -0,0 +1,9 @@ ++#ifndef __ASM_MACH_RALINK_IRQ_H ++#define __ASM_MACH_RALINK_IRQ_H ++ ++#define GIC_NUM_INTRS 64 ++#define NR_IRQS 256 ++ ++#include_next <irq.h> ++ ++#endif +--- /dev/null ++++ b/arch/mips/include/asm/mach-ralink/mt7621.h +@@ -0,0 +1,39 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ * Parts of this file are based on Ralink's 2.6.21 BSP ++ * ++ * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * Copyright (C) 2013 John Crispin <blogic@openwrt.org> ++ */ ++ ++#ifndef _MT7621_REGS_H_ ++#define _MT7621_REGS_H_ ++ ++#define MT7621_SYSC_BASE 0x1E000000 ++ ++#define SYSC_REG_CHIP_NAME0 0x00 ++#define SYSC_REG_CHIP_NAME1 0x04 ++#define SYSC_REG_CHIP_REV 0x0c ++#define SYSC_REG_SYSTEM_CONFIG0 0x10 ++#define SYSC_REG_SYSTEM_CONFIG1 0x14 ++ ++#define CHIP_REV_PKG_MASK 0x1 ++#define CHIP_REV_PKG_SHIFT 16 ++#define CHIP_REV_VER_MASK 0xf ++#define CHIP_REV_VER_SHIFT 8 ++#define CHIP_REV_ECO_MASK 0xf ++ ++#define MT7621_DRAM_BASE 0x0 ++#define MT7621_DDR2_SIZE_MIN 32 ++#define MT7621_DDR2_SIZE_MAX 256 ++ ++#define MT7621_CHIP_NAME0 0x3637544D ++#define MT7621_CHIP_NAME1 0x20203132 ++ ++#define MIPS_GIC_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8) ++ ++#endif +--- a/arch/mips/kernel/vmlinux.lds.S ++++ b/arch/mips/kernel/vmlinux.lds.S +@@ -51,6 +51,7 @@ SECTIONS + /* read-only */ + _text = .; /* Text and read-only data */ + .text : { ++ /*. = . + 0x8000; */ + TEXT_TEXT + SCHED_TEXT + LOCK_TEXT +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -12,6 +12,11 @@ config RALINK_ILL_ACC + depends on SOC_RT305X + default y + ++config IRQ_INTC ++ bool ++ default y ++ depends on !SOC_MT7621 ++ + choice + prompt "Ralink SoC selection" + default SOC_RT305X +@@ -33,6 +38,15 @@ choice + config SOC_MT7620 + bool "MT7620" + ++ config SOC_MT7621 ++ bool "MT7621" ++ select MIPS_CPU_SCACHE ++ select SYS_SUPPORTS_MULTITHREADING ++ select SYS_SUPPORTS_SMP ++ select SYS_SUPPORTS_MIPS_CMP ++ select IRQ_GIC ++ select HW_HAS_PCI ++ + endchoice + + choice +@@ -64,6 +78,10 @@ choice + depends on SOC_MT7620 + select BUILTIN_DTB + ++ config DTB_MT7621_EVAL ++ bool "MT7621 eval kit" ++ depends on SOC_MT7621 ++ + endchoice + + endif +--- a/arch/mips/ralink/Makefile ++++ b/arch/mips/ralink/Makefile +@@ -6,16 +6,21 @@ + # Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org> + # Copyright (C) 2013 John Crispin <blogic@openwrt.org> + +-obj-y := prom.o of.o reset.o clk.o irq.o timer.o ++obj-y := prom.o of.o reset.o clk.o timer.o + + obj-$(CONFIG_CLKEVT_RT3352) += cevt-rt3352.o + + obj-$(CONFIG_RALINK_ILL_ACC) += ill_acc.o + ++obj-$(CONFIG_IRQ_INTC) += irq.o ++obj-$(CONFIG_IRQ_GIC) += irq-gic.o ++obj-$(CONFIG_MIPS_MT_SMP) += malta-amon.o ++ + obj-$(CONFIG_SOC_RT288X) += rt288x.o + obj-$(CONFIG_SOC_RT305X) += rt305x.o + obj-$(CONFIG_SOC_RT3883) += rt3883.o + obj-$(CONFIG_SOC_MT7620) += mt7620.o ++obj-$(CONFIG_SOC_MT7621) += mt7621.o + + obj-$(CONFIG_EARLY_PRINTK) += early_printk.o + +--- a/arch/mips/ralink/Platform ++++ b/arch/mips/ralink/Platform +@@ -27,3 +27,8 @@ cflags-$(CONFIG_SOC_RT3883) += -I$(srctr + # + load-$(CONFIG_SOC_MT7620) += 0xffffffff80000000 + cflags-$(CONFIG_SOC_MT7620) += -I$(srctree)/arch/mips/include/asm/mach-ralink/mt7620 ++ ++# Ralink MT7621 ++# ++load-$(CONFIG_SOC_MT7621) += 0xffffffff80001000 ++cflags-$(CONFIG_SOC_MT7621) += -I$(srctree)/arch/mips/include/asm/mach-ralink/mt7621 +--- /dev/null ++++ b/arch/mips/ralink/irq-gic.c +@@ -0,0 +1,268 @@ ++#include <linux/init.h> ++#include <linux/sched.h> ++#include <linux/slab.h> ++#include <linux/interrupt.h> ++#include <linux/kernel_stat.h> ++#include <linux/hardirq.h> ++#include <linux/preempt.h> ++#include <linux/irqdomain.h> ++#include <linux/of_platform.h> ++#include <linux/of_address.h> ++#include <linux/of_irq.h> ++ ++#include <asm/irq_cpu.h> ++#include <asm/mipsregs.h> ++ ++#include <asm/irq.h> ++#include <asm/setup.h> ++ ++#include <asm/gic.h> ++ ++#include <asm/mach-ralink/mt7621.h> ++#define GIC_BASE_ADDR 0x1fbc0000 ++ ++unsigned long _gcmp_base; ++static int gic_resched_int_base = 56; ++static int gic_call_int_base = 60; ++static struct irq_chip *irq_gic; ++static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS]; ++ ++#if defined(CONFIG_MIPS_MT_SMP) ++static int gic_resched_int_base; ++static int gic_call_int_base; ++ ++#define GIC_RESCHED_INT(cpu) (gic_resched_int_base+(cpu)) ++#define GIC_CALL_INT(cpu) (gic_call_int_base+(cpu)) ++ ++static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) ++{ ++ scheduler_ipi(); ++ ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t ++ipi_call_interrupt(int irq, void *dev_id) ++{ ++ smp_call_function_interrupt(); ++ ++ return IRQ_HANDLED; ++} ++ ++static struct irqaction irq_resched = { ++ .handler = ipi_resched_interrupt, ++ .flags = IRQF_DISABLED|IRQF_PERCPU, ++ .name = "ipi resched" ++}; ++ ++static struct irqaction irq_call = { ++ .handler = ipi_call_interrupt, ++ .flags = IRQF_DISABLED|IRQF_PERCPU, ++ .name = "ipi call" ++}; ++ ++#endif ++ ++static void __init ++gic_fill_map(void) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(gic_intr_map); i++) { ++ gic_intr_map[i].cpunum = 0; ++ gic_intr_map[i].pin = GIC_CPU_INT0; ++ gic_intr_map[i].polarity = GIC_POL_POS; ++ gic_intr_map[i].trigtype = GIC_TRIG_LEVEL; ++ gic_intr_map[i].flags = 0; ++ } ++ ++#if defined(CONFIG_MIPS_MT_SMP) ++ { ++ int cpu; ++ ++ gic_call_int_base = ARRAY_SIZE(gic_intr_map) - nr_cpu_ids; ++ gic_resched_int_base = gic_call_int_base - nr_cpu_ids; ++ ++ i = gic_resched_int_base; ++ ++ for (cpu = 0; cpu < nr_cpu_ids; cpu++) { ++ gic_intr_map[i + cpu].cpunum = cpu; ++ gic_intr_map[i + cpu].pin = GIC_CPU_INT1; ++ gic_intr_map[i + cpu].trigtype = GIC_TRIG_EDGE; ++ ++ gic_intr_map[i + cpu + nr_cpu_ids].cpunum = cpu; ++ gic_intr_map[i + cpu + nr_cpu_ids].pin = GIC_CPU_INT2; ++ gic_intr_map[i + cpu + nr_cpu_ids].trigtype = GIC_TRIG_EDGE; ++ } ++ } ++#endif ++} ++ ++void ++gic_irq_ack(struct irq_data *d) ++{ ++ int irq = (d->irq - gic_irq_base); ++ ++ GIC_CLR_INTR_MASK(irq); ++ ++ if (gic_irq_flags[irq] & GIC_TRIG_EDGE) ++ GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq); ++} ++ ++void ++gic_finish_irq(struct irq_data *d) ++{ ++ GIC_SET_INTR_MASK(d->irq - gic_irq_base); ++} ++ ++void __init ++gic_platform_init(int irqs, struct irq_chip *irq_controller) ++{ ++ irq_gic = irq_controller; ++} ++ ++static void ++gic_irqdispatch(void) ++{ ++ unsigned int irq = gic_get_int(); ++ ++ if (likely(irq < GIC_NUM_INTRS)) ++ do_IRQ(MIPS_GIC_IRQ_BASE + irq); ++ else { ++ pr_debug("Spurious GIC Interrupt!\n"); ++ spurious_interrupt(); ++ } ++ ++} ++ ++static void ++vi_timer_irqdispatch(void) ++{ ++ do_IRQ(cp0_compare_irq); ++} ++ ++#if defined(CONFIG_MIPS_MT_SMP) ++unsigned int ++plat_ipi_call_int_xlate(unsigned int cpu) ++{ ++ return GIC_CALL_INT(cpu); ++} ++ ++unsigned int ++plat_ipi_resched_int_xlate(unsigned int cpu) ++{ ++ return GIC_RESCHED_INT(cpu); ++} ++#endif ++ ++asmlinkage void ++plat_irq_dispatch(void) ++{ ++ unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; ++ ++ if (unlikely(!pending)) { ++ pr_err("Spurious CP0 Interrupt!\n"); ++ spurious_interrupt(); ++ } else { ++ if (pending & CAUSEF_IP7) ++ do_IRQ(cp0_compare_irq); ++ ++ if (pending & (CAUSEF_IP4 | CAUSEF_IP3 | CAUSEF_IP2)) ++ gic_irqdispatch(); ++ } ++} ++ ++unsigned int __cpuinit ++get_c0_compare_int(void) ++{ ++ return CP0_LEGACY_COMPARE_IRQ; ++} ++ ++static int ++gic_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) ++{ ++ irq_set_chip_and_handler(irq, irq_gic, ++#if defined(CONFIG_MIPS_MT_SMP) ++ (hw >= gic_resched_int_base) ? ++ handle_percpu_irq : ++#endif ++ handle_level_irq); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops irq_domain_ops = { ++ .xlate = irq_domain_xlate_onecell, ++ .map = gic_map, ++}; ++ ++static int __init ++of_gic_init(struct device_node *node, ++ struct device_node *parent) ++{ ++ struct irq_domain *domain; ++ struct resource gcmp = { 0 }, gic = { 0 }; ++ unsigned int gic_rev; ++ int i; ++ ++ if (of_address_to_resource(node, 0, &gic)) ++ panic("Failed to get gic memory range"); ++ if (request_mem_region(gic.start, resource_size(&gic), ++ gic.name) < 0) ++ panic("Failed to request gic memory"); ++ if (of_address_to_resource(node, 2, &gcmp)) ++ panic("Failed to get gic memory range"); ++ if (request_mem_region(gcmp.start, resource_size(&gcmp), ++ gcmp.name) < 0) ++ panic("Failed to request gcmp memory"); ++ ++ _gcmp_base = (unsigned long) ioremap_nocache(gcmp.start, resource_size(&gcmp)); ++ if (!_gcmp_base) ++ panic("Failed to remap gcmp memory\n"); ++ ++ /* tell the gcmp where to find the gic */ ++ write_gcr_gic_base(GIC_BASE_ADDR | CM_GCR_GIC_BASE_GICEN_MSK); ++ gic_present = 1; ++ if (cpu_has_vint) { ++ set_vi_handler(2, gic_irqdispatch); ++ set_vi_handler(3, gic_irqdispatch); ++ set_vi_handler(4, gic_irqdispatch); ++ set_vi_handler(7, vi_timer_irqdispatch); ++ } ++ ++ gic_fill_map(); ++ ++ gic_init(gic.start, resource_size(&gic), gic_intr_map, ++ ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE); ++ ++ GICREAD(GIC_REG(SHARED, GIC_SH_REVISIONID), gic_rev); ++ pr_info("gic: revision %d.%d\n", (gic_rev >> 8) & 0xff, gic_rev & 0xff); ++ ++ domain = irq_domain_add_legacy(node, GIC_NUM_INTRS, MIPS_GIC_IRQ_BASE, ++ 0, &irq_domain_ops, NULL); ++ if (!domain) ++ panic("Failed to add irqdomain"); ++ ++#if defined(CONFIG_MIPS_MT_SMP) ++ for (i = 0; i < nr_cpu_ids; i++) { ++ setup_irq(MIPS_GIC_IRQ_BASE + GIC_RESCHED_INT(i), &irq_resched); ++ setup_irq(MIPS_GIC_IRQ_BASE + GIC_CALL_INT(i), &irq_call); ++ } ++#endif ++ ++ change_c0_status(ST0_IM, STATUSF_IP7 | STATUSF_IP4 | STATUSF_IP3 | ++ STATUSF_IP2); ++ return 0; ++} ++ ++static struct of_device_id __initdata of_irq_ids[] = { ++ { .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_intc_init }, ++ { .compatible = "ralink,mt7621-gic", .data = of_gic_init }, ++ {}, ++}; ++ ++void __init ++arch_init_irq(void) ++{ ++ of_irq_init(of_irq_ids); ++} +--- /dev/null ++++ b/arch/mips/ralink/malta-amon.c +@@ -0,0 +1,81 @@ ++/* ++ * Copyright (C) 2007 MIPS Technologies, Inc. ++ * All rights reserved. ++ ++ * This program is free software; you can distribute it and/or modify it ++ * under the terms of the GNU General Public License (Version 2) as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. ++ * ++ * Arbitrary Monitor interface ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/smp.h> ++ ++#include <asm/addrspace.h> ++#include <asm/mips-boards/launch.h> ++#include <asm/mipsmtregs.h> ++ ++int amon_cpu_avail(int cpu) ++{ ++ struct cpulaunch *launch = (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH); ++ ++ if (cpu < 0 || cpu >= NCPULAUNCH) { ++ pr_debug("avail: cpu%d is out of range\n", cpu); ++ return 0; ++ } ++ ++ launch += cpu; ++ if (!(launch->flags & LAUNCH_FREADY)) { ++ pr_debug("avail: cpu%d is not ready\n", cpu); ++ return 0; ++ } ++ if (launch->flags & (LAUNCH_FGO|LAUNCH_FGONE)) { ++ pr_debug("avail: too late.. cpu%d is already gone\n", cpu); ++ return 0; ++ } ++ ++ return 1; ++} ++ ++void amon_cpu_start(int cpu, ++ unsigned long pc, unsigned long sp, ++ unsigned long gp, unsigned long a0) ++{ ++ volatile struct cpulaunch *launch = ++ (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH); ++ ++ if (!amon_cpu_avail(cpu)) ++ return; ++ if (cpu == smp_processor_id()) { ++ pr_debug("launch: I am cpu%d!\n", cpu); ++ return; ++ } ++ launch += cpu; ++ ++ pr_debug("launch: starting cpu%d\n", cpu); ++ ++ launch->pc = pc; ++ launch->gp = gp; ++ launch->sp = sp; ++ launch->a0 = a0; ++ ++ smp_wmb(); /* Target must see parameters before go */ ++ launch->flags |= LAUNCH_FGO; ++ smp_wmb(); /* Target must see go before we poll */ ++ ++ while ((launch->flags & LAUNCH_FGONE) == 0) ++ ; ++ smp_rmb(); /* Target will be updating flags soon */ ++ pr_debug("launch: cpu%d gone!\n", cpu); ++} +--- /dev/null ++++ b/arch/mips/ralink/mt7621.c +@@ -0,0 +1,209 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ * Parts of this file are based on Ralink's 2.6.21 BSP ++ * ++ * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * Copyright (C) 2013 John Crispin <blogic@openwrt.org> ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/module.h> ++ ++#include <asm/mipsregs.h> ++#include <asm/smp-ops.h> ++#include <asm/mips-cm.h> ++#include <asm/mips-cpc.h> ++#include <asm/mach-ralink/ralink_regs.h> ++#include <asm/mach-ralink/mt7621.h> ++ ++#include <pinmux.h> ++ ++#include "common.h" ++ ++#define SYSC_REG_SYSCFG 0x10 ++#define SYSC_REG_CPLL_CLKCFG0 0x2c ++#define SYSC_REG_CUR_CLK_STS 0x44 ++#define CPU_CLK_SEL (BIT(30) | BIT(31)) ++ ++#define MT7621_GPIO_MODE_UART1 1 ++#define MT7621_GPIO_MODE_I2C 2 ++#define MT7621_GPIO_MODE_UART3_MASK 0x3 ++#define MT7621_GPIO_MODE_UART3_SHIFT 3 ++#define MT7621_GPIO_MODE_UART3_GPIO 1 ++#define MT7621_GPIO_MODE_UART2_MASK 0x3 ++#define MT7621_GPIO_MODE_UART2_SHIFT 5 ++#define MT7621_GPIO_MODE_UART2_GPIO 1 ++#define MT7621_GPIO_MODE_JTAG 7 ++#define MT7621_GPIO_MODE_WDT_MASK 0x3 ++#define MT7621_GPIO_MODE_WDT_SHIFT 8 ++#define MT7621_GPIO_MODE_WDT_GPIO 1 ++#define MT7621_GPIO_MODE_PCIE_RST 0 ++#define MT7621_GPIO_MODE_PCIE_REF 2 ++#define MT7621_GPIO_MODE_PCIE_MASK 0x3 ++#define MT7621_GPIO_MODE_PCIE_SHIFT 10 ++#define MT7621_GPIO_MODE_PCIE_GPIO 1 ++#define MT7621_GPIO_MODE_MDIO_MASK 0x3 ++#define MT7621_GPIO_MODE_MDIO_SHIFT 12 ++#define MT7621_GPIO_MODE_MDIO_GPIO 1 ++#define MT7621_GPIO_MODE_RGMII1 14 ++#define MT7621_GPIO_MODE_RGMII2 15 ++#define MT7621_GPIO_MODE_SPI_MASK 0x3 ++#define MT7621_GPIO_MODE_SPI_SHIFT 16 ++#define MT7621_GPIO_MODE_SPI_GPIO 1 ++#define MT7621_GPIO_MODE_SDHCI_MASK 0x3 ++#define MT7621_GPIO_MODE_SDHCI_SHIFT 18 ++#define MT7621_GPIO_MODE_SDHCI_GPIO 1 ++ ++static struct rt2880_pmx_func uart1_grp[] = { FUNC("uart1", 0, 1, 2) }; ++static struct rt2880_pmx_func i2c_grp[] = { FUNC("i2c", 0, 3, 2) }; ++static struct rt2880_pmx_func uart3_grp[] = { ++ FUNC("uart3", 0, 5, 4), ++ FUNC("i2s", 2, 5, 4), ++ FUNC("spdif3", 3, 5, 4), ++}; ++static struct rt2880_pmx_func uart2_grp[] = { ++ FUNC("uart2", 0, 9, 4), ++ FUNC("pcm", 2, 9, 4), ++ FUNC("spdif2", 3, 9, 4), ++}; ++static struct rt2880_pmx_func jtag_grp[] = { FUNC("jtag", 0, 13, 5) }; ++static struct rt2880_pmx_func wdt_grp[] = { ++ FUNC("wdt rst", 0, 18, 1), ++ FUNC("wdt refclk", 2, 18, 1), ++}; ++static struct rt2880_pmx_func pcie_rst_grp[] = { ++ FUNC("pcie rst", MT7621_GPIO_MODE_PCIE_RST, 19, 1), ++ FUNC("pcie refclk", MT7621_GPIO_MODE_PCIE_REF, 19, 1) ++}; ++static struct rt2880_pmx_func mdio_grp[] = { FUNC("mdio", 0, 20, 2) }; ++static struct rt2880_pmx_func rgmii2_grp[] = { FUNC("rgmii2", 0, 22, 12) }; ++static struct rt2880_pmx_func spi_grp[] = { ++ FUNC("spi", 0, 34, 7), ++ FUNC("nand1", 2, 34, 7), ++}; ++static struct rt2880_pmx_func sdhci_grp[] = { ++ FUNC("sdhci", 0, 41, 8), ++ FUNC("nand2", 2, 41, 8), ++}; ++static struct rt2880_pmx_func rgmii1_grp[] = { FUNC("rgmii1", 0, 49, 12) }; ++ ++static struct rt2880_pmx_group mt7621_pinmux_data[] = { ++ GRP("uart1", uart1_grp, 1, MT7621_GPIO_MODE_UART1), ++ GRP("i2c", i2c_grp, 1, MT7621_GPIO_MODE_I2C), ++ GRP_G("uart3", uart3_grp, MT7621_GPIO_MODE_UART3_MASK, ++ MT7621_GPIO_MODE_UART3_GPIO, MT7621_GPIO_MODE_UART3_SHIFT), ++ GRP_G("uart2", uart2_grp, MT7621_GPIO_MODE_UART2_MASK, ++ MT7621_GPIO_MODE_UART2_GPIO, MT7621_GPIO_MODE_UART2_SHIFT), ++ GRP("jtag", jtag_grp, 1, MT7621_GPIO_MODE_JTAG), ++ GRP_G("wdt", wdt_grp, MT7621_GPIO_MODE_WDT_MASK, ++ MT7621_GPIO_MODE_WDT_GPIO, MT7621_GPIO_MODE_WDT_SHIFT), ++ GRP_G("pcie", pcie_rst_grp, MT7621_GPIO_MODE_PCIE_MASK, ++ MT7621_GPIO_MODE_PCIE_GPIO, MT7621_GPIO_MODE_PCIE_SHIFT), ++ GRP_G("mdio", mdio_grp, MT7621_GPIO_MODE_MDIO_MASK, ++ MT7621_GPIO_MODE_MDIO_GPIO, MT7621_GPIO_MODE_MDIO_SHIFT), ++ GRP("rgmii2", rgmii2_grp, 1, MT7621_GPIO_MODE_RGMII2), ++ GRP_G("spi", spi_grp, MT7621_GPIO_MODE_SPI_MASK, ++ MT7621_GPIO_MODE_SPI_GPIO, MT7621_GPIO_MODE_SPI_SHIFT), ++ GRP_G("sdhci", sdhci_grp, MT7621_GPIO_MODE_SDHCI_MASK, ++ MT7621_GPIO_MODE_SDHCI_GPIO, MT7621_GPIO_MODE_SDHCI_SHIFT), ++ GRP("rgmii1", rgmii1_grp, 1, MT7621_GPIO_MODE_RGMII1), ++ { 0 } ++}; ++ ++void __init ralink_clk_init(void) ++{ ++ int cpu_fdiv = 0; ++ int cpu_ffrac = 0; ++ int fbdiv = 0; ++ u32 clk_sts, syscfg; ++ u8 clk_sel = 0, xtal_mode; ++ u32 cpu_clk; ++ ++ if ((rt_sysc_r32(SYSC_REG_CPLL_CLKCFG0) & CPU_CLK_SEL) != 0) ++ clk_sel = 1; ++ ++ switch (clk_sel) { ++ case 0: ++ clk_sts = rt_sysc_r32(SYSC_REG_CUR_CLK_STS); ++ cpu_fdiv = ((clk_sts >> 8) & 0x1F); ++ cpu_ffrac = (clk_sts & 0x1F); ++ cpu_clk = (500 * cpu_ffrac / cpu_fdiv) * 1000 * 1000; ++ break; ++ ++ case 1: ++ fbdiv = ((rt_sysc_r32(0x648) >> 4) & 0x7F) + 1; ++ syscfg = rt_sysc_r32(SYSC_REG_SYSCFG); ++ xtal_mode = (syscfg >> 6) & 0x7; ++ if(xtal_mode >= 6) { //25Mhz Xtal ++ cpu_clk = 25 * fbdiv * 1000 * 1000; ++ } else if(xtal_mode >=3) { //40Mhz Xtal ++ cpu_clk = 40 * fbdiv * 1000 * 1000; ++ } else { // 20Mhz Xtal ++ cpu_clk = 20 * fbdiv * 1000 * 1000; ++ } ++ break; ++ } ++ cpu_clk = 880000000; ++ ralink_clk_add("cpu", cpu_clk); ++ ralink_clk_add("1e000b00.spi", 50000000); ++ ralink_clk_add("1e000c00.uartlite", 50000000); ++ ralink_clk_add("1e000d00.uart", 50000000); ++} ++ ++void __init ralink_of_remap(void) ++{ ++ rt_sysc_membase = plat_of_remap_node("mtk,mt7621-sysc"); ++ rt_memc_membase = plat_of_remap_node("mtk,mt7621-memc"); ++ ++ if (!rt_sysc_membase || !rt_memc_membase) ++ panic("Failed to remap core resources"); ++} ++ ++void prom_soc_init(struct ralink_soc_info *soc_info) ++{ ++ void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7621_SYSC_BASE); ++ unsigned char *name = NULL; ++ u32 n0; ++ u32 n1; ++ u32 rev; ++ ++ n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0); ++ n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1); ++ ++ if (n0 == MT7621_CHIP_NAME0 && n1 == MT7621_CHIP_NAME1) { ++ name = "MT7621"; ++ soc_info->compatible = "mtk,mt7621-soc"; ++ } else { ++ panic("mt7621: unknown SoC, n0:%08x n1:%08x\n", n0, n1); ++ } ++ ++ rev = __raw_readl(sysc + SYSC_REG_CHIP_REV); ++ ++ snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, ++ "Mediatek %s ver:%u eco:%u", ++ name, ++ (rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK, ++ (rev & CHIP_REV_ECO_MASK)); ++ ++ soc_info->mem_size_min = MT7621_DDR2_SIZE_MIN; ++ soc_info->mem_size_max = MT7621_DDR2_SIZE_MAX; ++ soc_info->mem_base = MT7621_DRAM_BASE; ++ ++ rt2880_pinmux_data = mt7621_pinmux_data; ++ ++ /* Early detection of CMP support */ ++ mips_cm_probe(); ++ mips_cpc_probe(); ++ ++ if (!register_cps_smp_ops()) ++ return; ++ if (!register_cmp_smp_ops()) ++ return; ++ if (!register_vsmp_smp_ops()) ++ return; ++} +--- a/arch/mips/kernel/mips-cm.c ++++ b/arch/mips/kernel/mips-cm.c +@@ -105,7 +105,7 @@ int mips_cm_probe(void) + write_gcr_base(base_reg); + + /* disable CM regions */ +- write_gcr_reg0_base(CM_GCR_REGn_BASE_BASEADDR_MSK); ++/* write_gcr_reg0_base(CM_GCR_REGn_BASE_BASEADDR_MSK); + write_gcr_reg0_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK); + write_gcr_reg1_base(CM_GCR_REGn_BASE_BASEADDR_MSK); + write_gcr_reg1_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK); +@@ -113,7 +113,7 @@ int mips_cm_probe(void) + write_gcr_reg2_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK); + write_gcr_reg3_base(CM_GCR_REGn_BASE_BASEADDR_MSK); + write_gcr_reg3_mask(CM_GCR_REGn_MASK_ADDRMASK_MSK); +- ++*/ + /* probe for an L2-only sync region */ + mips_cm_probe_l2sync(); + diff --git a/target/linux/ramips/patches-3.18/0013-MIPS-ralink-add-MT7621-defconfig.patch b/target/linux/ramips/patches-3.18/0013-MIPS-ralink-add-MT7621-defconfig.patch new file mode 100644 index 0000000..daf27c1 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0013-MIPS-ralink-add-MT7621-defconfig.patch @@ -0,0 +1,211 @@ +From 8f92eac5ace0f834ec069b4bb8e9ad38f162de0e Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Mon, 27 Jan 2014 13:12:41 +0000 +Subject: [PATCH 13/57] MIPS: ralink: add MT7621 defconfig + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/configs/mt7621_defconfig | 197 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 197 insertions(+) + create mode 100644 arch/mips/configs/mt7621_defconfig + +--- /dev/null ++++ b/arch/mips/configs/mt7621_defconfig +@@ -0,0 +1,197 @@ ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_SYSVIPC=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_RCU_FANOUT=32 ++CONFIG_UIDGID_STRICT_TYPE_CHECKS=y ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="/openwrt/trunk/build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/root-ramips /openwrt/trunk/target/linux/generic/image/initramfs-base-files.txt" ++CONFIG_INITRAMFS_ROOT_UID=1000 ++CONFIG_INITRAMFS_ROOT_GID=1000 ++# CONFIG_RD_GZIP is not set ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++# CONFIG_AIO is not set ++CONFIG_EMBEDDED=y ++# CONFIG_VM_EVENT_COUNTERS is not set ++# CONFIG_SLUB_DEBUG is not set ++# CONFIG_COMPAT_BRK is not set ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++# CONFIG_BLK_DEV_BSG is not set ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_IOSCHED_CFQ is not set ++CONFIG_SMP=y ++CONFIG_NR_CPUS=4 ++CONFIG_SCHED_SMT=y ++# CONFIG_COMPACTION is not set ++# CONFIG_CROSS_MEMORY_ATTACH is not set ++# CONFIG_SECCOMP is not set ++CONFIG_HZ_100=y ++CONFIG_CMDLINE_BOOL=y ++CONFIG_CMDLINE="rootfstype=squashfs,jffs2" ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y ++CONFIG_IP_MROUTE=y ++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y ++CONFIG_ARPD=y ++CONFIG_SYN_COOKIES=y ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++# CONFIG_INET_LRO is not set ++# CONFIG_INET_DIAG is not set ++CONFIG_TCP_CONG_ADVANCED=y ++# CONFIG_TCP_CONG_BIC is not set ++# CONFIG_TCP_CONG_WESTWOOD is not set ++# CONFIG_TCP_CONG_HTCP is not set ++CONFIG_IPV6_PRIVACY=y ++# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET6_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET6_XFRM_MODE_BEET is not set ++# CONFIG_IPV6_SIT is not set ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_IPV6_SUBTREES=y ++CONFIG_IPV6_MROUTE=y ++CONFIG_NETFILTER=y ++# CONFIG_BRIDGE_NETFILTER is not set ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_FTP=m ++CONFIG_NF_CONNTRACK_IRC=m ++CONFIG_NETFILTER_XT_MARK=m ++CONFIG_NETFILTER_XT_TARGET_LOG=m ++CONFIG_NETFILTER_XT_TARGET_NOTRACK=m ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=m ++CONFIG_NETFILTER_XT_MATCH_COMMENT=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_MATCH_TIME=m ++CONFIG_NF_CONNTRACK_IPV4=m ++# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set ++CONFIG_IP_NF_IPTABLES=m ++CONFIG_IP_NF_FILTER=m ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_NF_NAT_IPV4=m ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_TARGET_REDIRECT=m ++CONFIG_IP_NF_MANGLE=m ++CONFIG_IP_NF_RAW=m ++CONFIG_NF_CONNTRACK_IPV6=m ++CONFIG_IP6_NF_IPTABLES=m ++CONFIG_IP6_NF_MATCH_AH=m ++CONFIG_IP6_NF_MATCH_EUI64=m ++CONFIG_IP6_NF_MATCH_FRAG=m ++CONFIG_IP6_NF_MATCH_OPTS=m ++CONFIG_IP6_NF_MATCH_IPV6HEADER=m ++CONFIG_IP6_NF_MATCH_MH=m ++CONFIG_IP6_NF_MATCH_RT=m ++CONFIG_IP6_NF_FILTER=m ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_MANGLE=m ++CONFIG_IP6_NF_RAW=m ++CONFIG_BRIDGE=m ++# CONFIG_BRIDGE_IGMP_SNOOPING is not set ++CONFIG_VLAN_8021Q=y ++CONFIG_NET_SCHED=y ++CONFIG_NET_SCH_FQ_CODEL=y ++CONFIG_HAMRADIO=y ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++# CONFIG_FIRMWARE_IN_KERNEL is not set ++CONFIG_MTD=y ++CONFIG_MTD_CMDLINE_PARTS=y ++CONFIG_MTD_BLOCK=y ++CONFIG_MTD_CFI=y ++CONFIG_MTD_CFI_AMDSTD=y ++CONFIG_MTD_COMPLEX_MAPPINGS=y ++CONFIG_MTD_PHYSMAP=y ++CONFIG_MTD_M25P80=y ++CONFIG_EEPROM_93CX6=m ++CONFIG_SCSI=y ++CONFIG_BLK_DEV_SD=y ++CONFIG_NETDEVICES=y ++# CONFIG_NET_PACKET_ENGINE is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++CONFIG_PHYLIB=y ++CONFIG_SWCONFIG=y ++CONFIG_PPP=m ++CONFIG_PPP_FILTER=y ++CONFIG_PPP_MULTILINK=y ++CONFIG_PPPOE=m ++CONFIG_PPP_ASYNC=m ++CONFIG_ISDN=y ++# CONFIG_INPUT is not set ++# CONFIG_SERIO is not set ++# CONFIG_VT is not set ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_DEVKMEM is not set ++CONFIG_SERIAL_8250=y ++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set ++CONFIG_SERIAL_8250_CONSOLE=y ++# CONFIG_SERIAL_8250_PCI is not set ++CONFIG_SERIAL_8250_RUNTIME_UARTS=2 ++CONFIG_SPI=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_SYSFS=y ++# CONFIG_HWMON is not set ++CONFIG_WATCHDOG=y ++CONFIG_WATCHDOG_CORE=y ++# CONFIG_VGA_ARB is not set ++CONFIG_USB=y ++CONFIG_USB_XHCI_HCD=y ++CONFIG_USB_XHCI_PLATFORM=y ++CONFIG_USB_MT7621_XHCI_PLATFORM=y ++CONFIG_USB_STORAGE=y ++CONFIG_USB_PHY=y ++CONFIG_NEW_LEDS=y ++CONFIG_LEDS_CLASS=y ++CONFIG_LEDS_GPIO=m ++CONFIG_LEDS_TRIGGERS=y ++CONFIG_LEDS_TRIGGER_TIMER=y ++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y ++CONFIG_STAGING=y ++CONFIG_USB_DWC2=m ++# CONFIG_IOMMU_SUPPORT is not set ++CONFIG_RESET_CONTROLLER=y ++# CONFIG_FIRMWARE_MEMMAP is not set ++# CONFIG_DNOTIFY is not set ++# CONFIG_PROC_PAGE_MONITOR is not set ++CONFIG_TMPFS=y ++CONFIG_TMPFS_XATTR=y ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_SUMMARY=y ++CONFIG_JFFS2_FS_XATTR=y ++# CONFIG_JFFS2_FS_POSIX_ACL is not set ++# CONFIG_JFFS2_FS_SECURITY is not set ++CONFIG_JFFS2_COMPRESSION_OPTIONS=y ++# CONFIG_JFFS2_ZLIB is not set ++CONFIG_SQUASHFS=y ++# CONFIG_SQUASHFS_ZLIB is not set ++CONFIG_SQUASHFS_XZ=y ++CONFIG_PRINTK_TIME=y ++# CONFIG_ENABLE_MUST_CHECK is not set ++CONFIG_FRAME_WARN=1024 ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_STRIP_ASM_SYMS=y ++# CONFIG_UNUSED_SYMBOLS is not set ++CONFIG_DEBUG_FS=y ++# CONFIG_SCHED_DEBUG is not set ++CONFIG_DEBUG_INFO=y ++CONFIG_DEBUG_INFO_REDUCED=y ++CONFIG_RCU_CPU_STALL_TIMEOUT=60 ++# CONFIG_FTRACE is not set ++CONFIG_CRYPTO_ARC4=m ++# CONFIG_CRYPTO_ANSI_CPRNG is not set ++# CONFIG_VIRTUALIZATION is not set ++CONFIG_CRC_ITU_T=m ++CONFIG_CRC32_SARWATE=y ++# CONFIG_XZ_DEC_X86 is not set ++CONFIG_AVERAGE=y diff --git a/target/linux/ramips/patches-3.18/0015-MIPS-ralink-cleanup-early_printk.patch b/target/linux/ramips/patches-3.18/0015-MIPS-ralink-cleanup-early_printk.patch new file mode 100644 index 0000000..1e5c90b --- /dev/null +++ b/target/linux/ramips/patches-3.18/0015-MIPS-ralink-cleanup-early_printk.patch @@ -0,0 +1,104 @@ +From e410b0069ee7c318a5b556f39b8b16814330a208 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Fri, 24 Jan 2014 17:01:17 +0100 +Subject: [PATCH 15/57] MIPS: ralink: cleanup early_printk + +Add support for the new MT7621/8 SoC and kill ifdefs. +Cleanup some whitespace error while we are at it. + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/ralink/early_printk.c | 45 ++++++++++++++++++++++++++------------- + 1 file changed, 30 insertions(+), 15 deletions(-) + +--- a/arch/mips/ralink/early_printk.c ++++ b/arch/mips/ralink/early_printk.c +@@ -12,21 +12,26 @@ + #include <asm/addrspace.h> + + #ifdef CONFIG_SOC_RT288X +-#define EARLY_UART_BASE 0x300c00 ++#define EARLY_UART_BASE 0x300c00 ++#define CHIPID_BASE 0x300004 ++#elif defined(CONFIG_SOC_MT7621) ++#define EARLY_UART_BASE 0x1E000c00 ++#define CHIPID_BASE 0x1E000004 + #else +-#define EARLY_UART_BASE 0x10000c00 ++#define EARLY_UART_BASE 0x10000c00 ++#define CHIPID_BASE 0x10000004 + #endif + +-#define UART_REG_RX 0x00 +-#define UART_REG_TX 0x04 +-#define UART_REG_IER 0x08 +-#define UART_REG_IIR 0x0c +-#define UART_REG_FCR 0x10 +-#define UART_REG_LCR 0x14 +-#define UART_REG_MCR 0x18 +-#define UART_REG_LSR 0x1c ++#define MT7628_CHIP_NAME1 0x20203832 ++ ++#define UART_REG_TX 0x04 ++#define UART_REG_LCR 0x0c ++#define UART_REG_LSR 0x14 ++#define UART_REG_LSR_RT2880 0x1c + + static __iomem void *uart_membase = (__iomem void *) KSEG1ADDR(EARLY_UART_BASE); ++static __iomem void *chipid_membase = (__iomem void *) KSEG1ADDR(CHIPID_BASE); ++static int init_complete; + + static inline void uart_w32(u32 val, unsigned reg) + { +@@ -38,11 +43,46 @@ static inline u32 uart_r32(unsigned reg) + return __raw_readl(uart_membase + reg); + } + ++static inline int soc_is_mt7628(void) ++{ ++ return IS_ENABLED(CONFIG_SOC_MT7620) && ++ (__raw_readl(chipid_membase) == MT7628_CHIP_NAME1); ++} ++ ++static inline void find_uart_base(void) ++{ ++ int i; ++ ++ if (!soc_is_mt7628()) ++ return; ++ ++ for (i = 0; i < 3; i++) { ++ u32 reg = uart_r32(UART_REG_LCR + (0x100 * i)); ++ ++ if (!reg) ++ continue; ++ ++ uart_membase = (__iomem void *) KSEG1ADDR(EARLY_UART_BASE + (0x100 * i)); ++ break; ++ } ++} ++ + void prom_putchar(unsigned char ch) + { +- while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0) +- ; +- uart_w32(ch, UART_REG_TX); +- while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0) +- ; ++ if (!init_complete) { ++ find_uart_base(); ++ init_complete = 1; ++ } ++ ++ if (IS_ENABLED(CONFIG_SOC_MT7621) || soc_is_mt7628()) { ++ uart_w32(ch, UART_TX); ++ while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0) ++ ; ++ } else { ++ while ((uart_r32(UART_REG_LSR_RT2880) & UART_LSR_THRE) == 0) ++ ; ++ uart_w32(ch, UART_REG_TX); ++ while ((uart_r32(UART_REG_LSR_RT2880) & UART_LSR_THRE) == 0) ++ ; ++ } + } diff --git a/target/linux/ramips/patches-3.18/0016-MIPS-ralink-add-MT7621-pcie-driver.patch b/target/linux/ramips/patches-3.18/0016-MIPS-ralink-add-MT7621-pcie-driver.patch new file mode 100644 index 0000000..2154e8a --- /dev/null +++ b/target/linux/ramips/patches-3.18/0016-MIPS-ralink-add-MT7621-pcie-driver.patch @@ -0,0 +1,838 @@ +From 95d7eb13a864ef666cea7f0e86349e86d80d28ce Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 16 Mar 2014 05:22:39 +0000 +Subject: [PATCH 16/57] MIPS: ralink: add MT7621 pcie driver + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/pci/Makefile | 1 + + arch/mips/pci/pci-mt7621.c | 797 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 798 insertions(+) + create mode 100644 arch/mips/pci/pci-mt7621.c + +--- a/arch/mips/pci/Makefile ++++ b/arch/mips/pci/Makefile +@@ -42,6 +42,7 @@ obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1 + obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o + obj-$(CONFIG_LANTIQ) += fixup-lantiq.o + obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o ++obj-$(CONFIG_SOC_MT7621) += pci-mt7621.o + obj-$(CONFIG_SOC_RT3883) += pci-rt3883.o + obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o + obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o +--- /dev/null ++++ b/arch/mips/pci/pci-mt7621.c +@@ -0,0 +1,813 @@ ++/************************************************************************** ++ * ++ * BRIEF MODULE DESCRIPTION ++ * PCI init for Ralink RT2880 solution ++ * ++ * Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw) ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN ++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ ************************************************************************** ++ * May 2007 Bruce Chang ++ * Initial Release ++ * ++ * May 2009 Bruce Chang ++ * support RT2880/RT3883 PCIe ++ * ++ * May 2011 Bruce Chang ++ * support RT6855/MT7620 PCIe ++ * ++ ************************************************************************** ++ */ ++ ++#include <linux/types.h> ++#include <linux/pci.h> ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/version.h> ++#include <asm/pci.h> ++#include <asm/io.h> ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/delay.h> ++#include <linux/of.h> ++#include <linux/of_pci.h> ++#include <linux/platform_device.h> ++ ++#include <ralink_regs.h> ++ ++extern void pcie_phy_init(void); ++extern void chk_phy_pll(void); ++ ++/* ++ * These functions and structures provide the BIOS scan and mapping of the PCI ++ * devices. ++ */ ++ ++#define CONFIG_PCIE_PORT0 ++#define CONFIG_PCIE_PORT1 ++#define CONFIG_PCIE_PORT2 ++#define RALINK_PCIE0_CLK_EN (1<<24) ++#define RALINK_PCIE1_CLK_EN (1<<25) ++#define RALINK_PCIE2_CLK_EN (1<<26) ++ ++#define RALINK_PCI_CONFIG_ADDR 0x20 ++#define RALINK_PCI_CONFIG_DATA_VIRTUAL_REG 0x24 ++#define SURFBOARDINT_PCIE0 12 /* PCIE0 */ ++#define RALINK_INT_PCIE0 SURFBOARDINT_PCIE0 ++#define RALINK_INT_PCIE1 SURFBOARDINT_PCIE1 ++#define RALINK_INT_PCIE2 SURFBOARDINT_PCIE2 ++#define SURFBOARDINT_PCIE1 32 /* PCIE1 */ ++#define SURFBOARDINT_PCIE2 33 /* PCIE2 */ ++#define RALINK_PCI_MEMBASE *(volatile u32 *)(RALINK_PCI_BASE + 0x0028) ++#define RALINK_PCI_IOBASE *(volatile u32 *)(RALINK_PCI_BASE + 0x002C) ++#define RALINK_PCIE0_RST (1<<24) ++#define RALINK_PCIE1_RST (1<<25) ++#define RALINK_PCIE2_RST (1<<26) ++#define RALINK_SYSCTL_BASE 0xBE000000 ++ ++#define RALINK_PCI_PCICFG_ADDR *(volatile u32 *)(RALINK_PCI_BASE + 0x0000) ++#define RALINK_PCI_PCIMSK_ADDR *(volatile u32 *)(RALINK_PCI_BASE + 0x000C) ++#define RALINK_PCI_BASE 0xBE140000 ++ ++#define RALINK_PCIEPHY_P0P1_CTL_OFFSET (RALINK_PCI_BASE + 0x9000) ++#define RT6855_PCIE0_OFFSET 0x2000 ++#define RT6855_PCIE1_OFFSET 0x3000 ++#define RT6855_PCIE2_OFFSET 0x4000 ++ ++#define RALINK_PCI0_BAR0SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0010) ++#define RALINK_PCI0_IMBASEBAR0_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0018) ++#define RALINK_PCI0_ID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0030) ++#define RALINK_PCI0_CLASS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0034) ++#define RALINK_PCI0_SUBID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0038) ++#define RALINK_PCI0_STATUS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0050) ++#define RALINK_PCI0_DERR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0060) ++#define RALINK_PCI0_ECRC *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0064) ++ ++#define RALINK_PCI1_BAR0SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0010) ++#define RALINK_PCI1_IMBASEBAR0_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0018) ++#define RALINK_PCI1_ID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0030) ++#define RALINK_PCI1_CLASS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0034) ++#define RALINK_PCI1_SUBID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0038) ++#define RALINK_PCI1_STATUS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0050) ++#define RALINK_PCI1_DERR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0060) ++#define RALINK_PCI1_ECRC *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0064) ++ ++#define RALINK_PCI2_BAR0SETUP_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0010) ++#define RALINK_PCI2_IMBASEBAR0_ADDR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0018) ++#define RALINK_PCI2_ID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0030) ++#define RALINK_PCI2_CLASS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0034) ++#define RALINK_PCI2_SUBID *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0038) ++#define RALINK_PCI2_STATUS *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0050) ++#define RALINK_PCI2_DERR *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0060) ++#define RALINK_PCI2_ECRC *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0064) ++ ++#define RALINK_PCIEPHY_P0P1_CTL_OFFSET (RALINK_PCI_BASE + 0x9000) ++#define RALINK_PCIEPHY_P2_CTL_OFFSET (RALINK_PCI_BASE + 0xA000) ++ ++ ++#define MV_WRITE(ofs, data) \ ++ *(volatile u32 *)(RALINK_PCI_BASE+(ofs)) = cpu_to_le32(data) ++#define MV_READ(ofs, data) \ ++ *(data) = le32_to_cpu(*(volatile u32 *)(RALINK_PCI_BASE+(ofs))) ++#define MV_READ_DATA(ofs) \ ++ le32_to_cpu(*(volatile u32 *)(RALINK_PCI_BASE+(ofs))) ++ ++#define MV_WRITE_16(ofs, data) \ ++ *(volatile u16 *)(RALINK_PCI_BASE+(ofs)) = cpu_to_le16(data) ++#define MV_READ_16(ofs, data) \ ++ *(data) = le16_to_cpu(*(volatile u16 *)(RALINK_PCI_BASE+(ofs))) ++ ++#define MV_WRITE_8(ofs, data) \ ++ *(volatile u8 *)(RALINK_PCI_BASE+(ofs)) = data ++#define MV_READ_8(ofs, data) \ ++ *(data) = *(volatile u8 *)(RALINK_PCI_BASE+(ofs)) ++ ++ ++ ++#define RALINK_PCI_MM_MAP_BASE 0x60000000 ++#define RALINK_PCI_IO_MAP_BASE 0x1e160000 ++ ++#define RALINK_SYSTEM_CONTROL_BASE 0xbe000000 ++#define GPIO_PERST ++#define ASSERT_SYSRST_PCIE(val) do { \ ++ if (*(unsigned int *)(0xbe00000c) == 0x00030101) \ ++ RALINK_RSTCTRL |= val; \ ++ else \ ++ RALINK_RSTCTRL &= ~val; \ ++ } while(0) ++#define DEASSERT_SYSRST_PCIE(val) do { \ ++ if (*(unsigned int *)(0xbe00000c) == 0x00030101) \ ++ RALINK_RSTCTRL &= ~val; \ ++ else \ ++ RALINK_RSTCTRL |= val; \ ++ } while(0) ++#define RALINK_SYSCFG1 *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x14) ++#define RALINK_CLKCFG1 *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x30) ++#define RALINK_RSTCTRL *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x34) ++#define RALINK_GPIOMODE *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x60) ++#define RALINK_PCIE_CLK_GEN *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x7c) ++#define RALINK_PCIE_CLK_GEN1 *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x80) ++#define PPLL_CFG1 *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x9c) ++#define PPLL_DRV *(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0xa0) ++//RALINK_SYSCFG1 bit ++#define RALINK_PCI_HOST_MODE_EN (1<<7) ++#define RALINK_PCIE_RC_MODE_EN (1<<8) ++//RALINK_RSTCTRL bit ++#define RALINK_PCIE_RST (1<<23) ++#define RALINK_PCI_RST (1<<24) ++//RALINK_CLKCFG1 bit ++#define RALINK_PCI_CLK_EN (1<<19) ++#define RALINK_PCIE_CLK_EN (1<<21) ++//RALINK_GPIOMODE bit ++#define PCI_SLOTx2 (1<<11) ++#define PCI_SLOTx1 (2<<11) ++//MTK PCIE PLL bit ++#define PDRV_SW_SET (1<<31) ++#define LC_CKDRVPD_ (1<<19) ++ ++#define MEMORY_BASE 0x0 ++static int pcie_link_status = 0; ++ ++#define PCI_ACCESS_READ_1 0 ++#define PCI_ACCESS_READ_2 1 ++#define PCI_ACCESS_READ_4 2 ++#define PCI_ACCESS_WRITE_1 3 ++#define PCI_ACCESS_WRITE_2 4 ++#define PCI_ACCESS_WRITE_4 5 ++ ++static int config_access(unsigned char access_type, struct pci_bus *bus, ++ unsigned int devfn, unsigned int where, u32 * data) ++{ ++ unsigned int slot = PCI_SLOT(devfn); ++ u8 func = PCI_FUNC(devfn); ++ uint32_t address_reg, data_reg; ++ unsigned int address; ++ ++ address_reg = RALINK_PCI_CONFIG_ADDR; ++ data_reg = RALINK_PCI_CONFIG_DATA_VIRTUAL_REG; ++ ++ address = (((where&0xF00)>>8)<<24) |(bus->number << 16) | (slot << 11) | (func << 8) | (where & 0xfc) | 0x80000000; ++ MV_WRITE(address_reg, address); ++ ++ switch(access_type) { ++ case PCI_ACCESS_WRITE_1: ++ MV_WRITE_8(data_reg+(where&0x3), *data); ++ break; ++ case PCI_ACCESS_WRITE_2: ++ MV_WRITE_16(data_reg+(where&0x3), *data); ++ break; ++ case PCI_ACCESS_WRITE_4: ++ MV_WRITE(data_reg, *data); ++ break; ++ case PCI_ACCESS_READ_1: ++ MV_READ_8( data_reg+(where&0x3), data); ++ break; ++ case PCI_ACCESS_READ_2: ++ MV_READ_16(data_reg+(where&0x3), data); ++ break; ++ case PCI_ACCESS_READ_4: ++ MV_READ(data_reg, data); ++ break; ++ default: ++ printk("no specify access type\n"); ++ break; ++ } ++ return 0; ++} ++ ++static int ++read_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 * val) ++{ ++ return config_access(PCI_ACCESS_READ_1, bus, devfn, (unsigned int)where, (u32 *)val); ++} ++ ++static int ++read_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 * val) ++{ ++ return config_access(PCI_ACCESS_READ_2, bus, devfn, (unsigned int)where, (u32 *)val); ++} ++ ++static int ++read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 * val) ++{ ++ return config_access(PCI_ACCESS_READ_4, bus, devfn, (unsigned int)where, (u32 *)val); ++} ++ ++static int ++write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 val) ++{ ++ if (config_access(PCI_ACCESS_WRITE_1, bus, devfn, (unsigned int)where, (u32 *)&val)) ++ return -1; ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int ++write_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 val) ++{ ++ if (config_access(PCI_ACCESS_WRITE_2, bus, devfn, where, (u32 *)&val)) ++ return -1; ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int ++write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val) ++{ ++ if (config_access(PCI_ACCESS_WRITE_4, bus, devfn, where, &val)) ++ return -1; ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++ ++static int ++pci_config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val) ++{ ++ switch (size) { ++ case 1: ++ return read_config_byte(bus, devfn, where, (u8 *) val); ++ case 2: ++ return read_config_word(bus, devfn, where, (u16 *) val); ++ default: ++ return read_config_dword(bus, devfn, where, val); ++ } ++} ++ ++static int ++pci_config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) ++{ ++ switch (size) { ++ case 1: ++ return write_config_byte(bus, devfn, where, (u8) val); ++ case 2: ++ return write_config_word(bus, devfn, where, (u16) val); ++ default: ++ return write_config_dword(bus, devfn, where, val); ++ } ++} ++ ++struct pci_ops mt7621_pci_ops= { ++ .read = pci_config_read, ++ .write = pci_config_write, ++}; ++ ++static struct resource mt7621_res_pci_mem1 = { ++ .name = "PCI MEM1", ++ .start = RALINK_PCI_MM_MAP_BASE, ++ .end = (u32)((RALINK_PCI_MM_MAP_BASE + (unsigned char *)0x0fffffff)), ++ .flags = IORESOURCE_MEM, ++}; ++static struct resource mt7621_res_pci_io1 = { ++ .name = "PCI I/O1", ++ .start = RALINK_PCI_IO_MAP_BASE, ++ .end = (u32)((RALINK_PCI_IO_MAP_BASE + (unsigned char *)0x0ffff)), ++ .flags = IORESOURCE_IO, ++}; ++ ++static struct pci_controller mt7621_controller = { ++ .pci_ops = &mt7621_pci_ops, ++ .mem_resource = &mt7621_res_pci_mem1, ++ .io_resource = &mt7621_res_pci_io1, ++ .mem_offset = 0x00000000UL, ++ .io_offset = 0x00000000UL, ++ .io_map_base = 0xa0000000, ++}; ++ ++static void ++read_config(unsigned long bus, unsigned long dev, unsigned long func, unsigned long reg, unsigned long *val) ++{ ++ unsigned int address_reg, data_reg, address; ++ ++ address_reg = RALINK_PCI_CONFIG_ADDR; ++ data_reg = RALINK_PCI_CONFIG_DATA_VIRTUAL_REG; ++ address = (((reg & 0xF00)>>8)<<24) | (bus << 16) | (dev << 11) | (func << 8) | (reg & 0xfc) | 0x80000000 ; ++ MV_WRITE(address_reg, address); ++ MV_READ(data_reg, val); ++ return; ++} ++ ++static void ++write_config(unsigned long bus, unsigned long dev, unsigned long func, unsigned long reg, unsigned long val) ++{ ++ unsigned int address_reg, data_reg, address; ++ ++ address_reg = RALINK_PCI_CONFIG_ADDR; ++ data_reg = RALINK_PCI_CONFIG_DATA_VIRTUAL_REG; ++ address = (((reg & 0xF00)>>8)<<24) | (bus << 16) | (dev << 11) | (func << 8) | (reg & 0xfc) | 0x80000000 ; ++ MV_WRITE(address_reg, address); ++ MV_WRITE(data_reg, val); ++ return; ++} ++ ++ ++int __init ++pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ u16 cmd; ++ u32 val; ++ int irq = 0; ++ ++ if ((dev->bus->number == 0) && (slot == 0)) { ++ write_config(0, 0, 0, PCI_BASE_ADDRESS_0, MEMORY_BASE); ++ read_config(0, 0, 0, PCI_BASE_ADDRESS_0, (unsigned long *)&val); ++ printk("BAR0 at slot 0 = %x\n", val); ++ printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot); ++ } else if((dev->bus->number == 0) && (slot == 0x1)) { ++ write_config(0, 1, 0, PCI_BASE_ADDRESS_0, MEMORY_BASE); ++ read_config(0, 1, 0, PCI_BASE_ADDRESS_0, (unsigned long *)&val); ++ printk("BAR0 at slot 1 = %x\n", val); ++ printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot); ++ } else if((dev->bus->number == 0) && (slot == 0x2)) { ++ write_config(0, 2, 0, PCI_BASE_ADDRESS_0, MEMORY_BASE); ++ read_config(0, 2, 0, PCI_BASE_ADDRESS_0, (unsigned long *)&val); ++ printk("BAR0 at slot 2 = %x\n", val); ++ printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot); ++ } else if ((dev->bus->number == 1) && (slot == 0x0)) { ++ switch (pcie_link_status) { ++ case 2: ++ case 6: ++ irq = RALINK_INT_PCIE1; ++ break; ++ case 4: ++ irq = RALINK_INT_PCIE2; ++ break; ++ default: ++ irq = RALINK_INT_PCIE0; ++ } ++ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); ++ } else if ((dev->bus->number == 2) && (slot == 0x0)) { ++ switch (pcie_link_status) { ++ case 5: ++ case 6: ++ irq = RALINK_INT_PCIE2; ++ break; ++ default: ++ irq = RALINK_INT_PCIE1; ++ } ++ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); ++ } else if ((dev->bus->number == 2) && (slot == 0x1)) { ++ switch (pcie_link_status) { ++ case 5: ++ case 6: ++ irq = RALINK_INT_PCIE2; ++ break; ++ default: ++ irq = RALINK_INT_PCIE1; ++ } ++ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); ++ } else if ((dev->bus->number ==3) && (slot == 0x0)) { ++ irq = RALINK_INT_PCIE2; ++ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); ++ } else if ((dev->bus->number ==3) && (slot == 0x1)) { ++ irq = RALINK_INT_PCIE2; ++ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); ++ } else if ((dev->bus->number ==3) && (slot == 0x2)) { ++ irq = RALINK_INT_PCIE2; ++ printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); ++ } else { ++ printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot); ++ return 0; ++ } ++ ++ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x14); //configure cache line size 0x14 ++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xFF); //configure latency timer 0x10 ++ pci_read_config_word(dev, PCI_COMMAND, &cmd); ++ cmd = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; ++ pci_write_config_word(dev, PCI_COMMAND, cmd); ++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); ++ return irq; ++} ++ ++void ++set_pcie_phy(u32 *addr, int start_b, int bits, int val) ++{ ++// printk("0x%p:", addr); ++// printk(" %x", *addr); ++ *(unsigned int *)(addr) &= ~(((1<<bits) - 1)<<start_b); ++ *(unsigned int *)(addr) |= val << start_b; ++// printk(" -> %x\n", *addr); ++} ++ ++void ++bypass_pipe_rst(void) ++{ ++#if defined (CONFIG_PCIE_PORT0) ++ /* PCIe Port 0 */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x02c), 12, 1, 0x01); // rg_pe1_pipe_rst_b ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x02c), 4, 1, 0x01); // rg_pe1_pipe_cmd_frc[4] ++#endif ++#if defined (CONFIG_PCIE_PORT1) ++ /* PCIe Port 1 */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x12c), 12, 1, 0x01); // rg_pe1_pipe_rst_b ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x12c), 4, 1, 0x01); // rg_pe1_pipe_cmd_frc[4] ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ /* PCIe Port 2 */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x02c), 12, 1, 0x01); // rg_pe1_pipe_rst_b ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x02c), 4, 1, 0x01); // rg_pe1_pipe_cmd_frc[4] ++#endif ++} ++ ++void ++set_phy_for_ssc(void) ++{ ++ unsigned long reg = (*(volatile u32 *)(RALINK_SYSCTL_BASE + 0x10)); ++ ++ reg = (reg >> 6) & 0x7; ++#if defined (CONFIG_PCIE_PORT0) || defined (CONFIG_PCIE_PORT1) ++ /* Set PCIe Port0 & Port1 PHY to disable SSC */ ++ /* Debug Xtal Type */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x400), 8, 1, 0x01); // rg_pe1_frc_h_xtal_type ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x400), 9, 2, 0x00); // rg_pe1_h_xtal_type ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 4, 1, 0x01); // rg_pe1_frc_phy_en //Force Port 0 enable control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 4, 1, 0x01); // rg_pe1_frc_phy_en //Force Port 1 enable control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 5, 1, 0x00); // rg_pe1_phy_en //Port 0 disable ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 5, 1, 0x00); // rg_pe1_phy_en //Port 1 disable ++ if(reg <= 5 && reg >= 3) { // 40MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 6, 2, 0x01); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode) ++ printk("***** Xtal 40MHz *****\n"); ++ } else { // 25MHz | 20MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 6, 2, 0x00); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode) ++ if (reg >= 6) { ++ printk("***** Xtal 25MHz *****\n"); ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4bc), 4, 2, 0x01); // RG_PE1_H_PLL_FBKSEL //Feedback clock select ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x49c), 0,31, 0x18000000); // RG_PE1_H_LCDDS_PCW_NCPO //DDS NCPO PCW (for host mode) ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a4), 0,16, 0x18d); // RG_PE1_H_LCDDS_SSC_PRD //DDS SSC dither period control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a8), 0,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA //DDS SSC dither amplitude control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a8), 16,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA1 //DDS SSC dither amplitude control for initial ++ } else { ++ printk("***** Xtal 20MHz *****\n"); ++ } ++ } ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a0), 5, 1, 0x01); // RG_PE1_LCDDS_CLK_PH_INV //DDS clock inversion ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 22, 2, 0x02); // RG_PE1_H_PLL_BC ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 18, 4, 0x06); // RG_PE1_H_PLL_BP ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 12, 4, 0x02); // RG_PE1_H_PLL_IR ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 8, 4, 0x01); // RG_PE1_H_PLL_IC ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4ac), 16, 3, 0x00); // RG_PE1_H_PLL_BR ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 1, 3, 0x02); // RG_PE1_PLL_DIVEN ++ if(reg <= 5 && reg >= 3) { // 40MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x414), 6, 2, 0x01); // rg_pe1_mstckdiv //value of da_pe1_mstckdiv when force mode enable ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x414), 5, 1, 0x01); // rg_pe1_frc_mstckdiv //force mode enable of da_pe1_mstckdiv ++ } ++ /* Enable PHY and disable force mode */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 5, 1, 0x01); // rg_pe1_phy_en //Port 0 enable ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 5, 1, 0x01); // rg_pe1_phy_en //Port 1 enable ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000), 4, 1, 0x00); // rg_pe1_frc_phy_en //Force Port 0 disable control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100), 4, 1, 0x00); // rg_pe1_frc_phy_en //Force Port 1 disable control ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ /* Set PCIe Port2 PHY to disable SSC */ ++ /* Debug Xtal Type */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x400), 8, 1, 0x01); // rg_pe1_frc_h_xtal_type ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x400), 9, 2, 0x00); // rg_pe1_h_xtal_type ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 4, 1, 0x01); // rg_pe1_frc_phy_en //Force Port 0 enable control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 5, 1, 0x00); // rg_pe1_phy_en //Port 0 disable ++ if(reg <= 5 && reg >= 3) { // 40MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 6, 2, 0x01); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode) ++ } else { // 25MHz | 20MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 6, 2, 0x00); // RG_PE1_H_PLL_PREDIV //Pre-divider ratio (for host mode) ++ if (reg >= 6) { // 25MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4bc), 4, 2, 0x01); // RG_PE1_H_PLL_FBKSEL //Feedback clock select ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x49c), 0,31, 0x18000000); // RG_PE1_H_LCDDS_PCW_NCPO //DDS NCPO PCW (for host mode) ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a4), 0,16, 0x18d); // RG_PE1_H_LCDDS_SSC_PRD //DDS SSC dither period control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a8), 0,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA //DDS SSC dither amplitude control ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a8), 16,12, 0x4a); // RG_PE1_H_LCDDS_SSC_DELTA1 //DDS SSC dither amplitude control for initial ++ } ++ } ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a0), 5, 1, 0x01); // RG_PE1_LCDDS_CLK_PH_INV //DDS clock inversion ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 22, 2, 0x02); // RG_PE1_H_PLL_BC ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 18, 4, 0x06); // RG_PE1_H_PLL_BP ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 12, 4, 0x02); // RG_PE1_H_PLL_IR ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 8, 4, 0x01); // RG_PE1_H_PLL_IC ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4ac), 16, 3, 0x00); // RG_PE1_H_PLL_BR ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 1, 3, 0x02); // RG_PE1_PLL_DIVEN ++ if(reg <= 5 && reg >= 3) { // 40MHz Xtal ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x414), 6, 2, 0x01); // rg_pe1_mstckdiv //value of da_pe1_mstckdiv when force mode enable ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x414), 5, 1, 0x01); // rg_pe1_frc_mstckdiv //force mode enable of da_pe1_mstckdiv ++ } ++ /* Enable PHY and disable force mode */ ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 5, 1, 0x01); // rg_pe1_phy_en //Port 0 enable ++ set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000), 4, 1, 0x00); // rg_pe1_frc_phy_en //Force Port 0 disable control ++#endif ++} ++ ++static int mt7621_pci_probe(struct platform_device *pdev) ++{ ++ unsigned long val = 0; ++ ++ iomem_resource.start = 0; ++ iomem_resource.end= ~0; ++ ioport_resource.start= 0; ++ ioport_resource.end = ~0; ++ ++#if defined (CONFIG_PCIE_PORT0) ++ val = RALINK_PCIE0_RST; ++#endif ++#if defined (CONFIG_PCIE_PORT1) ++ val |= RALINK_PCIE1_RST; ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ val |= RALINK_PCIE2_RST; ++#endif ++ ASSERT_SYSRST_PCIE(RALINK_PCIE0_RST | RALINK_PCIE1_RST | RALINK_PCIE2_RST); ++ printk("pull PCIe RST: RALINK_RSTCTRL = %x\n", RALINK_RSTCTRL); ++#if defined GPIO_PERST /* add GPIO control instead of PERST_N */ /*chhung*/ ++ *(unsigned int *)(0xbe000060) &= ~(0x3<<10 | 0x3<<3); ++ *(unsigned int *)(0xbe000060) |= 0x1<<10 | 0x1<<3; ++ mdelay(100); ++ *(unsigned int *)(0xbe000600) |= 0x1<<19 | 0x1<<8 | 0x1<<7; // use GPIO19/GPIO8/GPIO7 (PERST_N/UART_RXD3/UART_TXD3) ++ mdelay(100); ++ *(unsigned int *)(0xbe000620) &= ~(0x1<<19 | 0x1<<8 | 0x1<<7); // clear DATA ++ ++ mdelay(100); ++#else ++ *(unsigned int *)(0xbe000060) &= ~0x00000c00; ++#endif ++#if defined (CONFIG_PCIE_PORT0) ++ val = RALINK_PCIE0_RST; ++#endif ++#if defined (CONFIG_PCIE_PORT1) ++ val |= RALINK_PCIE1_RST; ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ val |= RALINK_PCIE2_RST; ++#endif ++ DEASSERT_SYSRST_PCIE(val); ++ printk("release PCIe RST: RALINK_RSTCTRL = %x\n", RALINK_RSTCTRL); ++ ++ if ((*(unsigned int *)(0xbe00000c)&0xFFFF) == 0x0101) // MT7621 E2 ++ bypass_pipe_rst(); ++ set_phy_for_ssc(); ++ printk("release PCIe RST: RALINK_RSTCTRL = %x\n", RALINK_RSTCTRL); ++ ++#if defined (CONFIG_PCIE_PORT0) ++ read_config(0, 0, 0, 0x70c, &val); ++ printk("Port 0 N_FTS = %x\n", (unsigned int)val); ++#endif ++#if defined (CONFIG_PCIE_PORT1) ++ read_config(0, 1, 0, 0x70c, &val); ++ printk("Port 1 N_FTS = %x\n", (unsigned int)val); ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ read_config(0, 2, 0, 0x70c, &val); ++ printk("Port 2 N_FTS = %x\n", (unsigned int)val); ++#endif ++ ++ RALINK_RSTCTRL = (RALINK_RSTCTRL | RALINK_PCIE_RST); ++ RALINK_SYSCFG1 &= ~(0x30); ++ RALINK_SYSCFG1 |= (2<<4); ++ RALINK_PCIE_CLK_GEN &= 0x7fffffff; ++ RALINK_PCIE_CLK_GEN1 &= 0x80ffffff; ++ RALINK_PCIE_CLK_GEN1 |= 0xa << 24; ++ RALINK_PCIE_CLK_GEN |= 0x80000000; ++ mdelay(50); ++ RALINK_RSTCTRL = (RALINK_RSTCTRL & ~RALINK_PCIE_RST); ++ ++ ++#if defined GPIO_PERST /* add GPIO control instead of PERST_N */ /*chhung*/ ++ *(unsigned int *)(0xbe000620) |= 0x1<<19 | 0x1<<8 | 0x1<<7; // set DATA ++ mdelay(100); ++#else ++ RALINK_PCI_PCICFG_ADDR &= ~(1<<1); //de-assert PERST ++#endif ++ mdelay(500); ++ ++ ++ mdelay(500); ++#if defined (CONFIG_PCIE_PORT0) ++ if(( RALINK_PCI0_STATUS & 0x1) == 0) ++ { ++ printk("PCIE0 no card, disable it(RST&CLK)\n"); ++ ASSERT_SYSRST_PCIE(RALINK_PCIE0_RST); ++ RALINK_CLKCFG1 = (RALINK_CLKCFG1 & ~RALINK_PCIE0_CLK_EN); ++ pcie_link_status &= ~(1<<0); ++ } else { ++ pcie_link_status |= 1<<0; ++ RALINK_PCI_PCIMSK_ADDR |= (1<<20); // enable pcie1 interrupt ++ } ++#endif ++#if defined (CONFIG_PCIE_PORT1) ++ if(( RALINK_PCI1_STATUS & 0x1) == 0) ++ { ++ printk("PCIE1 no card, disable it(RST&CLK)\n"); ++ ASSERT_SYSRST_PCIE(RALINK_PCIE1_RST); ++ RALINK_CLKCFG1 = (RALINK_CLKCFG1 & ~RALINK_PCIE1_CLK_EN); ++ pcie_link_status &= ~(1<<1); ++ } else { ++ pcie_link_status |= 1<<1; ++ RALINK_PCI_PCIMSK_ADDR |= (1<<21); // enable pcie1 interrupt ++ } ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ if (( RALINK_PCI2_STATUS & 0x1) == 0) { ++ printk("PCIE2 no card, disable it(RST&CLK)\n"); ++ ASSERT_SYSRST_PCIE(RALINK_PCIE2_RST); ++ RALINK_CLKCFG1 = (RALINK_CLKCFG1 & ~RALINK_PCIE2_CLK_EN); ++ pcie_link_status &= ~(1<<2); ++ } else { ++ pcie_link_status |= 1<<2; ++ RALINK_PCI_PCIMSK_ADDR |= (1<<22); // enable pcie2 interrupt ++ } ++#endif ++ if (pcie_link_status == 0) ++ return 0; ++ ++/* ++pcie(2/1/0) link status pcie2_num pcie1_num pcie0_num ++3'b000 x x x ++3'b001 x x 0 ++3'b010 x 0 x ++3'b011 x 1 0 ++3'b100 0 x x ++3'b101 1 x 0 ++3'b110 1 0 x ++3'b111 2 1 0 ++*/ ++ switch(pcie_link_status) { ++ case 2: ++ RALINK_PCI_PCICFG_ADDR &= ~0x00ff0000; ++ RALINK_PCI_PCICFG_ADDR |= 0x1 << 16; //port0 ++ RALINK_PCI_PCICFG_ADDR |= 0x0 << 20; //port1 ++ break; ++ case 4: ++ RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000; ++ RALINK_PCI_PCICFG_ADDR |= 0x1 << 16; //port0 ++ RALINK_PCI_PCICFG_ADDR |= 0x2 << 20; //port1 ++ RALINK_PCI_PCICFG_ADDR |= 0x0 << 24; //port2 ++ break; ++ case 5: ++ RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000; ++ RALINK_PCI_PCICFG_ADDR |= 0x0 << 16; //port0 ++ RALINK_PCI_PCICFG_ADDR |= 0x2 << 20; //port1 ++ RALINK_PCI_PCICFG_ADDR |= 0x1 << 24; //port2 ++ break; ++ case 6: ++ RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000; ++ RALINK_PCI_PCICFG_ADDR |= 0x2 << 16; //port0 ++ RALINK_PCI_PCICFG_ADDR |= 0x0 << 20; //port1 ++ RALINK_PCI_PCICFG_ADDR |= 0x1 << 24; //port2 ++ break; ++ } ++ printk(" -> %x\n", RALINK_PCI_PCICFG_ADDR); ++ //printk(" RALINK_PCI_ARBCTL = %x\n", RALINK_PCI_ARBCTL); ++ ++/* ++ ioport_resource.start = mt7621_res_pci_io1.start; ++ ioport_resource.end = mt7621_res_pci_io1.end; ++*/ ++ ++ RALINK_PCI_MEMBASE = 0xffffffff; //RALINK_PCI_MM_MAP_BASE; ++ RALINK_PCI_IOBASE = RALINK_PCI_IO_MAP_BASE; ++ ++#if defined (CONFIG_PCIE_PORT0) ++ //PCIe0 ++ if((pcie_link_status & 0x1) != 0) { ++ RALINK_PCI0_BAR0SETUP_ADDR = 0x7FFF0001; //open 7FFF:2G; ENABLE ++ RALINK_PCI0_IMBASEBAR0_ADDR = MEMORY_BASE; ++ RALINK_PCI0_CLASS = 0x06040001; ++ printk("PCIE0 enabled\n"); ++ } ++#endif ++#if defined (CONFIG_PCIE_PORT1) ++ //PCIe1 ++ if ((pcie_link_status & 0x2) != 0) { ++ RALINK_PCI1_BAR0SETUP_ADDR = 0x7FFF0001; //open 7FFF:2G; ENABLE ++ RALINK_PCI1_IMBASEBAR0_ADDR = MEMORY_BASE; ++ RALINK_PCI1_CLASS = 0x06040001; ++ printk("PCIE1 enabled\n"); ++ } ++#endif ++#if defined (CONFIG_PCIE_PORT2) ++ //PCIe2 ++ if ((pcie_link_status & 0x4) != 0) { ++ RALINK_PCI2_BAR0SETUP_ADDR = 0x7FFF0001; //open 7FFF:2G; ENABLE ++ RALINK_PCI2_IMBASEBAR0_ADDR = MEMORY_BASE; ++ RALINK_PCI2_CLASS = 0x06040001; ++ printk("PCIE2 enabled\n"); ++ } ++#endif ++ ++ ++ switch(pcie_link_status) { ++ case 7: ++ read_config(0, 2, 0, 0x4, &val); ++ write_config(0, 2, 0, 0x4, val|0x4); ++ // write_config(0, 1, 0, 0x4, val|0x7); ++ read_config(0, 2, 0, 0x70c, &val); ++ val &= ~(0xff)<<8; ++ val |= 0x50<<8; ++ write_config(0, 2, 0, 0x70c, val); ++ case 3: ++ case 5: ++ case 6: ++ read_config(0, 1, 0, 0x4, &val); ++ write_config(0, 1, 0, 0x4, val|0x4); ++ // write_config(0, 1, 0, 0x4, val|0x7); ++ read_config(0, 1, 0, 0x70c, &val); ++ val &= ~(0xff)<<8; ++ val |= 0x50<<8; ++ write_config(0, 1, 0, 0x70c, val); ++ default: ++ read_config(0, 0, 0, 0x4, &val); ++ write_config(0, 0, 0, 0x4, val|0x4); //bus master enable ++ // write_config(0, 0, 0, 0x4, val|0x7); //bus master enable ++ read_config(0, 0, 0, 0x70c, &val); ++ val &= ~(0xff)<<8; ++ val |= 0x50<<8; ++ write_config(0, 0, 0, 0x70c, val); ++ } ++ ++ pci_load_of_ranges(&mt7621_controller, pdev->dev.of_node); ++ register_pci_controller(&mt7621_controller); ++ return 0; ++ ++} ++ ++int pcibios_plat_dev_init(struct pci_dev *dev) ++{ ++ return 0; ++} ++ ++static const struct of_device_id mt7621_pci_ids[] = { ++ { .compatible = "mediatek,mt7621-pci" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mt7621_pci_ids); ++ ++static struct platform_driver mt7621_pci_driver = { ++ .probe = mt7621_pci_probe, ++ .driver = { ++ .name = "mt7621-pci", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(mt7621_pci_ids), ++ }, ++}; ++ ++static int __init mt7621_pci_init(void) ++{ ++ return platform_driver_register(&mt7621_pci_driver); ++} ++ ++arch_initcall(mt7621_pci_init); diff --git a/target/linux/ramips/patches-3.18/0017-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch b/target/linux/ramips/patches-3.18/0017-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch new file mode 100644 index 0000000..6bf0401 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0017-MIPS-use-set_mode-to-enable-disable-the-cevt-r4k-irq.patch @@ -0,0 +1,99 @@ +From f8da5caf65926d44581d4e7914b28ceab3d28a7c Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 14 Jul 2013 23:08:11 +0200 +Subject: [PATCH 17/57] MIPS: use set_mode() to enable/disable the cevt-r4k + irq + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/kernel/cevt-r4k.c | 37 +++++++++++++++++++++++++++++++------ + 1 file changed, 31 insertions(+), 6 deletions(-) + +--- a/arch/mips/kernel/cevt-r4k.c ++++ b/arch/mips/kernel/cevt-r4k.c +@@ -29,12 +29,6 @@ static int mips_next_event(unsigned long + return res; + } + +-void mips_set_clock_mode(enum clock_event_mode mode, +- struct clock_event_device *evt) +-{ +- /* Nothing to do ... */ +-} +- + DEFINE_PER_CPU(struct clock_event_device, mips_clockevent_device); + int cp0_timer_irq_installed; + +@@ -75,9 +69,38 @@ struct irqaction c0_compare_irqaction = + .name = "timer", + }; + ++void mips_set_clock_mode(enum clock_event_mode mode, ++ struct clock_event_device *evt) ++{ ++#ifdef CONFIG_CEVT_SYSTICK_QUIRK ++ switch (mode) { ++ case CLOCK_EVT_MODE_ONESHOT: ++ if (cp0_timer_irq_installed) ++ break; ++ ++ cp0_timer_irq_installed = 1; ++ ++ setup_irq(evt->irq, &c0_compare_irqaction); ++ break; ++ ++ case CLOCK_EVT_MODE_SHUTDOWN: ++ if (!cp0_timer_irq_installed) ++ break; ++ ++ cp0_timer_irq_installed = 0; ++ remove_irq(evt->irq, &c0_compare_irqaction); ++ break; ++ ++ default: ++ pr_err("Unhandeled mips clock_mode\n"); ++ break; ++ } ++#endif ++} + + void mips_event_handler(struct clock_event_device *dev) + { ++ + } + + /* +@@ -198,12 +221,14 @@ int r4k_clockevent_init(void) + + clockevents_register_device(cd); + ++#ifndef CONFIG_CEVT_SYSTICK_QUIRK + if (cp0_timer_irq_installed) + return 0; + + cp0_timer_irq_installed = 1; + + setup_irq(irq, &c0_compare_irqaction); ++#endif + + return 0; + } +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -1,11 +1,16 @@ + if RALINK + ++config CEVT_SYSTICK_QUIRK ++ bool ++ default n ++ + config CLKEVT_RT3352 + bool + depends on SOC_RT305X || SOC_MT7620 + default y + select CLKSRC_OF + select CLKSRC_MMIO ++ select CEVT_SYSTICK_QUIRK + + config RALINK_ILL_ACC + bool diff --git a/target/linux/ramips/patches-3.18/0019-MIPS-ralink-add-pseudo-pwm-led-trigger-based-on-time.patch b/target/linux/ramips/patches-3.18/0019-MIPS-ralink-add-pseudo-pwm-led-trigger-based-on-time.patch new file mode 100644 index 0000000..eff7cda --- /dev/null +++ b/target/linux/ramips/patches-3.18/0019-MIPS-ralink-add-pseudo-pwm-led-trigger-based-on-time.patch @@ -0,0 +1,300 @@ +From 9de00286e20a5f5edc419698373010f1cb6ff0ce Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 27 Jul 2014 09:25:02 +0100 +Subject: [PATCH 19/57] MIPS: ralink: add pseudo pwm led trigger based on + timer0 + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/ralink/timer.c | 213 ++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 197 insertions(+), 16 deletions(-) + +--- a/arch/mips/ralink/timer.c ++++ b/arch/mips/ralink/timer.c +@@ -12,6 +12,8 @@ + #include <linux/timer.h> + #include <linux/of_gpio.h> + #include <linux/clk.h> ++#include <linux/leds.h> ++#include <linux/slab.h> + + #include <asm/mach-ralink/ralink_regs.h> + +@@ -23,16 +25,34 @@ + + #define TMR0CTL_ENABLE BIT(7) + #define TMR0CTL_MODE_PERIODIC BIT(4) +-#define TMR0CTL_PRESCALER 1 ++#define TMR0CTL_PRESCALER 2 + #define TMR0CTL_PRESCALE_VAL (0xf - TMR0CTL_PRESCALER) + #define TMR0CTL_PRESCALE_DIV (65536 / BIT(TMR0CTL_PRESCALER)) + ++struct rt_timer_gpio { ++ struct list_head list; ++ struct led_classdev *led; ++}; ++ + struct rt_timer { +- struct device *dev; +- void __iomem *membase; +- int irq; +- unsigned long timer_freq; +- unsigned long timer_div; ++ struct device *dev; ++ void __iomem *membase; ++ int irq; ++ ++ unsigned long timer_freq; ++ unsigned long timer_div; ++ ++ struct list_head gpios; ++ struct led_trigger led_trigger; ++ unsigned int duty_cycle; ++ unsigned int duty; ++ ++ unsigned int fade; ++ unsigned int fade_min; ++ unsigned int fade_max; ++ unsigned int fade_speed; ++ unsigned int fade_dir; ++ unsigned int fade_count; + }; + + static inline void rt_timer_w32(struct rt_timer *rt, u8 reg, u32 val) +@@ -48,8 +68,37 @@ static inline u32 rt_timer_r32(struct rt + static irqreturn_t rt_timer_irq(int irq, void *_rt) + { + struct rt_timer *rt = (struct rt_timer *) _rt; ++ struct rt_timer_gpio *gpio; ++ unsigned int val; + +- rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div); ++ if (rt->fade && (rt->fade_count++ > rt->fade_speed)) { ++ rt->fade_count = 0; ++ if (rt->duty_cycle <= rt->fade_min) ++ rt->fade_dir = 1; ++ else if (rt->duty_cycle >= rt->fade_max) ++ rt->fade_dir = 0; ++ ++ if (rt->fade_dir) ++ rt->duty_cycle += 1; ++ else ++ rt->duty_cycle -= 1; ++ ++ } ++ ++ val = rt->timer_freq / rt->timer_div; ++ if (rt->duty) ++ val *= rt->duty_cycle; ++ else ++ val *= (100 - rt->duty_cycle); ++ val /= 100; ++ ++ if (!list_empty(&rt->gpios)) ++ list_for_each_entry(gpio, &rt->gpios, list) ++ led_set_brightness(gpio->led, !!rt->duty); ++ ++ rt->duty = !rt->duty; ++ ++ rt_timer_w32(rt, TIMER_REG_TMR0LOAD, val + 1); + rt_timer_w32(rt, TIMER_REG_TMRSTAT, TMRSTAT_TMR0INT); + + return IRQ_HANDLED; +@@ -58,8 +107,8 @@ static irqreturn_t rt_timer_irq(int irq, + + static int rt_timer_request(struct rt_timer *rt) + { +- int err = request_irq(rt->irq, rt_timer_irq, 0, +- dev_name(rt->dev), rt); ++ int err = devm_request_irq(rt->dev, rt->irq, rt_timer_irq, ++ 0, dev_name(rt->dev), rt); + if (err) { + dev_err(rt->dev, "failed to request irq\n"); + } else { +@@ -81,8 +130,6 @@ static int rt_timer_config(struct rt_tim + else + rt->timer_div = divisor; + +- rt_timer_w32(rt, TIMER_REG_TMR0LOAD, rt->timer_freq / rt->timer_div); +- + return 0; + } + +@@ -108,11 +155,128 @@ static void rt_timer_disable(struct rt_t + rt_timer_w32(rt, TIMER_REG_TMR0CTL, t); + } + ++static ssize_t led_fade_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct led_classdev *led_cdev = dev_get_drvdata(dev); ++ struct rt_timer *rt = container_of(led_cdev->trigger, struct rt_timer, led_trigger); ++ ++ return sprintf(buf, "speed: %d, min: %d, max: %d\n", rt->fade_speed, rt->fade_min, rt->fade_max); ++} ++ ++static ssize_t led_fade_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct led_classdev *led_cdev = dev_get_drvdata(dev); ++ struct rt_timer *rt = container_of(led_cdev->trigger, struct rt_timer, led_trigger); ++ unsigned int speed = 0, min = 0, max = 0; ++ ssize_t ret = -EINVAL; ++ ++ ret = sscanf(buf, "%u %u %u", &speed, &min, &max); ++ ++ if (ret == 3) { ++ rt->fade_speed = speed; ++ rt->fade_min = min; ++ rt->fade_max = max; ++ rt->fade = 1; ++ } else { ++ rt->fade = 0; ++ } ++ ++ return size; ++} ++ ++static DEVICE_ATTR(fade, 0644, led_fade_show, led_fade_store); ++ ++static ssize_t led_duty_cycle_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct led_classdev *led_cdev = dev_get_drvdata(dev); ++ struct rt_timer *rt = container_of(led_cdev->trigger, struct rt_timer, led_trigger); ++ ++ return sprintf(buf, "%u\n", rt->duty_cycle); ++} ++ ++static ssize_t led_duty_cycle_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct led_classdev *led_cdev = dev_get_drvdata(dev); ++ struct rt_timer *rt = container_of(led_cdev->trigger, struct rt_timer, led_trigger); ++ unsigned long state; ++ ssize_t ret = -EINVAL; ++ ++ ret = kstrtoul(buf, 10, &state); ++ if (ret) ++ return ret; ++ ++ if (state <= 100) ++ rt->duty_cycle = state; ++ else ++ rt->duty_cycle = 100; ++ ++ rt->fade = 0; ++ ++ return size; ++} ++ ++static DEVICE_ATTR(duty_cycle, 0644, led_duty_cycle_show, led_duty_cycle_store); ++ ++static void rt_timer_trig_activate(struct led_classdev *led_cdev) ++{ ++ struct rt_timer *rt = container_of(led_cdev->trigger, struct rt_timer, led_trigger); ++ struct rt_timer_gpio *gpio_data; ++ int rc; ++ ++ led_cdev->trigger_data = NULL; ++ gpio_data = kzalloc(sizeof(*gpio_data), GFP_KERNEL); ++ if (!gpio_data) ++ return; ++ ++ rc = device_create_file(led_cdev->dev, &dev_attr_duty_cycle); ++ if (rc) ++ goto err_gpio; ++ rc = device_create_file(led_cdev->dev, &dev_attr_fade); ++ if (rc) ++ goto err_out_duty_cycle; ++ ++ led_cdev->activated = true; ++ led_cdev->trigger_data = gpio_data; ++ gpio_data->led = led_cdev; ++ list_add(&gpio_data->list, &rt->gpios); ++ led_cdev->trigger_data = gpio_data; ++ rt_timer_enable(rt); ++ return; ++ ++err_out_duty_cycle: ++ device_remove_file(led_cdev->dev, &dev_attr_duty_cycle); ++ ++err_gpio: ++ kfree(gpio_data); ++} ++ ++static void rt_timer_trig_deactivate(struct led_classdev *led_cdev) ++{ ++ struct rt_timer *rt = container_of(led_cdev->trigger, struct rt_timer, led_trigger); ++ struct rt_timer_gpio *gpio_data = (struct rt_timer_gpio*) led_cdev->trigger_data; ++ ++ if (led_cdev->activated) { ++ device_remove_file(led_cdev->dev, &dev_attr_duty_cycle); ++ device_remove_file(led_cdev->dev, &dev_attr_fade); ++ led_cdev->activated = false; ++ } ++ ++ list_del(&gpio_data->list); ++ rt_timer_disable(rt); ++ led_set_brightness(led_cdev, LED_OFF); ++} ++ + static int rt_timer_probe(struct platform_device *pdev) + { + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ const __be32 *divisor; + struct rt_timer *rt; + struct clk *clk; ++ int ret; + + rt = devm_kzalloc(&pdev->dev, sizeof(*rt), GFP_KERNEL); + if (!rt) { +@@ -140,12 +304,29 @@ static int rt_timer_probe(struct platfor + if (!rt->timer_freq) + return -EINVAL; + ++ rt->duty_cycle = 100; + rt->dev = &pdev->dev; + platform_set_drvdata(pdev, rt); + +- rt_timer_request(rt); +- rt_timer_config(rt, 2); +- rt_timer_enable(rt); ++ ret = rt_timer_request(rt); ++ if (ret) ++ return ret; ++ ++ divisor = of_get_property(pdev->dev.of_node, "ralink,divisor", NULL); ++ if (divisor) ++ rt_timer_config(rt, be32_to_cpu(*divisor)); ++ else ++ rt_timer_config(rt, 200); ++ ++ rt->led_trigger.name = "pwmtimer", ++ rt->led_trigger.activate = rt_timer_trig_activate, ++ rt->led_trigger.deactivate = rt_timer_trig_deactivate, ++ ++ ret = led_trigger_register(&rt->led_trigger); ++ if (ret) ++ return ret; ++ ++ INIT_LIST_HEAD(&rt->gpios); + + dev_info(&pdev->dev, "maximum frequency is %luHz\n", rt->timer_freq); + +@@ -156,6 +337,7 @@ static int rt_timer_remove(struct platfo + { + struct rt_timer *rt = platform_get_drvdata(pdev); + ++ led_trigger_unregister(&rt->led_trigger); + rt_timer_disable(rt); + rt_timer_free(rt); + +@@ -180,6 +362,6 @@ static struct platform_driver rt_timer_d + + module_platform_driver(rt_timer_driver); + +-MODULE_DESCRIPTION("Ralink RT2880 timer"); ++MODULE_DESCRIPTION("Ralink RT2880 timer / pseudo pwm"); + MODULE_AUTHOR("John Crispin <blogic@openwrt.org"); + MODULE_LICENSE("GPL"); diff --git a/target/linux/ramips/patches-3.18/0021-MIPS-ralink-add-cpu-frequency-scaling.patch b/target/linux/ramips/patches-3.18/0021-MIPS-ralink-add-cpu-frequency-scaling.patch new file mode 100644 index 0000000..0e567cb --- /dev/null +++ b/target/linux/ramips/patches-3.18/0021-MIPS-ralink-add-cpu-frequency-scaling.patch @@ -0,0 +1,95 @@ +From e76ecd496c9b074ab21b17f12494d823a407e89a Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 28 Jul 2013 16:26:41 +0200 +Subject: [PATCH 21/57] MIPS: ralink: add cpu frequency scaling + +This feature will break udelay() and cause the delay loop to have longer delays +when the frequency is scaled causing a performance hit. + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/ralink/cevt-rt3352.c | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +--- a/arch/mips/ralink/cevt-rt3352.c ++++ b/arch/mips/ralink/cevt-rt3352.c +@@ -29,6 +29,10 @@ + /* enable the counter */ + #define CFG_CNT_EN 0x1 + ++/* mt7620 frequency scaling defines */ ++#define CLK_LUT_CFG 0x40 ++#define SLEEP_EN BIT(31) ++ + struct systick_device { + void __iomem *membase; + struct clock_event_device dev; +@@ -36,6 +40,8 @@ struct systick_device { + int freq_scale; + }; + ++static void (*systick_freq_scaling)(struct systick_device *sdev, int status); ++ + static void systick_set_clock_mode(enum clock_event_mode mode, + struct clock_event_device *evt); + +@@ -87,6 +93,21 @@ static struct irqaction systick_irqactio + .dev_id = &systick.dev, + }; + ++static inline void mt7620_freq_scaling(struct systick_device *sdev, int status) ++{ ++ if (sdev->freq_scale == status) ++ return; ++ ++ sdev->freq_scale = status; ++ ++ pr_info("%s: %s autosleep mode\n", systick.dev.name, ++ (status) ? ("enable") : ("disable")); ++ if (status) ++ rt_sysc_w32(rt_sysc_r32(CLK_LUT_CFG) | SLEEP_EN, CLK_LUT_CFG); ++ else ++ rt_sysc_w32(rt_sysc_r32(CLK_LUT_CFG) & ~SLEEP_EN, CLK_LUT_CFG); ++} ++ + static void systick_set_clock_mode(enum clock_event_mode mode, + struct clock_event_device *evt) + { +@@ -101,9 +122,13 @@ static void systick_set_clock_mode(enum + sdev->irq_requested = 1; + iowrite32(CFG_EXT_STK_EN | CFG_CNT_EN, + systick.membase + SYSTICK_CONFIG); ++ if (systick_freq_scaling) ++ systick_freq_scaling(sdev, 1); + break; + + case CLOCK_EVT_MODE_SHUTDOWN: ++ if (systick_freq_scaling) ++ systick_freq_scaling(sdev, 0); + if (sdev->irq_requested) + free_irq(systick.dev.irq, &systick_irqaction); + sdev->irq_requested = 0; +@@ -116,12 +141,23 @@ static void systick_set_clock_mode(enum + } + } + ++static const struct of_device_id systick_match[] = { ++ { .compatible = "ralink,mt7620-systick", .data = mt7620_freq_scaling}, ++ {}, ++}; ++ + static void __init ralink_systick_init(struct device_node *np) + { ++ const struct of_device_id *match; ++ + systick.membase = of_iomap(np, 0); + if (!systick.membase) + return; + ++ match = of_match_node(systick_match, np); ++ if (match) ++ systick_freq_scaling = match->data; ++ + systick_irqaction.name = np->name; + systick.dev.name = np->name; + clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60); diff --git a/target/linux/ramips/patches-3.18/0022-MIPS-ralink-copy-the-commandline-from-the-devicetree.patch b/target/linux/ramips/patches-3.18/0022-MIPS-ralink-copy-the-commandline-from-the-devicetree.patch new file mode 100644 index 0000000..96617e8 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0022-MIPS-ralink-copy-the-commandline-from-the-devicetree.patch @@ -0,0 +1,21 @@ +From ec26251ea980b1ee88733f178a4e86e3c70fd244 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Mon, 4 Aug 2014 18:46:02 +0200 +Subject: [PATCH 22/57] MIPS: ralink: copy the commandline from the devicetree + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/ralink/of.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/mips/ralink/of.c ++++ b/arch/mips/ralink/of.c +@@ -74,6 +74,8 @@ void __init plat_mem_setup(void) + */ + __dt_setup_arch(__dtb_start); + ++ strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); ++ + of_scan_flat_dt(early_init_dt_find_memory, NULL); + if (memory_dtb) + of_scan_flat_dt(early_init_dt_scan_memory, NULL); diff --git a/target/linux/ramips/patches-3.18/0023-MIPS-ralink-mt7620-fix-usb-issue-during-frequency-sc.patch b/target/linux/ramips/patches-3.18/0023-MIPS-ralink-mt7620-fix-usb-issue-during-frequency-sc.patch new file mode 100644 index 0000000..f3dead3 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0023-MIPS-ralink-mt7620-fix-usb-issue-during-frequency-sc.patch @@ -0,0 +1,52 @@ +From 1f1c12e85defba9459b41ec95b86f23b4791f1ab Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Mon, 4 Aug 2014 20:43:25 +0200 +Subject: [PATCH 23/57] MIPS: ralink: mt7620: fix usb issue during frequency + scaling + + If the USB HCD is running and the cpu is scaled too low, then the USB stops + working. Increase the idle speed of the core to fix this if the kernel is + built with USB support. + + The values are taken from the Ralink SDK Kernel. + + Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/ralink/mt7620.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +--- a/arch/mips/ralink/mt7620.c ++++ b/arch/mips/ralink/mt7620.c +@@ -36,6 +36,12 @@ + #define PMU1_CFG 0x8C + #define DIG_SW_SEL BIT(25) + ++/* clock scaling */ ++#define CLKCFG_FDIV_MASK 0x1f00 ++#define CLKCFG_FDIV_USB_VAL 0x0300 ++#define CLKCFG_FFRAC_MASK 0x001f ++#define CLKCFG_FFRAC_USB_VAL 0x0003 ++ + /* does the board have sdram or ddram */ + static int dram_type; + +@@ -337,6 +343,19 @@ void __init ralink_clk_init(void) + ralink_clk_add("10000b00.spi", sys_rate); + ralink_clk_add("10000c00.uartlite", periph_rate); + ralink_clk_add("10180000.wmac", xtal_rate); ++ ++ if (IS_ENABLED(CONFIG_USB)) { ++ /* ++ * When the CPU goes into sleep mode, the BUS clock will be too low for ++ * USB to function properly ++ */ ++ u32 val = rt_sysc_r32(SYSC_REG_CPU_SYS_CLKCFG); ++ ++ val &= ~(CLKCFG_FDIV_MASK | CLKCFG_FFRAC_MASK); ++ val |= CLKCFG_FDIV_USB_VAL | CLKCFG_FFRAC_USB_VAL; ++ ++ rt_sysc_w32(val, SYSC_REG_CPU_SYS_CLKCFG); ++ } + } + + void __init ralink_of_remap(void) diff --git a/target/linux/ramips/patches-3.18/0025-MIPS-ralink-allow-loading-irq-registers-from-the-dev.patch b/target/linux/ramips/patches-3.18/0025-MIPS-ralink-allow-loading-irq-registers-from-the-dev.patch new file mode 100644 index 0000000..f21ca3c --- /dev/null +++ b/target/linux/ramips/patches-3.18/0025-MIPS-ralink-allow-loading-irq-registers-from-the-dev.patch @@ -0,0 +1,75 @@ +From b1cc9a15f6ead8dbd849257e42d69a5799fb7597 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Wed, 6 Aug 2014 18:24:36 +0200 +Subject: [PATCH 25/57] MIPS: ralink: allow loading irq registers from the + devicetree + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/ralink/irq.c | 33 +++++++++++++++++++++++---------- + 1 file changed, 23 insertions(+), 10 deletions(-) + +--- a/arch/mips/ralink/irq.c ++++ b/arch/mips/ralink/irq.c +@@ -20,14 +20,6 @@ + + #include "common.h" + +-/* INTC register offsets */ +-#define INTC_REG_STATUS0 0x00 +-#define INTC_REG_STATUS1 0x04 +-#define INTC_REG_TYPE 0x20 +-#define INTC_REG_RAW_STATUS 0x30 +-#define INTC_REG_ENABLE 0x34 +-#define INTC_REG_DISABLE 0x38 +- + #define INTC_INT_GLOBAL BIT(31) + + #define RALINK_CPU_IRQ_INTC (MIPS_CPU_IRQ_BASE + 2) +@@ -44,16 +36,34 @@ + + #define RALINK_INTC_IRQ_PERFC (RALINK_INTC_IRQ_BASE + 9) + ++enum rt_intc_regs_enum { ++ INTC_REG_STATUS0 = 0, ++ INTC_REG_STATUS1, ++ INTC_REG_TYPE, ++ INTC_REG_RAW_STATUS, ++ INTC_REG_ENABLE, ++ INTC_REG_DISABLE, ++}; ++ ++static u32 rt_intc_regs[] = { ++ [INTC_REG_STATUS0] = 0x00, ++ [INTC_REG_STATUS1] = 0x04, ++ [INTC_REG_TYPE] = 0x20, ++ [INTC_REG_RAW_STATUS] = 0x30, ++ [INTC_REG_ENABLE] = 0x34, ++ [INTC_REG_DISABLE] = 0x38, ++}; ++ + static void __iomem *rt_intc_membase; + + static inline void rt_intc_w32(u32 val, unsigned reg) + { +- __raw_writel(val, rt_intc_membase + reg); ++ __raw_writel(val, rt_intc_membase + rt_intc_regs[reg]); + } + + static inline u32 rt_intc_r32(unsigned reg) + { +- return __raw_readl(rt_intc_membase + reg); ++ return __raw_readl(rt_intc_membase + rt_intc_regs[reg]); + } + + static void ralink_intc_irq_unmask(struct irq_data *d) +@@ -134,6 +144,9 @@ static int __init intc_of_init(struct de + struct irq_domain *domain; + int irq; + ++ if (!of_property_read_u32_array(node, "ralink,intc-registers", rt_intc_regs, 6)) ++ pr_info("intc: using register map from devicetree\n"); ++ + irq = irq_of_parse_and_map(node, 0); + if (!irq) + panic("Failed to get INTC IRQ"); diff --git a/target/linux/ramips/patches-3.18/0026-MIPS-ralink-add-mt7628an-support.patch b/target/linux/ramips/patches-3.18/0026-MIPS-ralink-add-mt7628an-support.patch new file mode 100644 index 0000000..c5c5d1a --- /dev/null +++ b/target/linux/ramips/patches-3.18/0026-MIPS-ralink-add-mt7628an-support.patch @@ -0,0 +1,398 @@ +From a375beba066516ecafddebc765454ac6ec599f3d Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Wed, 6 Aug 2014 18:26:08 +0200 +Subject: [PATCH 26/57] MIPS: ralink: add mt7628an support + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/include/asm/mach-ralink/mt7620.h | 11 ++ + arch/mips/ralink/Kconfig | 2 +- + arch/mips/ralink/mt7620.c | 266 +++++++++++++++++++++++----- + 3 files changed, 232 insertions(+), 47 deletions(-) + +--- a/arch/mips/include/asm/mach-ralink/mt7620.h ++++ b/arch/mips/include/asm/mach-ralink/mt7620.h +@@ -13,6 +13,13 @@ + #ifndef _MT7620_REGS_H_ + #define _MT7620_REGS_H_ + ++enum mt762x_soc_type { ++ MT762X_SOC_UNKNOWN = 0, ++ MT762X_SOC_MT7620A, ++ MT762X_SOC_MT7620N, ++ MT762X_SOC_MT7628AN, ++}; ++ + #define MT7620_SYSC_BASE 0x10000000 + + #define SYSC_REG_CHIP_NAME0 0x00 +@@ -27,6 +34,7 @@ + + #define MT7620_CHIP_NAME0 0x3637544d + #define MT7620_CHIP_NAME1 0x20203032 ++#define MT7628_CHIP_NAME1 0x20203832 + + #define SYSCFG0_XTAL_FREQ_SEL BIT(6) + +@@ -71,6 +79,9 @@ + #define SYSCFG0_DRAM_TYPE_DDR1 1 + #define SYSCFG0_DRAM_TYPE_DDR2 2 + ++#define SYSCFG0_DRAM_TYPE_DDR2_MT7628 0 ++#define SYSCFG0_DRAM_TYPE_DDR1_MT7628 1 ++ + #define MT7620_DRAM_BASE 0x0 + #define MT7620_SDRAM_SIZE_MIN 2 + #define MT7620_SDRAM_SIZE_MAX 64 +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -41,7 +41,7 @@ choice + select HW_HAS_PCI + + config SOC_MT7620 +- bool "MT7620" ++ bool "MT7620/8" + + config SOC_MT7621 + bool "MT7621" +--- a/arch/mips/ralink/mt7620.c ++++ b/arch/mips/ralink/mt7620.c +@@ -42,6 +42,8 @@ + #define CLKCFG_FFRAC_MASK 0x001f + #define CLKCFG_FFRAC_USB_VAL 0x0003 + ++enum mt762x_soc_type mt762x_soc; ++ + /* does the board have sdram or ddram */ + static int dram_type; + +@@ -159,6 +161,125 @@ struct ralink_pinmux rt_gpio_pinmux = { + .uart_mask = MT7620_GPIO_MODE_UART0_MASK, + }; + ++static struct rt2880_pmx_func pwm1_grp_mt7628[] = { ++ FUNC("sdxc", 3, 19, 1), ++ FUNC("utif", 2, 19, 1), ++ FUNC("gpio", 1, 19, 1), ++ FUNC("pwm", 0, 19, 1), ++}; ++ ++static struct rt2880_pmx_func pwm0_grp_mt7628[] = { ++ FUNC("sdxc", 3, 18, 1), ++ FUNC("utif", 2, 18, 1), ++ FUNC("gpio", 1, 18, 1), ++ FUNC("pwm", 0, 18, 1), ++}; ++ ++static struct rt2880_pmx_func uart2_grp_mt7628[] = { ++ FUNC("sdxc", 3, 20, 2), ++ FUNC("pwm", 2, 20, 2), ++ FUNC("gpio", 1, 20, 2), ++ FUNC("uart2", 0, 20, 2), ++}; ++ ++static struct rt2880_pmx_func uart1_grp_mt7628[] = { ++ FUNC("sdxc", 3, 45, 2), ++ FUNC("pwm", 2, 45, 2), ++ FUNC("gpio", 1, 45, 2), ++ FUNC("uart1", 0, 45, 2), ++}; ++ ++static struct rt2880_pmx_func i2c_grp_mt7628[] = { ++ FUNC("-", 3, 4, 2), ++ FUNC("debug", 2, 4, 2), ++ FUNC("gpio", 1, 4, 2), ++ FUNC("i2c", 0, 4, 2), ++}; ++ ++static struct rt2880_pmx_func refclk_grp_mt7628[] = { FUNC("reclk", 0, 36, 1) }; ++static struct rt2880_pmx_func perst_grp_mt7628[] = { FUNC("perst", 0, 37, 1) }; ++static struct rt2880_pmx_func wdt_grp_mt7628[] = { FUNC("wdt", 0, 38, 1) }; ++static struct rt2880_pmx_func spi_grp_mt7628[] = { FUNC("spi", 0, 7, 4) }; ++ ++static struct rt2880_pmx_func sd_mode_grp_mt7628[] = { ++ FUNC("jtag", 3, 22, 8), ++ FUNC("utif", 2, 22, 8), ++ FUNC("gpio", 1, 22, 8), ++ FUNC("sdxc", 0, 22, 8), ++}; ++ ++static struct rt2880_pmx_func uart0_grp_mt7628[] = { ++ FUNC("-", 3, 12, 2), ++ FUNC("-", 2, 12, 2), ++ FUNC("gpio", 1, 12, 2), ++ FUNC("uart0", 0, 12, 2), ++}; ++ ++static struct rt2880_pmx_func i2s_grp_mt7628[] = { ++ FUNC("antenna", 3, 0, 4), ++ FUNC("pcm", 2, 0, 4), ++ FUNC("gpio", 1, 0, 4), ++ FUNC("i2s", 0, 0, 4), ++}; ++ ++static struct rt2880_pmx_func spi_cs1_grp_mt7628[] = { ++ FUNC("-", 3, 6, 1), ++ FUNC("refclk", 2, 6, 1), ++ FUNC("gpio", 1, 6, 1), ++ FUNC("spi", 0, 6, 1), ++}; ++ ++static struct rt2880_pmx_func spis_grp_mt7628[] = { ++ FUNC("pwm", 3, 14, 4), ++ FUNC("util", 2, 14, 4), ++ FUNC("gpio", 1, 14, 4), ++ FUNC("spis", 0, 14, 4), ++}; ++ ++static struct rt2880_pmx_func gpio_grp_mt7628[] = { ++ FUNC("pcie", 3, 11, 1), ++ FUNC("refclk", 2, 11, 1), ++ FUNC("gpio", 1, 11, 1), ++ FUNC("gpio", 0, 11, 1), ++}; ++ ++#define MT7628_GPIO_MODE_MASK 0x3 ++ ++#define MT7628_GPIO_MODE_PWM1 30 ++#define MT7628_GPIO_MODE_PWM0 28 ++#define MT7628_GPIO_MODE_UART2 26 ++#define MT7628_GPIO_MODE_UART1 24 ++#define MT7628_GPIO_MODE_I2C 20 ++#define MT7628_GPIO_MODE_REFCLK 18 ++#define MT7628_GPIO_MODE_PERST 16 ++#define MT7628_GPIO_MODE_WDT 14 ++#define MT7628_GPIO_MODE_SPI 12 ++#define MT7628_GPIO_MODE_SDMODE 10 ++#define MT7628_GPIO_MODE_UART0 8 ++#define MT7628_GPIO_MODE_I2S 6 ++#define MT7628_GPIO_MODE_CS1 4 ++#define MT7628_GPIO_MODE_SPIS 2 ++#define MT7628_GPIO_MODE_GPIO 0 ++ ++static struct rt2880_pmx_group mt7628an_pinmux_data[] = { ++ GRP_G("pmw1", pwm1_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_PWM1), ++ GRP_G("pmw0", pwm0_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_PWM0), ++ GRP_G("uart2", uart2_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_UART2), ++ GRP_G("uart1", uart1_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_UART1), ++ GRP_G("i2c", i2c_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_I2C), ++ GRP("refclk", refclk_grp_mt7628, 1, MT7628_GPIO_MODE_REFCLK), ++ GRP("perst", perst_grp_mt7628, 1, MT7628_GPIO_MODE_PERST), ++ GRP("wdt", wdt_grp_mt7628, 1, MT7628_GPIO_MODE_WDT), ++ GRP("spi", spi_grp_mt7628, 1, MT7628_GPIO_MODE_SPI), ++ GRP_G("sdmode", sd_mode_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_SDMODE), ++ GRP_G("uart0", uart0_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_UART0), ++ GRP_G("i2s", i2s_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_I2S), ++ GRP_G("spi cs1", spi_cs1_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_CS1), ++ GRP_G("spis", spis_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_SPIS), ++ GRP_G("gpio", gpio_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_GPIO), ++ { 0 } ++}; ++ + static __init u32 + mt7620_calc_rate(u32 ref_rate, u32 mul, u32 div) + { +@@ -309,29 +430,42 @@ void __init ralink_clk_init(void) + + xtal_rate = mt7620_get_xtal_rate(); + +- cpu_pll_rate = mt7620_get_cpu_pll_rate(xtal_rate); +- pll_rate = mt7620_get_pll_rate(xtal_rate, cpu_pll_rate); +- +- cpu_rate = mt7620_get_cpu_rate(pll_rate); +- dram_rate = mt7620_get_dram_rate(pll_rate); +- sys_rate = mt7620_get_sys_rate(cpu_rate); +- periph_rate = mt7620_get_periph_rate(xtal_rate); +- + #define RFMT(label) label ":%lu.%03luMHz " + #define RINT(x) ((x) / 1000000) + #define RFRAC(x) (((x) / 1000) % 1000) + +- pr_debug(RFMT("XTAL") RFMT("CPU_PLL") RFMT("PLL"), +- RINT(xtal_rate), RFRAC(xtal_rate), +- RINT(cpu_pll_rate), RFRAC(cpu_pll_rate), +- RINT(pll_rate), RFRAC(pll_rate)); ++ if (mt762x_soc == MT762X_SOC_MT7628AN) { ++ if (xtal_rate == MHZ(40)) ++ cpu_rate = MHZ(580); ++ else ++ cpu_rate = MHZ(575); ++ dram_rate = sys_rate = cpu_rate / 3; ++ periph_rate = MHZ(40); ++ ++ ralink_clk_add("10000d00.uartlite", periph_rate); ++ ralink_clk_add("10000e00.uartlite", periph_rate); ++ } else { ++ cpu_pll_rate = mt7620_get_cpu_pll_rate(xtal_rate); ++ pll_rate = mt7620_get_pll_rate(xtal_rate, cpu_pll_rate); ++ ++ cpu_rate = mt7620_get_cpu_rate(pll_rate); ++ dram_rate = mt7620_get_dram_rate(pll_rate); ++ sys_rate = mt7620_get_sys_rate(cpu_rate); ++ periph_rate = mt7620_get_periph_rate(xtal_rate); ++ ++ pr_debug(RFMT("XTAL") RFMT("CPU_PLL") RFMT("PLL"), ++ RINT(xtal_rate), RFRAC(xtal_rate), ++ RINT(cpu_pll_rate), RFRAC(cpu_pll_rate), ++ RINT(pll_rate), RFRAC(pll_rate)); ++ ++ ralink_clk_add("10000500.uart", periph_rate); ++ } + + pr_debug(RFMT("CPU") RFMT("DRAM") RFMT("SYS") RFMT("PERIPH"), + RINT(cpu_rate), RFRAC(cpu_rate), + RINT(dram_rate), RFRAC(dram_rate), + RINT(sys_rate), RFRAC(sys_rate), + RINT(periph_rate), RFRAC(periph_rate)); +- + #undef RFRAC + #undef RINT + #undef RFMT +@@ -339,12 +473,13 @@ void __init ralink_clk_init(void) + ralink_clk_add("cpu", cpu_rate); + ralink_clk_add("10000100.timer", periph_rate); + ralink_clk_add("10000120.watchdog", periph_rate); +- ralink_clk_add("10000500.uart", periph_rate); + ralink_clk_add("10000b00.spi", sys_rate); + ralink_clk_add("10000c00.uartlite", periph_rate); ++ ralink_clk_add("10000d00.uart1", periph_rate); ++ ralink_clk_add("10000e00.uart2", periph_rate); + ralink_clk_add("10180000.wmac", xtal_rate); + +- if (IS_ENABLED(CONFIG_USB)) { ++ if (IS_ENABLED(CONFIG_USB) && mt762x_soc != MT762X_SOC_MT7628AN) { + /* + * When the CPU goes into sleep mode, the BUS clock will be too low for + * USB to function properly +@@ -367,6 +502,52 @@ void __init ralink_of_remap(void) + panic("Failed to remap core resources"); + } + ++static __init void ++mt7620_dram_init(struct ralink_soc_info *soc_info) ++{ ++ switch (dram_type) { ++ case SYSCFG0_DRAM_TYPE_SDRAM: ++ pr_info("Board has SDRAM\n"); ++ soc_info->mem_size_min = MT7620_SDRAM_SIZE_MIN; ++ soc_info->mem_size_max = MT7620_SDRAM_SIZE_MAX; ++ break; ++ ++ case SYSCFG0_DRAM_TYPE_DDR1: ++ pr_info("Board has DDR1\n"); ++ soc_info->mem_size_min = MT7620_DDR1_SIZE_MIN; ++ soc_info->mem_size_max = MT7620_DDR1_SIZE_MAX; ++ break; ++ ++ case SYSCFG0_DRAM_TYPE_DDR2: ++ pr_info("Board has DDR2\n"); ++ soc_info->mem_size_min = MT7620_DDR2_SIZE_MIN; ++ soc_info->mem_size_max = MT7620_DDR2_SIZE_MAX; ++ break; ++ default: ++ BUG(); ++ } ++} ++ ++static __init void ++mt7628_dram_init(struct ralink_soc_info *soc_info) ++{ ++ switch (dram_type) { ++ case SYSCFG0_DRAM_TYPE_DDR1_MT7628: ++ pr_info("Board has DDR1\n"); ++ soc_info->mem_size_min = MT7620_DDR1_SIZE_MIN; ++ soc_info->mem_size_max = MT7620_DDR1_SIZE_MAX; ++ break; ++ ++ case SYSCFG0_DRAM_TYPE_DDR2_MT7628: ++ pr_info("Board has DDR2\n"); ++ soc_info->mem_size_min = MT7620_DDR2_SIZE_MIN; ++ soc_info->mem_size_max = MT7620_DDR2_SIZE_MAX; ++ break; ++ default: ++ BUG(); ++ } ++} ++ + void prom_soc_init(struct ralink_soc_info *soc_info) + { + void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7620_SYSC_BASE); +@@ -384,18 +565,25 @@ void prom_soc_init(struct ralink_soc_inf + rev = __raw_readl(sysc + SYSC_REG_CHIP_REV); + bga = (rev >> CHIP_REV_PKG_SHIFT) & CHIP_REV_PKG_MASK; + +- if (n0 != MT7620_CHIP_NAME0 || n1 != MT7620_CHIP_NAME1) +- panic("mt7620: unknown SoC, n0:%08x n1:%08x\n", n0, n1); +- +- if (bga) { +- name = "MT7620A"; +- soc_info->compatible = "ralink,mt7620a-soc"; +- } else { +- name = "MT7620N"; +- soc_info->compatible = "ralink,mt7620n-soc"; ++ if (n0 == MT7620_CHIP_NAME0 && n1 == MT7620_CHIP_NAME1) { ++ if (bga) { ++ mt762x_soc = MT762X_SOC_MT7620A; ++ name = "MT7620A"; ++ soc_info->compatible = "ralink,mt7620a-soc"; ++ } else { ++ mt762x_soc = MT762X_SOC_MT7620N; ++ name = "MT7620N"; ++ soc_info->compatible = "ralink,mt7620n-soc"; + #ifdef CONFIG_PCI +- panic("mt7620n is only supported for non pci kernels"); ++ panic("mt7620n is only supported for non pci kernels"); + #endif ++ } ++ } else if (n0 == MT7620_CHIP_NAME0 && n1 == MT7628_CHIP_NAME1) { ++ mt762x_soc = MT762X_SOC_MT7628AN; ++ name = "MT7628AN"; ++ soc_info->compatible = "ralink,mt7628an-soc"; ++ } else { ++ panic("mt762x: unknown SoC, n0:%08x n1:%08x\n", n0, n1); + } + + snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, +@@ -407,28 +595,11 @@ void prom_soc_init(struct ralink_soc_inf + cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0); + dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK; + +- switch (dram_type) { +- case SYSCFG0_DRAM_TYPE_SDRAM: +- pr_info("Board has SDRAM\n"); +- soc_info->mem_size_min = MT7620_SDRAM_SIZE_MIN; +- soc_info->mem_size_max = MT7620_SDRAM_SIZE_MAX; +- break; +- +- case SYSCFG0_DRAM_TYPE_DDR1: +- pr_info("Board has DDR1\n"); +- soc_info->mem_size_min = MT7620_DDR1_SIZE_MIN; +- soc_info->mem_size_max = MT7620_DDR1_SIZE_MAX; +- break; +- +- case SYSCFG0_DRAM_TYPE_DDR2: +- pr_info("Board has DDR2\n"); +- soc_info->mem_size_min = MT7620_DDR2_SIZE_MIN; +- soc_info->mem_size_max = MT7620_DDR2_SIZE_MAX; +- break; +- default: +- BUG(); +- } + soc_info->mem_base = MT7620_DRAM_BASE; ++ if (mt762x_soc == MT762X_SOC_MT7628AN) ++ mt7628_dram_init(soc_info); ++ else ++ mt7620_dram_init(soc_info); + + pmu0 = __raw_readl(sysc + PMU0_CFG); + pmu1 = __raw_readl(sysc + PMU1_CFG); +@@ -437,4 +608,9 @@ void prom_soc_init(struct ralink_soc_inf + (pmu0 & PMU_SW_SET) ? ("sw") : ("hw")); + pr_info("Digital PMU set to %s control\n", + (pmu1 & DIG_SW_SEL) ? ("sw") : ("hw")); ++ ++ if (mt762x_soc == MT762X_SOC_MT7628AN) ++ rt2880_pinmux_data = mt7628an_pinmux_data; ++ else ++ rt2880_pinmux_data = mt7620a_pinmux_data; + } diff --git a/target/linux/ramips/patches-3.18/0027-serial-ralink-adds-mt7620-serial.patch b/target/linux/ramips/patches-3.18/0027-serial-ralink-adds-mt7620-serial.patch new file mode 100644 index 0000000..c7f59c1 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0027-serial-ralink-adds-mt7620-serial.patch @@ -0,0 +1,23 @@ +From 0b24e0e6bf2d9a1ca5f95446bc025dafc226998c Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Fri, 15 Mar 2013 18:16:01 +0100 +Subject: [PATCH 27/57] serial: ralink: adds mt7620 serial + +Add the config symbol for Mediatek7620 SoC to SERIAL_8250_RT288X + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + drivers/tty/serial/8250/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/tty/serial/8250/Kconfig ++++ b/drivers/tty/serial/8250/Kconfig +@@ -297,7 +297,7 @@ config SERIAL_8250_EM + + config SERIAL_8250_RT288X + bool "Ralink RT288x/RT305x/RT3662/RT3883 serial port support" +- depends on SERIAL_8250 && (SOC_RT288X || SOC_RT305X || SOC_RT3883) ++ depends on SERIAL_8250 && (SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620) + help + If you have a Ralink RT288x/RT305x SoC based board and want to use the + serial port, say Y to this option. The driver can handle up to 2 serial diff --git a/target/linux/ramips/patches-3.18/0028-serial-ralink-the-core-has-a-size-of-0x100-and-not-0.patch b/target/linux/ramips/patches-3.18/0028-serial-ralink-the-core-has-a-size-of-0x100-and-not-0.patch new file mode 100644 index 0000000..ab60f2d --- /dev/null +++ b/target/linux/ramips/patches-3.18/0028-serial-ralink-the-core-has-a-size-of-0x100-and-not-0.patch @@ -0,0 +1,22 @@ +From b9ba09038dab4d824176ea2c2f2b73f49b567217 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 16 Mar 2014 04:52:01 +0000 +Subject: [PATCH 28/57] serial: ralink: the core has a size of 0x100 and not + 0x1000 + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + drivers/tty/serial/8250/8250_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/tty/serial/8250/8250_core.c ++++ b/drivers/tty/serial/8250/8250_core.c +@@ -2634,7 +2634,7 @@ serial8250_pm(struct uart_port *port, un + static unsigned int serial8250_port_size(struct uart_8250_port *pt) + { + if (pt->port.iotype == UPIO_AU) +- return 0x1000; ++ return 0x100; + if (is_omap1_8250(pt)) + return 0x16 << pt->port.regshift; + diff --git a/target/linux/ramips/patches-3.18/0029-serial-of-allow-au1x00-and-rt288x-to-load-from-OF.patch b/target/linux/ramips/patches-3.18/0029-serial-of-allow-au1x00-and-rt288x-to-load-from-OF.patch new file mode 100644 index 0000000..ef29697 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0029-serial-of-allow-au1x00-and-rt288x-to-load-from-OF.patch @@ -0,0 +1,27 @@ +From 49b47dfcef1353cd28eac8f64170e75d28ce4311 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 14 Jul 2013 23:18:57 +0200 +Subject: [PATCH 29/57] serial: of: allow au1x00 and rt288x to load from OF + +In order to make serial_8250 loadable via OF on Au1x00 and Ralink WiSoC we need +to default the iotype to UPIO_AU. + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + drivers/tty/serial/of_serial.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/tty/serial/of_serial.c ++++ b/drivers/tty/serial/of_serial.c +@@ -102,7 +102,10 @@ static int of_platform_serial_setup(stru + port->fifosize = prop; + + port->irq = irq_of_parse_and_map(np, 0); +- port->iotype = UPIO_MEM; ++ if (of_device_is_compatible(np, "ralink,rt2880-uart")) ++ port->iotype = UPIO_AU; ++ else ++ port->iotype = UPIO_MEM; + if (of_property_read_u32(np, "reg-io-width", &prop) == 0) { + switch (prop) { + case 1: diff --git a/target/linux/ramips/patches-3.18/0030-GPIO-add-named-gpio-exports.patch b/target/linux/ramips/patches-3.18/0030-GPIO-add-named-gpio-exports.patch new file mode 100644 index 0000000..855da68 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0030-GPIO-add-named-gpio-exports.patch @@ -0,0 +1,166 @@ +From cc809a441d8f2924f785eb863dfa6aef47a25b0b Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Tue, 12 Aug 2014 20:49:27 +0200 +Subject: [PATCH 30/36] GPIO: add named gpio exports + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + drivers/gpio/gpiolib-of.c | 68 +++++++++++++++++++++++++++++++++++++++++ + drivers/gpio/gpiolib.c | 11 +++++-- + include/asm-generic/gpio.h | 5 +++ + include/linux/gpio/consumer.h | 8 +++++ + 4 files changed, 90 insertions(+), 2 deletions(-) + +--- a/drivers/gpio/gpiolib-of.c ++++ b/drivers/gpio/gpiolib-of.c +@@ -22,6 +22,8 @@ + #include <linux/of_gpio.h> + #include <linux/pinctrl/pinctrl.h> + #include <linux/slab.h> ++#include <linux/init.h> ++#include <linux/platform_device.h> + + #include "gpiolib.h" + +@@ -316,3 +318,69 @@ void of_gpiochip_remove(struct gpio_chip + gpiochip_remove_pin_ranges(chip); + of_node_put(chip->of_node); + } ++ ++static struct of_device_id gpio_export_ids[] = { ++ { .compatible = "gpio-export" }, ++ { /* sentinel */ } ++}; ++ ++static int __init of_gpio_export_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct device_node *cnp; ++ u32 val; ++ int nb = 0; ++ ++ for_each_child_of_node(np, cnp) { ++ const char *name = NULL; ++ int gpio; ++ bool dmc; ++ int max_gpio = 1; ++ int i; ++ ++ of_property_read_string(cnp, "gpio-export,name", &name); ++ ++ if (!name) ++ max_gpio = of_gpio_count(cnp); ++ ++ for (i = 0; i < max_gpio; i++) { ++ unsigned flags = 0; ++ enum of_gpio_flags of_flags; ++ ++ gpio = of_get_gpio_flags(cnp, i, &of_flags); ++ ++ if (of_flags == OF_GPIO_ACTIVE_LOW) ++ flags |= GPIOF_ACTIVE_LOW; ++ ++ if (!of_property_read_u32(cnp, "gpio-export,output", &val)) ++ flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; ++ else ++ flags |= GPIOF_IN; ++ ++ if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np))) ++ continue; ++ ++ dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change"); ++ gpio_export_with_name(gpio, dmc, name); ++ nb++; ++ } ++ } ++ ++ dev_info(&pdev->dev, "%d gpio(s) exported\n", nb); ++ ++ return 0; ++} ++ ++static struct platform_driver gpio_export_driver = { ++ .driver = { ++ .name = "gpio-export", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(gpio_export_ids), ++ }, ++}; ++ ++static int __init of_gpio_export_init(void) ++{ ++ return platform_driver_probe(&gpio_export_driver, of_gpio_export_probe); ++} ++device_initcall(of_gpio_export_init); +--- a/include/asm-generic/gpio.h ++++ b/include/asm-generic/gpio.h +@@ -123,6 +123,12 @@ static inline int gpio_export(unsigned g + return gpiod_export(gpio_to_desc(gpio), direction_may_change); + } + ++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); ++static inline int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name) ++{ ++ return __gpiod_export(gpio_to_desc(gpio), direction_may_change, name); ++} ++ + static inline int gpio_export_link(struct device *dev, const char *name, + unsigned gpio) + { +--- a/include/linux/gpio/consumer.h ++++ b/include/linux/gpio/consumer.h +@@ -323,6 +323,7 @@ static inline int desc_to_gpio(const str + + #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) + ++int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); + int gpiod_export(struct gpio_desc *desc, bool direction_may_change); + int gpiod_export_link(struct device *dev, const char *name, + struct gpio_desc *desc); +@@ -331,6 +332,13 @@ void gpiod_unexport(struct gpio_desc *de + + #else /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ + ++static inline int _gpiod_export(struct gpio_desc *desc, ++ bool direction_may_change, ++ const char *name) ++{ ++ return -ENOSYS; ++} ++ + static inline int gpiod_export(struct gpio_desc *desc, + bool direction_may_change) + { +--- a/drivers/gpio/gpiolib-sysfs.c ++++ b/drivers/gpio/gpiolib-sysfs.c +@@ -517,7 +517,7 @@ static struct class gpio_class = { + * + * Returns zero on success, else an error. + */ +-int gpiod_export(struct gpio_desc *desc, bool direction_may_change) ++int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name) + { + struct gpio_chip *chip; + unsigned long flags; +@@ -566,6 +566,8 @@ int gpiod_export(struct gpio_desc *desc, + offset = gpio_chip_hwgpio(desc); + if (desc->chip->names && desc->chip->names[offset]) + ioname = desc->chip->names[offset]; ++ if (name) ++ ioname = name; + + dev = device_create_with_groups(&gpio_class, desc->chip->dev, + MKDEV(0, 0), desc, gpio_groups, +@@ -602,6 +604,12 @@ fail_unlock: + gpiod_dbg(desc, "%s: status %d\n", __func__, status); + return status; + } ++EXPORT_SYMBOL_GPL(__gpiod_export); ++ ++int gpiod_export(struct gpio_desc *desc, bool direction_may_change) ++{ ++ return __gpiod_export(desc, direction_may_change, NULL); ++} + EXPORT_SYMBOL_GPL(gpiod_export); + + static int match_export(struct device *dev, const void *data) diff --git a/target/linux/ramips/patches-3.18/0030-pinctrl-ralink-add-pinctrl-driver.patch b/target/linux/ramips/patches-3.18/0030-pinctrl-ralink-add-pinctrl-driver.patch new file mode 100644 index 0000000..63e8401 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0030-pinctrl-ralink-add-pinctrl-driver.patch @@ -0,0 +1,1404 @@ +From 675c6ddd9432c39f508f9d6bdda17d9c675788cf Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 27 Jul 2014 09:34:05 +0100 +Subject: [PATCH 30/57] pinctrl: ralink: add pinctrl driver + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/Kconfig | 2 + + arch/mips/include/asm/mach-ralink/mt7620.h | 41 ++- + arch/mips/include/asm/mach-ralink/pinmux.h | 53 ++++ + arch/mips/include/asm/mach-ralink/rt305x.h | 35 ++- + arch/mips/include/asm/mach-ralink/rt3883.h | 16 +- + arch/mips/ralink/common.h | 19 -- + arch/mips/ralink/mt7620.c | 159 +++------- + arch/mips/ralink/rt288x.c | 62 ++-- + arch/mips/ralink/rt305x.c | 151 ++++----- + arch/mips/ralink/rt3883.c | 173 +++-------- + drivers/pinctrl/Kconfig | 5 + + drivers/pinctrl/Makefile | 1 + + drivers/pinctrl/pinctrl-rt2880.c | 467 ++++++++++++++++++++++++++++ + 13 files changed, 764 insertions(+), 420 deletions(-) + create mode 100644 arch/mips/include/asm/mach-ralink/pinmux.h + create mode 100644 drivers/pinctrl/pinctrl-rt2880.c + +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -453,6 +453,8 @@ config RALINK + select CLKDEV_LOOKUP + select ARCH_HAS_RESET_CONTROLLER + select RESET_CONTROLLER ++ select PINCTRL ++ select PINCTRL_RT2880 + + config SGI_IP22 + bool "SGI IP22 (Indy/Indigo2)" +--- a/arch/mips/include/asm/mach-ralink/mt7620.h ++++ b/arch/mips/include/asm/mach-ralink/mt7620.h +@@ -90,7 +90,6 @@ enum mt762x_soc_type { + #define MT7620_DDR2_SIZE_MIN 32 + #define MT7620_DDR2_SIZE_MAX 256 + +-#define MT7620_GPIO_MODE_I2C BIT(0) + #define MT7620_GPIO_MODE_UART0_SHIFT 2 + #define MT7620_GPIO_MODE_UART0_MASK 0x7 + #define MT7620_GPIO_MODE_UART0(x) ((x) << MT7620_GPIO_MODE_UART0_SHIFT) +@@ -102,16 +101,36 @@ enum mt762x_soc_type { + #define MT7620_GPIO_MODE_GPIO_UARTF 0x5 + #define MT7620_GPIO_MODE_GPIO_I2S 0x6 + #define MT7620_GPIO_MODE_GPIO 0x7 +-#define MT7620_GPIO_MODE_UART1 BIT(5) +-#define MT7620_GPIO_MODE_MDIO BIT(8) +-#define MT7620_GPIO_MODE_RGMII1 BIT(9) +-#define MT7620_GPIO_MODE_RGMII2 BIT(10) +-#define MT7620_GPIO_MODE_SPI BIT(11) +-#define MT7620_GPIO_MODE_SPI_REF_CLK BIT(12) +-#define MT7620_GPIO_MODE_WLED BIT(13) +-#define MT7620_GPIO_MODE_JTAG BIT(15) +-#define MT7620_GPIO_MODE_EPHY BIT(15) +-#define MT7620_GPIO_MODE_WDT BIT(22) ++ ++#define MT7620_GPIO_MODE_NAND 0 ++#define MT7620_GPIO_MODE_SD 1 ++#define MT7620_GPIO_MODE_ND_SD_GPIO 2 ++#define MT7620_GPIO_MODE_ND_SD_MASK 0x3 ++#define MT7620_GPIO_MODE_ND_SD_SHIFT 18 ++ ++#define MT7620_GPIO_MODE_PCIE_RST 0 ++#define MT7620_GPIO_MODE_PCIE_REF 1 ++#define MT7620_GPIO_MODE_PCIE_GPIO 2 ++#define MT7620_GPIO_MODE_PCIE_MASK 0x3 ++#define MT7620_GPIO_MODE_PCIE_SHIFT 16 ++ ++#define MT7620_GPIO_MODE_WDT_RST 0 ++#define MT7620_GPIO_MODE_WDT_REF 1 ++#define MT7620_GPIO_MODE_WDT_GPIO 2 ++#define MT7620_GPIO_MODE_WDT_MASK 0x3 ++#define MT7620_GPIO_MODE_WDT_SHIFT 21 ++ ++#define MT7620_GPIO_MODE_I2C 0 ++#define MT7620_GPIO_MODE_UART1 5 ++#define MT7620_GPIO_MODE_MDIO 8 ++#define MT7620_GPIO_MODE_RGMII1 9 ++#define MT7620_GPIO_MODE_RGMII2 10 ++#define MT7620_GPIO_MODE_SPI 11 ++#define MT7620_GPIO_MODE_SPI_REF_CLK 12 ++#define MT7620_GPIO_MODE_WLED 13 ++#define MT7620_GPIO_MODE_JTAG 15 ++#define MT7620_GPIO_MODE_EPHY 15 ++#define MT7620_GPIO_MODE_PA 20 + + static inline int mt7620_get_eco(void) + { +--- /dev/null ++++ b/arch/mips/include/asm/mach-ralink/pinmux.h +@@ -0,0 +1,53 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * publishhed by the Free Software Foundation. ++ * ++ * Copyright (C) 2012 John Crispin <blogic@openwrt.org> ++ */ ++ ++#ifndef _RT288X_PINMUX_H__ ++#define _RT288X_PINMUX_H__ ++ ++#define FUNC(name, value, pin_first, pin_count) { name, value, pin_first, pin_count } ++#define GRP(_name, _func, _mask, _shift) \ ++ { .name = _name, .mask = _mask, .shift = _shift, \ ++ .func = _func, .gpio = _mask, \ ++ .func_count = ARRAY_SIZE(_func) } ++ ++#define GRP_G(_name, _func, _mask, _gpio, _shift) \ ++ { .name = _name, .mask = _mask, .shift = _shift, \ ++ .func = _func, .gpio = _gpio, \ ++ .func_count = ARRAY_SIZE(_func) } ++ ++struct rt2880_pmx_group; ++ ++struct rt2880_pmx_func { ++ const char *name; ++ const char value; ++ ++ int pin_first; ++ int pin_count; ++ int *pins; ++ ++ int *groups; ++ int group_count; ++ ++ int enabled; ++}; ++ ++struct rt2880_pmx_group { ++ const char *name; ++ int enabled; ++ ++ const u32 shift; ++ const char mask; ++ const char gpio; ++ ++ struct rt2880_pmx_func *func; ++ int func_count; ++}; ++ ++extern struct rt2880_pmx_group *rt2880_pinmux_data; ++ ++#endif +--- a/arch/mips/include/asm/mach-ralink/rt305x.h ++++ b/arch/mips/include/asm/mach-ralink/rt305x.h +@@ -125,24 +125,29 @@ static inline int soc_is_rt5350(void) + #define RT305X_GPIO_GE0_TXD0 40 + #define RT305X_GPIO_GE0_RXCLK 51 + +-#define RT305X_GPIO_MODE_I2C BIT(0) +-#define RT305X_GPIO_MODE_SPI BIT(1) + #define RT305X_GPIO_MODE_UART0_SHIFT 2 + #define RT305X_GPIO_MODE_UART0_MASK 0x7 + #define RT305X_GPIO_MODE_UART0(x) ((x) << RT305X_GPIO_MODE_UART0_SHIFT) +-#define RT305X_GPIO_MODE_UARTF 0x0 +-#define RT305X_GPIO_MODE_PCM_UARTF 0x1 +-#define RT305X_GPIO_MODE_PCM_I2S 0x2 +-#define RT305X_GPIO_MODE_I2S_UARTF 0x3 +-#define RT305X_GPIO_MODE_PCM_GPIO 0x4 +-#define RT305X_GPIO_MODE_GPIO_UARTF 0x5 +-#define RT305X_GPIO_MODE_GPIO_I2S 0x6 +-#define RT305X_GPIO_MODE_GPIO 0x7 +-#define RT305X_GPIO_MODE_UART1 BIT(5) +-#define RT305X_GPIO_MODE_JTAG BIT(6) +-#define RT305X_GPIO_MODE_MDIO BIT(7) +-#define RT305X_GPIO_MODE_SDRAM BIT(8) +-#define RT305X_GPIO_MODE_RGMII BIT(9) ++#define RT305X_GPIO_MODE_UARTF 0 ++#define RT305X_GPIO_MODE_PCM_UARTF 1 ++#define RT305X_GPIO_MODE_PCM_I2S 2 ++#define RT305X_GPIO_MODE_I2S_UARTF 3 ++#define RT305X_GPIO_MODE_PCM_GPIO 4 ++#define RT305X_GPIO_MODE_GPIO_UARTF 5 ++#define RT305X_GPIO_MODE_GPIO_I2S 6 ++#define RT305X_GPIO_MODE_GPIO 7 ++ ++#define RT305X_GPIO_MODE_I2C 0 ++#define RT305X_GPIO_MODE_SPI 1 ++#define RT305X_GPIO_MODE_UART1 5 ++#define RT305X_GPIO_MODE_JTAG 6 ++#define RT305X_GPIO_MODE_MDIO 7 ++#define RT305X_GPIO_MODE_SDRAM 8 ++#define RT305X_GPIO_MODE_RGMII 9 ++#define RT5350_GPIO_MODE_PHY_LED 14 ++#define RT5350_GPIO_MODE_SPI_CS1 21 ++#define RT3352_GPIO_MODE_LNA 18 ++#define RT3352_GPIO_MODE_PA 20 + + #define RT3352_SYSC_REG_SYSCFG0 0x010 + #define RT3352_SYSC_REG_SYSCFG1 0x014 +--- a/arch/mips/include/asm/mach-ralink/rt3883.h ++++ b/arch/mips/include/asm/mach-ralink/rt3883.h +@@ -112,8 +112,6 @@ + #define RT3883_CLKCFG1_PCI_CLK_EN BIT(19) + #define RT3883_CLKCFG1_UPHY0_CLK_EN BIT(18) + +-#define RT3883_GPIO_MODE_I2C BIT(0) +-#define RT3883_GPIO_MODE_SPI BIT(1) + #define RT3883_GPIO_MODE_UART0_SHIFT 2 + #define RT3883_GPIO_MODE_UART0_MASK 0x7 + #define RT3883_GPIO_MODE_UART0(x) ((x) << RT3883_GPIO_MODE_UART0_SHIFT) +@@ -125,11 +123,15 @@ + #define RT3883_GPIO_MODE_GPIO_UARTF 0x5 + #define RT3883_GPIO_MODE_GPIO_I2S 0x6 + #define RT3883_GPIO_MODE_GPIO 0x7 +-#define RT3883_GPIO_MODE_UART1 BIT(5) +-#define RT3883_GPIO_MODE_JTAG BIT(6) +-#define RT3883_GPIO_MODE_MDIO BIT(7) +-#define RT3883_GPIO_MODE_GE1 BIT(9) +-#define RT3883_GPIO_MODE_GE2 BIT(10) ++ ++#define RT3883_GPIO_MODE_I2C 0 ++#define RT3883_GPIO_MODE_SPI 1 ++#define RT3883_GPIO_MODE_UART1 5 ++#define RT3883_GPIO_MODE_JTAG 6 ++#define RT3883_GPIO_MODE_MDIO 7 ++#define RT3883_GPIO_MODE_GE1 9 ++#define RT3883_GPIO_MODE_GE2 10 ++ + #define RT3883_GPIO_MODE_PCI_SHIFT 11 + #define RT3883_GPIO_MODE_PCI_MASK 0x7 + #define RT3883_GPIO_MODE_PCI (RT3883_GPIO_MODE_PCI_MASK << RT3883_GPIO_MODE_PCI_SHIFT) +--- a/arch/mips/ralink/common.h ++++ b/arch/mips/ralink/common.h +@@ -11,25 +11,6 @@ + + #define RAMIPS_SYS_TYPE_LEN 32 + +-struct ralink_pinmux_grp { +- const char *name; +- u32 mask; +- int gpio_first; +- int gpio_last; +-}; +- +-struct ralink_pinmux { +- struct ralink_pinmux_grp *mode; +- struct ralink_pinmux_grp *uart; +- int uart_shift; +- u32 uart_mask; +- void (*wdt_reset)(void); +- struct ralink_pinmux_grp *pci; +- int pci_shift; +- u32 pci_mask; +-}; +-extern struct ralink_pinmux rt_gpio_pinmux; +- + struct ralink_soc_info { + unsigned char sys_type[RAMIPS_SYS_TYPE_LEN]; + unsigned char *compatible; +--- a/arch/mips/ralink/mt7620.c ++++ b/arch/mips/ralink/mt7620.c +@@ -17,6 +17,7 @@ + #include <asm/mipsregs.h> + #include <asm/mach-ralink/ralink_regs.h> + #include <asm/mach-ralink/mt7620.h> ++#include <asm/mach-ralink/pinmux.h> + + #include "common.h" + +@@ -47,118 +48,58 @@ enum mt762x_soc_type mt762x_soc; + /* does the board have sdram or ddram */ + static int dram_type; + +-static struct ralink_pinmux_grp mode_mux[] = { +- { +- .name = "i2c", +- .mask = MT7620_GPIO_MODE_I2C, +- .gpio_first = 1, +- .gpio_last = 2, +- }, { +- .name = "spi", +- .mask = MT7620_GPIO_MODE_SPI, +- .gpio_first = 3, +- .gpio_last = 6, +- }, { +- .name = "uartlite", +- .mask = MT7620_GPIO_MODE_UART1, +- .gpio_first = 15, +- .gpio_last = 16, +- }, { +- .name = "wdt", +- .mask = MT7620_GPIO_MODE_WDT, +- .gpio_first = 17, +- .gpio_last = 17, +- }, { +- .name = "mdio", +- .mask = MT7620_GPIO_MODE_MDIO, +- .gpio_first = 22, +- .gpio_last = 23, +- }, { +- .name = "rgmii1", +- .mask = MT7620_GPIO_MODE_RGMII1, +- .gpio_first = 24, +- .gpio_last = 35, +- }, { +- .name = "spi refclk", +- .mask = MT7620_GPIO_MODE_SPI_REF_CLK, +- .gpio_first = 37, +- .gpio_last = 39, +- }, { +- .name = "jtag", +- .mask = MT7620_GPIO_MODE_JTAG, +- .gpio_first = 40, +- .gpio_last = 44, +- }, { +- /* shared lines with jtag */ +- .name = "ephy", +- .mask = MT7620_GPIO_MODE_EPHY, +- .gpio_first = 40, +- .gpio_last = 44, +- }, { +- .name = "nand", +- .mask = MT7620_GPIO_MODE_JTAG, +- .gpio_first = 45, +- .gpio_last = 59, +- }, { +- .name = "rgmii2", +- .mask = MT7620_GPIO_MODE_RGMII2, +- .gpio_first = 60, +- .gpio_last = 71, +- }, { +- .name = "wled", +- .mask = MT7620_GPIO_MODE_WLED, +- .gpio_first = 72, +- .gpio_last = 72, +- }, {0} ++static struct rt2880_pmx_func i2c_grp[] = { FUNC("i2c", 0, 1, 2) }; ++static struct rt2880_pmx_func spi_grp[] = { FUNC("spi", 0, 3, 4) }; ++static struct rt2880_pmx_func uartlite_grp[] = { FUNC("uartlite", 0, 15, 2) }; ++static struct rt2880_pmx_func mdio_grp[] = { FUNC("mdio", 0, 22, 2) }; ++static struct rt2880_pmx_func rgmii1_grp[] = { FUNC("rgmii1", 0, 24, 12) }; ++static struct rt2880_pmx_func refclk_grp[] = { FUNC("spi refclk", 0, 37, 3) }; ++static struct rt2880_pmx_func ephy_grp[] = { FUNC("ephy", 0, 40, 5) }; ++static struct rt2880_pmx_func rgmii2_grp[] = { FUNC("rgmii2", 0, 60, 12) }; ++static struct rt2880_pmx_func wled_grp[] = { FUNC("wled", 0, 72, 1) }; ++static struct rt2880_pmx_func pa_grp[] = { FUNC("pa", 0, 18, 4) }; ++static struct rt2880_pmx_func uartf_grp[] = { ++ FUNC("uartf", MT7620_GPIO_MODE_UARTF, 7, 8), ++ FUNC("pcm uartf", MT7620_GPIO_MODE_PCM_UARTF, 7, 8), ++ FUNC("pcm i2s", MT7620_GPIO_MODE_PCM_I2S, 7, 8), ++ FUNC("i2s uartf", MT7620_GPIO_MODE_I2S_UARTF, 7, 8), ++ FUNC("pcm gpio", MT7620_GPIO_MODE_PCM_GPIO, 11, 4), ++ FUNC("gpio uartf", MT7620_GPIO_MODE_GPIO_UARTF, 7, 4), ++ FUNC("gpio i2s", MT7620_GPIO_MODE_GPIO_I2S, 7, 4), + }; +- +-static struct ralink_pinmux_grp uart_mux[] = { +- { +- .name = "uartf", +- .mask = MT7620_GPIO_MODE_UARTF, +- .gpio_first = 7, +- .gpio_last = 14, +- }, { +- .name = "pcm uartf", +- .mask = MT7620_GPIO_MODE_PCM_UARTF, +- .gpio_first = 7, +- .gpio_last = 14, +- }, { +- .name = "pcm i2s", +- .mask = MT7620_GPIO_MODE_PCM_I2S, +- .gpio_first = 7, +- .gpio_last = 14, +- }, { +- .name = "i2s uartf", +- .mask = MT7620_GPIO_MODE_I2S_UARTF, +- .gpio_first = 7, +- .gpio_last = 14, +- }, { +- .name = "pcm gpio", +- .mask = MT7620_GPIO_MODE_PCM_GPIO, +- .gpio_first = 11, +- .gpio_last = 14, +- }, { +- .name = "gpio uartf", +- .mask = MT7620_GPIO_MODE_GPIO_UARTF, +- .gpio_first = 7, +- .gpio_last = 10, +- }, { +- .name = "gpio i2s", +- .mask = MT7620_GPIO_MODE_GPIO_I2S, +- .gpio_first = 7, +- .gpio_last = 10, +- }, { +- .name = "gpio", +- .mask = MT7620_GPIO_MODE_GPIO, +- }, {0} ++static struct rt2880_pmx_func wdt_grp[] = { ++ FUNC("wdt rst", 0, 17, 1), ++ FUNC("wdt refclk", 0, 17, 1), ++ }; ++static struct rt2880_pmx_func pcie_rst_grp[] = { ++ FUNC("pcie rst", MT7620_GPIO_MODE_PCIE_RST, 36, 1), ++ FUNC("pcie refclk", MT7620_GPIO_MODE_PCIE_REF, 36, 1) ++}; ++static struct rt2880_pmx_func nd_sd_grp[] = { ++ FUNC("nand", MT7620_GPIO_MODE_NAND, 45, 15), ++ FUNC("sd", MT7620_GPIO_MODE_SD, 45, 15) + }; + +-struct ralink_pinmux rt_gpio_pinmux = { +- .mode = mode_mux, +- .uart = uart_mux, +- .uart_shift = MT7620_GPIO_MODE_UART0_SHIFT, +- .uart_mask = MT7620_GPIO_MODE_UART0_MASK, ++static struct rt2880_pmx_group mt7620a_pinmux_data[] = { ++ GRP("i2c", i2c_grp, 1, MT7620_GPIO_MODE_I2C), ++ GRP("uartf", uartf_grp, MT7620_GPIO_MODE_UART0_MASK, ++ MT7620_GPIO_MODE_UART0_SHIFT), ++ GRP("spi", spi_grp, 1, MT7620_GPIO_MODE_SPI), ++ GRP("uartlite", uartlite_grp, 1, MT7620_GPIO_MODE_UART1), ++ GRP_G("wdt", wdt_grp, MT7620_GPIO_MODE_WDT_MASK, ++ MT7620_GPIO_MODE_WDT_GPIO, MT7620_GPIO_MODE_WDT_SHIFT), ++ GRP("mdio", mdio_grp, 1, MT7620_GPIO_MODE_MDIO), ++ GRP("rgmii1", rgmii1_grp, 1, MT7620_GPIO_MODE_RGMII1), ++ GRP("spi refclk", refclk_grp, 1, MT7620_GPIO_MODE_SPI_REF_CLK), ++ GRP_G("pcie", pcie_rst_grp, MT7620_GPIO_MODE_PCIE_MASK, ++ MT7620_GPIO_MODE_PCIE_GPIO, MT7620_GPIO_MODE_PCIE_SHIFT), ++ GRP_G("nd_sd", nd_sd_grp, MT7620_GPIO_MODE_ND_SD_MASK, ++ MT7620_GPIO_MODE_ND_SD_GPIO, MT7620_GPIO_MODE_ND_SD_SHIFT), ++ GRP("rgmii2", rgmii2_grp, 1, MT7620_GPIO_MODE_RGMII2), ++ GRP("wled", wled_grp, 1, MT7620_GPIO_MODE_WLED), ++ GRP("ephy", ephy_grp, 1, MT7620_GPIO_MODE_EPHY), ++ GRP("pa", pa_grp, 1, MT7620_GPIO_MODE_PA), ++ { 0 } + }; + + static struct rt2880_pmx_func pwm1_grp_mt7628[] = { +--- a/arch/mips/ralink/rt288x.c ++++ b/arch/mips/ralink/rt288x.c +@@ -17,46 +17,27 @@ + #include <asm/mipsregs.h> + #include <asm/mach-ralink/ralink_regs.h> + #include <asm/mach-ralink/rt288x.h> ++#include <asm/mach-ralink/pinmux.h> + + #include "common.h" + +-static struct ralink_pinmux_grp mode_mux[] = { +- { +- .name = "i2c", +- .mask = RT2880_GPIO_MODE_I2C, +- .gpio_first = 1, +- .gpio_last = 2, +- }, { +- .name = "spi", +- .mask = RT2880_GPIO_MODE_SPI, +- .gpio_first = 3, +- .gpio_last = 6, +- }, { +- .name = "uartlite", +- .mask = RT2880_GPIO_MODE_UART0, +- .gpio_first = 7, +- .gpio_last = 14, +- }, { +- .name = "jtag", +- .mask = RT2880_GPIO_MODE_JTAG, +- .gpio_first = 17, +- .gpio_last = 21, +- }, { +- .name = "mdio", +- .mask = RT2880_GPIO_MODE_MDIO, +- .gpio_first = 22, +- .gpio_last = 23, +- }, { +- .name = "sdram", +- .mask = RT2880_GPIO_MODE_SDRAM, +- .gpio_first = 24, +- .gpio_last = 39, +- }, { +- .name = "pci", +- .mask = RT2880_GPIO_MODE_PCI, +- .gpio_first = 40, +- .gpio_last = 71, +- }, {0} ++static struct rt2880_pmx_func i2c_func[] = { FUNC("i2c", 0, 1, 2) }; ++static struct rt2880_pmx_func spi_func[] = { FUNC("spi", 0, 3, 4) }; ++static struct rt2880_pmx_func uartlite_func[] = { FUNC("uartlite", 0, 7, 8) }; ++static struct rt2880_pmx_func jtag_func[] = { FUNC("jtag", 0, 17, 5) }; ++static struct rt2880_pmx_func mdio_func[] = { FUNC("mdio", 0, 22, 2) }; ++static struct rt2880_pmx_func sdram_func[] = { FUNC("sdram", 0, 24, 16) }; ++static struct rt2880_pmx_func pci_func[] = { FUNC("pci", 0, 40, 32) }; ++ ++static struct rt2880_pmx_group rt2880_pinmux_data_act[] = { ++ GRP("i2c", i2c_func, 1, RT2880_GPIO_MODE_I2C), ++ GRP("spi", spi_func, 1, RT2880_GPIO_MODE_SPI), ++ GRP("uartlite", uartlite_func, 1, RT2880_GPIO_MODE_UART0), ++ GRP("jtag", jtag_func, 1, RT2880_GPIO_MODE_JTAG), ++ GRP("mdio", mdio_func, 1, RT2880_GPIO_MODE_MDIO), ++ GRP("sdram", sdram_func, 1, RT2880_GPIO_MODE_SDRAM), ++ GRP("pci", pci_func, 1, RT2880_GPIO_MODE_PCI), ++ { 0 } + }; + + static void rt288x_wdt_reset(void) +@@ -69,11 +50,6 @@ static void rt288x_wdt_reset(void) + rt_sysc_w32(t, SYSC_REG_CLKCFG); + } + +-struct ralink_pinmux rt_gpio_pinmux = { +- .mode = mode_mux, +- .wdt_reset = rt288x_wdt_reset, +-}; +- + void __init ralink_clk_init(void) + { + unsigned long cpu_rate, wmac_rate = 40000000; +@@ -141,4 +117,6 @@ void prom_soc_init(struct ralink_soc_inf + soc_info->mem_base = RT2880_SDRAM_BASE; + soc_info->mem_size_min = RT2880_MEM_SIZE_MIN; + soc_info->mem_size_max = RT2880_MEM_SIZE_MAX; ++ ++ rt2880_pinmux_data = rt2880_pinmux_data_act; + } +--- a/arch/mips/ralink/rt305x.c ++++ b/arch/mips/ralink/rt305x.c +@@ -17,90 +17,76 @@ + #include <asm/mipsregs.h> + #include <asm/mach-ralink/ralink_regs.h> + #include <asm/mach-ralink/rt305x.h> ++#include <asm/mach-ralink/pinmux.h> + + #include "common.h" + + enum rt305x_soc_type rt305x_soc; + +-static struct ralink_pinmux_grp mode_mux[] = { +- { +- .name = "i2c", +- .mask = RT305X_GPIO_MODE_I2C, +- .gpio_first = RT305X_GPIO_I2C_SD, +- .gpio_last = RT305X_GPIO_I2C_SCLK, +- }, { +- .name = "spi", +- .mask = RT305X_GPIO_MODE_SPI, +- .gpio_first = RT305X_GPIO_SPI_EN, +- .gpio_last = RT305X_GPIO_SPI_CLK, +- }, { +- .name = "uartlite", +- .mask = RT305X_GPIO_MODE_UART1, +- .gpio_first = RT305X_GPIO_UART1_TXD, +- .gpio_last = RT305X_GPIO_UART1_RXD, +- }, { +- .name = "jtag", +- .mask = RT305X_GPIO_MODE_JTAG, +- .gpio_first = RT305X_GPIO_JTAG_TDO, +- .gpio_last = RT305X_GPIO_JTAG_TDI, +- }, { +- .name = "mdio", +- .mask = RT305X_GPIO_MODE_MDIO, +- .gpio_first = RT305X_GPIO_MDIO_MDC, +- .gpio_last = RT305X_GPIO_MDIO_MDIO, +- }, { +- .name = "sdram", +- .mask = RT305X_GPIO_MODE_SDRAM, +- .gpio_first = RT305X_GPIO_SDRAM_MD16, +- .gpio_last = RT305X_GPIO_SDRAM_MD31, +- }, { +- .name = "rgmii", +- .mask = RT305X_GPIO_MODE_RGMII, +- .gpio_first = RT305X_GPIO_GE0_TXD0, +- .gpio_last = RT305X_GPIO_GE0_RXCLK, +- }, {0} ++static struct rt2880_pmx_func i2c_func[] = { FUNC("i2c", 0, 1, 2) }; ++static struct rt2880_pmx_func spi_func[] = { FUNC("spi", 0, 3, 4) }; ++static struct rt2880_pmx_func uartf_func[] = { ++ FUNC("uartf", RT305X_GPIO_MODE_UARTF, 7, 8), ++ FUNC("pcm uartf", RT305X_GPIO_MODE_PCM_UARTF, 7, 8), ++ FUNC("pcm i2s", RT305X_GPIO_MODE_PCM_I2S, 7, 8), ++ FUNC("i2s uartf", RT305X_GPIO_MODE_I2S_UARTF, 7, 8), ++ FUNC("pcm gpio", RT305X_GPIO_MODE_PCM_GPIO, 11, 4), ++ FUNC("gpio uartf", RT305X_GPIO_MODE_GPIO_UARTF, 7, 4), ++ FUNC("gpio i2s", RT305X_GPIO_MODE_GPIO_I2S, 7, 4), ++}; ++static struct rt2880_pmx_func uartlite_func[] = { FUNC("uartlite", 0, 15, 2) }; ++static struct rt2880_pmx_func jtag_func[] = { FUNC("jtag", 0, 17, 5) }; ++static struct rt2880_pmx_func mdio_func[] = { FUNC("mdio", 0, 22, 2) }; ++static struct rt2880_pmx_func rt5350_led_func[] = { FUNC("led", 0, 22, 5) }; ++static struct rt2880_pmx_func rt5350_cs1_func[] = { ++ FUNC("spi_cs1", 0, 27, 1), ++ FUNC("wdg_cs1", 1, 27, 1), ++}; ++static struct rt2880_pmx_func sdram_func[] = { FUNC("sdram", 0, 24, 16) }; ++static struct rt2880_pmx_func rt3352_rgmii_func[] = { FUNC("rgmii", 0, 24, 12) }; ++static struct rt2880_pmx_func rgmii_func[] = { FUNC("rgmii", 0, 40, 12) }; ++static struct rt2880_pmx_func rt3352_lna_func[] = { FUNC("lna", 0, 36, 2) }; ++static struct rt2880_pmx_func rt3352_pa_func[] = { FUNC("pa", 0, 38, 2) }; ++static struct rt2880_pmx_func rt3352_led_func[] = { FUNC("led", 0, 40, 5) }; ++ ++static struct rt2880_pmx_group rt3050_pinmux_data[] = { ++ GRP("i2c", i2c_func, 1, RT305X_GPIO_MODE_I2C), ++ GRP("spi", spi_func, 1, RT305X_GPIO_MODE_SPI), ++ GRP("uartf", uartf_func, RT305X_GPIO_MODE_UART0_MASK, ++ RT305X_GPIO_MODE_UART0_SHIFT), ++ GRP("uartlite", uartlite_func, 1, RT305X_GPIO_MODE_UART1), ++ GRP("jtag", jtag_func, 1, RT305X_GPIO_MODE_JTAG), ++ GRP("mdio", mdio_func, 1, RT305X_GPIO_MODE_MDIO), ++ GRP("rgmii", rgmii_func, 1, RT305X_GPIO_MODE_RGMII), ++ GRP("sdram", sdram_func, 1, RT305X_GPIO_MODE_SDRAM), ++ { 0 } ++}; ++ ++static struct rt2880_pmx_group rt3352_pinmux_data[] = { ++ GRP("i2c", i2c_func, 1, RT305X_GPIO_MODE_I2C), ++ GRP("spi", spi_func, 1, RT305X_GPIO_MODE_SPI), ++ GRP("uartf", uartf_func, RT305X_GPIO_MODE_UART0_MASK, ++ RT305X_GPIO_MODE_UART0_SHIFT), ++ GRP("uartlite", uartlite_func, 1, RT305X_GPIO_MODE_UART1), ++ GRP("jtag", jtag_func, 1, RT305X_GPIO_MODE_JTAG), ++ GRP("mdio", mdio_func, 1, RT305X_GPIO_MODE_MDIO), ++ GRP("rgmii", rt3352_rgmii_func, 1, RT305X_GPIO_MODE_RGMII), ++ GRP("lna", rt3352_lna_func, 1, RT3352_GPIO_MODE_LNA), ++ GRP("pa", rt3352_pa_func, 1, RT3352_GPIO_MODE_PA), ++ GRP("led", rt3352_led_func, 1, RT5350_GPIO_MODE_PHY_LED), ++ { 0 } + }; + +-static struct ralink_pinmux_grp uart_mux[] = { +- { +- .name = "uartf", +- .mask = RT305X_GPIO_MODE_UARTF, +- .gpio_first = RT305X_GPIO_7, +- .gpio_last = RT305X_GPIO_14, +- }, { +- .name = "pcm uartf", +- .mask = RT305X_GPIO_MODE_PCM_UARTF, +- .gpio_first = RT305X_GPIO_7, +- .gpio_last = RT305X_GPIO_14, +- }, { +- .name = "pcm i2s", +- .mask = RT305X_GPIO_MODE_PCM_I2S, +- .gpio_first = RT305X_GPIO_7, +- .gpio_last = RT305X_GPIO_14, +- }, { +- .name = "i2s uartf", +- .mask = RT305X_GPIO_MODE_I2S_UARTF, +- .gpio_first = RT305X_GPIO_7, +- .gpio_last = RT305X_GPIO_14, +- }, { +- .name = "pcm gpio", +- .mask = RT305X_GPIO_MODE_PCM_GPIO, +- .gpio_first = RT305X_GPIO_10, +- .gpio_last = RT305X_GPIO_14, +- }, { +- .name = "gpio uartf", +- .mask = RT305X_GPIO_MODE_GPIO_UARTF, +- .gpio_first = RT305X_GPIO_7, +- .gpio_last = RT305X_GPIO_10, +- }, { +- .name = "gpio i2s", +- .mask = RT305X_GPIO_MODE_GPIO_I2S, +- .gpio_first = RT305X_GPIO_7, +- .gpio_last = RT305X_GPIO_10, +- }, { +- .name = "gpio", +- .mask = RT305X_GPIO_MODE_GPIO, +- }, {0} ++static struct rt2880_pmx_group rt5350_pinmux_data[] = { ++ GRP("i2c", i2c_func, 1, RT305X_GPIO_MODE_I2C), ++ GRP("spi", spi_func, 1, RT305X_GPIO_MODE_SPI), ++ GRP("uartf", uartf_func, RT305X_GPIO_MODE_UART0_MASK, ++ RT305X_GPIO_MODE_UART0_SHIFT), ++ GRP("uartlite", uartlite_func, 1, RT305X_GPIO_MODE_UART1), ++ GRP("jtag", jtag_func, 1, RT305X_GPIO_MODE_JTAG), ++ GRP("led", rt5350_led_func, 1, RT5350_GPIO_MODE_PHY_LED), ++ GRP("spi_cs1", rt5350_cs1_func, 2, RT5350_GPIO_MODE_SPI_CS1), ++ { 0 } + }; + + static void rt305x_wdt_reset(void) +@@ -114,14 +100,6 @@ static void rt305x_wdt_reset(void) + rt_sysc_w32(t, SYSC_REG_SYSTEM_CONFIG); + } + +-struct ralink_pinmux rt_gpio_pinmux = { +- .mode = mode_mux, +- .uart = uart_mux, +- .uart_shift = RT305X_GPIO_MODE_UART0_SHIFT, +- .uart_mask = RT305X_GPIO_MODE_UART0_MASK, +- .wdt_reset = rt305x_wdt_reset, +-}; +- + static unsigned long rt5350_get_mem_size(void) + { + void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT305X_SYSC_BASE); +@@ -290,11 +268,14 @@ void prom_soc_init(struct ralink_soc_inf + soc_info->mem_base = RT305X_SDRAM_BASE; + if (soc_is_rt5350()) { + soc_info->mem_size = rt5350_get_mem_size(); ++ rt2880_pinmux_data = rt5350_pinmux_data; + } else if (soc_is_rt305x() || soc_is_rt3350()) { + soc_info->mem_size_min = RT305X_MEM_SIZE_MIN; + soc_info->mem_size_max = RT305X_MEM_SIZE_MAX; ++ rt2880_pinmux_data = rt3050_pinmux_data; + } else if (soc_is_rt3352()) { + soc_info->mem_size_min = RT3352_MEM_SIZE_MIN; + soc_info->mem_size_max = RT3352_MEM_SIZE_MAX; ++ rt2880_pinmux_data = rt3352_pinmux_data; + } + } +--- a/arch/mips/ralink/rt3883.c ++++ b/arch/mips/ralink/rt3883.c +@@ -17,132 +17,50 @@ + #include <asm/mipsregs.h> + #include <asm/mach-ralink/ralink_regs.h> + #include <asm/mach-ralink/rt3883.h> ++#include <asm/mach-ralink/pinmux.h> + + #include "common.h" + +-static struct ralink_pinmux_grp mode_mux[] = { +- { +- .name = "i2c", +- .mask = RT3883_GPIO_MODE_I2C, +- .gpio_first = RT3883_GPIO_I2C_SD, +- .gpio_last = RT3883_GPIO_I2C_SCLK, +- }, { +- .name = "spi", +- .mask = RT3883_GPIO_MODE_SPI, +- .gpio_first = RT3883_GPIO_SPI_CS0, +- .gpio_last = RT3883_GPIO_SPI_MISO, +- }, { +- .name = "uartlite", +- .mask = RT3883_GPIO_MODE_UART1, +- .gpio_first = RT3883_GPIO_UART1_TXD, +- .gpio_last = RT3883_GPIO_UART1_RXD, +- }, { +- .name = "jtag", +- .mask = RT3883_GPIO_MODE_JTAG, +- .gpio_first = RT3883_GPIO_JTAG_TDO, +- .gpio_last = RT3883_GPIO_JTAG_TCLK, +- }, { +- .name = "mdio", +- .mask = RT3883_GPIO_MODE_MDIO, +- .gpio_first = RT3883_GPIO_MDIO_MDC, +- .gpio_last = RT3883_GPIO_MDIO_MDIO, +- }, { +- .name = "ge1", +- .mask = RT3883_GPIO_MODE_GE1, +- .gpio_first = RT3883_GPIO_GE1_TXD0, +- .gpio_last = RT3883_GPIO_GE1_RXCLK, +- }, { +- .name = "ge2", +- .mask = RT3883_GPIO_MODE_GE2, +- .gpio_first = RT3883_GPIO_GE2_TXD0, +- .gpio_last = RT3883_GPIO_GE2_RXCLK, +- }, { +- .name = "pci", +- .mask = RT3883_GPIO_MODE_PCI, +- .gpio_first = RT3883_GPIO_PCI_AD0, +- .gpio_last = RT3883_GPIO_PCI_AD31, +- }, { +- .name = "lna a", +- .mask = RT3883_GPIO_MODE_LNA_A, +- .gpio_first = RT3883_GPIO_LNA_PE_A0, +- .gpio_last = RT3883_GPIO_LNA_PE_A2, +- }, { +- .name = "lna g", +- .mask = RT3883_GPIO_MODE_LNA_G, +- .gpio_first = RT3883_GPIO_LNA_PE_G0, +- .gpio_last = RT3883_GPIO_LNA_PE_G2, +- }, {0} ++static struct rt2880_pmx_func i2c_func[] = { FUNC("i2c", 0, 1, 2) }; ++static struct rt2880_pmx_func spi_func[] = { FUNC("spi", 0, 3, 4) }; ++static struct rt2880_pmx_func uartf_func[] = { ++ FUNC("uartf", RT3883_GPIO_MODE_UARTF, 7, 8), ++ FUNC("pcm uartf", RT3883_GPIO_MODE_PCM_UARTF, 7, 8), ++ FUNC("pcm i2s", RT3883_GPIO_MODE_PCM_I2S, 7, 8), ++ FUNC("i2s uartf", RT3883_GPIO_MODE_I2S_UARTF, 7, 8), ++ FUNC("pcm gpio", RT3883_GPIO_MODE_PCM_GPIO, 11, 4), ++ FUNC("gpio uartf", RT3883_GPIO_MODE_GPIO_UARTF, 7, 4), ++ FUNC("gpio i2s", RT3883_GPIO_MODE_GPIO_I2S, 7, 4), + }; +- +-static struct ralink_pinmux_grp uart_mux[] = { +- { +- .name = "uartf", +- .mask = RT3883_GPIO_MODE_UARTF, +- .gpio_first = RT3883_GPIO_7, +- .gpio_last = RT3883_GPIO_14, +- }, { +- .name = "pcm uartf", +- .mask = RT3883_GPIO_MODE_PCM_UARTF, +- .gpio_first = RT3883_GPIO_7, +- .gpio_last = RT3883_GPIO_14, +- }, { +- .name = "pcm i2s", +- .mask = RT3883_GPIO_MODE_PCM_I2S, +- .gpio_first = RT3883_GPIO_7, +- .gpio_last = RT3883_GPIO_14, +- }, { +- .name = "i2s uartf", +- .mask = RT3883_GPIO_MODE_I2S_UARTF, +- .gpio_first = RT3883_GPIO_7, +- .gpio_last = RT3883_GPIO_14, +- }, { +- .name = "pcm gpio", +- .mask = RT3883_GPIO_MODE_PCM_GPIO, +- .gpio_first = RT3883_GPIO_11, +- .gpio_last = RT3883_GPIO_14, +- }, { +- .name = "gpio uartf", +- .mask = RT3883_GPIO_MODE_GPIO_UARTF, +- .gpio_first = RT3883_GPIO_7, +- .gpio_last = RT3883_GPIO_10, +- }, { +- .name = "gpio i2s", +- .mask = RT3883_GPIO_MODE_GPIO_I2S, +- .gpio_first = RT3883_GPIO_7, +- .gpio_last = RT3883_GPIO_10, +- }, { +- .name = "gpio", +- .mask = RT3883_GPIO_MODE_GPIO, +- }, {0} ++static struct rt2880_pmx_func uartlite_func[] = { FUNC("uartlite", 0, 15, 2) }; ++static struct rt2880_pmx_func jtag_func[] = { FUNC("jtag", 0, 17, 5) }; ++static struct rt2880_pmx_func mdio_func[] = { FUNC("mdio", 0, 22, 2) }; ++static struct rt2880_pmx_func lna_a_func[] = { FUNC("lna a", 0, 32, 3) }; ++static struct rt2880_pmx_func lna_g_func[] = { FUNC("lna a", 0, 35, 3) }; ++static struct rt2880_pmx_func pci_func[] = { ++ FUNC("pci-dev", 0, 40, 32), ++ FUNC("pci-host2", 1, 40, 32), ++ FUNC("pci-host1", 2, 40, 32), ++ FUNC("pci-fnc", 3, 40, 32) + }; ++static struct rt2880_pmx_func ge1_func[] = { FUNC("ge1", 0, 84, 12) }; ++static struct rt2880_pmx_func ge2_func[] = { FUNC("ge2", 0, 72, 12) }; + +-static struct ralink_pinmux_grp pci_mux[] = { +- { +- .name = "pci-dev", +- .mask = 0, +- .gpio_first = RT3883_GPIO_PCI_AD0, +- .gpio_last = RT3883_GPIO_PCI_AD31, +- }, { +- .name = "pci-host2", +- .mask = 1, +- .gpio_first = RT3883_GPIO_PCI_AD0, +- .gpio_last = RT3883_GPIO_PCI_AD31, +- }, { +- .name = "pci-host1", +- .mask = 2, +- .gpio_first = RT3883_GPIO_PCI_AD0, +- .gpio_last = RT3883_GPIO_PCI_AD31, +- }, { +- .name = "pci-fnc", +- .mask = 3, +- .gpio_first = RT3883_GPIO_PCI_AD0, +- .gpio_last = RT3883_GPIO_PCI_AD31, +- }, { +- .name = "pci-gpio", +- .mask = 7, +- .gpio_first = RT3883_GPIO_PCI_AD0, +- .gpio_last = RT3883_GPIO_PCI_AD31, +- }, {0} ++static struct rt2880_pmx_group rt3883_pinmux_data[] = { ++ GRP("i2c", i2c_func, 1, RT3883_GPIO_MODE_I2C), ++ GRP("spi", spi_func, 1, RT3883_GPIO_MODE_SPI), ++ GRP("uartf", uartf_func, RT3883_GPIO_MODE_UART0_MASK, ++ RT3883_GPIO_MODE_UART0_SHIFT), ++ GRP("uartlite", uartlite_func, 1, RT3883_GPIO_MODE_UART1), ++ GRP("jtag", jtag_func, 1, RT3883_GPIO_MODE_JTAG), ++ GRP("mdio", mdio_func, 1, RT3883_GPIO_MODE_MDIO), ++ GRP("lna a", lna_a_func, 1, RT3883_GPIO_MODE_LNA_A), ++ GRP("lna g", lna_g_func, 1, RT3883_GPIO_MODE_LNA_G), ++ GRP("pci", pci_func, RT3883_GPIO_MODE_PCI_MASK, ++ RT3883_GPIO_MODE_PCI_SHIFT), ++ GRP("ge1", ge1_func, 1, RT3883_GPIO_MODE_GE1), ++ GRP("ge2", ge2_func, 1, RT3883_GPIO_MODE_GE2), ++ { 0 } + }; + + static void rt3883_wdt_reset(void) +@@ -155,17 +73,6 @@ static void rt3883_wdt_reset(void) + rt_sysc_w32(t, RT3883_SYSC_REG_SYSCFG1); + } + +-struct ralink_pinmux rt_gpio_pinmux = { +- .mode = mode_mux, +- .uart = uart_mux, +- .uart_shift = RT3883_GPIO_MODE_UART0_SHIFT, +- .uart_mask = RT3883_GPIO_MODE_UART0_MASK, +- .wdt_reset = rt3883_wdt_reset, +- .pci = pci_mux, +- .pci_shift = RT3883_GPIO_MODE_PCI_SHIFT, +- .pci_mask = RT3883_GPIO_MODE_PCI_MASK, +-}; +- + void __init ralink_clk_init(void) + { + unsigned long cpu_rate, sys_rate; +@@ -244,4 +151,6 @@ void prom_soc_init(struct ralink_soc_inf + soc_info->mem_base = RT3883_SDRAM_BASE; + soc_info->mem_size_min = RT3883_MEM_SIZE_MIN; + soc_info->mem_size_max = RT3883_MEM_SIZE_MAX; ++ ++ rt2880_pinmux_data = rt3883_pinmux_data; + } +--- a/drivers/pinctrl/Kconfig ++++ b/drivers/pinctrl/Kconfig +@@ -103,6 +103,11 @@ config PINCTRL_LANTIQ + select PINMUX + select PINCONF + ++config PINCTRL_RT2880 ++ bool ++ depends on RALINK ++ select PINMUX ++ + config PINCTRL_FALCON + bool + depends on SOC_FALCON +--- a/drivers/pinctrl/Makefile ++++ b/drivers/pinctrl/Makefile +@@ -20,6 +20,7 @@ obj-$(CONFIG_PINCTRL_BCM281XX) += pinctr + obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o + obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o + obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o ++obj-$(CONFIG_PINCTRL_RT2880) += pinctrl-rt2880.o + obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o + obj-$(CONFIG_PINCTRL_SIRF) += sirf/ + obj-$(CONFIG_PINCTRL_TEGRA) += pinctrl-tegra.o +--- /dev/null ++++ b/drivers/pinctrl/pinctrl-rt2880.c +@@ -0,0 +1,474 @@ ++/* ++ * linux/drivers/pinctrl/pinctrl-rt2880.c ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * publishhed by the Free Software Foundation. ++ * ++ * Copyright (C) 2013 John Crispin <blogic@openwrt.org> ++ */ ++ ++#include <linux/module.h> ++#include <linux/device.h> ++#include <linux/io.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++#include <linux/of.h> ++#include <linux/pinctrl/pinctrl.h> ++#include <linux/pinctrl/pinconf.h> ++#include <linux/pinctrl/pinmux.h> ++#include <linux/pinctrl/consumer.h> ++#include <linux/pinctrl/machine.h> ++ ++#include <asm/mach-ralink/ralink_regs.h> ++#include <asm/mach-ralink/pinmux.h> ++#include <asm/mach-ralink/mt7620.h> ++ ++#include "core.h" ++ ++#define SYSC_REG_GPIO_MODE 0x60 ++#define SYSC_REG_GPIO_MODE2 0x64 ++ ++struct rt2880_priv { ++ struct device *dev; ++ ++ struct pinctrl_pin_desc *pads; ++ struct pinctrl_desc *desc; ++ ++ struct rt2880_pmx_func **func; ++ int func_count; ++ ++ struct rt2880_pmx_group *groups; ++ const char **group_names; ++ int group_count; ++ ++ uint8_t *gpio; ++ int max_pins; ++}; ++ ++struct rt2880_pmx_group *rt2880_pinmux_data = NULL; ++ ++static int rt2880_get_group_count(struct pinctrl_dev *pctrldev) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ return p->group_count; ++} ++ ++static const char *rt2880_get_group_name(struct pinctrl_dev *pctrldev, ++ unsigned group) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ if (group >= p->group_count) ++ return NULL; ++ ++ return p->group_names[group]; ++} ++ ++static int rt2880_get_group_pins(struct pinctrl_dev *pctrldev, ++ unsigned group, ++ const unsigned **pins, ++ unsigned *num_pins) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ if (group >= p->group_count) ++ return -EINVAL; ++ ++ *pins = p->groups[group].func[0].pins; ++ *num_pins = p->groups[group].func[0].pin_count; ++ ++ return 0; ++} ++ ++static void rt2880_pinctrl_dt_free_map(struct pinctrl_dev *pctrldev, ++ struct pinctrl_map *map, unsigned num_maps) ++{ ++ int i; ++ ++ for (i = 0; i < num_maps; i++) ++ if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN || ++ map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP) ++ kfree(map[i].data.configs.configs); ++ kfree(map); ++} ++ ++static void rt2880_pinctrl_pin_dbg_show(struct pinctrl_dev *pctrldev, ++ struct seq_file *s, ++ unsigned offset) ++{ ++ seq_printf(s, "ralink pio"); ++} ++ ++static void rt2880_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctrldev, ++ struct device_node *np, ++ struct pinctrl_map **map) ++{ ++ const char *function; ++ int func = of_property_read_string(np, "ralink,function", &function); ++ int grps = of_property_count_strings(np, "ralink,group"); ++ int i; ++ ++ if (func || !grps) ++ return; ++ ++ for (i = 0; i < grps; i++) { ++ const char *group; ++ ++ of_property_read_string_index(np, "ralink,group", i, &group); ++ ++ (*map)->type = PIN_MAP_TYPE_MUX_GROUP; ++ (*map)->name = function; ++ (*map)->data.mux.group = group; ++ (*map)->data.mux.function = function; ++ (*map)++; ++ } ++} ++ ++static int rt2880_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrldev, ++ struct device_node *np_config, ++ struct pinctrl_map **map, ++ unsigned *num_maps) ++{ ++ int max_maps = 0; ++ struct pinctrl_map *tmp; ++ struct device_node *np; ++ ++ for_each_child_of_node(np_config, np) { ++ int ret = of_property_count_strings(np, "ralink,group"); ++ ++ if (ret >= 0) ++ max_maps += ret; ++ } ++ ++ if (!max_maps) ++ return max_maps; ++ ++ *map = kzalloc(max_maps * sizeof(struct pinctrl_map), GFP_KERNEL); ++ if (!*map) ++ return -ENOMEM; ++ ++ tmp = *map; ++ ++ for_each_child_of_node(np_config, np) ++ rt2880_pinctrl_dt_subnode_to_map(pctrldev, np, &tmp); ++ *num_maps = max_maps; ++ ++ return 0; ++} ++ ++static const struct pinctrl_ops rt2880_pctrl_ops = { ++ .get_groups_count = rt2880_get_group_count, ++ .get_group_name = rt2880_get_group_name, ++ .get_group_pins = rt2880_get_group_pins, ++ .pin_dbg_show = rt2880_pinctrl_pin_dbg_show, ++ .dt_node_to_map = rt2880_pinctrl_dt_node_to_map, ++ .dt_free_map = rt2880_pinctrl_dt_free_map, ++}; ++ ++static int rt2880_pmx_func_count(struct pinctrl_dev *pctrldev) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ return p->func_count; ++} ++ ++static const char *rt2880_pmx_func_name(struct pinctrl_dev *pctrldev, ++ unsigned func) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ return p->func[func]->name; ++} ++ ++static int rt2880_pmx_group_get_groups(struct pinctrl_dev *pctrldev, ++ unsigned func, ++ const char * const **groups, ++ unsigned * const num_groups) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ if (p->func[func]->group_count == 1) ++ *groups = &p->group_names[p->func[func]->groups[0]]; ++ else ++ *groups = p->group_names; ++ ++ *num_groups = p->func[func]->group_count; ++ ++ return 0; ++} ++ ++static int rt2880_pmx_group_enable(struct pinctrl_dev *pctrldev, ++ unsigned func, ++ unsigned group) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ u32 mode = 0; ++ u32 reg = SYSC_REG_GPIO_MODE; ++ int i; ++ int shift; ++ ++ /* dont allow double use */ ++ if (p->groups[group].enabled) { ++ dev_err(p->dev, "%s is already enabled\n", p->groups[group].name); ++ return -EBUSY; ++ } ++ ++ p->groups[group].enabled = 1; ++ p->func[func]->enabled = 1; ++ ++ shift = p->groups[group].shift; ++ if (shift >= 32) { ++ shift -= 32; ++ reg = SYSC_REG_GPIO_MODE2; ++ } ++ mode = rt_sysc_r32(reg); ++ mode &= ~(p->groups[group].mask << shift); ++ ++ /* mark the pins as gpio */ ++ for (i = 0; i < p->groups[group].func[0].pin_count; i++) ++ p->gpio[p->groups[group].func[0].pins[i]] = 1; ++ ++ /* function 0 is gpio and needs special handling */ ++ if (func == 0) { ++ mode |= p->groups[group].gpio << shift; ++ } else { ++ for (i = 0; i < p->func[func]->pin_count; i++) ++ p->gpio[p->func[func]->pins[i]] = 0; ++ mode |= p->func[func]->value << shift; ++ } ++ rt_sysc_w32(mode, reg); ++ ++ return 0; ++} ++ ++static int rt2880_pmx_group_gpio_request_enable(struct pinctrl_dev *pctrldev, ++ struct pinctrl_gpio_range *range, ++ unsigned pin) ++{ ++ struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); ++ ++ if (!p->gpio[pin]) { ++ dev_err(p->dev, "pin %d is not set to gpio mux\n", pin); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static const struct pinmux_ops rt2880_pmx_group_ops = { ++ .get_functions_count = rt2880_pmx_func_count, ++ .get_function_name = rt2880_pmx_func_name, ++ .get_function_groups = rt2880_pmx_group_get_groups, ++ .set_mux = rt2880_pmx_group_enable, ++ .gpio_request_enable = rt2880_pmx_group_gpio_request_enable, ++}; ++ ++static struct pinctrl_desc rt2880_pctrl_desc = { ++ .owner = THIS_MODULE, ++ .name = "rt2880-pinmux", ++ .pctlops = &rt2880_pctrl_ops, ++ .pmxops = &rt2880_pmx_group_ops, ++}; ++ ++static struct rt2880_pmx_func gpio_func = { ++ .name = "gpio", ++}; ++ ++static int rt2880_pinmux_index(struct rt2880_priv *p) ++{ ++ struct rt2880_pmx_func **f; ++ struct rt2880_pmx_group *mux = p->groups; ++ int i, j, c = 0; ++ ++ /* count the mux functions */ ++ while (mux->name) { ++ p->group_count++; ++ mux++; ++ } ++ ++ /* allocate the group names array needed by the gpio function */ ++ p->group_names = devm_kzalloc(p->dev, sizeof(char *) * p->group_count, GFP_KERNEL); ++ if (!p->group_names) ++ return -1; ++ ++ for (i = 0; i < p->group_count; i++) { ++ p->group_names[i] = p->groups[i].name; ++ p->func_count += p->groups[i].func_count; ++ } ++ ++ /* we have a dummy function[0] for gpio */ ++ p->func_count++; ++ ++ /* allocate our function and group mapping index buffers */ ++ f = p->func = devm_kzalloc(p->dev, sizeof(struct rt2880_pmx_func) * p->func_count, GFP_KERNEL); ++ gpio_func.groups = devm_kzalloc(p->dev, sizeof(int) * p->group_count, GFP_KERNEL); ++ if (!f || !gpio_func.groups) ++ return -1; ++ ++ /* add a backpointer to the function so it knows its group */ ++ gpio_func.group_count = p->group_count; ++ for (i = 0; i < gpio_func.group_count; i++) ++ gpio_func.groups[i] = i; ++ ++ f[c] = &gpio_func; ++ c++; ++ ++ /* add remaining functions */ ++ for (i = 0; i < p->group_count; i++) { ++ for (j = 0; j < p->groups[i].func_count; j++) { ++ f[c] = &p->groups[i].func[j]; ++ f[c]->groups = devm_kzalloc(p->dev, sizeof(int), GFP_KERNEL); ++ f[c]->groups[0] = i; ++ f[c]->group_count = 1; ++ c++; ++ } ++ } ++ return 0; ++} ++ ++static int rt2880_pinmux_pins(struct rt2880_priv *p) ++{ ++ int i, j; ++ ++ /* loop over the functions and initialize the pins array. also work out the highest pin used */ ++ for (i = 0; i < p->func_count; i++) { ++ int pin; ++ ++ if (!p->func[i]->pin_count) ++ continue; ++ ++ p->func[i]->pins = devm_kzalloc(p->dev, sizeof(int) * p->func[i]->pin_count, GFP_KERNEL); ++ for (j = 0; j < p->func[i]->pin_count; j++) ++ p->func[i]->pins[j] = p->func[i]->pin_first + j; ++ ++ pin = p->func[i]->pin_first + p->func[i]->pin_count; ++ if (pin > p->max_pins) ++ p->max_pins = pin; ++ } ++ ++ /* the buffer that tells us which pins are gpio */ ++ p->gpio = devm_kzalloc(p->dev,sizeof(uint8_t) * p->max_pins, ++ GFP_KERNEL); ++ /* the pads needed to tell pinctrl about our pins */ ++ p->pads = devm_kzalloc(p->dev, ++ sizeof(struct pinctrl_pin_desc) * p->max_pins, ++ GFP_KERNEL); ++ if (!p->pads || !p->gpio ) { ++ dev_err(p->dev, "Failed to allocate gpio data\n"); ++ return -ENOMEM; ++ } ++ ++ memset(p->gpio, 1, sizeof(uint8_t) * p->max_pins); ++ for (i = 0; i < p->func_count; i++) { ++ if (!p->func[i]->pin_count) ++ continue; ++ ++ for (j = 0; j < p->func[i]->pin_count; j++) ++ p->gpio[p->func[i]->pins[j]] = 0; ++ } ++ ++ /* pin 0 is always a gpio */ ++ p->gpio[0] = 1; ++ ++ /* set the pads */ ++ for (i = 0; i < p->max_pins; i++) { ++ /* strlen("ioXY") + 1 = 5 */ ++ char *name = devm_kzalloc(p->dev, 5, GFP_KERNEL); ++ ++ if (!name) { ++ dev_err(p->dev, "Failed to allocate pad name\n"); ++ return -ENOMEM; ++ } ++ snprintf(name, 5, "io%d", i); ++ p->pads[i].number = i; ++ p->pads[i].name = name; ++ } ++ p->desc->pins = p->pads; ++ p->desc->npins = p->max_pins; ++ ++ return 0; ++} ++ ++static int rt2880_pinmux_probe(struct platform_device *pdev) ++{ ++ struct rt2880_priv *p; ++ struct pinctrl_dev *dev; ++ struct device_node *np; ++ ++ if (!rt2880_pinmux_data) ++ return -ENOSYS; ++ ++ /* setup the private data */ ++ p = devm_kzalloc(&pdev->dev, sizeof(struct rt2880_priv), GFP_KERNEL); ++ if (!p) ++ return -ENOMEM; ++ ++ p->dev = &pdev->dev; ++ p->desc = &rt2880_pctrl_desc; ++ p->groups = rt2880_pinmux_data; ++ platform_set_drvdata(pdev, p); ++ ++ /* init the device */ ++ if (rt2880_pinmux_index(p)) { ++ dev_err(&pdev->dev, "failed to load index\n"); ++ return -EINVAL; ++ } ++ if (rt2880_pinmux_pins(p)) { ++ dev_err(&pdev->dev, "failed to load pins\n"); ++ return -EINVAL; ++ } ++ dev = pinctrl_register(p->desc, &pdev->dev, p); ++ if (IS_ERR(dev)) ++ return PTR_ERR(dev); ++ ++ /* finalize by adding gpio ranges for enables gpio controllers */ ++ for_each_compatible_node(np, NULL, "ralink,rt2880-gpio") { ++ const __be32 *ngpio, *gpiobase; ++ struct pinctrl_gpio_range *range; ++ char *name; ++ ++ if (!of_device_is_available(np)) ++ continue; ++ ++ ngpio = of_get_property(np, "ralink,num-gpios", NULL); ++ gpiobase = of_get_property(np, "ralink,gpio-base", NULL); ++ if (!ngpio || !gpiobase) { ++ dev_err(&pdev->dev, "failed to load chip info\n"); ++ return -EINVAL; ++ } ++ ++ range = devm_kzalloc(p->dev, sizeof(struct pinctrl_gpio_range) + 4, GFP_KERNEL); ++ range->name = name = (char *) &range[1]; ++ sprintf(name, "pio"); ++ range->npins = __be32_to_cpu(*ngpio); ++ range->base = __be32_to_cpu(*gpiobase); ++ range->pin_base = range->base; ++ pinctrl_add_gpio_range(dev, range); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id rt2880_pinmux_match[] = { ++ { .compatible = "ralink,rt2880-pinmux" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rt2880_pinmux_match); ++ ++static struct platform_driver rt2880_pinmux_driver = { ++ .probe = rt2880_pinmux_probe, ++ .driver = { ++ .name = "rt2880-pinmux", ++ .owner = THIS_MODULE, ++ .of_match_table = rt2880_pinmux_match, ++ }, ++}; ++ ++int __init rt2880_pinmux_init(void) ++{ ++ return platform_driver_register(&rt2880_pinmux_driver); ++} ++ ++core_initcall_sync(rt2880_pinmux_init); diff --git a/target/linux/ramips/patches-3.18/0031-PCI-MIPS-adds-rt2880-pci-support.patch b/target/linux/ramips/patches-3.18/0031-PCI-MIPS-adds-rt2880-pci-support.patch new file mode 100644 index 0000000..193f1c2 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0031-PCI-MIPS-adds-rt2880-pci-support.patch @@ -0,0 +1,319 @@ +From 5b0bcc314005dd14eeae190948165a81eef7da1f Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 27 Jul 2014 09:36:02 +0100 +Subject: [PATCH 31/57] PCI: MIPS: adds rt2880 pci support + +Add support for the pci found on the rt2880 SoC. + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/pci/Makefile | 1 + + arch/mips/pci/pci-rt2880.c | 281 ++++++++++++++++++++++++++++++++++++++++++++ + arch/mips/ralink/Kconfig | 1 + + 3 files changed, 283 insertions(+) + create mode 100644 arch/mips/pci/pci-rt2880.c + +--- a/arch/mips/pci/Makefile ++++ b/arch/mips/pci/Makefile +@@ -43,6 +43,7 @@ obj-$(CONFIG_SNI_RM) += fixup-sni.o ops + obj-$(CONFIG_LANTIQ) += fixup-lantiq.o + obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o + obj-$(CONFIG_SOC_MT7621) += pci-mt7621.o ++obj-$(CONFIG_SOC_RT2880) += pci-rt2880.o + obj-$(CONFIG_SOC_RT3883) += pci-rt3883.o + obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o + obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o +--- /dev/null ++++ b/arch/mips/pci/pci-rt2880.c +@@ -0,0 +1,281 @@ ++/* ++ * Ralink RT288x SoC PCI register definitions ++ * ++ * Copyright (C) 2009 John Crispin <blogic@openwrt.org> ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * Parts of this file are based on Ralink's 2.6.21 BSP ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/types.h> ++#include <linux/pci.h> ++#include <linux/io.h> ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/of_platform.h> ++#include <linux/of_irq.h> ++#include <linux/of_pci.h> ++ ++#include <asm/mach-ralink/rt288x.h> ++ ++#define RT2880_PCI_BASE 0x00440000 ++#define RT288X_CPU_IRQ_PCI 4 ++ ++#define RT2880_PCI_MEM_BASE 0x20000000 ++#define RT2880_PCI_MEM_SIZE 0x10000000 ++#define RT2880_PCI_IO_BASE 0x00460000 ++#define RT2880_PCI_IO_SIZE 0x00010000 ++ ++#define RT2880_PCI_REG_PCICFG_ADDR 0x00 ++#define RT2880_PCI_REG_PCIMSK_ADDR 0x0c ++#define RT2880_PCI_REG_BAR0SETUP_ADDR 0x10 ++#define RT2880_PCI_REG_IMBASEBAR0_ADDR 0x18 ++#define RT2880_PCI_REG_CONFIG_ADDR 0x20 ++#define RT2880_PCI_REG_CONFIG_DATA 0x24 ++#define RT2880_PCI_REG_MEMBASE 0x28 ++#define RT2880_PCI_REG_IOBASE 0x2c ++#define RT2880_PCI_REG_ID 0x30 ++#define RT2880_PCI_REG_CLASS 0x34 ++#define RT2880_PCI_REG_SUBID 0x38 ++#define RT2880_PCI_REG_ARBCTL 0x80 ++ ++static void __iomem *rt2880_pci_base; ++static DEFINE_SPINLOCK(rt2880_pci_lock); ++ ++static u32 rt2880_pci_reg_read(u32 reg) ++{ ++ return readl(rt2880_pci_base + reg); ++} ++ ++static void rt2880_pci_reg_write(u32 val, u32 reg) ++{ ++ writel(val, rt2880_pci_base + reg); ++} ++ ++static inline u32 rt2880_pci_get_cfgaddr(unsigned int bus, unsigned int slot, ++ unsigned int func, unsigned int where) ++{ ++ return ((bus << 16) | (slot << 11) | (func << 8) | (where & 0xfc) | ++ 0x80000000); ++} ++ ++static int rt2880_pci_config_read(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 *val) ++{ ++ unsigned long flags; ++ u32 address; ++ u32 data; ++ ++ address = rt2880_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), ++ PCI_FUNC(devfn), where); ++ ++ spin_lock_irqsave(&rt2880_pci_lock, flags); ++ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR); ++ data = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA); ++ spin_unlock_irqrestore(&rt2880_pci_lock, flags); ++ ++ switch (size) { ++ case 1: ++ *val = (data >> ((where & 3) << 3)) & 0xff; ++ break; ++ case 2: ++ *val = (data >> ((where & 3) << 3)) & 0xffff; ++ break; ++ case 4: ++ *val = data; ++ break; ++ } ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int rt2880_pci_config_write(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 val) ++{ ++ unsigned long flags; ++ u32 address; ++ u32 data; ++ ++ address = rt2880_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), ++ PCI_FUNC(devfn), where); ++ ++ spin_lock_irqsave(&rt2880_pci_lock, flags); ++ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR); ++ data = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA); ++ ++ switch (size) { ++ case 1: ++ data = (data & ~(0xff << ((where & 3) << 3))) | ++ (val << ((where & 3) << 3)); ++ break; ++ case 2: ++ data = (data & ~(0xffff << ((where & 3) << 3))) | ++ (val << ((where & 3) << 3)); ++ break; ++ case 4: ++ data = val; ++ break; ++ } ++ ++ rt2880_pci_reg_write(data, RT2880_PCI_REG_CONFIG_DATA); ++ spin_unlock_irqrestore(&rt2880_pci_lock, flags); ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static struct pci_ops rt2880_pci_ops = { ++ .read = rt2880_pci_config_read, ++ .write = rt2880_pci_config_write, ++}; ++ ++static struct resource rt2880_pci_mem_resource = { ++ .name = "PCI MEM space", ++ .start = RT2880_PCI_MEM_BASE, ++ .end = RT2880_PCI_MEM_BASE + RT2880_PCI_MEM_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct resource rt2880_pci_io_resource = { ++ .name = "PCI IO space", ++ .start = RT2880_PCI_IO_BASE, ++ .end = RT2880_PCI_IO_BASE + RT2880_PCI_IO_SIZE - 1, ++ .flags = IORESOURCE_IO, ++}; ++ ++static struct pci_controller rt2880_pci_controller = { ++ .pci_ops = &rt2880_pci_ops, ++ .mem_resource = &rt2880_pci_mem_resource, ++ .io_resource = &rt2880_pci_io_resource, ++}; ++ ++static inline u32 rt2880_pci_read_u32(unsigned long reg) ++{ ++ unsigned long flags; ++ u32 address; ++ u32 ret; ++ ++ address = rt2880_pci_get_cfgaddr(0, 0, 0, reg); ++ ++ spin_lock_irqsave(&rt2880_pci_lock, flags); ++ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR); ++ ret = rt2880_pci_reg_read(RT2880_PCI_REG_CONFIG_DATA); ++ spin_unlock_irqrestore(&rt2880_pci_lock, flags); ++ ++ return ret; ++} ++ ++static inline void rt2880_pci_write_u32(unsigned long reg, u32 val) ++{ ++ unsigned long flags; ++ u32 address; ++ ++ address = rt2880_pci_get_cfgaddr(0, 0, 0, reg); ++ ++ spin_lock_irqsave(&rt2880_pci_lock, flags); ++ rt2880_pci_reg_write(address, RT2880_PCI_REG_CONFIG_ADDR); ++ rt2880_pci_reg_write(val, RT2880_PCI_REG_CONFIG_DATA); ++ spin_unlock_irqrestore(&rt2880_pci_lock, flags); ++} ++ ++int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ u16 cmd; ++ int irq = -1; ++ ++ if (dev->bus->number != 0) ++ return irq; ++ ++ switch (PCI_SLOT(dev->devfn)) { ++ case 0x00: ++ rt2880_pci_write_u32(PCI_BASE_ADDRESS_0, 0x08000000); ++ (void) rt2880_pci_read_u32(PCI_BASE_ADDRESS_0); ++ break; ++ case 0x11: ++ irq = RT288X_CPU_IRQ_PCI; ++ break; ++ default: ++ printk("%s:%s[%d] trying to alloc unknown pci irq\n", ++ __FILE__, __func__, __LINE__); ++ BUG(); ++ break; ++ } ++ ++ pci_write_config_byte((struct pci_dev*)dev, PCI_CACHE_LINE_SIZE, 0x14); ++ pci_write_config_byte((struct pci_dev*)dev, PCI_LATENCY_TIMER, 0xFF); ++ pci_read_config_word((struct pci_dev*)dev, PCI_COMMAND, &cmd); ++ cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | ++ PCI_COMMAND_INVALIDATE | PCI_COMMAND_FAST_BACK | ++ PCI_COMMAND_SERR | PCI_COMMAND_WAIT | PCI_COMMAND_PARITY; ++ pci_write_config_word((struct pci_dev*)dev, PCI_COMMAND, cmd); ++ pci_write_config_byte((struct pci_dev*)dev, PCI_INTERRUPT_LINE, ++ dev->irq); ++ return irq; ++} ++ ++static int rt288x_pci_probe(struct platform_device *pdev) ++{ ++ void __iomem *io_map_base; ++ int i; ++ ++ rt2880_pci_base = ioremap_nocache(RT2880_PCI_BASE, PAGE_SIZE); ++ ++ io_map_base = ioremap(RT2880_PCI_IO_BASE, RT2880_PCI_IO_SIZE); ++ rt2880_pci_controller.io_map_base = (unsigned long) io_map_base; ++ set_io_port_base((unsigned long) io_map_base); ++ ++ ioport_resource.start = RT2880_PCI_IO_BASE; ++ ioport_resource.end = RT2880_PCI_IO_BASE + RT2880_PCI_IO_SIZE - 1; ++ ++ rt2880_pci_reg_write(0, RT2880_PCI_REG_PCICFG_ADDR); ++ for(i = 0; i < 0xfffff; i++) {} ++ ++ rt2880_pci_reg_write(0x79, RT2880_PCI_REG_ARBCTL); ++ rt2880_pci_reg_write(0x07FF0001, RT2880_PCI_REG_BAR0SETUP_ADDR); ++ rt2880_pci_reg_write(RT2880_PCI_MEM_BASE, RT2880_PCI_REG_MEMBASE); ++ rt2880_pci_reg_write(RT2880_PCI_IO_BASE, RT2880_PCI_REG_IOBASE); ++ rt2880_pci_reg_write(0x08000000, RT2880_PCI_REG_IMBASEBAR0_ADDR); ++ rt2880_pci_reg_write(0x08021814, RT2880_PCI_REG_ID); ++ rt2880_pci_reg_write(0x00800001, RT2880_PCI_REG_CLASS); ++ rt2880_pci_reg_write(0x28801814, RT2880_PCI_REG_SUBID); ++ rt2880_pci_reg_write(0x000c0000, RT2880_PCI_REG_PCIMSK_ADDR); ++ ++ rt2880_pci_write_u32(PCI_BASE_ADDRESS_0, 0x08000000); ++ (void) rt2880_pci_read_u32(PCI_BASE_ADDRESS_0); ++ ++ register_pci_controller(&rt2880_pci_controller); ++ return 0; ++} ++ ++int pcibios_plat_dev_init(struct pci_dev *dev) ++{ ++ return 0; ++} ++ ++static const struct of_device_id rt288x_pci_match[] = { ++ { .compatible = "ralink,rt288x-pci" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rt288x_pci_match); ++ ++static struct platform_driver rt288x_pci_driver = { ++ .probe = rt288x_pci_probe, ++ .driver = { ++ .name = "rt288x-pci", ++ .owner = THIS_MODULE, ++ .of_match_table = rt288x_pci_match, ++ }, ++}; ++ ++int __init pcibios_init(void) ++{ ++ int ret = platform_driver_register(&rt288x_pci_driver); ++ if (ret) ++ pr_info("rt288x-pci: Error registering platform driver!"); ++ return ret; ++} ++ ++arch_initcall(pcibios_init); +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -31,6 +31,7 @@ choice + config SOC_RT288X + bool "RT288x" + select MIPS_L1_CACHE_SHIFT_4 ++ select HW_HAS_PCI + + config SOC_RT305X + bool "RT305x" diff --git a/target/linux/ramips/patches-3.18/0032-PCI-MIPS-adds-mt7620a-pcie-driver.patch b/target/linux/ramips/patches-3.18/0032-PCI-MIPS-adds-mt7620a-pcie-driver.patch new file mode 100644 index 0000000..c20a5df --- /dev/null +++ b/target/linux/ramips/patches-3.18/0032-PCI-MIPS-adds-mt7620a-pcie-driver.patch @@ -0,0 +1,442 @@ +From 307b7a71a634ae3848fb7c5c05759d647e140e12 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sat, 18 May 2013 22:06:15 +0200 +Subject: [PATCH 32/57] PCI: MIPS: adds mt7620a pcie driver + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/pci/Makefile | 1 + + arch/mips/pci/pci-mt7620.c | 363 +++++++++++++++++++++++++++++++++++++++++++ + arch/mips/ralink/Kconfig | 1 + + 3 files changed, 365 insertions(+) + create mode 100644 arch/mips/pci/pci-mt7620.c + +--- a/arch/mips/pci/Makefile ++++ b/arch/mips/pci/Makefile +@@ -43,6 +43,7 @@ obj-$(CONFIG_SNI_RM) += fixup-sni.o ops + obj-$(CONFIG_LANTIQ) += fixup-lantiq.o + obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o + obj-$(CONFIG_SOC_MT7621) += pci-mt7621.o ++obj-$(CONFIG_SOC_MT7620) += pci-mt7620.o + obj-$(CONFIG_SOC_RT2880) += pci-rt2880.o + obj-$(CONFIG_SOC_RT3883) += pci-rt3883.o + obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o +--- /dev/null ++++ b/arch/mips/pci/pci-mt7620.c +@@ -0,0 +1,396 @@ ++/* ++ * Ralink MT7620A SoC PCI support ++ * ++ * Copyright (C) 2007-2013 Bruce Chang ++ * Copyright (C) 2013 John Crispin <blogic@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/types.h> ++#include <linux/pci.h> ++#include <linux/io.h> ++#include <linux/init.h> ++#include <linux/delay.h> ++#include <linux/interrupt.h> ++#include <linux/module.h> ++#include <linux/of.h> ++#include <linux/of_irq.h> ++#include <linux/of_pci.h> ++#include <linux/reset.h> ++#include <linux/platform_device.h> ++ ++#include <asm/mach-ralink/ralink_regs.h> ++#include <asm/mach-ralink/mt7620.h> ++ ++#define RALINK_PCI_MM_MAP_BASE 0x20000000 ++#define RALINK_PCI_IO_MAP_BASE 0x10160000 ++ ++#define RALINK_INT_PCIE0 4 ++#define RALINK_SYSCFG1 0x14 ++#define RALINK_CLKCFG1 0x30 ++#define RALINK_GPIOMODE 0x60 ++#define RALINK_PCIE_CLK_GEN 0x7c ++#define RALINK_PCIE_CLK_GEN1 0x80 ++#define PCIEPHY0_CFG 0x90 ++#define PPLL_CFG1 0x9c ++#define PPLL_DRV 0xa0 ++#define PDRV_SW_SET (1<<31) ++#define LC_CKDRVPD_ (1<<19) ++ ++#define RALINK_PCI_CONFIG_ADDR 0x20 ++#define RALINK_PCI_CONFIG_DATA_VIRT_REG 0x24 ++#define MEMORY_BASE 0x0 ++#define RALINK_PCIE0_RST (1<<26) ++#define RALINK_PCI_BASE 0xB0140000 ++#define RALINK_PCI_MEMBASE 0x28 ++#define RALINK_PCI_IOBASE 0x2C ++ ++#define RT6855_PCIE0_OFFSET 0x2000 ++ ++#define RALINK_PCI_PCICFG_ADDR 0x00 ++#define RALINK_PCI0_BAR0SETUP_ADDR 0x10 ++#define RALINK_PCI0_IMBASEBAR0_ADDR 0x18 ++#define RALINK_PCI0_ID 0x30 ++#define RALINK_PCI0_CLASS 0x34 ++#define RALINK_PCI0_SUBID 0x38 ++#define RALINK_PCI0_STATUS 0x50 ++#define RALINK_PCI_PCIMSK_ADDR 0x0C ++ ++#define RALINK_PCIEPHY_P0_CTL_OFFSET 0x7498 ++#define RALINK_PCIE0_CLK_EN (1 << 26) ++ ++#define BUSY 0x80000000 ++#define WAITRETRY_MAX 10 ++#define WRITE_MODE (1UL << 23) ++#define DATA_SHIFT 0 ++#define ADDR_SHIFT 8 ++ ++static void __iomem *bridge_base; ++static void __iomem *pcie_base; ++ ++static struct reset_control *rstpcie0; ++ ++static inline void bridge_w32(u32 val, unsigned reg) ++{ ++ iowrite32(val, bridge_base + reg); ++} ++ ++static inline u32 bridge_r32(unsigned reg) ++{ ++ return ioread32(bridge_base + reg); ++} ++ ++static inline void pcie_w32(u32 val, unsigned reg) ++{ ++ iowrite32(val, pcie_base + reg); ++} ++ ++static inline u32 pcie_r32(unsigned reg) ++{ ++ return ioread32(pcie_base + reg); ++} ++ ++static inline void pcie_m32(u32 clr, u32 set, unsigned reg) ++{ ++ u32 val = pcie_r32(reg); ++ ++ val &= ~clr; ++ val |= set; ++ pcie_w32(val, reg); ++} ++ ++static int wait_pciephy_busy(void) ++{ ++ unsigned long reg_value = 0x0, retry = 0; ++ ++ while (1) { ++ reg_value = pcie_r32(PCIEPHY0_CFG); ++ ++ if (reg_value & BUSY) ++ mdelay(100); ++ else ++ break; ++ if (retry++ > WAITRETRY_MAX){ ++ printk("PCIE-PHY retry failed.\n"); ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++static void pcie_phy(unsigned long addr, unsigned long val) ++{ ++ wait_pciephy_busy(); ++ pcie_w32(WRITE_MODE | (val << DATA_SHIFT) | (addr << ADDR_SHIFT), PCIEPHY0_CFG); ++ mdelay(1); ++ wait_pciephy_busy(); ++} ++ ++static int pci_config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val) ++{ ++ unsigned int slot = PCI_SLOT(devfn); ++ u8 func = PCI_FUNC(devfn); ++ u32 address; ++ u32 data; ++ u32 num = 0; ++ ++ if (bus) ++ num = bus->number; ++ ++ address = (((where & 0xF00) >> 8) << 24) | (num << 16) | (slot << 11) | (func << 8) | (where & 0xfc) | 0x80000000; ++ bridge_w32(address, RALINK_PCI_CONFIG_ADDR); ++ data = bridge_r32(RALINK_PCI_CONFIG_DATA_VIRT_REG); ++ ++ switch (size) { ++ case 1: ++ *val = (data >> ((where & 3) << 3)) & 0xff; ++ break; ++ case 2: ++ *val = (data >> ((where & 3) << 3)) & 0xffff; ++ break; ++ case 4: ++ *val = data; ++ break; ++ } ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int pci_config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) ++{ ++ unsigned int slot = PCI_SLOT(devfn); ++ u8 func = PCI_FUNC(devfn); ++ u32 address; ++ u32 data; ++ u32 num = 0; ++ ++ if (bus) ++ num = bus->number; ++ ++ address = (((where & 0xF00) >> 8) << 24) | (num << 16) | (slot << 11) | (func << 8) | (where & 0xfc) | 0x80000000; ++ bridge_w32(address, RALINK_PCI_CONFIG_ADDR); ++ data = bridge_r32(RALINK_PCI_CONFIG_DATA_VIRT_REG); ++ ++ switch (size) { ++ case 1: ++ data = (data & ~(0xff << ((where & 3) << 3))) | ++ (val << ((where & 3) << 3)); ++ break; ++ case 2: ++ data = (data & ~(0xffff << ((where & 3) << 3))) | ++ (val << ((where & 3) << 3)); ++ break; ++ case 4: ++ data = val; ++ break; ++ } ++ ++ bridge_w32(data, RALINK_PCI_CONFIG_DATA_VIRT_REG); ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++struct pci_ops mt7620_pci_ops= { ++ .read = pci_config_read, ++ .write = pci_config_write, ++}; ++ ++static struct resource mt7620_res_pci_mem1; ++static struct resource mt7620_res_pci_io1; ++struct pci_controller mt7620_controller = { ++ .pci_ops = &mt7620_pci_ops, ++ .mem_resource = &mt7620_res_pci_mem1, ++ .mem_offset = 0x00000000UL, ++ .io_resource = &mt7620_res_pci_io1, ++ .io_offset = 0x00000000UL, ++ .io_map_base = 0xa0000000, ++}; ++ ++static int mt7620_pci_hw_init(struct platform_device *pdev) { ++ /* PCIE: bypass PCIe DLL */ ++ pcie_phy(0x0, 0x80); ++ pcie_phy(0x1, 0x04); ++ ++ /* PCIE: Elastic buffer control */ ++ pcie_phy(0x68, 0xB4); ++ ++ pcie_m32(0, BIT(1), RALINK_PCI_PCICFG_ADDR); ++ ++ reset_control_assert(rstpcie0); ++ ++ rt_sysc_m32(RALINK_PCIE0_CLK_EN, 0, RALINK_CLKCFG1); ++ rt_sysc_m32(BIT(19), BIT(31), PPLL_DRV); ++ ++ reset_control_deassert(rstpcie0); ++ rt_sysc_m32(0, RALINK_PCIE0_CLK_EN, RALINK_CLKCFG1); ++ ++ mdelay(100); ++ ++ if (!(rt_sysc_r32(PPLL_CFG1) & BIT(23))) { ++ dev_err(&pdev->dev, "MT7620 PPLL unlock\n"); ++ reset_control_assert(rstpcie0); ++ rt_sysc_m32(RALINK_PCIE0_CLK_EN, 0, RALINK_CLKCFG1); ++ return -1; ++ } ++ rt_sysc_m32(BIT(18) | BIT(17), BIT(19) | BIT(31), PPLL_DRV); ++ ++ return 0; ++} ++ ++static int mt7628_pci_hw_init(struct platform_device *pdev) { ++ u32 val = 0; ++ ++ rt_sysc_m32(BIT(16), 0, RALINK_GPIOMODE); ++ reset_control_deassert(rstpcie0); ++ rt_sysc_m32(0, RALINK_PCIE0_CLK_EN, RALINK_CLKCFG1); ++ mdelay(100); ++ ++ pcie_m32(~0xff, 0x5, RALINK_PCIEPHY_P0_CTL_OFFSET); ++ ++ pci_config_read(NULL, 0, 0x70c, 4, &val); ++ val &= ~(0xff) << 8; ++ val |= 0x50 << 8; ++ pci_config_write(NULL, 0, 0x70c, 4, val); ++ ++ pci_config_read(NULL, 0, 0x70c, 4, &val); ++ dev_err(&pdev->dev, "Port 0 N_FTS = %x\n", (unsigned int) val); ++ ++ return 0; ++} ++ ++static int mt7620_pci_probe(struct platform_device *pdev) ++{ ++ struct resource *bridge_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ struct resource *pcie_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ u32 val = 0; ++ ++ rstpcie0 = devm_reset_control_get(&pdev->dev, "pcie0"); ++ if (IS_ERR(rstpcie0)) ++ return PTR_ERR(rstpcie0); ++ ++ bridge_base = devm_ioremap_resource(&pdev->dev, bridge_res); ++ if (!bridge_base) ++ return -ENOMEM; ++ ++ pcie_base = devm_ioremap_resource(&pdev->dev, pcie_res); ++ if (!pcie_base) ++ return -ENOMEM; ++ ++ iomem_resource.start = 0; ++ iomem_resource.end = ~0; ++ ioport_resource.start = 0; ++ ioport_resource.end = ~0; ++ ++ /* bring up the pci core */ ++ switch (ralink_soc) { ++ case MT762X_SOC_MT7620A: ++ if (mt7620_pci_hw_init(pdev)) ++ return -1; ++ break; ++ ++ case MT762X_SOC_MT7628AN: ++ if (mt7628_pci_hw_init(pdev)) ++ return -1; ++ break; ++ ++ default: ++ dev_err(&pdev->dev, "pcie is not supported on this hardware\n"); ++ return -1; ++ } ++ mdelay(50); ++ ++ /* enable write access */ ++ pcie_m32(BIT(1), 0, RALINK_PCI_PCICFG_ADDR); ++ mdelay(100); ++ ++ /* check if there is a card present */ ++ if ((pcie_r32(RALINK_PCI0_STATUS) & 0x1) == 0) { ++ reset_control_assert(rstpcie0); ++ rt_sysc_m32(RALINK_PCIE0_CLK_EN, 0, RALINK_CLKCFG1); ++ if (ralink_soc == MT762X_SOC_MT7620A) ++ rt_sysc_m32(LC_CKDRVPD_, PDRV_SW_SET, PPLL_DRV); ++ dev_err(&pdev->dev, "PCIE0 no card, disable it(RST&CLK)\n"); ++ return -1; ++ } ++ ++ /* setup ranges */ ++ bridge_w32(0xffffffff, RALINK_PCI_MEMBASE); ++ bridge_w32(RALINK_PCI_IO_MAP_BASE, RALINK_PCI_IOBASE); ++ ++ pcie_w32(0x7FFF0001, RALINK_PCI0_BAR0SETUP_ADDR); ++ pcie_w32(MEMORY_BASE, RALINK_PCI0_IMBASEBAR0_ADDR); ++ pcie_w32(0x06040001, RALINK_PCI0_CLASS); ++ ++ /* enable interrupts */ ++ pcie_m32(0, BIT(20), RALINK_PCI_PCIMSK_ADDR); ++ ++ /* voodoo from the SDK driver */ ++ pci_config_read(NULL, 0, 4, 4, &val); ++ pci_config_write(NULL, 0, 4, 4, val | 0x7); ++ ++ pci_load_of_ranges(&mt7620_controller, pdev->dev.of_node); ++ register_pci_controller(&mt7620_controller); ++ ++ return 0; ++} ++ ++int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ u16 cmd; ++ u32 val; ++ int irq = 0; ++ ++ if ((dev->bus->number == 0) && (slot == 0)) { ++ pcie_w32(0x7FFF0001, RALINK_PCI0_BAR0SETUP_ADDR); //open 7FFF:2G; ENABLE ++ pci_config_write(dev->bus, 0, PCI_BASE_ADDRESS_0, 4, MEMORY_BASE); ++ pci_config_read(dev->bus, 0, PCI_BASE_ADDRESS_0, 4, &val); ++ } else if ((dev->bus->number == 1) && (slot == 0x0)) { ++ irq = RALINK_INT_PCIE0; ++ } else { ++ dev_err(&dev->dev, "no irq found - bus=0x%x, slot = 0x%x\n", dev->bus->number, slot); ++ return 0; ++ } ++ dev_err(&dev->dev, "card - bus=0x%x, slot = 0x%x irq=%d\n", dev->bus->number, slot, irq); ++ ++ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x14); //configure cache line size 0x14 ++ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xFF); //configure latency timer 0x10 ++ pci_read_config_word(dev, PCI_COMMAND, &cmd); ++ ++ // FIXME ++ cmd = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; ++ pci_write_config_word(dev, PCI_COMMAND, cmd); ++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); ++ //pci_write_config_byte(dev, PCI_INTERRUPT_PIN, dev->irq); ++ ++ return irq; ++} ++ ++int pcibios_plat_dev_init(struct pci_dev *dev) ++{ ++ return 0; ++} ++ ++static const struct of_device_id mt7620_pci_ids[] = { ++ { .compatible = "mediatek,mt7620-pci" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mt7620_pci_ids); ++ ++static struct platform_driver mt7620_pci_driver = { ++ .probe = mt7620_pci_probe, ++ .driver = { ++ .name = "mt7620-pci", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(mt7620_pci_ids), ++ }, ++}; ++ ++static int __init mt7620_pci_init(void) ++{ ++ return platform_driver_register(&mt7620_pci_driver); ++} ++ ++arch_initcall(mt7620_pci_init); +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -43,6 +43,7 @@ choice + + config SOC_MT7620 + bool "MT7620/8" ++ select HW_HAS_PCI + + config SOC_MT7621 + bool "MT7621" +--- a/arch/mips/include/asm/mach-ralink/mt7620.h ++++ b/arch/mips/include/asm/mach-ralink/mt7620.h +@@ -19,6 +19,7 @@ enum mt762x_soc_type { + MT762X_SOC_MT7620N, + MT762X_SOC_MT7628AN, + }; ++extern enum mt762x_soc_type mt762x_soc; + + #define MT7620_SYSC_BASE 0x10000000 + diff --git a/target/linux/ramips/patches-3.18/0033-NET-multi-phy-support.patch b/target/linux/ramips/patches-3.18/0033-NET-multi-phy-support.patch new file mode 100644 index 0000000..f6d2456 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0033-NET-multi-phy-support.patch @@ -0,0 +1,53 @@ +From 9c34372c25519234add1cfdfe2b69c0847f2037e Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 27 Jul 2014 09:38:50 +0100 +Subject: [PATCH 33/57] NET: multi phy support + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + drivers/net/phy/phy.c | 9 ++++++--- + include/linux/phy.h | 1 + + 2 files changed, 7 insertions(+), 3 deletions(-) + +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -838,7 +838,8 @@ void phy_state_machine(struct work_struc + /* If the link is down, give up on negotiation for now */ + if (!phydev->link) { + phydev->state = PHY_NOLINK; +- netif_carrier_off(phydev->attached_dev); ++ if (!phydev->no_auto_carrier_off) ++ netif_carrier_off(phydev->attached_dev); + phydev->adjust_link(phydev->attached_dev); + break; + } +@@ -911,7 +912,8 @@ void phy_state_machine(struct work_struc + netif_carrier_on(phydev->attached_dev); + } else { + phydev->state = PHY_NOLINK; +- netif_carrier_off(phydev->attached_dev); ++ if (!phydev->no_auto_carrier_off) ++ netif_carrier_off(phydev->attached_dev); + } + + phydev->adjust_link(phydev->attached_dev); +@@ -923,7 +925,8 @@ void phy_state_machine(struct work_struc + case PHY_HALTED: + if (phydev->link) { + phydev->link = 0; +- netif_carrier_off(phydev->attached_dev); ++ if (!phydev->no_auto_carrier_off) ++ netif_carrier_off(phydev->attached_dev); + phydev->adjust_link(phydev->attached_dev); + do_suspend = true; + } +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -363,6 +363,7 @@ struct phy_device { + struct phy_c45_device_ids c45_ids; + bool is_c45; + bool is_internal; ++ bool no_auto_carrier_off; + bool has_fixups; + + enum phy_state state; diff --git a/target/linux/ramips/patches-3.18/0035-NET-MIPS-add-ralink-SoC-ethernet-driver.patch b/target/linux/ramips/patches-3.18/0035-NET-MIPS-add-ralink-SoC-ethernet-driver.patch new file mode 100644 index 0000000..ede6d7d --- /dev/null +++ b/target/linux/ramips/patches-3.18/0035-NET-MIPS-add-ralink-SoC-ethernet-driver.patch @@ -0,0 +1,39 @@ +From c55d6cf3e2c593bf7d228c6532ec9bd8da82e09d Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Mon, 22 Apr 2013 23:20:03 +0200 +Subject: [PATCH 35/57] NET: MIPS: add ralink SoC ethernet driver + +Add support for Ralink FE and ESW. + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- +--- a/arch/mips/ralink/rt305x.c ++++ b/arch/mips/ralink/rt305x.c +@@ -199,6 +199,7 @@ void __init ralink_clk_init(void) + } + + ralink_clk_add("cpu", cpu_rate); ++ ralink_clk_add("sys", sys_rate); + ralink_clk_add("10000b00.spi", sys_rate); + ralink_clk_add("10000100.timer", wdt_rate); + ralink_clk_add("10000120.watchdog", wdt_rate); +--- a/drivers/net/ethernet/Kconfig ++++ b/drivers/net/ethernet/Kconfig +@@ -152,6 +152,7 @@ source "drivers/net/ethernet/packetengin + source "drivers/net/ethernet/pasemi/Kconfig" + source "drivers/net/ethernet/qlogic/Kconfig" + source "drivers/net/ethernet/qualcomm/Kconfig" ++source "drivers/net/ethernet/ralink/Kconfig" + source "drivers/net/ethernet/realtek/Kconfig" + source "drivers/net/ethernet/renesas/Kconfig" + source "drivers/net/ethernet/rdc/Kconfig" +--- a/drivers/net/ethernet/Makefile ++++ b/drivers/net/ethernet/Makefile +@@ -62,6 +62,7 @@ obj-$(CONFIG_NET_PACKET_ENGINE) += packe + obj-$(CONFIG_NET_VENDOR_PASEMI) += pasemi/ + obj-$(CONFIG_NET_VENDOR_QLOGIC) += qlogic/ + obj-$(CONFIG_NET_VENDOR_QUALCOMM) += qualcomm/ ++obj-$(CONFIG_NET_RALINK) += ralink/ + obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/ + obj-$(CONFIG_SH_ETH) += renesas/ + obj-$(CONFIG_NET_VENDOR_RDC) += rdc/ diff --git a/target/linux/ramips/patches-3.18/0037-USB-phy-add-ralink-SoC-driver.patch b/target/linux/ramips/patches-3.18/0037-USB-phy-add-ralink-SoC-driver.patch new file mode 100644 index 0000000..2448d0a --- /dev/null +++ b/target/linux/ramips/patches-3.18/0037-USB-phy-add-ralink-SoC-driver.patch @@ -0,0 +1,199 @@ +--- a/drivers/phy/Kconfig ++++ b/drivers/phy/Kconfig +@@ -239,6 +239,11 @@ config PHY_XGENE + help + This option enables support for APM X-Gene SoC multi-purpose PHY. + ++config PHY_RALINK_USB ++ tristate "Ralink USB PHY driver" ++ select GENERIC_PHY ++ depends on RALINK ++ + config PHY_STIH407_USB + tristate "STMicroelectronics USB2 picoPHY driver for STiH407 family" + depends on RESET_CONTROLLER +--- a/drivers/phy/Makefile ++++ b/drivers/phy/Makefile +@@ -31,3 +31,4 @@ obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += + obj-$(CONFIG_PHY_XGENE) += phy-xgene.o + obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb.o + obj-$(CONFIG_PHY_STIH41X_USB) += phy-stih41x-usb.o ++obj-$(CONFIG_PHY_RALINK_USB) += phy-ralink-usb.o +--- /dev/null ++++ b/drivers/phy/phy-ralink-usb.c +@@ -0,0 +1,175 @@ ++/* ++ * Allwinner ralink USB phy driver ++ * ++ * Copyright (C) 2014 John Crispin <blogic@openwrt.org> ++ * ++ * Based on code from ++ * Allwinner Technology Co., Ltd. <www.allwinnertech.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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/delay.h> ++#include <linux/err.h> ++#include <linux/io.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/mutex.h> ++#include <linux/phy/phy.h> ++#include <linux/platform_device.h> ++#include <linux/reset.h> ++#include <linux/of_platform.h> ++ ++#include <asm/mach-ralink/ralink_regs.h> ++ ++#define RT_SYSC_REG_SYSCFG1 0x014 ++#define RT_SYSC_REG_CLKCFG1 0x030 ++#define RT_SYSC_REG_USB_PHY_CFG 0x05c ++ ++#define RT_RSTCTRL_UDEV BIT(25) ++#define RT_RSTCTRL_UHST BIT(22) ++#define RT_SYSCFG1_USB0_HOST_MODE BIT(10) ++ ++#define MT7620_CLKCFG1_UPHY0_CLK_EN BIT(25) ++#define MT7620_CLKCFG1_UPHY1_CLK_EN BIT(22) ++#define RT_CLKCFG1_UPHY1_CLK_EN BIT(20) ++#define RT_CLKCFG1_UPHY0_CLK_EN BIT(18) ++ ++#define USB_PHY_UTMI_8B60M BIT(1) ++#define UDEV_WAKEUP BIT(0) ++ ++static atomic_t usb_pwr_ref = ATOMIC_INIT(0); ++static struct reset_control *rstdev; ++static struct reset_control *rsthost; ++static u32 phy_clk; ++static struct phy *rt_phy; ++ ++static void usb_phy_enable(int state) ++{ ++ if (state) ++ rt_sysc_m32(0, phy_clk, RT_SYSC_REG_CLKCFG1); ++ else ++ rt_sysc_m32(phy_clk, 0, RT_SYSC_REG_CLKCFG1); ++ mdelay(100); ++} ++ ++static int ralink_usb_phy_init(struct phy *_phy) ++{ ++ return 0; ++} ++ ++static int ralink_usb_phy_exit(struct phy *_phy) ++{ ++ return 0; ++} ++ ++static int ralink_usb_phy_power_on(struct phy *_phy) ++{ ++ if (atomic_inc_return(&usb_pwr_ref) == 1) { ++ int host = 1; ++ u32 t; ++ ++ usb_phy_enable(1); ++ ++ if (host) { ++ rt_sysc_m32(0, RT_SYSCFG1_USB0_HOST_MODE, RT_SYSC_REG_SYSCFG1); ++ if (!IS_ERR(rsthost)) ++ reset_control_deassert(rsthost); ++ if (!IS_ERR(rstdev)) ++ reset_control_deassert(rstdev); ++ } else { ++ rt_sysc_m32(RT_SYSCFG1_USB0_HOST_MODE, 0, RT_SYSC_REG_SYSCFG1); ++ if (!IS_ERR(rstdev)) ++ reset_control_deassert(rstdev); ++ } ++ mdelay(100); ++ ++ t = rt_sysc_r32(RT_SYSC_REG_USB_PHY_CFG); ++ dev_info(&_phy->dev, "remote usb device wakeup %s\n", ++ (t & UDEV_WAKEUP) ? ("enabbled") : ("disabled")); ++ if (t & USB_PHY_UTMI_8B60M) ++ dev_info(&_phy->dev, "UTMI 8bit 60MHz\n"); ++ else ++ dev_info(&_phy->dev, "UTMI 16bit 30MHz\n"); ++ } ++ ++ return 0; ++} ++ ++static int ralink_usb_phy_power_off(struct phy *_phy) ++{ ++ if (atomic_dec_return(&usb_pwr_ref) == 0) { ++ usb_phy_enable(0); ++ if (!IS_ERR(rstdev)) ++ reset_control_assert(rstdev); ++ if (!IS_ERR(rsthost)) ++ reset_control_assert(rsthost); ++ } ++ ++ return 0; ++} ++ ++static struct phy_ops ralink_usb_phy_ops = { ++ .init = ralink_usb_phy_init, ++ .exit = ralink_usb_phy_exit, ++ .power_on = ralink_usb_phy_power_on, ++ .power_off = ralink_usb_phy_power_off, ++ .owner = THIS_MODULE, ++}; ++ ++static struct phy *ralink_usb_phy_xlate(struct device *dev, ++ struct of_phandle_args *args) ++{ ++ return rt_phy; ++} ++ ++static const struct of_device_id ralink_usb_phy_of_match[] = { ++ { .compatible = "ralink,rt3xxx-usbphy", .data = (void *) (RT_CLKCFG1_UPHY1_CLK_EN | RT_CLKCFG1_UPHY0_CLK_EN) }, ++ { .compatible = "ralink,mt7620a-usbphy", .data = (void *) (MT7620_CLKCFG1_UPHY1_CLK_EN | MT7620_CLKCFG1_UPHY0_CLK_EN) }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, ralink_usb_phy_of_match); ++ ++static int ralink_usb_phy_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct phy_provider *phy_provider; ++ const struct of_device_id *match; ++ ++ match = of_match_device(ralink_usb_phy_of_match, &pdev->dev); ++ phy_clk = (int) match->data; ++ ++ rsthost = devm_reset_control_get(&pdev->dev, "host"); ++ rstdev = devm_reset_control_get(&pdev->dev, "device"); ++ ++ rt_phy = devm_phy_create(dev, NULL, &ralink_usb_phy_ops, NULL); ++ if (IS_ERR(rt_phy)) { ++ dev_err(dev, "failed to create PHY\n"); ++ return PTR_ERR(rt_phy); ++ } ++ ++ phy_provider = devm_of_phy_provider_register(dev, ralink_usb_phy_xlate); ++ ++ return PTR_ERR_OR_ZERO(phy_provider); ++} ++ ++static struct platform_driver ralink_usb_phy_driver = { ++ .probe = ralink_usb_phy_probe, ++ .driver = { ++ .of_match_table = ralink_usb_phy_of_match, ++ .name = "ralink-usb-phy", ++ } ++}; ++module_platform_driver(ralink_usb_phy_driver); ++ ++MODULE_DESCRIPTION("Ralink USB phy driver"); ++MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ramips/patches-3.18/0038-USB-add-OHCI-EHCI-OF-binding.patch b/target/linux/ramips/patches-3.18/0038-USB-add-OHCI-EHCI-OF-binding.patch new file mode 100644 index 0000000..a5fb5ab --- /dev/null +++ b/target/linux/ramips/patches-3.18/0038-USB-add-OHCI-EHCI-OF-binding.patch @@ -0,0 +1,34 @@ +From ffb27de4760595c356ef619c97f25722c8db28e7 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 27 Jul 2014 09:49:07 +0100 +Subject: [PATCH 38/57] USB: add OHCI/EHCI OF binding + +based on f3bc64d6d1f21c1b92d75f233a37b75d77af6963 + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + drivers/usb/Makefile | 3 ++- + drivers/usb/host/ehci-platform.c | 21 +++++++++++++++++---- + drivers/usb/host/ohci-platform.c | 37 +++++++++++++++++++++++++++++++------ + 3 files changed, 50 insertions(+), 11 deletions(-) + +--- a/drivers/usb/host/ehci-platform.c ++++ b/drivers/usb/host/ehci-platform.c +@@ -359,6 +359,7 @@ static int ehci_platform_resume(struct d + static const struct of_device_id vt8500_ehci_ids[] = { + { .compatible = "via,vt8500-ehci", }, + { .compatible = "wm,prizm-ehci", }, ++ { .compatible = "ralink,rt3xxx-ehci", }, + { .compatible = "generic-ehci", }, + {} + }; +--- a/drivers/usb/host/ohci-platform.c ++++ b/drivers/usb/host/ohci-platform.c +@@ -342,6 +342,7 @@ static int ohci_platform_resume(struct d + #endif /* CONFIG_PM */ + + static const struct of_device_id ohci_platform_ids[] = { ++ { .compatible = "ralink,rt3xxx-ohci", }, + { .compatible = "generic-ohci", }, + { } + }; diff --git a/target/linux/ramips/patches-3.18/0041-mtd-fix-cfi-cmdset-0002-erase-status-check.patch b/target/linux/ramips/patches-3.18/0041-mtd-fix-cfi-cmdset-0002-erase-status-check.patch new file mode 100644 index 0000000..b51756d --- /dev/null +++ b/target/linux/ramips/patches-3.18/0041-mtd-fix-cfi-cmdset-0002-erase-status-check.patch @@ -0,0 +1,29 @@ +From f0df443ca7d5d0e4d31aa6769ea12a8cf24d2cd8 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Mon, 15 Jul 2013 00:38:51 +0200 +Subject: [PATCH 41/57] mtd: fix cfi cmdset 0002 erase status check + +--- + drivers/mtd/chips/cfi_cmdset_0002.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/mtd/chips/cfi_cmdset_0002.c ++++ b/drivers/mtd/chips/cfi_cmdset_0002.c +@@ -2291,7 +2291,7 @@ static int __xipram do_erase_chip(struct + chip->erase_suspended = 0; + } + +- if (chip_ready(map, adr)) ++ if (chip_good(map, adr, map_word_ff(map))) + break; + + if (time_after(jiffies, timeo)) { +@@ -2380,7 +2380,7 @@ static int __xipram do_erase_oneblock(st + chip->erase_suspended = 0; + } + +- if (chip_ready(map, adr)) { ++ if (chip_good(map, adr, map_word_ff(map))) { + xip_enable(map, chip, adr); + break; + } diff --git a/target/linux/ramips/patches-3.18/0042-mtd-cfi-cmdset-0002-force-word-write.patch b/target/linux/ramips/patches-3.18/0042-mtd-cfi-cmdset-0002-force-word-write.patch new file mode 100644 index 0000000..971738c --- /dev/null +++ b/target/linux/ramips/patches-3.18/0042-mtd-cfi-cmdset-0002-force-word-write.patch @@ -0,0 +1,70 @@ +From 39010a26a34a56a7928f9217ac23e5138c5ea952 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Mon, 15 Jul 2013 00:39:21 +0200 +Subject: [PATCH 42/57] mtd: cfi cmdset 0002 force word write + +--- + drivers/mtd/chips/cfi_cmdset_0002.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/drivers/mtd/chips/cfi_cmdset_0002.c ++++ b/drivers/mtd/chips/cfi_cmdset_0002.c +@@ -40,7 +40,7 @@ + #include <linux/mtd/xip.h> + + #define AMD_BOOTLOC_BUG +-#define FORCE_WORD_WRITE 0 ++#define FORCE_WORD_WRITE 1 + + #define MAX_WORD_RETRIES 3 + +@@ -51,7 +51,9 @@ + + static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); + static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); ++#if !FORCE_WORD_WRITE + static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); ++#endif + static int cfi_amdstd_erase_chip(struct mtd_info *, struct erase_info *); + static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *); + static void cfi_amdstd_sync (struct mtd_info *); +@@ -202,6 +204,7 @@ static void fixup_amd_bootblock(struct m + } + #endif + ++#if !FORCE_WORD_WRITE + static void fixup_use_write_buffers(struct mtd_info *mtd) + { + struct map_info *map = mtd->priv; +@@ -211,6 +214,7 @@ static void fixup_use_write_buffers(stru + mtd->_write = cfi_amdstd_write_buffers; + } + } ++#endif /* !FORCE_WORD_WRITE */ + + /* Atmel chips don't use the same PRI format as AMD chips */ + static void fixup_convert_atmel_pri(struct mtd_info *mtd) +@@ -1789,6 +1793,7 @@ static int cfi_amdstd_write_words(struct + /* + * FIXME: interleaved mode not tested, and probably not supported! + */ ++#if !FORCE_WORD_WRITE + static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, + unsigned long adr, const u_char *buf, + int len) +@@ -1917,7 +1922,6 @@ static int __xipram do_write_buffer(stru + return ret; + } + +- + static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) + { +@@ -1992,6 +1996,7 @@ static int cfi_amdstd_write_buffers(stru + + return 0; + } ++#endif /* !FORCE_WORD_WRITE */ + + /* + * Wait for the flash chip to become ready to write data diff --git a/target/linux/ramips/patches-3.18/0043-mtd-ralink-add-mt7620-nand-driver.patch b/target/linux/ramips/patches-3.18/0043-mtd-ralink-add-mt7620-nand-driver.patch new file mode 100644 index 0000000..8ee26d5 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0043-mtd-ralink-add-mt7620-nand-driver.patch @@ -0,0 +1,2408 @@ +From b915fe7cd934160bfaf2cd52f03c118abcae2419 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 17 Nov 2013 17:41:46 +0100 +Subject: [PATCH 43/57] mtd: ralink: add mt7620 nand driver + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + drivers/mtd/maps/Kconfig | 4 + + drivers/mtd/maps/Makefile | 2 + + drivers/mtd/maps/ralink_nand.c | 2136 ++++++++++++++++++++++++++++++++++++++++ + drivers/mtd/maps/ralink_nand.h | 232 +++++ + 4 files changed, 2374 insertions(+) + create mode 100644 drivers/mtd/maps/ralink_nand.c + create mode 100644 drivers/mtd/maps/ralink_nand.h + +--- a/drivers/mtd/maps/Kconfig ++++ b/drivers/mtd/maps/Kconfig +@@ -399,4 +399,8 @@ config MTD_LATCH_ADDR + + If compiled as a module, it will be called latch-addr-flash. + ++config MTD_NAND_MT7620 ++ tristate "Support for NAND on Mediatek MT7620" ++ depends on RALINK && SOC_MT7620 ++ + endmenu +--- a/drivers/mtd/maps/Makefile ++++ b/drivers/mtd/maps/Makefile +@@ -43,3 +43,5 @@ obj-$(CONFIG_MTD_VMU) += vmu-flash.o + obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o + obj-$(CONFIG_MTD_LATCH_ADDR) += latch-addr-flash.o + obj-$(CONFIG_MTD_LANTIQ) += lantiq-flash.o ++obj-$(CONFIG_MTD_NAND_MT7620) += ralink_nand.o ++ +--- /dev/null ++++ b/drivers/mtd/maps/ralink_nand.c +@@ -0,0 +1,2136 @@ ++#define DEBUG ++#include <linux/device.h> ++#undef DEBUG ++#include <linux/slab.h> ++#include <linux/mtd/mtd.h> ++#include <linux/delay.h> ++#include <linux/module.h> ++#include <linux/interrupt.h> ++#include <linux/dma-mapping.h> ++#include <linux/mtd/partitions.h> ++#include <asm/io.h> ++#include <linux/delay.h> ++#include <linux/sched.h> ++#include <linux/of.h> ++#include <linux/platform_device.h> ++ ++#include "ralink_nand.h" ++#ifdef RANDOM_GEN_BAD_BLOCK ++#include <linux/random.h> ++#endif ++ ++#define LARGE_MTD_BOOT_PART_SIZE (CFG_BLOCKSIZE<<2) ++#define LARGE_MTD_CONFIG_PART_SIZE (CFG_BLOCKSIZE<<2) ++#define LARGE_MTD_FACTORY_PART_SIZE (CFG_BLOCKSIZE<<1) ++ ++ ++#define BLOCK_ALIGNED(a) ((a) & (CFG_BLOCKSIZE - 1)) ++ ++#define READ_STATUS_RETRY 1000 ++ ++struct mtd_info *ranfc_mtd = NULL; ++ ++int skipbbt = 0; ++int ranfc_debug = 1; ++static int ranfc_bbt = 1; ++#if defined (WORKAROUND_RX_BUF_OV) ++static int ranfc_verify = 1; ++#endif ++static u32 nand_addrlen; ++ ++#if 0 ++module_param(ranfc_debug, int, 0644); ++module_param(ranfc_bbt, int, 0644); ++module_param(ranfc_verify, int, 0644); ++#endif ++ ++#if 0 ++#define ra_dbg(args...) do { if (ranfc_debug) printk(args); } while(0) ++#else ++#define ra_dbg(args...) ++#endif ++ ++#define CLEAR_INT_STATUS() ra_outl(NFC_INT_ST, ra_inl(NFC_INT_ST)) ++#define NFC_TRANS_DONE() (ra_inl(NFC_INT_ST) & INT_ST_ND_DONE) ++ ++int is_nand_page_2048 = 0; ++const unsigned int nand_size_map[2][3] = {{25, 30, 30}, {20, 27, 30}}; ++ ++static int nfc_wait_ready(int snooze_ms); ++ ++static const char * const mtk_probe_types[] = { "cmdlinepart", "ofpart", NULL }; ++ ++/** ++ * reset nand chip ++ */ ++static int nfc_chip_reset(void) ++{ ++ int status; ++ ++ //ra_dbg("%s:\n", __func__); ++ ++ // reset nand flash ++ ra_outl(NFC_CMD1, 0x0); ++ ra_outl(NFC_CMD2, 0xff); ++ ra_outl(NFC_ADDR, 0x0); ++ ra_outl(NFC_CONF, 0x0411); ++ ++ status = nfc_wait_ready(5); //erase wait 5us ++ if (status & NAND_STATUS_FAIL) { ++ printk("%s: fail \n", __func__); ++ } ++ ++ return (int)(status & NAND_STATUS_FAIL); ++ ++} ++ ++ ++ ++/** ++ * clear NFC and flash chip. ++ */ ++static int nfc_all_reset(void) ++{ ++ int retry; ++ ++ ra_dbg("%s: \n", __func__); ++ ++ // reset controller ++ ra_outl(NFC_CTRL, ra_inl(NFC_CTRL) | 0x02); //clear data buffer ++ ra_outl(NFC_CTRL, ra_inl(NFC_CTRL) & ~0x02); //clear data buffer ++ ++ CLEAR_INT_STATUS(); ++ ++ retry = READ_STATUS_RETRY; ++ while ((ra_inl(NFC_INT_ST) & 0x02) != 0x02 && retry--); ++ if (retry <= 0) { ++ printk("nfc_all_reset: clean buffer fail \n"); ++ return -1; ++ } ++ ++ retry = READ_STATUS_RETRY; ++ while ((ra_inl(NFC_STATUS) & 0x1) != 0x0 && retry--) { //fixme, controller is busy ? ++ udelay(1); ++ } ++ ++ nfc_chip_reset(); ++ ++ return 0; ++} ++ ++/** NOTICE: only called by nfc_wait_ready(). ++ * @return -1, nfc can not get transction done ++ * @return 0, ok. ++ */ ++static int _nfc_read_status(char *status) ++{ ++ unsigned long cmd1, conf; ++ int int_st, nfc_st; ++ int retry; ++ ++ cmd1 = 0x70; ++ conf = 0x000101 | (1 << 20); ++ ++ //fixme, should we check nfc status? ++ CLEAR_INT_STATUS(); ++ ++ ra_outl(NFC_CMD1, cmd1); ++ ra_outl(NFC_CONF, conf); ++ ++ /* FIXME, ++ * 1. since we have no wired ready signal, directly ++ * calling this function is not gurantee to read right status under ready state. ++ * 2. the other side, we can not determine how long to become ready, this timeout retry is nonsense. ++ * 3. SUGGESTION: call nfc_read_status() from nfc_wait_ready(), ++ * that is aware about caller (in sementics) and has snooze plused nfc ND_DONE. ++ */ ++ retry = READ_STATUS_RETRY; ++ do { ++ nfc_st = ra_inl(NFC_STATUS); ++ int_st = ra_inl(NFC_INT_ST); ++ ++ ndelay(10); ++ } while (!(int_st & INT_ST_RX_BUF_RDY) && retry--); ++ ++ if (!(int_st & INT_ST_RX_BUF_RDY)) { ++ printk("nfc_read_status: NFC fail, int_st(%x), retry:%x. nfc:%x, reset nfc and flash. \n", ++ int_st, retry, nfc_st); ++ nfc_all_reset(); ++ *status = NAND_STATUS_FAIL; ++ return -1; ++ } ++ ++ *status = (char)(le32_to_cpu(ra_inl(NFC_DATA)) & 0x0ff); ++ return 0; ++} ++ ++/** ++ * @return !0, chip protect. ++ * @return 0, chip not protected. ++ */ ++static int nfc_check_wp(void) ++{ ++ /* Check the WP bit */ ++#if !defined CONFIG_NOT_SUPPORT_WP ++ return !!(ra_inl(NFC_CTRL) & 0x01); ++#else ++ char result = 0; ++ int ret; ++ ++ ret = _nfc_read_status(&result); ++ //FIXME, if ret < 0 ++ ++ return !(result & NAND_STATUS_WP); ++#endif ++} ++ ++#if !defined CONFIG_NOT_SUPPORT_RB ++/* ++ * @return !0, chip ready. ++ * @return 0, chip busy. ++ */ ++static int nfc_device_ready(void) ++{ ++ /* Check the ready */ ++ return !!(ra_inl(NFC_STATUS) & 0x04); ++} ++#endif ++ ++ ++/** ++ * generic function to get data from flash. ++ * @return data length reading from flash. ++ */ ++static int _ra_nand_pull_data(char *buf, int len, int use_gdma) ++{ ++#ifdef RW_DATA_BY_BYTE ++ char *p = buf; ++#else ++ __u32 *p = (__u32 *)buf; ++#endif ++ int retry, int_st; ++ unsigned int ret_data; ++ int ret_size; ++ ++ // receive data by use_gdma ++ if (use_gdma) { ++ //if (_ra_nand_dma_pull((unsigned long)p, len)) { ++ if (1) { ++ printk("%s: fail \n", __func__); ++ len = -1; //return error ++ } ++ ++ return len; ++ } ++ ++ //fixme: retry count size? ++ retry = READ_STATUS_RETRY; ++ // no gdma ++ while (len > 0) { ++ int_st = ra_inl(NFC_INT_ST); ++ if (int_st & INT_ST_RX_BUF_RDY) { ++ ++ ret_data = ra_inl(NFC_DATA); ++ ra_outl(NFC_INT_ST, INT_ST_RX_BUF_RDY); ++#ifdef RW_DATA_BY_BYTE ++ ret_size = sizeof(unsigned int); ++ ret_size = min(ret_size, len); ++ len -= ret_size; ++ while (ret_size-- > 0) { ++ //nfc is little endian ++ *p++ = ret_data & 0x0ff; ++ ret_data >>= 8; ++ } ++#else ++ ret_size = min(len, 4); ++ len -= ret_size; ++ if (ret_size == 4) ++ *p++ = ret_data; ++ else { ++ __u8 *q = (__u8 *)p; ++ while (ret_size-- > 0) { ++ *q++ = ret_data & 0x0ff; ++ ret_data >>= 8; ++ } ++ p = (__u32 *)q; ++ } ++#endif ++ retry = READ_STATUS_RETRY; ++ } ++ else if (int_st & INT_ST_ND_DONE) { ++ break; ++ } ++ else { ++ udelay(1); ++ if (retry-- < 0) ++ break; ++ } ++ } ++ ++#ifdef RW_DATA_BY_BYTE ++ return (int)(p - buf); ++#else ++ return ((int)p - (int)buf); ++#endif ++} ++ ++/** ++ * generic function to put data into flash. ++ * @return data length writing into flash. ++ */ ++static int _ra_nand_push_data(char *buf, int len, int use_gdma) ++{ ++#ifdef RW_DATA_BY_BYTE ++ char *p = buf; ++#else ++ __u32 *p = (__u32 *)buf; ++#endif ++ int retry, int_st; ++ unsigned int tx_data = 0; ++ int tx_size, iter = 0; ++ ++ // receive data by use_gdma ++ if (use_gdma) { ++ //if (_ra_nand_dma_push((unsigned long)p, len)) ++ if (1) ++ len = 0; ++ printk("%s: fail \n", __func__); ++ return len; ++ } ++ ++ // no gdma ++ retry = READ_STATUS_RETRY; ++ while (len > 0) { ++ int_st = ra_inl(NFC_INT_ST); ++ if (int_st & INT_ST_TX_BUF_RDY) { ++#ifdef RW_DATA_BY_BYTE ++ tx_size = min(len, (int)sizeof(unsigned long)); ++ for (iter = 0; iter < tx_size; iter++) { ++ tx_data |= (*p++ << (8*iter)); ++ } ++#else ++ tx_size = min(len, 4); ++ if (tx_size == 4) ++ tx_data = (*p++); ++ else { ++ __u8 *q = (__u8 *)p; ++ for (iter = 0; iter < tx_size; iter++) ++ tx_data |= (*q++ << (8*iter)); ++ p = (__u32 *)q; ++ } ++#endif ++ ra_outl(NFC_INT_ST, INT_ST_TX_BUF_RDY); ++ ra_outl(NFC_DATA, tx_data); ++ len -= tx_size; ++ retry = READ_STATUS_RETRY; ++ } ++ else if (int_st & INT_ST_ND_DONE) { ++ break; ++ } ++ else { ++ udelay(1); ++ if (retry-- < 0) { ++ ra_dbg("%s p:%p buf:%p \n", __func__, p, buf); ++ break; ++ } ++ } ++ } ++ ++ ++#ifdef RW_DATA_BY_BYTE ++ return (int)(p - buf); ++#else ++ return ((int)p - (int)buf); ++#endif ++ ++} ++ ++static int nfc_select_chip(struct ra_nand_chip *ra, int chipnr) ++{ ++#if (CONFIG_NUMCHIPS == 1) ++ if (!(chipnr < CONFIG_NUMCHIPS)) ++ return -1; ++ return 0; ++#else ++ BUG(); ++#endif ++} ++ ++/** @return -1: chip_select fail ++ * 0 : both CE and WP==0 are OK ++ * 1 : CE OK and WP==1 ++ */ ++static int nfc_enable_chip(struct ra_nand_chip *ra, unsigned int offs, int read_only) ++{ ++ int chipnr = offs >> ra->chip_shift; ++ ++ ra_dbg("%s: offs:%x read_only:%x \n", __func__, offs, read_only); ++ ++ chipnr = nfc_select_chip(ra, chipnr); ++ if (chipnr < 0) { ++ printk("%s: chip select error, offs(%x)\n", __func__, offs); ++ return -1; ++ } ++ ++ if (!read_only) ++ return nfc_check_wp(); ++ ++ return 0; ++} ++ ++/** wait nand chip becomeing ready and return queried status. ++ * @param snooze: sleep time in ms unit before polling device ready. ++ * @return status of nand chip ++ * @return NAN_STATUS_FAIL if something unexpected. ++ */ ++static int nfc_wait_ready(int snooze_ms) ++{ ++ int retry; ++ char status; ++ ++ // wait nfc idle, ++ if (snooze_ms == 0) ++ snooze_ms = 1; ++ else ++ schedule_timeout(snooze_ms * HZ / 1000); ++ ++ snooze_ms = retry = snooze_ms *1000000 / 100 ; // ndelay(100) ++ ++ while (!NFC_TRANS_DONE() && retry--) { ++ if (!cond_resched()) ++ ndelay(100); ++ } ++ ++ if (!NFC_TRANS_DONE()) { ++ printk("nfc_wait_ready: no transaction done \n"); ++ return NAND_STATUS_FAIL; ++ } ++ ++#if !defined (CONFIG_NOT_SUPPORT_RB) ++ //fixme ++ while(!(status = nfc_device_ready()) && retry--) { ++ ndelay(100); ++ } ++ ++ if (status == 0) { ++ printk("nfc_wait_ready: no device ready. \n"); ++ return NAND_STATUS_FAIL; ++ } ++ ++ _nfc_read_status(&status); ++ return status; ++#else ++ ++ while(retry--) { ++ _nfc_read_status(&status); ++ if (status & NAND_STATUS_READY) ++ break; ++ ndelay(100); ++ } ++ if (retry<0) ++ printk("nfc_wait_ready 2: no device ready, status(%x). \n", status); ++ ++ return status; ++#endif ++} ++ ++/** ++ * return 0: erase OK ++ * return -EIO: fail ++ */ ++int nfc_erase_block(struct ra_nand_chip *ra, int row_addr) ++{ ++ unsigned long cmd1, cmd2, bus_addr, conf; ++ char status; ++ ++ cmd1 = 0x60; ++ cmd2 = 0xd0; ++ bus_addr = row_addr; ++ conf = 0x00511 | ((CFG_ROW_ADDR_CYCLE)<<16); ++ ++ // set NFC ++ ra_dbg("%s: cmd1: %lx, cmd2:%lx bus_addr: %lx, conf: %lx \n", ++ __func__, cmd1, cmd2, bus_addr, conf); ++ ++ //fixme, should we check nfc status? ++ CLEAR_INT_STATUS(); ++ ++ ra_outl(NFC_CMD1, cmd1); ++ ra_outl(NFC_CMD2, cmd2); ++ ra_outl(NFC_ADDR, bus_addr); ++ ra_outl(NFC_CONF, conf); ++ ++ status = nfc_wait_ready(3); //erase wait 3ms ++ if (status & NAND_STATUS_FAIL) { ++ printk("%s: fail \n", __func__); ++ return -EIO; ++ } ++ ++ return 0; ++ ++} ++ ++static inline int _nfc_read_raw_data(int cmd1, int cmd2, int bus_addr, int bus_addr2, int conf, char *buf, int len, int flags) ++{ ++ int ret; ++ ++ CLEAR_INT_STATUS(); ++ ra_outl(NFC_CMD1, cmd1); ++ ra_outl(NFC_CMD2, cmd2); ++ ra_outl(NFC_ADDR, bus_addr); ++#if defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) ++ ra_outl(NFC_ADDR2, bus_addr2); ++#endif ++ ra_outl(NFC_CONF, conf); ++ ++ ret = _ra_nand_pull_data(buf, len, 0); ++ if (ret != len) { ++ ra_dbg("%s: ret:%x (%x) \n", __func__, ret, len); ++ return NAND_STATUS_FAIL; ++ } ++ ++ //FIXME, this section is not necessary ++ ret = nfc_wait_ready(0); //wait ready ++ /* to prevent the DATA FIFO 's old data from next operation */ ++ ra_outl(NFC_CTRL, ra_inl(NFC_CTRL) | 0x02); //clear data buffer ++ ra_outl(NFC_CTRL, ra_inl(NFC_CTRL) & ~0x02); //clear data buffer ++ ++ if (ret & NAND_STATUS_FAIL) { ++ printk("%s: fail \n", __func__); ++ return NAND_STATUS_FAIL; ++ } ++ ++ return 0; ++} ++ ++static inline int _nfc_write_raw_data(int cmd1, int cmd3, int bus_addr, int bus_addr2, int conf, char *buf, int len, int flags) ++{ ++ int ret; ++ ++ CLEAR_INT_STATUS(); ++ ra_outl(NFC_CMD1, cmd1); ++ ra_outl(NFC_CMD3, cmd3); ++ ra_outl(NFC_ADDR, bus_addr); ++#if defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) ++ ra_outl(NFC_ADDR2, bus_addr2); ++#endif ++ ra_outl(NFC_CONF, conf); ++ ++ ret = _ra_nand_push_data(buf, len, 0); ++ if (ret != len) { ++ ra_dbg("%s: ret:%x (%x) \n", __func__, ret, len); ++ return NAND_STATUS_FAIL; ++ } ++ ++ ret = nfc_wait_ready(1); //write wait 1ms ++ /* to prevent the DATA FIFO 's old data from next operation */ ++ ra_outl(NFC_CTRL, ra_inl(NFC_CTRL) | 0x02); //clear data buffer ++ ra_outl(NFC_CTRL, ra_inl(NFC_CTRL) & ~0x02); //clear data buffer ++ ++ if (ret & NAND_STATUS_FAIL) { ++ printk("%s: fail \n", __func__); ++ return NAND_STATUS_FAIL; ++ } ++ ++ return 0; ++} ++ ++/** ++ * @return !0: fail ++ * @return 0: OK ++ */ ++int nfc_read_oob(struct ra_nand_chip *ra, int page, unsigned int offs, char *buf, int len, int flags) ++{ ++ unsigned int cmd1 = 0, cmd2 = 0, conf = 0; ++ unsigned int bus_addr = 0, bus_addr2 = 0; ++ unsigned int ecc_en; ++ int use_gdma; ++ int status; ++ ++ int pages_perblock = 1<<(ra->erase_shift - ra->page_shift); ++ // constrain of nfc read function ++ ++#if defined (WORKAROUND_RX_BUF_OV) ++ BUG_ON (len > 60); //problem of rx-buffer overrun ++#endif ++ BUG_ON (offs >> ra->oob_shift); //page boundry ++ BUG_ON ((unsigned int)(((offs + len) >> ra->oob_shift) + page) > ++ ((page + pages_perblock) & ~(pages_perblock-1))); //block boundry ++ ++ use_gdma = flags & FLAG_USE_GDMA; ++ ecc_en = flags & FLAG_ECC_EN; ++ bus_addr = (page << (CFG_COLUMN_ADDR_CYCLE*8)) | (offs & ((1<<CFG_COLUMN_ADDR_CYCLE*8) - 1)); ++ ++ if (is_nand_page_2048) { ++ bus_addr += CFG_PAGESIZE; ++ bus_addr2 = page >> (CFG_COLUMN_ADDR_CYCLE*8); ++ cmd1 = 0x0; ++ cmd2 = 0x30; ++ conf = 0x000511| ((CFG_ADDR_CYCLE)<<16) | (len << 20); ++ } ++ else { ++ cmd1 = 0x50; ++ conf = 0x000141| ((CFG_ADDR_CYCLE)<<16) | (len << 20); ++ } ++ if (ecc_en) ++ conf |= (1<<3); ++ if (use_gdma) ++ conf |= (1<<2); ++ ++ ra_dbg("%s: cmd1:%x, bus_addr:%x, conf:%x, len:%x, flag:%x\n", ++ __func__, cmd1, bus_addr, conf, len, flags); ++ ++ status = _nfc_read_raw_data(cmd1, cmd2, bus_addr, bus_addr2, conf, buf, len, flags); ++ if (status & NAND_STATUS_FAIL) { ++ printk("%s: fail\n", __func__); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++/** ++ * @return !0: fail ++ * @return 0: OK ++ */ ++int nfc_write_oob(struct ra_nand_chip *ra, int page, unsigned int offs, char *buf, int len, int flags) ++{ ++ unsigned int cmd1 = 0, cmd3=0, conf = 0; ++ unsigned int bus_addr = 0, bus_addr2 = 0; ++ int use_gdma; ++ int status; ++ ++ int pages_perblock = 1<<(ra->erase_shift - ra->page_shift); ++ // constrain of nfc read function ++ ++ BUG_ON (offs >> ra->oob_shift); //page boundry ++ BUG_ON ((unsigned int)(((offs + len) >> ra->oob_shift) + page) > ++ ((page + pages_perblock) & ~(pages_perblock-1))); //block boundry ++ ++ use_gdma = flags & FLAG_USE_GDMA; ++ bus_addr = (page << (CFG_COLUMN_ADDR_CYCLE*8)) | (offs & ((1<<CFG_COLUMN_ADDR_CYCLE*8) - 1)); ++ ++ if (is_nand_page_2048) { ++ cmd1 = 0x80; ++ cmd3 = 0x10; ++ bus_addr += CFG_PAGESIZE; ++ bus_addr2 = page >> (CFG_COLUMN_ADDR_CYCLE*8); ++ conf = 0x001123 | ((CFG_ADDR_CYCLE)<<16) | ((len) << 20); ++ } ++ else { ++ cmd1 = 0x08050; ++ cmd3 = 0x10; ++ conf = 0x001223 | ((CFG_ADDR_CYCLE)<<16) | ((len) << 20); ++ } ++ if (use_gdma) ++ conf |= (1<<2); ++ ++ // set NFC ++ ra_dbg("%s: cmd1: %x, cmd3: %x bus_addr: %x, conf: %x, len:%x\n", ++ __func__, cmd1, cmd3, bus_addr, conf, len); ++ ++ status = _nfc_write_raw_data(cmd1, cmd3, bus_addr, bus_addr2, conf, buf, len, flags); ++ if (status & NAND_STATUS_FAIL) { ++ printk("%s: fail \n", __func__); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++ ++int nfc_read_page(struct ra_nand_chip *ra, char *buf, int page, int flags); ++int nfc_write_page(struct ra_nand_chip *ra, char *buf, int page, int flags); ++ ++ ++#if !defined (WORKAROUND_RX_BUF_OV) ++static int one_bit_correction(char *ecc, char *expected, int *bytes, int *bits); ++int nfc_ecc_verify(struct ra_nand_chip *ra, char *buf, int page, int mode) ++{ ++ int ret, i; ++ char *p, *e; ++ int ecc; ++ ++ //ra_dbg("%s, page:%x mode:%d\n", __func__, page, mode); ++ ++ if (mode == FL_WRITING) { ++ int len = CFG_PAGESIZE + CFG_PAGE_OOBSIZE; ++ int conf = 0x000141| ((CFG_ADDR_CYCLE)<<16) | (len << 20); ++ conf |= (1<<3); //(ecc_en) ++ //conf |= (1<<2); // (use_gdma) ++ ++ p = ra->readback_buffers; ++ ret = nfc_read_page(ra, ra->readback_buffers, page, FLAG_ECC_EN); ++ if (ret == 0) ++ goto ecc_check; ++ ++ //FIXME, double comfirm ++ printk("%s: read back fail, try again \n",__func__); ++ ret = nfc_read_page(ra, ra->readback_buffers, page, FLAG_ECC_EN); ++ if (ret != 0) { ++ printk("\t%s: read back fail agian \n",__func__); ++ goto bad_block; ++ } ++ } ++ else if (mode == FL_READING) { ++ p = buf; ++ } ++ else ++ return -2; ++ ++ecc_check: ++ p += CFG_PAGESIZE; ++ if (!is_nand_page_2048) { ++ ecc = ra_inl(NFC_ECC); ++ if (ecc == 0) //clean page. ++ return 0; ++ e = (char*)&ecc; ++ for (i=0; i<CONFIG_ECC_BYTES; i++) { ++ int eccpos = CONFIG_ECC_OFFSET + i; ++ if (*(p + eccpos) != (char)0xff) ++ break; ++ if (i == CONFIG_ECC_BYTES - 1) { ++ printk("skip ecc 0xff at page %x\n", page); ++ return 0; ++ } ++ } ++ for (i=0; i<CONFIG_ECC_BYTES; i++) { ++ int eccpos = CONFIG_ECC_OFFSET + i; ++ if (*(p + eccpos) != *(e + i)) { ++ printk("%s mode:%s, invalid ecc, page: %x read:%x %x %x, ecc:%x \n", ++ __func__, (mode == FL_READING)?"read":"write", page, ++ *(p+ CONFIG_ECC_OFFSET), *(p+ CONFIG_ECC_OFFSET+1), *(p+ CONFIG_ECC_OFFSET +2), ecc); ++ return -1; ++ } ++ } ++ } ++#if defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) ++ else { ++ int ecc2, ecc3, ecc4, qsz; ++ char *e2, *e3, *e4; ++ int correction_flag = 0; ++ ecc = ra_inl(NFC_ECC_P1); ++ ecc2 = ra_inl(NFC_ECC_P2); ++ ecc3 = ra_inl(NFC_ECC_P3); ++ ecc4 = ra_inl(NFC_ECC_P4); ++ e = (char*)&ecc; ++ e2 = (char*)&ecc2; ++ e3 = (char*)&ecc3; ++ e4 = (char*)&ecc4; ++ qsz = CFG_PAGE_OOBSIZE / 4; ++ if (ecc == 0 && ecc2 == 0 && ecc3 == 0 && ecc4 == 0) ++ return 0; ++ for (i=0; i<CONFIG_ECC_BYTES; i++) { ++ int eccpos = CONFIG_ECC_OFFSET + i; ++ if (*(p + eccpos) != (char)0xff) ++ break; ++ else if (*(p + eccpos + qsz) != (char)0xff) ++ break; ++ else if (*(p + eccpos + qsz*2) != (char)0xff) ++ break; ++ else if (*(p + eccpos + qsz*3) != (char)0xff) ++ break; ++ if (i == CONFIG_ECC_BYTES - 1) { ++ printk("skip ecc 0xff at page %x\n", page); ++ return 0; ++ } ++ } ++ for (i=0; i<CONFIG_ECC_BYTES; i++) { ++ int eccpos = CONFIG_ECC_OFFSET + i; ++ if (*(p + eccpos) != *(e + i)) { ++ printk("%s mode:%s, invalid ecc, page: %x read:%x %x %x, ecc:%x \n", ++ __func__, (mode == FL_READING)?"read":"write", page, ++ *(p+ CONFIG_ECC_OFFSET), *(p+ CONFIG_ECC_OFFSET+1), *(p+ CONFIG_ECC_OFFSET +2), ecc); ++ correction_flag |= 0x1; ++ } ++ if (*(p + eccpos + qsz) != *(e2 + i)) { ++ printk("%s mode:%s, invalid ecc2, page: %x read:%x %x %x, ecc2:%x \n", ++ __func__, (mode == FL_READING)?"read":"write", page, ++ *(p+CONFIG_ECC_OFFSET+qsz), *(p+ CONFIG_ECC_OFFSET+1+qsz), *(p+ CONFIG_ECC_OFFSET+2+qsz), ecc2); ++ correction_flag |= 0x2; ++ } ++ if (*(p + eccpos + qsz*2) != *(e3 + i)) { ++ printk("%s mode:%s, invalid ecc3, page: %x read:%x %x %x, ecc3:%x \n", ++ __func__, (mode == FL_READING)?"read":"write", page, ++ *(p+CONFIG_ECC_OFFSET+qsz*2), *(p+ CONFIG_ECC_OFFSET+1+qsz*2), *(p+ CONFIG_ECC_OFFSET+2+qsz*2), ecc3); ++ correction_flag |= 0x4; ++ } ++ if (*(p + eccpos + qsz*3) != *(e4 + i)) { ++ printk("%s mode:%s, invalid ecc4, page: %x read:%x %x %x, ecc4:%x \n", ++ __func__, (mode == FL_READING)?"read":"write", page, ++ *(p+CONFIG_ECC_OFFSET+qsz*3), *(p+ CONFIG_ECC_OFFSET+1+qsz*3), *(p+ CONFIG_ECC_OFFSET+2+qsz*3), ecc4); ++ correction_flag |= 0x8; ++ } ++ } ++ ++ if (correction_flag) ++ { ++ printk("trying to do correction!\n"); ++ if (correction_flag & 0x1) ++ { ++ int bytes, bits; ++ char *pBuf = p - CFG_PAGESIZE; ++ ++ if (one_bit_correction(p + CONFIG_ECC_OFFSET, e, &bytes, &bits) == 0) ++ { ++ pBuf[bytes] = pBuf[bytes] ^ (1 << bits); ++ printk("1. correct byte %d, bit %d!\n", bytes, bits); ++ } ++ else ++ { ++ printk("failed to correct!\n"); ++ return -1; ++ } ++ } ++ ++ if (correction_flag & 0x2) ++ { ++ int bytes, bits; ++ char *pBuf = (p - CFG_PAGESIZE) + CFG_PAGESIZE/4; ++ ++ if (one_bit_correction((p + CONFIG_ECC_OFFSET + qsz), e2, &bytes, &bits) == 0) ++ { ++ pBuf[bytes] = pBuf[bytes] ^ (1 << bits); ++ printk("2. correct byte %d, bit %d!\n", bytes, bits); ++ } ++ else ++ { ++ printk("failed to correct!\n"); ++ return -1; ++ } ++ } ++ if (correction_flag & 0x4) ++ { ++ int bytes, bits; ++ char *pBuf = (p - CFG_PAGESIZE) + CFG_PAGESIZE/2; ++ ++ if (one_bit_correction((p + CONFIG_ECC_OFFSET + qsz * 2), e3, &bytes, &bits) == 0) ++ { ++ pBuf[bytes] = pBuf[bytes] ^ (1 << bits); ++ printk("3. correct byte %d, bit %d!\n", bytes, bits); ++ } ++ else ++ { ++ printk("failed to correct!\n"); ++ return -1; ++ } ++ } ++ if (correction_flag & 0x8) ++ { ++ int bytes, bits; ++ char *pBuf = (p - CFG_PAGESIZE) + CFG_PAGESIZE*3/4; ++ ++ if (one_bit_correction((p + CONFIG_ECC_OFFSET + qsz * 3), e4, &bytes, &bits) == 0) ++ { ++ pBuf[bytes] = pBuf[bytes] ^ (1 << bits); ++ printk("4. correct byte %d, bit %d!\n", bytes, bits); ++ } ++ else ++ { ++ printk("failed to correct!\n"); ++ return -1; ++ } ++ } ++ } ++ ++ } ++#endif ++ return 0; ++ ++bad_block: ++ return -1; ++} ++ ++#else ++ ++void ranfc_dump(void) ++{ ++ int i; ++ for (i=0; i<11; i++) { ++ if (i==6) ++ continue; ++ printk("%x: %x \n", NFC_BASE + i*4, ra_inl(NFC_BASE + i*4)); ++ } ++} ++ ++/** ++ * @return 0, ecc OK or corrected. ++ * @return NAND_STATUS_FAIL, ecc fail. ++ */ ++ ++int nfc_ecc_verify(struct ra_nand_chip *ra, char *buf, int page, int mode) ++{ ++ int ret, i; ++ char *p, *e; ++ int ecc; ++ ++ if (ranfc_verify == 0) ++ return 0; ++ ++ ra_dbg("%s, page:%x mode:%d\n", __func__, page, mode); ++ ++ if (mode == FL_WRITING) { // read back and memcmp ++ ret = nfc_read_page(ra, ra->readback_buffers, page, FLAG_NONE); ++ if (ret != 0) //double comfirm ++ ret = nfc_read_page(ra, ra->readback_buffers, page, FLAG_NONE); ++ ++ if (ret != 0) { ++ printk("%s: mode:%x read back fail \n", __func__, mode); ++ return -1; ++ } ++ return memcmp(buf, ra->readback_buffers, 1<<ra->page_shift); ++ } ++ ++ if (mode == FL_READING) { ++#if 0 ++ if (ra->sandbox_page == 0) ++ return 0; ++ ++ ret = nfc_write_page(ra, buf, ra->sandbox_page, FLAG_USE_GDMA | FLAG_ECC_EN); ++ if (ret != 0) { ++ printk("%s, fail write sandbox_page \n", __func__); ++ return -1; ++ } ++#else ++ /** @note: ++ * The following command is actually not 'write' command to drive NFC to write flash. ++ * However, it can make NFC to calculate ECC, that will be used to compare with original ones. ++ * --YT ++ */ ++ unsigned int conf = 0x001223| (CFG_ADDR_CYCLE<<16) | (0x200 << 20) | (1<<3) | (1<<2); ++ _nfc_write_raw_data(0xff, 0xff, ra->sandbox_page<<ra->page_shift, conf, buf, 0x200, FLAG_USE_GDMA); ++#endif ++ ++ ecc = ra_inl(NFC_ECC); ++ if (ecc == 0) //clean page. ++ return 0; ++ e = (char*)&ecc; ++ p = buf + (1<<ra->page_shift); ++ for (i=0; i<CONFIG_ECC_BYTES; i++) { ++ int eccpos = CONFIG_ECC_OFFSET + i; ++ if (*(p + eccpos) != *(e + i)) { ++ printk("%s mode:%s, invalid ecc, page: %x read:%x %x %x, write:%x \n", ++ __func__, (mode == FL_READING)?"read":"write", page, ++ *(p+ CONFIG_ECC_OFFSET), *(p+ CONFIG_ECC_OFFSET+1), *(p+ CONFIG_ECC_OFFSET +2), ecc); ++ ++ for (i=0; i<528; i++) ++ printk("%-2x \n", *(buf + i)); ++ return -1; ++ } ++ } ++ return 0; ++ } ++ ++ return -1; ++ ++} ++ ++#endif ++ ++ ++/** ++ * @return -EIO, writing size is less than a page ++ * @return 0, OK ++ */ ++int nfc_read_page(struct ra_nand_chip *ra, char *buf, int page, int flags) ++{ ++ unsigned int cmd1 = 0, cmd2 = 0, conf = 0; ++ unsigned int bus_addr = 0, bus_addr2 = 0; ++ unsigned int ecc_en; ++ int use_gdma; ++ int size, offs; ++ int status = 0; ++ ++ use_gdma = flags & FLAG_USE_GDMA; ++ ecc_en = flags & FLAG_ECC_EN; ++ ++ page = page & (CFG_CHIPSIZE - 1); // chip boundary ++ size = CFG_PAGESIZE + CFG_PAGE_OOBSIZE; //add oobsize ++ offs = 0; ++ ++ while (size > 0) { ++ int len; ++#if defined (WORKAROUND_RX_BUF_OV) ++ len = min(60, size); ++#else ++ len = size; ++#endif ++ bus_addr = (page << (CFG_COLUMN_ADDR_CYCLE*8)) | (offs & ((1<<CFG_COLUMN_ADDR_CYCLE*8)-1)); ++ if (is_nand_page_2048) { ++ bus_addr2 = page >> (CFG_COLUMN_ADDR_CYCLE*8); ++ cmd1 = 0x0; ++ cmd2 = 0x30; ++ conf = 0x000511| ((CFG_ADDR_CYCLE)<<16) | (len << 20); ++ } ++ else { ++ if (offs & ~(CFG_PAGESIZE-1)) ++ cmd1 = 0x50; ++ else if (offs & ~((1<<CFG_COLUMN_ADDR_CYCLE*8)-1)) ++ cmd1 = 0x01; ++ else ++ cmd1 = 0; ++ ++ conf = 0x000141| ((CFG_ADDR_CYCLE)<<16) | (len << 20); ++ } ++#if !defined (WORKAROUND_RX_BUF_OV) ++ if (ecc_en) ++ conf |= (1<<3); ++#endif ++ if (use_gdma) ++ conf |= (1<<2); ++ ++ status = _nfc_read_raw_data(cmd1, cmd2, bus_addr, bus_addr2, conf, buf+offs, len, flags); ++ if (status & NAND_STATUS_FAIL) { ++ printk("%s: fail \n", __func__); ++ return -EIO; ++ } ++ ++ offs += len; ++ size -= len; ++ } ++ ++ // verify and correct ecc ++ if ((flags & (FLAG_VERIFY | FLAG_ECC_EN)) == (FLAG_VERIFY | FLAG_ECC_EN)) { ++ status = nfc_ecc_verify(ra, buf, page, FL_READING); ++ if (status != 0) { ++ printk("%s: fail, buf:%x, page:%x, flag:%x\n", ++ __func__, (unsigned int)buf, page, flags); ++ return -EBADMSG; ++ } ++ } ++ else { ++ // fix,e not yet support ++ ra->buffers_page = -1; //cached ++ } ++ ++ return 0; ++} ++ ++ ++/** ++ * @return -EIO, fail to write ++ * @return 0, OK ++ */ ++int nfc_write_page(struct ra_nand_chip *ra, char *buf, int page, int flags) ++{ ++ unsigned int cmd1 = 0, cmd3, conf = 0; ++ unsigned int bus_addr = 0, bus_addr2 = 0; ++ unsigned int ecc_en; ++ int use_gdma; ++ int size; ++ char status; ++ uint8_t *oob = buf + (1<<ra->page_shift); ++ ++ use_gdma = flags & FLAG_USE_GDMA; ++ ecc_en = flags & FLAG_ECC_EN; ++ ++ oob[ra->badblockpos] = 0xff; //tag as good block. ++ ra->buffers_page = -1; //cached ++ ++ page = page & (CFG_CHIPSIZE-1); //chip boundary ++ size = CFG_PAGESIZE + CFG_PAGE_OOBSIZE; //add oobsize ++ bus_addr = (page << (CFG_COLUMN_ADDR_CYCLE*8)); //write_page always write from offset 0. ++ ++ if (is_nand_page_2048) { ++ bus_addr2 = page >> (CFG_COLUMN_ADDR_CYCLE*8); ++ cmd1 = 0x80; ++ cmd3 = 0x10; ++ conf = 0x001123| ((CFG_ADDR_CYCLE)<<16) | (size << 20); ++ } ++ else { ++ cmd1 = 0x8000; ++ cmd3 = 0x10; ++ conf = 0x001223| ((CFG_ADDR_CYCLE)<<16) | (size << 20); ++} ++ if (ecc_en) ++ conf |= (1<<3); //enable ecc ++ if (use_gdma) ++ conf |= (1<<2); ++ ++ // set NFC ++ ra_dbg("nfc_write_page: cmd1: %x, cmd3: %x bus_addr: %x, conf: %x, len:%x\n", ++ cmd1, cmd3, bus_addr, conf, size); ++ ++ status = _nfc_write_raw_data(cmd1, cmd3, bus_addr, bus_addr2, conf, buf, size, flags); ++ if (status & NAND_STATUS_FAIL) { ++ printk("%s: fail \n", __func__); ++ return -EIO; ++ } ++ ++ ++ if (flags & FLAG_VERIFY) { // verify and correct ecc ++ status = nfc_ecc_verify(ra, buf, page, FL_WRITING); ++ ++#ifdef RANDOM_GEN_BAD_BLOCK ++ if (((random32() & 0x1ff) == 0x0) && (page >= 0x100)) // randomly create bad block ++ { ++ printk("hmm... create a bad block at page %x\n", (bus_addr >> 16)); ++ status = -1; ++ } ++#endif ++ ++ if (status != 0) { ++ printk("%s: ecc_verify fail: ret:%x \n", __func__, status); ++ oob[ra->badblockpos] = 0x33; ++ page -= page % (CFG_BLOCKSIZE/CFG_PAGESIZE); ++ printk("create a bad block at page %x\n", page); ++ if (!is_nand_page_2048) ++ status = nfc_write_oob(ra, page, ra->badblockpos, oob+ra->badblockpos, 1, flags); ++ else ++ { ++ status = _nfc_write_raw_data(cmd1, cmd3, bus_addr, bus_addr2, conf, buf, size, flags); ++ nfc_write_oob(ra, page, 0, oob, 16, FLAG_NONE); ++ } ++ return -EBADMSG; ++ } ++ } ++ ++ ++ ra->buffers_page = page; //cached ++ return 0; ++} ++ ++ ++ ++/************************************************************* ++ * nand internal process ++ *************************************************************/ ++ ++/** ++ * nand_release_device - [GENERIC] release chip ++ * @mtd: MTD device structure ++ * ++ * Deselect, release chip lock and wake up anyone waiting on the device ++ */ ++static void nand_release_device(struct ra_nand_chip *ra) ++{ ++ /* De-select the NAND device */ ++ nfc_select_chip(ra, -1); ++ ++ /* Release the controller and the chip */ ++ ra->state = FL_READY; ++ ++ mutex_unlock(ra->controller); ++} ++ ++/** ++ * nand_get_device - [GENERIC] Get chip for selected access ++ * @chip: the nand chip descriptor ++ * @mtd: MTD device structure ++ * @new_state: the state which is requested ++ * ++ * Get the device and lock it for exclusive access ++ */ ++static int ++nand_get_device(struct ra_nand_chip *ra, int new_state) ++{ ++ int ret = 0; ++ ++ ret = mutex_lock_interruptible(ra->controller); ++ if (!ret) ++ ra->state = new_state; ++ ++ return ret; ++ ++} ++ ++ ++ ++/************************************************************* ++ * nand internal process ++ *************************************************************/ ++ ++int nand_bbt_get(struct ra_nand_chip *ra, int block) ++{ ++ int byte, bits; ++ bits = block * BBTTAG_BITS; ++ ++ byte = bits / 8; ++ bits = bits % 8; ++ ++ return (ra->bbt[byte] >> bits) & BBTTAG_BITS_MASK; ++} ++ ++int nand_bbt_set(struct ra_nand_chip *ra, int block, int tag) ++{ ++ int byte, bits; ++ bits = block * BBTTAG_BITS; ++ ++ byte = bits / 8; ++ bits = bits % 8; ++ ++ // If previous tag is bad, dont overwrite it ++ if (((ra->bbt[byte] >> bits) & BBTTAG_BITS_MASK) == BBT_TAG_BAD) ++ { ++ return BBT_TAG_BAD; ++ } ++ ++ ra->bbt[byte] = (ra->bbt[byte] & ~(BBTTAG_BITS_MASK << bits)) | ((tag & BBTTAG_BITS_MASK) << bits); ++ ++ return tag; ++} ++ ++/** ++ * nand_block_checkbad - [GENERIC] Check if a block is marked bad ++ * @mtd: MTD device structure ++ * @ofs: offset from device start ++ * ++ * Check, if the block is bad. Either by reading the bad block table or ++ * calling of the scan function. ++ */ ++int nand_block_checkbad(struct ra_nand_chip *ra, loff_t offs) ++{ ++ int page, block; ++ int ret = 4; ++ unsigned int tag; ++ char *str[]= {"UNK", "RES", "BAD", "GOOD"}; ++ ++ if (ranfc_bbt == 0) ++ return 0; ++ ++ { ++ // align with chip ++ ++ offs = offs & ((1<<ra->chip_shift) -1); ++ ++ page = offs >> ra->page_shift; ++ block = offs >> ra->erase_shift; ++ } ++ ++ tag = nand_bbt_get(ra, block); ++ ++ if (tag == BBT_TAG_UNKNOWN) { ++ ret = nfc_read_oob(ra, page, ra->badblockpos, (char*)&tag, 1, FLAG_NONE); ++ if (ret == 0) ++ tag = ((le32_to_cpu(tag) & 0x0ff) == 0x0ff) ? BBT_TAG_GOOD : BBT_TAG_BAD; ++ else ++ tag = BBT_TAG_BAD; ++ ++ nand_bbt_set(ra, block, tag); ++ } ++ ++ if (tag != BBT_TAG_GOOD) { ++ printk("%s: offs:%x tag: %s \n", __func__, (unsigned int)offs, str[tag]); ++ return 1; ++ } ++ else ++ return 0; ++ ++} ++ ++ ++ ++/** ++ * nand_block_markbad - ++ */ ++int nand_block_markbad(struct ra_nand_chip *ra, loff_t offs) ++{ ++ int page, block; ++ int ret = 4; ++ unsigned int tag; ++ char *ecc; ++ ++ // align with chip ++ ra_dbg("%s offs: %x \n", __func__, (int)offs); ++ ++ offs = offs & ((1<<ra->chip_shift) -1); ++ ++ page = offs >> ra->page_shift; ++ block = offs >> ra->erase_shift; ++ ++ tag = nand_bbt_get(ra, block); ++ ++ if (tag == BBT_TAG_BAD) { ++ printk("%s: mark repeatedly \n", __func__); ++ return 0; ++ } ++ ++ // new tag as bad ++ tag =BBT_TAG_BAD; ++ ret = nfc_read_page(ra, ra->buffers, page, FLAG_NONE); ++ if (ret != 0) { ++ printk("%s: fail to read bad block tag \n", __func__); ++ goto tag_bbt; ++ } ++ ++ ecc = &ra->buffers[(1<<ra->page_shift)+ra->badblockpos]; ++ if (*ecc == (char)0x0ff) { ++ //tag into flash ++ *ecc = (char)tag; ++ ret = nfc_write_page(ra, ra->buffers, page, FLAG_USE_GDMA); ++ if (ret) ++ printk("%s: fail to write bad block tag \n", __func__); ++ ++ } ++ ++tag_bbt: ++ //update bbt ++ nand_bbt_set(ra, block, tag); ++ ++ return 0; ++} ++ ++ ++#if defined (WORKAROUND_RX_BUF_OV) ++/** ++ * to find a bad block for ecc verify of read_page ++ */ ++unsigned int nand_bbt_find_sandbox(struct ra_nand_chip *ra) ++{ ++ loff_t offs = 0; ++ int chipsize = 1 << ra->chip_shift; ++ int blocksize = 1 << ra->erase_shift; ++ ++ ++ while (offs < chipsize) { ++ if (nand_block_checkbad(ra, offs)) //scan and verify the unknown tag ++ break; ++ offs += blocksize; ++ } ++ ++ if (offs >= chipsize) { ++ offs = chipsize - blocksize; ++ } ++ ++ nand_bbt_set(ra, (unsigned int)offs>>ra->erase_shift, BBT_TAG_RES); // tag bbt only, instead of update badblockpos of flash. ++ return (offs >> ra->page_shift); ++} ++#endif ++ ++ ++ ++/** ++ * nand_erase_nand - [Internal] erase block(s) ++ * @mtd: MTD device structure ++ * @instr: erase instruction ++ * @allowbbt: allow erasing the bbt area ++ * ++ * Erase one ore more blocks ++ */ ++int _nand_erase_nand(struct ra_nand_chip *ra, struct erase_info *instr) ++{ ++ int page, len, status, ret; ++ unsigned int addr, blocksize = 1<<ra->erase_shift; ++ ++ ra_dbg("%s: start:%x, len:%x \n", __func__, ++ (unsigned int)instr->addr, (unsigned int)instr->len); ++ ++//#define BLOCK_ALIGNED(a) ((a) & (blocksize - 1)) // already defined ++ ++ if (BLOCK_ALIGNED(instr->addr) || BLOCK_ALIGNED(instr->len)) { ++ ra_dbg("%s: erase block not aligned, addr:%x len:%x\n", __func__, instr->addr, instr->len); ++ return -EINVAL; ++ } ++ ++ instr->fail_addr = 0xffffffff; ++ ++ len = instr->len; ++ addr = instr->addr; ++ instr->state = MTD_ERASING; ++ ++ while (len) { ++ ++ page = (int)(addr >> ra->page_shift); ++ ++ /* select device and check wp */ ++ if (nfc_enable_chip(ra, addr, 0)) { ++ printk("%s: nand is write protected \n", __func__); ++ instr->state = MTD_ERASE_FAILED; ++ goto erase_exit; ++ } ++ ++ /* if we have a bad block, we do not erase bad blocks */ ++ if (nand_block_checkbad(ra, addr)) { ++ printk(KERN_WARNING "nand_erase: attempt to erase a " ++ "bad block at 0x%08x\n", addr); ++ instr->state = MTD_ERASE_FAILED; ++ goto erase_exit; ++ } ++ ++ /* ++ * Invalidate the page cache, if we erase the block which ++ * contains the current cached page ++ */ ++ if (BLOCK_ALIGNED(addr) == BLOCK_ALIGNED(ra->buffers_page << ra->page_shift)) ++ ra->buffers_page = -1; ++ ++ status = nfc_erase_block(ra, page); ++ /* See if block erase succeeded */ ++ if (status) { ++ printk("%s: failed erase, page 0x%08x\n", __func__, page); ++ instr->state = MTD_ERASE_FAILED; ++ instr->fail_addr = (page << ra->page_shift); ++ goto erase_exit; ++ } ++ ++ ++ /* Increment page address and decrement length */ ++ len -= blocksize; ++ addr += blocksize; ++ ++ } ++ instr->state = MTD_ERASE_DONE; ++ ++erase_exit: ++ ++ ret = ((instr->state == MTD_ERASE_DONE) ? 0 : -EIO); ++ /* Do call back function */ ++ if (!ret) ++ mtd_erase_callback(instr); ++ ++ if (ret) { ++ nand_bbt_set(ra, addr >> ra->erase_shift, BBT_TAG_BAD); ++ } ++ ++ /* Return more or less happy */ ++ return ret; ++} ++ ++static int ++nand_write_oob_buf(struct ra_nand_chip *ra, uint8_t *buf, uint8_t *oob, size_t size, ++ int mode, int ooboffs) ++{ ++ size_t oobsize = 1<<ra->oob_shift; ++ struct nand_oobfree *free; ++ uint32_t woffs = ooboffs; ++ int retsize = 0; ++ ++ ra_dbg("%s: size:%x, mode:%x, offs:%x \n", __func__, size, mode, ooboffs); ++ ++ switch(mode) { ++ case MTD_OPS_PLACE_OOB: ++ case MTD_OPS_RAW: ++ if (ooboffs > oobsize) ++ return -1; ++ ++ size = min(size, oobsize - ooboffs); ++ memcpy(buf + ooboffs, oob, size); ++ retsize = size; ++ break; ++ ++ case MTD_OPS_AUTO_OOB: ++ if (ooboffs > ra->oob->oobavail) ++ return -1; ++ ++ while (size) { ++ for(free = ra->oob->oobfree; free->length && size; free++) { ++ int wlen = free->length - woffs; ++ int bytes = 0; ++ ++ /* Write request not from offset 0 ? */ ++ if (wlen <= 0) { ++ woffs = -wlen; ++ continue; ++ } ++ ++ bytes = min_t(size_t, size, wlen); ++ memcpy (buf + free->offset + woffs, oob, bytes); ++ woffs = 0; ++ oob += bytes; ++ size -= bytes; ++ retsize += bytes; ++ } ++ buf += oobsize; ++ } ++ break; ++ ++ default: ++ BUG(); ++ } ++ ++ return retsize; ++} ++ ++static int nand_read_oob_buf(struct ra_nand_chip *ra, uint8_t *oob, size_t size, ++ int mode, int ooboffs) ++{ ++ size_t oobsize = 1<<ra->oob_shift; ++ uint8_t *buf = ra->buffers + (1<<ra->page_shift); ++ int retsize=0; ++ ++ ra_dbg("%s: size:%x, mode:%x, offs:%x \n", __func__, size, mode, ooboffs); ++ ++ switch(mode) { ++ case MTD_OPS_PLACE_OOB: ++ case MTD_OPS_RAW: ++ if (ooboffs > oobsize) ++ return -1; ++ ++ size = min(size, oobsize - ooboffs); ++ memcpy(oob, buf + ooboffs, size); ++ return size; ++ ++ case MTD_OPS_AUTO_OOB: { ++ struct nand_oobfree *free; ++ uint32_t woffs = ooboffs; ++ ++ if (ooboffs > ra->oob->oobavail) ++ return -1; ++ ++ size = min(size, ra->oob->oobavail - ooboffs); ++ for(free = ra->oob->oobfree; free->length && size; free++) { ++ int wlen = free->length - woffs; ++ int bytes = 0; ++ ++ /* Write request not from offset 0 ? */ ++ if (wlen <= 0) { ++ woffs = -wlen; ++ continue; ++ } ++ ++ bytes = min_t(size_t, size, wlen); ++ memcpy (oob, buf + free->offset + woffs, bytes); ++ woffs = 0; ++ oob += bytes; ++ size -= bytes; ++ retsize += bytes; ++ } ++ return retsize; ++ } ++ default: ++ BUG(); ++ } ++ ++ return -1; ++} ++ ++/** ++ * nand_do_write_ops - [Internal] NAND write with ECC ++ * @mtd: MTD device structure ++ * @to: offset to write to ++ * @ops: oob operations description structure ++ * ++ * NAND write with ECC ++ */ ++static int nand_do_write_ops(struct ra_nand_chip *ra, loff_t to, ++ struct mtd_oob_ops *ops) ++{ ++ int page; ++ uint32_t datalen = ops->len; ++ uint32_t ooblen = ops->ooblen; ++ uint8_t *oob = ops->oobbuf; ++ uint8_t *data = ops->datbuf; ++ int pagesize = (1<<ra->page_shift); ++ int pagemask = (pagesize -1); ++ int oobsize = 1<<ra->oob_shift; ++ loff_t addr = to; ++ //int i = 0; //for ra_dbg only ++ ++ ra_dbg("%s: to:%x, ops data:%p, oob:%p datalen:%x ooblen:%x, ooboffs:%x oobmode:%x \n", ++ __func__, (unsigned int)to, data, oob, datalen, ooblen, ops->ooboffs, ops->mode); ++ ++ ops->retlen = 0; ++ ops->oobretlen = 0; ++ ++ ++ /* Invalidate the page cache, when we write to the cached page */ ++ ra->buffers_page = -1; ++ ++ ++ if (data ==0) ++ datalen = 0; ++ ++ // oob sequential (burst) write ++ if (datalen == 0 && ooblen) { ++ int len = ((ooblen + ops->ooboffs) + (ra->oob->oobavail - 1)) / ra->oob->oobavail * oobsize; ++ ++ /* select chip, and check if it is write protected */ ++ if (nfc_enable_chip(ra, addr, 0)) ++ return -EIO; ++ ++ //FIXME, need sanity check of block boundary ++ page = (int)((to & ((1<<ra->chip_shift)-1)) >> ra->page_shift); //chip boundary ++ memset(ra->buffers, 0x0ff, pagesize); ++ //fixme, should we reserve the original content? ++ if (ops->mode == MTD_OPS_AUTO_OOB) { ++ nfc_read_oob(ra, page, 0, ra->buffers, len, FLAG_NONE); ++ } ++ //prepare buffers ++ if (ooblen != 8) ++ { ++ nand_write_oob_buf(ra, ra->buffers, oob, ooblen, ops->mode, ops->ooboffs); ++ // write out buffer to chip ++ nfc_write_oob(ra, page, 0, ra->buffers, len, FLAG_USE_GDMA); ++ } ++ ++ ops->oobretlen = ooblen; ++ ooblen = 0; ++ } ++ ++ // data sequential (burst) write ++ if (datalen && ooblen == 0) { ++ // ranfc can not support write_data_burst, since hw-ecc and fifo constraints.. ++ } ++ ++ // page write ++ while(datalen || ooblen) { ++ int len; ++ int ret; ++ int offs; ++ int ecc_en = 0; ++ ++ ra_dbg("%s (%d): addr:%x, ops data:%p, oob:%p datalen:%x ooblen:%x, ooboffs:%x \n", ++ __func__, i++, (unsigned int)addr, data, oob, datalen, ooblen, ops->ooboffs); ++ ++ page = (int)((addr & ((1<<ra->chip_shift)-1)) >> ra->page_shift); //chip boundary ++ ++ /* select chip, and check if it is write protected */ ++ if (nfc_enable_chip(ra, addr, 0)) ++ return -EIO; ++ ++ // oob write ++ if (ops->mode == MTD_OPS_AUTO_OOB) { ++ //fixme, this path is not yet varified ++ nfc_read_oob(ra, page, 0, ra->buffers + pagesize, oobsize, FLAG_NONE); ++ } ++ if (oob && ooblen > 0) { ++ len = nand_write_oob_buf(ra, ra->buffers + pagesize, oob, ooblen, ops->mode, ops->ooboffs); ++ if (len < 0) ++ return -EINVAL; ++ ++ oob += len; ++ ops->oobretlen += len; ++ ooblen -= len; ++ } ++ ++ // data write ++ offs = addr & pagemask; ++ len = min_t(size_t, datalen, pagesize - offs); ++ if (data && len > 0) { ++ memcpy(ra->buffers + offs, data, len); // we can not sure ops->buf wether is DMA-able. ++ ++ data += len; ++ datalen -= len; ++ ops->retlen += len; ++ ++ ecc_en = FLAG_ECC_EN; ++ } ++ ret = nfc_write_page(ra, ra->buffers, page, FLAG_USE_GDMA | FLAG_VERIFY | ++ ((ops->mode == MTD_OPS_RAW || ops->mode == MTD_OPS_PLACE_OOB) ? 0 : ecc_en )); ++ if (ret) { ++ nand_bbt_set(ra, addr >> ra->erase_shift, BBT_TAG_BAD); ++ return ret; ++ } ++ ++ nand_bbt_set(ra, addr >> ra->erase_shift, BBT_TAG_GOOD); ++ ++ addr = (page+1) << ra->page_shift; ++ ++ } ++ return 0; ++} ++ ++/** ++ * nand_do_read_ops - [Internal] Read data with ECC ++ * ++ * @mtd: MTD device structure ++ * @from: offset to read from ++ * @ops: oob ops structure ++ * ++ * Internal function. Called with chip held. ++ */ ++static int nand_do_read_ops(struct ra_nand_chip *ra, loff_t from, ++ struct mtd_oob_ops *ops) ++{ ++ int page; ++ uint32_t datalen = ops->len; ++ uint32_t ooblen = ops->ooblen; ++ uint8_t *oob = ops->oobbuf; ++ uint8_t *data = ops->datbuf; ++ int pagesize = (1<<ra->page_shift); ++ int pagemask = (pagesize -1); ++ loff_t addr = from; ++ //int i = 0; //for ra_dbg only ++ ++ ra_dbg("%s: addr:%x, ops data:%p, oob:%p datalen:%x ooblen:%x, ooboffs:%x \n", ++ __func__, (unsigned int)addr, data, oob, datalen, ooblen, ops->ooboffs); ++ ++ ops->retlen = 0; ++ ops->oobretlen = 0; ++ if (data == 0) ++ datalen = 0; ++ ++ ++ while(datalen || ooblen) { ++ int len; ++ int ret; ++ int offs; ++ ++ ra_dbg("%s (%d): addr:%x, ops data:%p, oob:%p datalen:%x ooblen:%x, ooboffs:%x \n", ++ __func__, i++, (unsigned int)addr, data, oob, datalen, ooblen, ops->ooboffs); ++ /* select chip */ ++ if (nfc_enable_chip(ra, addr, 1) < 0) ++ return -EIO; ++ ++ page = (int)((addr & ((1<<ra->chip_shift)-1)) >> ra->page_shift); ++ ++ ret = nfc_read_page(ra, ra->buffers, page, FLAG_VERIFY | ++ ((ops->mode == MTD_OPS_RAW || ops->mode == MTD_OPS_PLACE_OOB) ? 0: FLAG_ECC_EN )); ++ //FIXME, something strange here, some page needs 2 more tries to guarantee read success. ++ if (ret) { ++ printk("read again:\n"); ++ ret = nfc_read_page(ra, ra->buffers, page, FLAG_VERIFY | ++ ((ops->mode == MTD_OPS_RAW || ops->mode == MTD_OPS_PLACE_OOB) ? 0: FLAG_ECC_EN )); ++ ++ if (ret) { ++ printk("read again fail \n"); ++ nand_bbt_set(ra, addr >> ra->erase_shift, BBT_TAG_BAD); ++ if ((ret != -EUCLEAN) && (ret != -EBADMSG)) { ++ return ret; ++ } ++ else { ++ /* ecc verification fail, but data need to be returned. */ ++ } ++ } ++ else { ++ printk(" read agian susccess \n"); ++ } ++ } ++ ++ // oob read ++ if (oob && ooblen > 0) { ++ len = nand_read_oob_buf(ra, oob, ooblen, ops->mode, ops->ooboffs); ++ if (len < 0) { ++ printk("nand_read_oob_buf: fail return %x \n", len); ++ return -EINVAL; ++ } ++ ++ oob += len; ++ ops->oobretlen += len; ++ ooblen -= len; ++ } ++ ++ // data read ++ offs = addr & pagemask; ++ len = min_t(size_t, datalen, pagesize - offs); ++ if (data && len > 0) { ++ memcpy(data, ra->buffers + offs, len); // we can not sure ops->buf wether is DMA-able. ++ ++ data += len; ++ datalen -= len; ++ ops->retlen += len; ++ if (ret) ++ return ret; ++ } ++ ++ ++ nand_bbt_set(ra, addr >> ra->erase_shift, BBT_TAG_GOOD); ++ // address go further to next page, instead of increasing of length of write. This avoids some special cases wrong. ++ addr = (page+1) << ra->page_shift; ++ } ++ return 0; ++} ++ ++static int ++ramtd_nand_erase(struct mtd_info *mtd, struct erase_info *instr) ++{ ++ struct ra_nand_chip *ra = (struct ra_nand_chip *)mtd->priv; ++ int ret; ++ ++ ra_dbg("%s: start:%x, len:%x \n", __func__, ++ (unsigned int)instr->addr, (unsigned int)instr->len); ++ ++ nand_get_device(ra, FL_ERASING); ++ ret = _nand_erase_nand((struct ra_nand_chip *)mtd->priv, instr); ++ nand_release_device(ra); ++ ++ return ret; ++} ++ ++static int ++ramtd_nand_write(struct mtd_info *mtd, loff_t to, size_t len, ++ size_t *retlen, const uint8_t *buf) ++{ ++ struct ra_nand_chip *ra = mtd->priv; ++ struct mtd_oob_ops ops; ++ int ret; ++ ++ ra_dbg("%s: to 0x%x len=0x%x\n", __func__, to, len); ++ ++ if ((to + len) > mtd->size) ++ return -EINVAL; ++ ++ if (!len) ++ return 0; ++ ++ nand_get_device(ra, FL_WRITING); ++ ++ memset(&ops, 0, sizeof(ops)); ++ ops.len = len; ++ ops.datbuf = (uint8_t *)buf; ++ ops.oobbuf = NULL; ++ ops.mode = MTD_OPS_AUTO_OOB; ++ ++ ret = nand_do_write_ops(ra, to, &ops); ++ ++ *retlen = ops.retlen; ++ ++ nand_release_device(ra); ++ ++ return ret; ++} ++ ++static int ++ramtd_nand_read(struct mtd_info *mtd, loff_t from, size_t len, ++ size_t *retlen, uint8_t *buf) ++{ ++ ++ struct ra_nand_chip *ra = mtd->priv; ++ int ret; ++ struct mtd_oob_ops ops; ++ ++ ra_dbg("%s: mtd:%p from:%x, len:%x, buf:%p \n", __func__, mtd, (unsigned int)from, len, buf); ++ ++ /* Do not allow reads past end of device */ ++ if ((from + len) > mtd->size) ++ return -EINVAL; ++ if (!len) ++ return 0; ++ ++ nand_get_device(ra, FL_READING); ++ ++ memset(&ops, 0, sizeof(ops)); ++ ops.len = len; ++ ops.datbuf = buf; ++ ops.oobbuf = NULL; ++ ops.mode = MTD_OPS_AUTO_OOB; ++ ++ ret = nand_do_read_ops(ra, from, &ops); ++ ++ *retlen = ops.retlen; ++ ++ nand_release_device(ra); ++ ++ return ret; ++ ++} ++ ++static int ++ramtd_nand_readoob(struct mtd_info *mtd, loff_t from, ++ struct mtd_oob_ops *ops) ++{ ++ struct ra_nand_chip *ra = mtd->priv; ++ int ret; ++ ++ ra_dbg("%s: \n", __func__); ++ ++ nand_get_device(ra, FL_READING); ++ ++ ret = nand_do_read_ops(ra, from, ops); ++ ++ nand_release_device(ra); ++ ++ return ret; ++} ++ ++static int ++ramtd_nand_writeoob(struct mtd_info *mtd, loff_t to, ++ struct mtd_oob_ops *ops) ++{ ++ struct ra_nand_chip *ra = mtd->priv; ++ int ret; ++ ++ nand_get_device(ra, FL_READING); ++ ret = nand_do_write_ops(ra, to, ops); ++ nand_release_device(ra); ++ ++ return ret; ++} ++ ++static int ++ramtd_nand_block_isbad(struct mtd_info *mtd, loff_t offs) ++{ ++ if (offs > mtd->size) ++ return -EINVAL; ++ ++ return nand_block_checkbad((struct ra_nand_chip *)mtd->priv, offs); ++} ++ ++static int ++ramtd_nand_block_markbad(struct mtd_info *mtd, loff_t ofs) ++{ ++ struct ra_nand_chip *ra = mtd->priv; ++ int ret; ++ ++ ra_dbg("%s: \n", __func__); ++ nand_get_device(ra, FL_WRITING); ++ ret = nand_block_markbad(ra, ofs); ++ nand_release_device(ra); ++ ++ return ret; ++} ++ ++// 1-bit error detection ++static int one_bit_correction(char *ecc1, char *ecc2, int *bytes, int *bits) ++{ ++ // check if ecc and expected are all valid ++ char *p, nibble, crumb; ++ int i, xor, iecc1 = 0, iecc2 = 0; ++ ++ printk("correction : %x %x %x\n", ecc1[0], ecc1[1], ecc1[2]); ++ printk("correction : %x %x %x\n", ecc2[0], ecc2[1], ecc2[2]); ++ ++ p = (char *)ecc1; ++ for (i = 0; i < CONFIG_ECC_BYTES; i++) ++ { ++ nibble = *(p+i) & 0xf; ++ if ((nibble != 0x0) && (nibble != 0xf) && (nibble != 0x3) && (nibble != 0xc) && ++ (nibble != 0x5) && (nibble != 0xa) && (nibble != 0x6) && (nibble != 0x9)) ++ return -1; ++ nibble = ((*(p+i)) >> 4) & 0xf; ++ if ((nibble != 0x0) && (nibble != 0xf) && (nibble != 0x3) && (nibble != 0xc) && ++ (nibble != 0x5) && (nibble != 0xa) && (nibble != 0x6) && (nibble != 0x9)) ++ return -1; ++ } ++ ++ p = (char *)ecc2; ++ for (i = 0; i < CONFIG_ECC_BYTES; i++) ++ { ++ nibble = *(p+i) & 0xf; ++ if ((nibble != 0x0) && (nibble != 0xf) && (nibble != 0x3) && (nibble != 0xc) && ++ (nibble != 0x5) && (nibble != 0xa) && (nibble != 0x6) && (nibble != 0x9)) ++ return -1; ++ nibble = ((*(p+i)) >> 4) & 0xf; ++ if ((nibble != 0x0) && (nibble != 0xf) && (nibble != 0x3) && (nibble != 0xc) && ++ (nibble != 0x5) && (nibble != 0xa) && (nibble != 0x6) && (nibble != 0x9)) ++ return -1; ++ } ++ ++ memcpy(&iecc1, ecc1, 3); ++ memcpy(&iecc2, ecc2, 3); ++ ++ xor = iecc1 ^ iecc2; ++ printk("xor = %x (%x %x)\n", xor, iecc1, iecc2); ++ ++ *bytes = 0; ++ for (i = 0; i < 9; i++) ++ { ++ crumb = (xor >> (2*i)) & 0x3; ++ if ((crumb == 0x0) || (crumb == 0x3)) ++ return -1; ++ if (crumb == 0x2) ++ *bytes += (1 << i); ++ } ++ ++ *bits = 0; ++ for (i = 0; i < 3; i++) ++ { ++ crumb = (xor >> (18 + 2*i)) & 0x3; ++ if ((crumb == 0x0) || (crumb == 0x3)) ++ return -1; ++ if (crumb == 0x2) ++ *bits += (1 << i); ++ } ++ ++ return 0; ++} ++ ++ ++ ++/************************************************************ ++ * the init/exit section. ++ */ ++ ++static struct nand_ecclayout ra_oob_layout = { ++ .eccbytes = CONFIG_ECC_BYTES, ++ .eccpos = {5, 6, 7}, ++ .oobfree = { ++ {.offset = 0, .length = 4}, ++ {.offset = 8, .length = 8}, ++ {.offset = 0, .length = 0} ++ }, ++#define RA_CHIP_OOB_AVAIL (4+8) ++ .oobavail = RA_CHIP_OOB_AVAIL, ++ // 5th byte is bad-block flag. ++}; ++ ++static int ++mtk_nand_probe(struct platform_device *pdev) ++{ ++ struct mtd_part_parser_data ppdata; ++ struct ra_nand_chip *ra; ++ int alloc_size, bbt_size, buffers_size, reg, err; ++ unsigned char chip_mode = 12; ++ ++/* if(ra_check_flash_type()!=BOOT_FROM_NAND) { ++ return 0; ++ }*/ ++ ++ //FIXME: config 512 or 2048-byte page according to HWCONF ++#if defined (CONFIG_RALINK_RT6855A) ++ reg = ra_inl(RALINK_SYSCTL_BASE+0x8c); ++ chip_mode = ((reg>>28) & 0x3)|(((reg>>22) & 0x3)<<2); ++ if (chip_mode == 1) { ++ printk("! nand 2048\n"); ++ ra_or(NFC_CONF1, 1); ++ is_nand_page_2048 = 1; ++ nand_addrlen = 5; ++ } ++ else { ++ printk("! nand 512\n"); ++ ra_and(NFC_CONF1, ~1); ++ is_nand_page_2048 = 0; ++ nand_addrlen = 4; ++ } ++#elif (defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_RT6855)) ++ ra_outl(RALINK_SYSCTL_BASE+0x60, ra_inl(RALINK_SYSCTL_BASE+0x60) & ~(0x3<<18)); ++ reg = ra_inl(RALINK_SYSCTL_BASE+0x10); ++ chip_mode = (reg & 0x0F); ++ if((chip_mode==1)||(chip_mode==11)) { ++ ra_or(NFC_CONF1, 1); ++ is_nand_page_2048 = 1; ++ nand_addrlen = ((chip_mode!=11) ? 4 : 5); ++ printk("!!! nand page size = 2048, addr len=%d\n", nand_addrlen); ++ } ++ else { ++ ra_and(NFC_CONF1, ~1); ++ is_nand_page_2048 = 0; ++ nand_addrlen = ((chip_mode!=10) ? 3 : 4); ++ printk("!!! nand page size = 512, addr len=%d\n", nand_addrlen); ++ } ++#else ++ is_nand_page_2048 = 0; ++ nand_addrlen = 3; ++ printk("!!! nand page size = 512, addr len=%d\n", nand_addrlen); ++#endif ++ ++#if defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_RT6855) ++ //config ECC location ++ ra_and(NFC_CONF1, 0xfff000ff); ++ ra_or(NFC_CONF1, ((CONFIG_ECC_OFFSET + 2) << 16) + ++ ((CONFIG_ECC_OFFSET + 1) << 12) + ++ (CONFIG_ECC_OFFSET << 8)); ++#endif ++ ++#define ALIGNE_16(a) (((unsigned long)(a)+15) & ~15) ++ buffers_size = ALIGNE_16((1<<CONFIG_PAGE_SIZE_BIT) + (1<<CONFIG_OOBSIZE_PER_PAGE_BIT)); //ra->buffers ++ bbt_size = BBTTAG_BITS * (1<<(CONFIG_CHIP_SIZE_BIT - (CONFIG_PAGE_SIZE_BIT + CONFIG_NUMPAGE_PER_BLOCK_BIT))) / 8; //ra->bbt ++ bbt_size = ALIGNE_16(bbt_size); ++ ++ alloc_size = buffers_size + bbt_size; ++ alloc_size += buffers_size; //for ra->readback_buffers ++ alloc_size += sizeof(*ra); ++ alloc_size += sizeof(*ranfc_mtd); ++ ++ //make sure gpio-0 is input ++ ra_outl(RALINK_PIO_BASE+0x24, ra_inl(RALINK_PIO_BASE+0x24) & ~0x01); ++ ++ ra = (struct ra_nand_chip *)kzalloc(alloc_size, GFP_KERNEL | GFP_DMA); ++ if (!ra) { ++ printk("%s: mem alloc fail \n", __func__); ++ return -ENOMEM; ++ } ++ memset(ra, 0, alloc_size); ++ ++ //dynamic ++ ra->buffers = (char *)((char *)ra + sizeof(*ra)); ++ ra->readback_buffers = ra->buffers + buffers_size; ++ ra->bbt = ra->readback_buffers + buffers_size; ++ ranfc_mtd = (struct mtd_info *)(ra->bbt + bbt_size); ++ ++ //static ++ ra->numchips = CONFIG_NUMCHIPS; ++ ra->chip_shift = CONFIG_CHIP_SIZE_BIT; ++ ra->page_shift = CONFIG_PAGE_SIZE_BIT; ++ ra->oob_shift = CONFIG_OOBSIZE_PER_PAGE_BIT; ++ ra->erase_shift = (CONFIG_PAGE_SIZE_BIT + CONFIG_NUMPAGE_PER_BLOCK_BIT); ++ ra->badblockpos = CONFIG_BAD_BLOCK_POS; ++ ra_oob_layout.eccpos[0] = CONFIG_ECC_OFFSET; ++ ra_oob_layout.eccpos[1] = CONFIG_ECC_OFFSET + 1; ++ ra_oob_layout.eccpos[2] = CONFIG_ECC_OFFSET + 2; ++ ra->oob = &ra_oob_layout; ++ ra->buffers_page = -1; ++ ++#if defined (WORKAROUND_RX_BUF_OV) ++ if (ranfc_verify) { ++ ra->sandbox_page = nand_bbt_find_sandbox(ra); ++ } ++#endif ++ ra_outl(NFC_CTRL, ra_inl(NFC_CTRL) | 0x01); //set wp to high ++ nfc_all_reset(); ++ ++ ranfc_mtd->type = MTD_NANDFLASH; ++ ranfc_mtd->flags = MTD_CAP_NANDFLASH; ++ ranfc_mtd->size = CONFIG_NUMCHIPS * CFG_CHIPSIZE; ++ ranfc_mtd->erasesize = CFG_BLOCKSIZE; ++ ranfc_mtd->writesize = CFG_PAGESIZE; ++ ranfc_mtd->oobsize = CFG_PAGE_OOBSIZE; ++ ranfc_mtd->oobavail = RA_CHIP_OOB_AVAIL; ++ ranfc_mtd->name = "ra_nfc"; ++ //ranfc_mtd->index ++ ranfc_mtd->ecclayout = &ra_oob_layout; ++ //ranfc_mtd->numberaseregions ++ //ranfc_mtd->eraseregions ++ //ranfc_mtd->bansize ++ ranfc_mtd->_erase = ramtd_nand_erase; ++ //ranfc_mtd->point ++ //ranfc_mtd->unpoint ++ ranfc_mtd->_read = ramtd_nand_read; ++ ranfc_mtd->_write = ramtd_nand_write; ++ ranfc_mtd->_read_oob = ramtd_nand_readoob; ++ ranfc_mtd->_write_oob = ramtd_nand_writeoob; ++ //ranfc_mtd->get_fact_prot_info; ranfc_mtd->read_fact_prot_reg; ++ //ranfc_mtd->get_user_prot_info; ranfc_mtd->read_user_prot_reg; ++ //ranfc_mtd->write_user_prot_reg; ranfc_mtd->lock_user_prot_reg; ++ //ranfc_mtd->writev; ranfc_mtd->sync; ranfc_mtd->lock; ranfc_mtd->unlock; ranfc_mtd->suspend; ranfc_mtd->resume; ++ ranfc_mtd->_block_isbad = ramtd_nand_block_isbad; ++ ranfc_mtd->_block_markbad = ramtd_nand_block_markbad; ++ //ranfc_mtd->reboot_notifier ++ //ranfc_mtd->ecc_stats; ++ // subpage_sht; ++ ++ //ranfc_mtd->get_device; ranfc_mtd->put_device ++ ranfc_mtd->priv = ra; ++ ++ ranfc_mtd->owner = THIS_MODULE; ++ ra->controller = &ra->hwcontrol; ++ mutex_init(ra->controller); ++ ++ printk("%s: alloc %x, at %p , btt(%p, %x), ranfc_mtd:%p\n", ++ __func__ , alloc_size, ra, ra->bbt, bbt_size, ranfc_mtd); ++ ++ ppdata.of_node = pdev->dev.of_node; ++ err = mtd_device_parse_register(ranfc_mtd, mtk_probe_types, ++ &ppdata, NULL, 0); ++ ++ return err; ++} ++ ++static int ++mtk_nand_remove(struct platform_device *pdev) ++{ ++ struct ra_nand_chip *ra; ++ ++ if (ranfc_mtd) { ++ ra = (struct ra_nand_chip *)ranfc_mtd->priv; ++ ++ /* Deregister partitions */ ++ //del_mtd_partitions(ranfc_mtd); ++ kfree(ra); ++ } ++ return 0; ++} ++ ++static const struct of_device_id mtk_nand_match[] = { ++ { .compatible = "mtk,mt7620-nand" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mtk_nand_match); ++ ++static struct platform_driver mtk_nand_driver = { ++ .probe = mtk_nand_probe, ++ .remove = mtk_nand_remove, ++ .driver = { ++ .name = "mt7620_nand", ++ .owner = THIS_MODULE, ++ .of_match_table = mtk_nand_match, ++ }, ++}; ++ ++module_platform_driver(mtk_nand_driver); ++ ++ ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/mtd/maps/ralink_nand.h +@@ -0,0 +1,232 @@ ++#ifndef RT2880_NAND_H ++#define RT2880_NAND_H ++ ++#include <linux/mtd/mtd.h> ++ ++//#include "gdma.h" ++ ++#define RALINK_SYSCTL_BASE 0xB0000000 ++#define RALINK_PIO_BASE 0xB0000600 ++#define RALINK_NAND_CTRL_BASE 0xB0000810 ++#define CONFIG_RALINK_MT7620 ++ ++#define SKIP_BAD_BLOCK ++//#define RANDOM_GEN_BAD_BLOCK ++ ++#define ra_inl(addr) (*(volatile unsigned int *)(addr)) ++#define ra_outl(addr, value) (*(volatile unsigned int *)(addr) = (value)) ++#define ra_aor(addr, a_mask, o_value) ra_outl(addr, (ra_inl(addr) & (a_mask)) | (o_value)) ++#define ra_and(addr, a_mask) ra_aor(addr, a_mask, 0) ++#define ra_or(addr, o_value) ra_aor(addr, -1, o_value) ++ ++ ++#define CONFIG_NUMCHIPS 1 ++#define CONFIG_NOT_SUPPORT_WP //rt3052 has no WP signal for chip. ++//#define CONFIG_NOT_SUPPORT_RB ++ ++extern int is_nand_page_2048; ++extern const unsigned int nand_size_map[2][3]; ++ ++//chip ++// chip geometry: SAMSUNG small size 32MB. ++#define CONFIG_CHIP_SIZE_BIT (nand_size_map[is_nand_page_2048][nand_addrlen-3]) //! (1<<NAND_SIZE_BYTE) MB ++//#define CONFIG_CHIP_SIZE_BIT (is_nand_page_2048? 29 : 25) //! (1<<NAND_SIZE_BYTE) MB ++#define CONFIG_PAGE_SIZE_BIT (is_nand_page_2048? 11 : 9) //! (1<<PAGE_SIZE) MB ++//#define CONFIG_SUBPAGE_BIT 1 //! these bits will be compensate by command cycle ++#define CONFIG_NUMPAGE_PER_BLOCK_BIT (is_nand_page_2048? 6 : 5) //! order of number of pages a block. ++#define CONFIG_OOBSIZE_PER_PAGE_BIT (is_nand_page_2048? 6 : 4) //! byte number of oob a page. ++#define CONFIG_BAD_BLOCK_POS (is_nand_page_2048? 0 : 4) //! offset of byte to denote bad block. ++#define CONFIG_ECC_BYTES 3 //! ecc has 3 bytes ++#define CONFIG_ECC_OFFSET (is_nand_page_2048? 6 : 5) //! ecc starts from offset 5. ++ ++//this section should not be modified. ++//#define CFG_COLUMN_ADDR_MASK ((1 << (CONFIG_PAGE_SIZE_BIT - CONFIG_SUBPAGE_BIT)) - 1) ++//#define CFG_COLUMN_ADDR_CYCLE (((CONFIG_PAGE_SIZE_BIT - CONFIG_SUBPAGE_BIT) + 7)/8) ++//#define CFG_ROW_ADDR_CYCLE ((CONFIG_CHIP_SIZE_BIT - CONFIG_PAGE_SIZE_BIT + 7)/8) ++//#define CFG_ADDR_CYCLE (CFG_COLUMN_ADDR_CYCLE + CFG_ROW_ADDR_CYCLE) ++ ++#define CFG_COLUMN_ADDR_CYCLE (is_nand_page_2048? 2 : 1) ++#define CFG_ROW_ADDR_CYCLE (nand_addrlen - CFG_COLUMN_ADDR_CYCLE) ++#define CFG_ADDR_CYCLE (CFG_COLUMN_ADDR_CYCLE + CFG_ROW_ADDR_CYCLE) ++ ++#define CFG_CHIPSIZE (1 << ((CONFIG_CHIP_SIZE_BIT>=32)? 31 : CONFIG_CHIP_SIZE_BIT)) ++//#define CFG_CHIPSIZE (1 << CONFIG_CHIP_SIZE_BIT) ++#define CFG_PAGESIZE (1 << CONFIG_PAGE_SIZE_BIT) ++#define CFG_BLOCKSIZE (CFG_PAGESIZE << CONFIG_NUMPAGE_PER_BLOCK_BIT) ++#define CFG_NUMPAGE (1 << (CONFIG_CHIP_SIZE_BIT - CONFIG_PAGE_SIZE_BIT)) ++#define CFG_NUMBLOCK (CFG_NUMPAGE >> CONFIG_NUMPAGE_PER_BLOCK_BIT) ++#define CFG_BLOCK_OOBSIZE (1 << (CONFIG_OOBSIZE_PER_PAGE_BIT + CONFIG_NUMPAGE_PER_BLOCK_BIT)) ++#define CFG_PAGE_OOBSIZE (1 << CONFIG_OOBSIZE_PER_PAGE_BIT) ++ ++#define NAND_BLOCK_ALIGN(addr) ((addr) & (CFG_BLOCKSIZE-1)) ++#define NAND_PAGE_ALIGN(addr) ((addr) & (CFG_PAGESIZE-1)) ++ ++ ++#define NFC_BASE RALINK_NAND_CTRL_BASE ++#define NFC_CTRL (NFC_BASE + 0x0) ++#define NFC_CONF (NFC_BASE + 0x4) ++#define NFC_CMD1 (NFC_BASE + 0x8) ++#define NFC_CMD2 (NFC_BASE + 0xc) ++#define NFC_CMD3 (NFC_BASE + 0x10) ++#define NFC_ADDR (NFC_BASE + 0x14) ++#define NFC_DATA (NFC_BASE + 0x18) ++#if defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) ++#define NFC_ECC (NFC_BASE + 0x30) ++#else ++#define NFC_ECC (NFC_BASE + 0x1c) ++#endif ++#define NFC_STATUS (NFC_BASE + 0x20) ++#define NFC_INT_EN (NFC_BASE + 0x24) ++#define NFC_INT_ST (NFC_BASE + 0x28) ++#if defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || \ ++ defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) ++#define NFC_CONF1 (NFC_BASE + 0x2c) ++#define NFC_ECC_P1 (NFC_BASE + 0x30) ++#define NFC_ECC_P2 (NFC_BASE + 0x34) ++#define NFC_ECC_P3 (NFC_BASE + 0x38) ++#define NFC_ECC_P4 (NFC_BASE + 0x3c) ++#define NFC_ECC_ERR1 (NFC_BASE + 0x40) ++#define NFC_ECC_ERR2 (NFC_BASE + 0x44) ++#define NFC_ECC_ERR3 (NFC_BASE + 0x48) ++#define NFC_ECC_ERR4 (NFC_BASE + 0x4c) ++#define NFC_ADDR2 (NFC_BASE + 0x50) ++#endif ++ ++enum _int_stat { ++ INT_ST_ND_DONE = 1<<0, ++ INT_ST_TX_BUF_RDY = 1<<1, ++ INT_ST_RX_BUF_RDY = 1<<2, ++ INT_ST_ECC_ERR = 1<<3, ++ INT_ST_TX_TRAS_ERR = 1<<4, ++ INT_ST_RX_TRAS_ERR = 1<<5, ++ INT_ST_TX_KICK_ERR = 1<<6, ++ INT_ST_RX_KICK_ERR = 1<<7 ++}; ++ ++ ++//#define WORKAROUND_RX_BUF_OV 1 ++ ++ ++/************************************************************* ++ * stolen from nand.h ++ *************************************************************/ ++ ++/* ++ * Standard NAND flash commands ++ */ ++#define NAND_CMD_READ0 0 ++#define NAND_CMD_READ1 1 ++#define NAND_CMD_RNDOUT 5 ++#define NAND_CMD_PAGEPROG 0x10 ++#define NAND_CMD_READOOB 0x50 ++#define NAND_CMD_ERASE1 0x60 ++#define NAND_CMD_STATUS 0x70 ++#define NAND_CMD_STATUS_MULTI 0x71 ++#define NAND_CMD_SEQIN 0x80 ++#define NAND_CMD_RNDIN 0x85 ++#define NAND_CMD_READID 0x90 ++#define NAND_CMD_ERASE2 0xd0 ++#define NAND_CMD_RESET 0xff ++ ++/* Extended commands for large page devices */ ++#define NAND_CMD_READSTART 0x30 ++#define NAND_CMD_RNDOUTSTART 0xE0 ++#define NAND_CMD_CACHEDPROG 0x15 ++ ++/* Extended commands for AG-AND device */ ++/* ++ * Note: the command for NAND_CMD_DEPLETE1 is really 0x00 but ++ * there is no way to distinguish that from NAND_CMD_READ0 ++ * until the remaining sequence of commands has been completed ++ * so add a high order bit and mask it off in the command. ++ */ ++#define NAND_CMD_DEPLETE1 0x100 ++#define NAND_CMD_DEPLETE2 0x38 ++#define NAND_CMD_STATUS_MULTI 0x71 ++#define NAND_CMD_STATUS_ERROR 0x72 ++/* multi-bank error status (banks 0-3) */ ++#define NAND_CMD_STATUS_ERROR0 0x73 ++#define NAND_CMD_STATUS_ERROR1 0x74 ++#define NAND_CMD_STATUS_ERROR2 0x75 ++#define NAND_CMD_STATUS_ERROR3 0x76 ++#define NAND_CMD_STATUS_RESET 0x7f ++#define NAND_CMD_STATUS_CLEAR 0xff ++ ++#define NAND_CMD_NONE -1 ++ ++/* Status bits */ ++#define NAND_STATUS_FAIL 0x01 ++#define NAND_STATUS_FAIL_N1 0x02 ++#define NAND_STATUS_TRUE_READY 0x20 ++#define NAND_STATUS_READY 0x40 ++#define NAND_STATUS_WP 0x80 ++ ++typedef enum { ++ FL_READY, ++ FL_READING, ++ FL_WRITING, ++ FL_ERASING, ++ FL_SYNCING, ++ FL_CACHEDPRG, ++ FL_PM_SUSPENDED, ++} nand_state_t; ++ ++/*************************************************************/ ++ ++ ++ ++typedef enum _ra_flags { ++ FLAG_NONE = 0, ++ FLAG_ECC_EN = (1<<0), ++ FLAG_USE_GDMA = (1<<1), ++ FLAG_VERIFY = (1<<2), ++} RA_FLAGS; ++ ++ ++#define BBTTAG_BITS 2 ++#define BBTTAG_BITS_MASK ((1<<BBTTAG_BITS) -1) ++enum BBT_TAG { ++ BBT_TAG_UNKNOWN = 0, //2'b01 ++ BBT_TAG_GOOD = 3, //2'b11 ++ BBT_TAG_BAD = 2, //2'b10 ++ BBT_TAG_RES = 1, //2'b01 ++}; ++ ++struct ra_nand_chip { ++ int numchips; ++ int chip_shift; ++ int page_shift; ++ int erase_shift; ++ int oob_shift; ++ int badblockpos; ++#if !defined (__UBOOT__) ++ struct mutex hwcontrol; ++ struct mutex *controller; ++#endif ++ struct nand_ecclayout *oob; ++ int state; ++ unsigned int buffers_page; ++ char *buffers; //[CFG_PAGESIZE + CFG_PAGE_OOBSIZE]; ++ char *readback_buffers; ++ unsigned char *bbt; ++#if defined (WORKAROUND_RX_BUF_OV) ++ unsigned int sandbox_page; // steal a page (block) for read ECC verification ++#endif ++ ++}; ++ ++ ++ ++//fixme, gdma api ++int nand_dma_sync(void); ++void release_dma_buf(void); ++int set_gdma_ch(unsigned long dst, ++ unsigned long src, unsigned int len, int burst_size, ++ int soft_mode, int src_req_type, int dst_req_type, ++ int src_burst_mode, int dst_burst_mode); ++ ++ ++ ++ ++#endif diff --git a/target/linux/ramips/patches-3.18/0044-mtd-add-chunked-read-io-to-m25p80.patch b/target/linux/ramips/patches-3.18/0044-mtd-add-chunked-read-io-to-m25p80.patch new file mode 100644 index 0000000..2e81e45 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0044-mtd-add-chunked-read-io-to-m25p80.patch @@ -0,0 +1,154 @@ +--- a/drivers/mtd/devices/m25p80.c ++++ b/drivers/mtd/devices/m25p80.c +@@ -19,6 +19,7 @@ + #include <linux/errno.h> + #include <linux/module.h> + #include <linux/device.h> ++#include <linux/of.h> + + #include <linux/mtd/mtd.h> + #include <linux/mtd/partitions.h> +@@ -32,6 +33,7 @@ struct m25p { + struct spi_device *spi; + struct spi_nor spi_nor; + struct mtd_info mtd; ++ u16 chunk_size; + u8 command[MAX_CMD_SIZE]; + }; + +@@ -117,25 +119,14 @@ static inline unsigned int m25p80_rx_nbi + } + } + +-/* +- * Read an address range from the nor chip. The address range +- * may be any size provided it is within the physical boundaries. +- */ +-static int m25p80_read(struct spi_nor *nor, loff_t from, size_t len, +- size_t *retlen, u_char *buf) ++static int __m25p80_read(struct spi_nor *nor, loff_t from, size_t len, ++ size_t *retlen, u_char *buf) + { + struct m25p *flash = nor->priv; + struct spi_device *spi = flash->spi; + struct spi_transfer t[2]; + struct spi_message m; + int dummy = nor->read_dummy; +- int ret; +- +- /* Wait till previous write/erase is done. */ +- ret = nor->wait_till_ready(nor); +- if (ret) +- return ret; +- + spi_message_init(&m); + memset(t, 0, (sizeof t)); + +@@ -156,6 +147,84 @@ static int m25p80_read(struct spi_nor *n + *retlen = m.actual_length - m25p_cmdsz(nor) - dummy; + return 0; + } ++/* ++ * Read an address range from the nor chip. The address range ++ * may be any size provided it is within the physical boundaries. ++ */ ++static int m25p80_read(struct spi_nor *nor, loff_t from, size_t len, ++ size_t *retlen, u_char *buf) ++{ ++ int ret; ++ ++ /* Wait till previous write/erase is done. */ ++ ret = nor->wait_till_ready(nor); ++ if (ret) ++ return ret; ++ ++ return __m25p80_read(nor, from, len, retlen, buf); ++} ++ ++ ++static void m25p80_chunked_write(struct spi_nor *nor, loff_t _from, size_t _len, ++ size_t *_retlen, const u_char *_buf) ++{ ++ struct m25p *flash = nor->priv; ++ int chunk_size; ++ int retlen = 0; ++ ++ chunk_size = flash->chunk_size; ++ if (!chunk_size) ++ chunk_size = _len; ++ ++ if (nor->addr_width > 3) ++ chunk_size -= nor->addr_width - 3; ++ ++ while (retlen < _len) { ++ size_t len = min_t(int, chunk_size, _len - retlen); ++ const u_char *buf = _buf + retlen; ++ loff_t from = _from + retlen; ++ ++ nor->wait_till_ready(nor); ++ nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0, 0); ++ ++ m25p80_write(nor, from, len, &retlen, buf); ++ } ++ *_retlen += retlen; ++} ++ ++static int m25p80_chunked_read(struct spi_nor *nor, loff_t _from, size_t _len, ++ size_t *_retlen, u_char *_buf) ++{ ++ struct m25p *flash = nor->priv; ++ int chunk_size; ++ int ret; ++ ++ /* Wait till previous write/erase is done. */ ++ ret = nor->wait_till_ready(nor); ++ if (ret) ++ return ret; ++ ++ chunk_size = flash->chunk_size; ++ if (!chunk_size) ++ chunk_size = _len; ++ ++ *_retlen = 0; ++ ++ while (*_retlen < _len) { ++ size_t len = min_t(int, chunk_size, _len - *_retlen); ++ u_char *buf = _buf + *_retlen; ++ loff_t from = _from + *_retlen; ++ int retlen = 0; ++ int ret = __m25p80_read(nor, from, len, &retlen, buf); ++ ++ if (ret) ++ return ret; ++ ++ *_retlen += retlen; ++ } ++ ++ return 0; ++} + + static int m25p80_erase(struct spi_nor *nor, loff_t offset) + { +@@ -197,6 +266,7 @@ static int m25p_probe(struct spi_device + struct spi_nor *nor; + enum read_mode mode = SPI_NOR_NORMAL; + char *flash_name = NULL; ++ u32 val; + int ret; + + data = dev_get_platdata(&spi->dev); +@@ -244,6 +314,14 @@ static int m25p_probe(struct spi_device + if (ret) + return ret; + ++ if (spi->dev.of_node && ++ !of_property_read_u32(spi->dev.of_node, "m25p,chunked-io", &val)) { ++ dev_warn(&spi->dev, "using chunked io\n"); ++ nor->read = m25p80_chunked_read; ++ nor->write = m25p80_chunked_write; ++ flash->chunk_size = val; ++ } ++ + ppdata.of_node = spi->dev.of_node; + + return mtd_device_parse_register(&flash->mtd, NULL, &ppdata, diff --git a/target/linux/ramips/patches-3.18/0045-mtd-add-mt7621-nand-support.patch b/target/linux/ramips/patches-3.18/0045-mtd-add-mt7621-nand-support.patch new file mode 100644 index 0000000..3999f54 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0045-mtd-add-mt7621-nand-support.patch @@ -0,0 +1,4417 @@ +From 5db075c5dd038fbf4b5a0196e10f4f9658236372 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 27 Jul 2014 11:05:17 +0100 +Subject: [PATCH 45/57] mtd: add mt7621 nand support + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + drivers/mtd/nand/Kconfig | 6 + + drivers/mtd/nand/Makefile | 1 + + drivers/mtd/nand/bmt.c | 750 ++++++++++++ + drivers/mtd/nand/bmt.h | 80 ++ + drivers/mtd/nand/dev-nand.c | 63 + + drivers/mtd/nand/mt6575_typedefs.h | 340 ++++++ + drivers/mtd/nand/mtk_nand.c | 2304 +++++++++++++++++++++++++++++++++++ + drivers/mtd/nand/mtk_nand.h | 452 +++++++ + drivers/mtd/nand/nand_base.c | 6 +- + drivers/mtd/nand/nand_bbt.c | 19 + + drivers/mtd/nand/nand_def.h | 123 ++ + drivers/mtd/nand/nand_device_list.h | 55 + + drivers/mtd/nand/partition.h | 115 ++ + 13 files changed, 4311 insertions(+), 3 deletions(-) + create mode 100644 drivers/mtd/nand/bmt.c + create mode 100644 drivers/mtd/nand/bmt.h + create mode 100644 drivers/mtd/nand/dev-nand.c + create mode 100644 drivers/mtd/nand/mt6575_typedefs.h + create mode 100644 drivers/mtd/nand/mtk_nand.c + create mode 100644 drivers/mtd/nand/mtk_nand.h + create mode 100644 drivers/mtd/nand/nand_def.h + create mode 100644 drivers/mtd/nand/nand_device_list.h + create mode 100644 drivers/mtd/nand/partition.h + +--- a/drivers/mtd/nand/Kconfig ++++ b/drivers/mtd/nand/Kconfig +@@ -516,4 +516,10 @@ config MTD_NAND_XWAY + Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached + to the External Bus Unit (EBU). + ++config MTK_MTD_NAND ++ tristate "Support for MTK SoC NAND controller" ++ depends on SOC_MT7621 ++ select MTD_NAND_IDS ++ select MTD_NAND_ECC ++ + endif # MTD_NAND +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -50,5 +50,6 @@ obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740 + obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/ + obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o + obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ ++obj-$(CONFIG_MTK_MTD_NAND) += mtk_nand.o bmt.o + + nand-objs := nand_base.o nand_bbt.o nand_timings.o +--- /dev/null ++++ b/drivers/mtd/nand/bmt.c +@@ -0,0 +1,750 @@ ++#include "bmt.h" ++ ++typedef struct ++{ ++ char signature[3]; ++ u8 version; ++ u8 bad_count; // bad block count in pool ++ u8 mapped_count; // mapped block count in pool ++ u8 checksum; ++ u8 reseverd[13]; ++} phys_bmt_header; ++ ++typedef struct ++{ ++ phys_bmt_header header; ++ bmt_entry table[MAX_BMT_SIZE]; ++} phys_bmt_struct; ++ ++typedef struct ++{ ++ char signature[3]; ++} bmt_oob_data; ++ ++static char MAIN_SIGNATURE[] = "BMT"; ++static char OOB_SIGNATURE[] = "bmt"; ++#define SIGNATURE_SIZE (3) ++ ++#define MAX_DAT_SIZE 0x1000 ++#define MAX_OOB_SIZE 0x80 ++ ++static struct mtd_info *mtd_bmt; ++static struct nand_chip *nand_chip_bmt; ++#define BLOCK_SIZE_BMT (1 << nand_chip_bmt->phys_erase_shift) ++#define PAGE_SIZE_BMT (1 << nand_chip_bmt->page_shift) ++ ++#define OFFSET(block) ((block) * BLOCK_SIZE_BMT) ++#define PAGE_ADDR(block) ((block) * BLOCK_SIZE_BMT / PAGE_SIZE_BMT) ++ ++/********************************************************************* ++* Flash is splited into 2 parts, system part is for normal system * ++* system usage, size is system_block_count, another is replace pool * ++* +-------------------------------------------------+ * ++* | system_block_count | bmt_block_count | * ++* +-------------------------------------------------+ * ++*********************************************************************/ ++static u32 total_block_count; // block number in flash ++static u32 system_block_count; ++static int bmt_block_count; // bmt table size ++// static int bmt_count; // block used in bmt ++static int page_per_block; // page per count ++ ++static u32 bmt_block_index; // bmt block index ++static bmt_struct bmt; // dynamic created global bmt table ++ ++static u8 dat_buf[MAX_DAT_SIZE]; ++static u8 oob_buf[MAX_OOB_SIZE]; ++static bool pool_erased; ++ ++/*************************************************************** ++* ++* Interface adaptor for preloader/uboot/kernel ++* These interfaces operate on physical address, read/write ++* physical data. ++* ++***************************************************************/ ++int nand_read_page_bmt(u32 page, u8 * dat, u8 * oob) ++{ ++ return mtk_nand_exec_read_page(mtd_bmt, page, PAGE_SIZE_BMT, dat, oob); ++} ++ ++bool nand_block_bad_bmt(u32 offset) ++{ ++ return mtk_nand_block_bad_hw(mtd_bmt, offset); ++} ++ ++bool nand_erase_bmt(u32 offset) ++{ ++ int status; ++ if (offset < 0x20000) ++ { ++ MSG(INIT, "erase offset: 0x%x\n", offset); ++ } ++ ++ status = mtk_nand_erase_hw(mtd_bmt, offset / PAGE_SIZE_BMT); // as nand_chip structure doesn't have a erase function defined ++ if (status & NAND_STATUS_FAIL) ++ return false; ++ else ++ return true; ++} ++ ++int mark_block_bad_bmt(u32 offset) ++{ ++ return mtk_nand_block_markbad_hw(mtd_bmt, offset); //mark_block_bad_hw(offset); ++} ++ ++bool nand_write_page_bmt(u32 page, u8 * dat, u8 * oob) ++{ ++ if (mtk_nand_exec_write_page(mtd_bmt, page, PAGE_SIZE_BMT, dat, oob)) ++ return false; ++ else ++ return true; ++} ++ ++/*************************************************************** ++* * ++* static internal function * ++* * ++***************************************************************/ ++static void dump_bmt_info(bmt_struct * bmt) ++{ ++ int i; ++ ++ MSG(INIT, "BMT v%d. total %d mapping:\n", bmt->version, bmt->mapped_count); ++ for (i = 0; i < bmt->mapped_count; i++) ++ { ++ MSG(INIT, "\t0x%x -> 0x%x\n", bmt->table[i].bad_index, bmt->table[i].mapped_index); ++ } ++} ++ ++static bool match_bmt_signature(u8 * dat, u8 * oob) ++{ ++ ++ if (memcmp(dat + MAIN_SIGNATURE_OFFSET, MAIN_SIGNATURE, SIGNATURE_SIZE)) ++ { ++ return false; ++ } ++ ++ if (memcmp(oob + OOB_SIGNATURE_OFFSET, OOB_SIGNATURE, SIGNATURE_SIZE)) ++ { ++ MSG(INIT, "main signature match, oob signature doesn't match, but ignore\n"); ++ } ++ return true; ++} ++ ++static u8 cal_bmt_checksum(phys_bmt_struct * phys_table, int bmt_size) ++{ ++ int i; ++ u8 checksum = 0; ++ u8 *dat = (u8 *) phys_table; ++ ++ checksum += phys_table->header.version; ++ checksum += phys_table->header.mapped_count; ++ ++ dat += sizeof(phys_bmt_header); ++ for (i = 0; i < bmt_size * sizeof(bmt_entry); i++) ++ { ++ checksum += dat[i]; ++ } ++ ++ return checksum; ++} ++ ++ ++static int is_block_mapped(int index) ++{ ++ int i; ++ for (i = 0; i < bmt.mapped_count; i++) ++ { ++ if (index == bmt.table[i].mapped_index) ++ return i; ++ } ++ return -1; ++} ++ ++static bool is_page_used(u8 * dat, u8 * oob) ++{ ++ return ((oob[OOB_INDEX_OFFSET] != 0xFF) || (oob[OOB_INDEX_OFFSET + 1] != 0xFF)); ++} ++ ++static bool valid_bmt_data(phys_bmt_struct * phys_table) ++{ ++ int i; ++ u8 checksum = cal_bmt_checksum(phys_table, bmt_block_count); ++ ++ // checksum correct? ++ if (phys_table->header.checksum != checksum) ++ { ++ MSG(INIT, "BMT Data checksum error: %x %x\n", phys_table->header.checksum, checksum); ++ return false; ++ } ++ ++ MSG(INIT, "BMT Checksum is: 0x%x\n", phys_table->header.checksum); ++ ++ // block index correct? ++ for (i = 0; i < phys_table->header.mapped_count; i++) ++ { ++ if (phys_table->table[i].bad_index >= total_block_count || phys_table->table[i].mapped_index >= total_block_count || phys_table->table[i].mapped_index < system_block_count) ++ { ++ MSG(INIT, "index error: bad_index: %d, mapped_index: %d\n", phys_table->table[i].bad_index, phys_table->table[i].mapped_index); ++ return false; ++ } ++ } ++ ++ // pass check, valid bmt. ++ MSG(INIT, "Valid BMT, version v%d\n", phys_table->header.version); ++ return true; ++} ++ ++static void fill_nand_bmt_buffer(bmt_struct * bmt, u8 * dat, u8 * oob) ++{ ++ phys_bmt_struct phys_bmt; ++ ++ dump_bmt_info(bmt); ++ ++ // fill phys_bmt_struct structure with bmt_struct ++ memset(&phys_bmt, 0xFF, sizeof(phys_bmt)); ++ ++ memcpy(phys_bmt.header.signature, MAIN_SIGNATURE, SIGNATURE_SIZE); ++ phys_bmt.header.version = BMT_VERSION; ++ // phys_bmt.header.bad_count = bmt->bad_count; ++ phys_bmt.header.mapped_count = bmt->mapped_count; ++ memcpy(phys_bmt.table, bmt->table, sizeof(bmt_entry) * bmt_block_count); ++ ++ phys_bmt.header.checksum = cal_bmt_checksum(&phys_bmt, bmt_block_count); ++ ++ memcpy(dat + MAIN_SIGNATURE_OFFSET, &phys_bmt, sizeof(phys_bmt)); ++ memcpy(oob + OOB_SIGNATURE_OFFSET, OOB_SIGNATURE, SIGNATURE_SIZE); ++} ++ ++// return valid index if found BMT, else return 0 ++static int load_bmt_data(int start, int pool_size) ++{ ++ int bmt_index = start + pool_size - 1; // find from the end ++ phys_bmt_struct phys_table; ++ int i; ++ ++ MSG(INIT, "[%s]: begin to search BMT from block 0x%x\n", __FUNCTION__, bmt_index); ++ ++ for (bmt_index = start + pool_size - 1; bmt_index >= start; bmt_index--) ++ { ++ if (nand_block_bad_bmt(OFFSET(bmt_index))) ++ { ++ MSG(INIT, "Skip bad block: %d\n", bmt_index); ++ continue; ++ } ++ ++ if (!nand_read_page_bmt(PAGE_ADDR(bmt_index), dat_buf, oob_buf)) ++ { ++ MSG(INIT, "Error found when read block %d\n", bmt_index); ++ continue; ++ } ++ ++ if (!match_bmt_signature(dat_buf, oob_buf)) ++ { ++ continue; ++ } ++ ++ MSG(INIT, "Match bmt signature @ block: 0x%x\n", bmt_index); ++ ++ memcpy(&phys_table, dat_buf + MAIN_SIGNATURE_OFFSET, sizeof(phys_table)); ++ ++ if (!valid_bmt_data(&phys_table)) ++ { ++ MSG(INIT, "BMT data is not correct %d\n", bmt_index); ++ continue; ++ } else ++ { ++ bmt.mapped_count = phys_table.header.mapped_count; ++ bmt.version = phys_table.header.version; ++ // bmt.bad_count = phys_table.header.bad_count; ++ memcpy(bmt.table, phys_table.table, bmt.mapped_count * sizeof(bmt_entry)); ++ ++ MSG(INIT, "bmt found at block: %d, mapped block: %d\n", bmt_index, bmt.mapped_count); ++ ++ for (i = 0; i < bmt.mapped_count; i++) ++ { ++ if (!nand_block_bad_bmt(OFFSET(bmt.table[i].bad_index))) ++ { ++ MSG(INIT, "block 0x%x is not mark bad, should be power lost last time\n", bmt.table[i].bad_index); ++ mark_block_bad_bmt(OFFSET(bmt.table[i].bad_index)); ++ } ++ } ++ ++ return bmt_index; ++ } ++ } ++ ++ MSG(INIT, "bmt block not found!\n"); ++ return 0; ++} ++ ++/************************************************************************* ++* Find an available block and erase. * ++* start_from_end: if true, find available block from end of flash. * ++* else, find from the beginning of the pool * ++* need_erase: if true, all unmapped blocks in the pool will be erased * ++*************************************************************************/ ++static int find_available_block(bool start_from_end) ++{ ++ int i; // , j; ++ int block = system_block_count; ++ int direction; ++ // int avail_index = 0; ++ MSG(INIT, "Try to find_available_block, pool_erase: %d\n", pool_erased); ++ ++ // erase all un-mapped blocks in pool when finding avaliable block ++ if (!pool_erased) ++ { ++ MSG(INIT, "Erase all un-mapped blocks in pool\n"); ++ for (i = 0; i < bmt_block_count; i++) ++ { ++ if (block == bmt_block_index) ++ { ++ MSG(INIT, "Skip bmt block 0x%x\n", block); ++ continue; ++ } ++ ++ if (nand_block_bad_bmt(OFFSET(block + i))) ++ { ++ MSG(INIT, "Skip bad block 0x%x\n", block + i); ++ continue; ++ } ++//if(block==4095) ++//{ ++// continue; ++//} ++ ++ if (is_block_mapped(block + i) >= 0) ++ { ++ MSG(INIT, "Skip mapped block 0x%x\n", block + i); ++ continue; ++ } ++ ++ if (!nand_erase_bmt(OFFSET(block + i))) ++ { ++ MSG(INIT, "Erase block 0x%x failed\n", block + i); ++ mark_block_bad_bmt(OFFSET(block + i)); ++ } ++ } ++ ++ pool_erased = 1; ++ } ++ ++ if (start_from_end) ++ { ++ block = total_block_count - 1; ++ direction = -1; ++ } else ++ { ++ block = system_block_count; ++ direction = 1; ++ } ++ ++ for (i = 0; i < bmt_block_count; i++, block += direction) ++ { ++ if (block == bmt_block_index) ++ { ++ MSG(INIT, "Skip bmt block 0x%x\n", block); ++ continue; ++ } ++ ++ if (nand_block_bad_bmt(OFFSET(block))) ++ { ++ MSG(INIT, "Skip bad block 0x%x\n", block); ++ continue; ++ } ++ ++ if (is_block_mapped(block) >= 0) ++ { ++ MSG(INIT, "Skip mapped block 0x%x\n", block); ++ continue; ++ } ++ ++ MSG(INIT, "Find block 0x%x available\n", block); ++ return block; ++ } ++ ++ return 0; ++} ++ ++static unsigned short get_bad_index_from_oob(u8 * oob_buf) ++{ ++ unsigned short index; ++ memcpy(&index, oob_buf + OOB_INDEX_OFFSET, OOB_INDEX_SIZE); ++ ++ return index; ++} ++ ++void set_bad_index_to_oob(u8 * oob, u16 index) ++{ ++ memcpy(oob + OOB_INDEX_OFFSET, &index, sizeof(index)); ++} ++ ++static int migrate_from_bad(int offset, u8 * write_dat, u8 * write_oob) ++{ ++ int page; ++ int error_block = offset / BLOCK_SIZE_BMT; ++ int error_page = (offset / PAGE_SIZE_BMT) % page_per_block; ++ int to_index; ++ ++ memcpy(oob_buf, write_oob, MAX_OOB_SIZE); ++ ++ to_index = find_available_block(false); ++ ++ if (!to_index) ++ { ++ MSG(INIT, "Cannot find an available block for BMT\n"); ++ return 0; ++ } ++ ++ { // migrate error page first ++ MSG(INIT, "Write error page: 0x%x\n", error_page); ++ if (!write_dat) ++ { ++ nand_read_page_bmt(PAGE_ADDR(error_block) + error_page, dat_buf, NULL); ++ write_dat = dat_buf; ++ } ++ // memcpy(oob_buf, write_oob, MAX_OOB_SIZE); ++ ++ if (error_block < system_block_count) ++ set_bad_index_to_oob(oob_buf, error_block); // if error_block is already a mapped block, original mapping index is in OOB. ++ ++ if (!nand_write_page_bmt(PAGE_ADDR(to_index) + error_page, write_dat, oob_buf)) ++ { ++ MSG(INIT, "Write to page 0x%x fail\n", PAGE_ADDR(to_index) + error_page); ++ mark_block_bad_bmt(to_index); ++ return migrate_from_bad(offset, write_dat, write_oob); ++ } ++ } ++ ++ for (page = 0; page < page_per_block; page++) ++ { ++ if (page != error_page) ++ { ++ nand_read_page_bmt(PAGE_ADDR(error_block) + page, dat_buf, oob_buf); ++ if (is_page_used(dat_buf, oob_buf)) ++ { ++ if (error_block < system_block_count) ++ { ++ set_bad_index_to_oob(oob_buf, error_block); ++ } ++ MSG(INIT, "\tmigrate page 0x%x to page 0x%x\n", PAGE_ADDR(error_block) + page, PAGE_ADDR(to_index) + page); ++ if (!nand_write_page_bmt(PAGE_ADDR(to_index) + page, dat_buf, oob_buf)) ++ { ++ MSG(INIT, "Write to page 0x%x fail\n", PAGE_ADDR(to_index) + page); ++ mark_block_bad_bmt(to_index); ++ return migrate_from_bad(offset, write_dat, write_oob); ++ } ++ } ++ } ++ } ++ ++ MSG(INIT, "Migrate from 0x%x to 0x%x done!\n", error_block, to_index); ++ ++ return to_index; ++} ++ ++static bool write_bmt_to_flash(u8 * dat, u8 * oob) ++{ ++ bool need_erase = true; ++ MSG(INIT, "Try to write BMT\n"); ++ ++ if (bmt_block_index == 0) ++ { ++ // if we don't have index, we don't need to erase found block as it has been erased in find_available_block() ++ need_erase = false; ++ if (!(bmt_block_index = find_available_block(true))) ++ { ++ MSG(INIT, "Cannot find an available block for BMT\n"); ++ return false; ++ } ++ } ++ ++ MSG(INIT, "Find BMT block: 0x%x\n", bmt_block_index); ++ ++ // write bmt to flash ++ if (need_erase) ++ { ++ if (!nand_erase_bmt(OFFSET(bmt_block_index))) ++ { ++ MSG(INIT, "BMT block erase fail, mark bad: 0x%x\n", bmt_block_index); ++ mark_block_bad_bmt(OFFSET(bmt_block_index)); ++ // bmt.bad_count++; ++ ++ bmt_block_index = 0; ++ return write_bmt_to_flash(dat, oob); // recursive call ++ } ++ } ++ ++ if (!nand_write_page_bmt(PAGE_ADDR(bmt_block_index), dat, oob)) ++ { ++ MSG(INIT, "Write BMT data fail, need to write again\n"); ++ mark_block_bad_bmt(OFFSET(bmt_block_index)); ++ // bmt.bad_count++; ++ ++ bmt_block_index = 0; ++ return write_bmt_to_flash(dat, oob); // recursive call ++ } ++ ++ MSG(INIT, "Write BMT data to block 0x%x success\n", bmt_block_index); ++ return true; ++} ++ ++/******************************************************************* ++* Reconstruct bmt, called when found bmt info doesn't match bad ++* block info in flash. ++* ++* Return NULL for failure ++*******************************************************************/ ++bmt_struct *reconstruct_bmt(bmt_struct * bmt) ++{ ++ int i; ++ int index = system_block_count; ++ unsigned short bad_index; ++ int mapped; ++ ++ // init everything in BMT struct ++ bmt->version = BMT_VERSION; ++ bmt->bad_count = 0; ++ bmt->mapped_count = 0; ++ ++ memset(bmt->table, 0, bmt_block_count * sizeof(bmt_entry)); ++ ++ for (i = 0; i < bmt_block_count; i++, index++) ++ { ++ if (nand_block_bad_bmt(OFFSET(index))) ++ { ++ MSG(INIT, "Skip bad block: 0x%x\n", index); ++ // bmt->bad_count++; ++ continue; ++ } ++ ++ MSG(INIT, "read page: 0x%x\n", PAGE_ADDR(index)); ++ nand_read_page_bmt(PAGE_ADDR(index), dat_buf, oob_buf); ++ /* if (mtk_nand_read_page_hw(PAGE_ADDR(index), dat_buf)) ++ { ++ MSG(INIT, "Error when read block %d\n", bmt_block_index); ++ continue; ++ } */ ++ ++ if ((bad_index = get_bad_index_from_oob(oob_buf)) >= system_block_count) ++ { ++ MSG(INIT, "get bad index: 0x%x\n", bad_index); ++ if (bad_index != 0xFFFF) ++ MSG(INIT, "Invalid bad index found in block 0x%x, bad index 0x%x\n", index, bad_index); ++ continue; ++ } ++ ++ MSG(INIT, "Block 0x%x is mapped to bad block: 0x%x\n", index, bad_index); ++ ++ if (!nand_block_bad_bmt(OFFSET(bad_index))) ++ { ++ MSG(INIT, "\tbut block 0x%x is not marked as bad, invalid mapping\n", bad_index); ++ continue; // no need to erase here, it will be erased later when trying to write BMT ++ } ++ ++ if ((mapped = is_block_mapped(bad_index)) >= 0) ++ { ++ MSG(INIT, "bad block 0x%x is mapped to 0x%x, should be caused by power lost, replace with one\n", bmt->table[mapped].bad_index, bmt->table[mapped].mapped_index); ++ bmt->table[mapped].mapped_index = index; // use new one instead. ++ } else ++ { ++ // add mapping to BMT ++ bmt->table[bmt->mapped_count].bad_index = bad_index; ++ bmt->table[bmt->mapped_count].mapped_index = index; ++ bmt->mapped_count++; ++ } ++ ++ MSG(INIT, "Add mapping: 0x%x -> 0x%x to BMT\n", bad_index, index); ++ ++ } ++ ++ MSG(INIT, "Scan replace pool done, mapped block: %d\n", bmt->mapped_count); ++ // dump_bmt_info(bmt); ++ ++ // fill NAND BMT buffer ++ memset(oob_buf, 0xFF, sizeof(oob_buf)); ++ fill_nand_bmt_buffer(bmt, dat_buf, oob_buf); ++ ++ // write BMT back ++ if (!write_bmt_to_flash(dat_buf, oob_buf)) ++ { ++ MSG(INIT, "TRAGEDY: cannot find a place to write BMT!!!!\n"); ++ } ++ ++ return bmt; ++} ++ ++/******************************************************************* ++* [BMT Interface] ++* ++* Description: ++* Init bmt from nand. Reconstruct if not found or data error ++* ++* Parameter: ++* size: size of bmt and replace pool ++* ++* Return: ++* NULL for failure, and a bmt struct for success ++*******************************************************************/ ++bmt_struct *init_bmt(struct nand_chip * chip, int size) ++{ ++ struct mtk_nand_host *host; ++ ++ if (size > 0 && size < MAX_BMT_SIZE) ++ { ++ MSG(INIT, "Init bmt table, size: %d\n", size); ++ bmt_block_count = size; ++ } else ++ { ++ MSG(INIT, "Invalid bmt table size: %d\n", size); ++ return NULL; ++ } ++ nand_chip_bmt = chip; ++ system_block_count = chip->chipsize >> chip->phys_erase_shift; ++ total_block_count = bmt_block_count + system_block_count; ++ page_per_block = BLOCK_SIZE_BMT / PAGE_SIZE_BMT; ++ host = (struct mtk_nand_host *)chip->priv; ++ mtd_bmt = &host->mtd; ++ ++ MSG(INIT, "mtd_bmt: %p, nand_chip_bmt: %p\n", mtd_bmt, nand_chip_bmt); ++ MSG(INIT, "bmt count: %d, system count: %d\n", bmt_block_count, system_block_count); ++ ++ // set this flag, and unmapped block in pool will be erased. ++ pool_erased = 0; ++ memset(bmt.table, 0, size * sizeof(bmt_entry)); ++ if ((bmt_block_index = load_bmt_data(system_block_count, size))) ++ { ++ MSG(INIT, "Load bmt data success @ block 0x%x\n", bmt_block_index); ++ dump_bmt_info(&bmt); ++ return &bmt; ++ } else ++ { ++ MSG(INIT, "Load bmt data fail, need re-construct!\n"); ++#ifndef __UBOOT_NAND__ // BMT is not re-constructed in UBOOT. ++ if (reconstruct_bmt(&bmt)) ++ return &bmt; ++ else ++#endif ++ return NULL; ++ } ++} ++ ++/******************************************************************* ++* [BMT Interface] ++* ++* Description: ++* Update BMT. ++* ++* Parameter: ++* offset: update block/page offset. ++* reason: update reason, see update_reason_t for reason. ++* dat/oob: data and oob buffer for write fail. ++* ++* Return: ++* Return true for success, and false for failure. ++*******************************************************************/ ++bool update_bmt(u32 offset, update_reason_t reason, u8 * dat, u8 * oob) ++{ ++ int map_index; ++ int orig_bad_block = -1; ++ // int bmt_update_index; ++ int i; ++ int bad_index = offset / BLOCK_SIZE_BMT; ++ ++#ifndef MTK_NAND_BMT ++ return false; ++#endif ++ if (reason == UPDATE_WRITE_FAIL) ++ { ++ MSG(INIT, "Write fail, need to migrate\n"); ++ if (!(map_index = migrate_from_bad(offset, dat, oob))) ++ { ++ MSG(INIT, "migrate fail\n"); ++ return false; ++ } ++ } else ++ { ++ if (!(map_index = find_available_block(false))) ++ { ++ MSG(INIT, "Cannot find block in pool\n"); ++ return false; ++ } ++ } ++ ++ // now let's update BMT ++ if (bad_index >= system_block_count) // mapped block become bad, find original bad block ++ { ++ for (i = 0; i < bmt_block_count; i++) ++ { ++ if (bmt.table[i].mapped_index == bad_index) ++ { ++ orig_bad_block = bmt.table[i].bad_index; ++ break; ++ } ++ } ++ // bmt.bad_count++; ++ MSG(INIT, "Mapped block becomes bad, orig bad block is 0x%x\n", orig_bad_block); ++ ++ bmt.table[i].mapped_index = map_index; ++ } else ++ { ++ bmt.table[bmt.mapped_count].mapped_index = map_index; ++ bmt.table[bmt.mapped_count].bad_index = bad_index; ++ bmt.mapped_count++; ++ } ++ ++ memset(oob_buf, 0xFF, sizeof(oob_buf)); ++ fill_nand_bmt_buffer(&bmt, dat_buf, oob_buf); ++ if (!write_bmt_to_flash(dat_buf, oob_buf)) ++ return false; ++ ++ mark_block_bad_bmt(offset); ++ ++ return true; ++} ++ ++/******************************************************************* ++* [BMT Interface] ++* ++* Description: ++* Given an block index, return mapped index if it's mapped, else ++* return given index. ++* ++* Parameter: ++* index: given an block index. This value cannot exceed ++* system_block_count. ++* ++* Return NULL for failure ++*******************************************************************/ ++u16 get_mapping_block_index(int index) ++{ ++ int i; ++#ifndef MTK_NAND_BMT ++ return index; ++#endif ++ if (index > system_block_count) ++ { ++ return index; ++ } ++ ++ for (i = 0; i < bmt.mapped_count; i++) ++ { ++ if (bmt.table[i].bad_index == index) ++ { ++ return bmt.table[i].mapped_index; ++ } ++ } ++ ++ return index; ++} ++#ifdef __KERNEL_NAND__ ++EXPORT_SYMBOL_GPL(init_bmt); ++EXPORT_SYMBOL_GPL(update_bmt); ++EXPORT_SYMBOL_GPL(get_mapping_block_index); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("MediaTek"); ++MODULE_DESCRIPTION("Bad Block mapping management for MediaTek NAND Flash Driver"); ++#endif +--- /dev/null ++++ b/drivers/mtd/nand/bmt.h +@@ -0,0 +1,80 @@ ++#ifndef __BMT_H__ ++#define __BMT_H__ ++ ++#include "nand_def.h" ++ ++#if defined(__PRELOADER_NAND__) ++ ++#include "nand.h" ++ ++#elif defined(__UBOOT_NAND__) ++ ++#include <linux/mtd/nand.h> ++#include "mtk_nand.h" ++ ++#elif defined(__KERNEL_NAND__) ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/nand.h> ++#include <linux/module.h> ++#include "mtk_nand.h" ++ ++#endif ++ ++ ++#define MAX_BMT_SIZE (0x80) ++#define BMT_VERSION (1) // initial version ++ ++#define MAIN_SIGNATURE_OFFSET (0) ++#define OOB_SIGNATURE_OFFSET (1) ++#define OOB_INDEX_OFFSET (29) ++#define OOB_INDEX_SIZE (2) ++#define FAKE_INDEX (0xAAAA) ++ ++typedef struct _bmt_entry_ ++{ ++ u16 bad_index; // bad block index ++ u16 mapped_index; // mapping block index in the replace pool ++} bmt_entry; ++ ++typedef enum ++{ ++ UPDATE_ERASE_FAIL, ++ UPDATE_WRITE_FAIL, ++ UPDATE_UNMAPPED_BLOCK, ++ UPDATE_REASON_COUNT, ++} update_reason_t; ++ ++typedef struct ++{ ++ bmt_entry table[MAX_BMT_SIZE]; ++ u8 version; ++ u8 mapped_count; // mapped block count in pool ++ u8 bad_count; // bad block count in pool. Not used in V1 ++} bmt_struct; ++ ++/*************************************************************** ++* * ++* Interface BMT need to use * ++* * ++***************************************************************/ ++extern bool mtk_nand_exec_read_page(struct mtd_info *mtd, u32 row, u32 page_size, u8 * dat, u8 * oob); ++extern int mtk_nand_block_bad_hw(struct mtd_info *mtd, loff_t ofs); ++extern int mtk_nand_erase_hw(struct mtd_info *mtd, int page); ++extern int mtk_nand_block_markbad_hw(struct mtd_info *mtd, loff_t ofs); ++extern int mtk_nand_exec_write_page(struct mtd_info *mtd, u32 row, u32 page_size, u8 * dat, u8 * oob); ++ ++ ++/*************************************************************** ++* * ++* Different function interface for preloader/uboot/kernel * ++* * ++***************************************************************/ ++void set_bad_index_to_oob(u8 * oob, u16 index); ++ ++ ++bmt_struct *init_bmt(struct nand_chip *nand, int size); ++bool update_bmt(u32 offset, update_reason_t reason, u8 * dat, u8 * oob); ++unsigned short get_mapping_block_index(int index); ++ ++#endif // #ifndef __BMT_H__ +--- /dev/null ++++ b/drivers/mtd/nand/dev-nand.c +@@ -0,0 +1,63 @@ ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/platform_device.h> ++ ++#include "mt6575_typedefs.h" ++ ++#define RALINK_NAND_CTRL_BASE 0xBE003000 ++#define NFI_base RALINK_NAND_CTRL_BASE ++#define RALINK_NANDECC_CTRL_BASE 0xBE003800 ++#define NFIECC_base RALINK_NANDECC_CTRL_BASE ++#define MT7621_NFI_IRQ_ID SURFBOARDINT_NAND ++#define MT7621_NFIECC_IRQ_ID SURFBOARDINT_NAND_ECC ++ ++#define SURFBOARDINT_NAND 22 ++#define SURFBOARDINT_NAND_ECC 23 ++ ++static struct resource MT7621_resource_nand[] = { ++ { ++ .start = NFI_base, ++ .end = NFI_base + 0x1A0, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = NFIECC_base, ++ .end = NFIECC_base + 0x150, ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .start = MT7621_NFI_IRQ_ID, ++ .flags = IORESOURCE_IRQ, ++ }, ++ { ++ .start = MT7621_NFIECC_IRQ_ID, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device MT7621_nand_dev = { ++ .name = "MT7621-NAND", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(MT7621_resource_nand), ++ .resource = MT7621_resource_nand, ++ .dev = { ++ .platform_data = &mt7621_nand_hw, ++ }, ++}; ++ ++ ++int __init mtk_nand_register(void) ++{ ++ ++ int retval = 0; ++ ++ retval = platform_device_register(&MT7621_nand_dev); ++ if (retval != 0) { ++ printk(KERN_ERR "register nand device fail\n"); ++ return retval; ++ } ++ ++ ++ return retval; ++} ++arch_initcall(mtk_nand_register); +--- /dev/null ++++ b/drivers/mtd/nand/mt6575_typedefs.h +@@ -0,0 +1,340 @@ ++/* Copyright Statement: ++ * ++ * This software/firmware and related documentation ("MediaTek Software") are ++ * protected under relevant copyright laws. The information contained herein ++ * is confidential and proprietary to MediaTek Inc. and/or its licensors. ++ * Without the prior written permission of MediaTek inc. and/or its licensors, ++ * any reproduction, modification, use or disclosure of MediaTek Software, ++ * and information contained herein, in whole or in part, shall be strictly prohibited. ++ */ ++/* MediaTek Inc. (C) 2010. All rights reserved. ++ * ++ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES ++ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") ++ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON ++ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. ++ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ++ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR ++ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH ++ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES ++ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES ++ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK ++ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR ++ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND ++ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, ++ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, ++ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO ++ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. ++ * ++ * The following software/firmware and/or related documentation ("MediaTek Software") ++ * have been modified by MediaTek Inc. All revisions are subject to any receiver's ++ * applicable license agreements with MediaTek Inc. ++ */ ++ ++/***************************************************************************** ++* Copyright Statement: ++* -------------------- ++* This software is protected by Copyright and the information contained ++* herein is confidential. The software may not be copied and the information ++* contained herein may not be used or disclosed except with the written ++* permission of MediaTek Inc. (C) 2008 ++* ++* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES ++* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") ++* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON ++* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, ++* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF ++* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. ++* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ++* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR ++* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH ++* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO ++* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S ++* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. ++* ++* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE ++* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, ++* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, ++* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO ++* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. ++* ++* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE ++* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF ++* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND ++* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER ++* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC). ++* ++*****************************************************************************/ ++ ++#ifndef _MT6575_TYPEDEFS_H ++#define _MT6575_TYPEDEFS_H ++ ++#if defined (__KERNEL_NAND__) ++#include <linux/bug.h> ++#else ++#define true 1 ++#define false 0 ++#define bool u8 ++#endif ++ ++// --------------------------------------------------------------------------- ++// Basic Type Definitions ++// --------------------------------------------------------------------------- ++ ++typedef volatile unsigned char *P_kal_uint8; ++typedef volatile unsigned short *P_kal_uint16; ++typedef volatile unsigned int *P_kal_uint32; ++ ++typedef long LONG; ++typedef unsigned char UBYTE; ++typedef short SHORT; ++ ++typedef signed char kal_int8; ++typedef signed short kal_int16; ++typedef signed int kal_int32; ++typedef long long kal_int64; ++typedef unsigned char kal_uint8; ++typedef unsigned short kal_uint16; ++typedef unsigned int kal_uint32; ++typedef unsigned long long kal_uint64; ++typedef char kal_char; ++ ++typedef unsigned int *UINT32P; ++typedef volatile unsigned short *UINT16P; ++typedef volatile unsigned char *UINT8P; ++typedef unsigned char *U8P; ++ ++typedef volatile unsigned char *P_U8; ++typedef volatile signed char *P_S8; ++typedef volatile unsigned short *P_U16; ++typedef volatile signed short *P_S16; ++typedef volatile unsigned int *P_U32; ++typedef volatile signed int *P_S32; ++typedef unsigned long long *P_U64; ++typedef signed long long *P_S64; ++ ++typedef unsigned char U8; ++typedef signed char S8; ++typedef unsigned short U16; ++typedef signed short S16; ++typedef unsigned int U32; ++typedef signed int S32; ++typedef unsigned long long U64; ++typedef signed long long S64; ++//typedef unsigned char bool; ++ ++typedef unsigned char UINT8; ++typedef unsigned short UINT16; ++typedef unsigned int UINT32; ++typedef unsigned short USHORT; ++typedef signed char INT8; ++typedef signed short INT16; ++typedef signed int INT32; ++typedef unsigned int DWORD; ++typedef void VOID; ++typedef unsigned char BYTE; ++typedef float FLOAT; ++ ++typedef char *LPCSTR; ++typedef short *LPWSTR; ++ ++ ++// --------------------------------------------------------------------------- ++// Constants ++// --------------------------------------------------------------------------- ++ ++#define IMPORT EXTERN ++#ifndef __cplusplus ++ #define EXTERN extern ++#else ++ #define EXTERN extern "C" ++#endif ++#define LOCAL static ++#define GLOBAL ++#define EXPORT GLOBAL ++ ++#define EQ == ++#define NEQ != ++#define AND && ++#define OR || ++#define XOR(A,B) ((!(A) AND (B)) OR ((A) AND !(B))) ++ ++#ifndef FALSE ++ #define FALSE (0) ++#endif ++ ++#ifndef TRUE ++ #define TRUE (1) ++#endif ++ ++#ifndef NULL ++ #define NULL (0) ++#endif ++ ++//enum boolean {false, true}; ++enum {RX, TX, NONE}; ++ ++#ifndef BOOL ++typedef unsigned char BOOL; ++#endif ++ ++typedef enum { ++ KAL_FALSE = 0, ++ KAL_TRUE = 1, ++} kal_bool; ++ ++ ++// --------------------------------------------------------------------------- ++// Type Casting ++// --------------------------------------------------------------------------- ++ ++#define AS_INT32(x) (*(INT32 *)((void*)x)) ++#define AS_INT16(x) (*(INT16 *)((void*)x)) ++#define AS_INT8(x) (*(INT8 *)((void*)x)) ++ ++#define AS_UINT32(x) (*(UINT32 *)((void*)x)) ++#define AS_UINT16(x) (*(UINT16 *)((void*)x)) ++#define AS_UINT8(x) (*(UINT8 *)((void*)x)) ++ ++ ++// --------------------------------------------------------------------------- ++// Register Manipulations ++// --------------------------------------------------------------------------- ++ ++#define READ_REGISTER_UINT32(reg) \ ++ (*(volatile UINT32 * const)(reg)) ++ ++#define WRITE_REGISTER_UINT32(reg, val) \ ++ (*(volatile UINT32 * const)(reg)) = (val) ++ ++#define READ_REGISTER_UINT16(reg) \ ++ (*(volatile UINT16 * const)(reg)) ++ ++#define WRITE_REGISTER_UINT16(reg, val) \ ++ (*(volatile UINT16 * const)(reg)) = (val) ++ ++#define READ_REGISTER_UINT8(reg) \ ++ (*(volatile UINT8 * const)(reg)) ++ ++#define WRITE_REGISTER_UINT8(reg, val) \ ++ (*(volatile UINT8 * const)(reg)) = (val) ++ ++#define INREG8(x) READ_REGISTER_UINT8((UINT8*)((void*)(x))) ++#define OUTREG8(x, y) WRITE_REGISTER_UINT8((UINT8*)((void*)(x)), (UINT8)(y)) ++#define SETREG8(x, y) OUTREG8(x, INREG8(x)|(y)) ++#define CLRREG8(x, y) OUTREG8(x, INREG8(x)&~(y)) ++#define MASKREG8(x, y, z) OUTREG8(x, (INREG8(x)&~(y))|(z)) ++ ++#define INREG16(x) READ_REGISTER_UINT16((UINT16*)((void*)(x))) ++#define OUTREG16(x, y) WRITE_REGISTER_UINT16((UINT16*)((void*)(x)),(UINT16)(y)) ++#define SETREG16(x, y) OUTREG16(x, INREG16(x)|(y)) ++#define CLRREG16(x, y) OUTREG16(x, INREG16(x)&~(y)) ++#define MASKREG16(x, y, z) OUTREG16(x, (INREG16(x)&~(y))|(z)) ++ ++#define INREG32(x) READ_REGISTER_UINT32((UINT32*)((void*)(x))) ++#define OUTREG32(x, y) WRITE_REGISTER_UINT32((UINT32*)((void*)(x)), (UINT32)(y)) ++#define SETREG32(x, y) OUTREG32(x, INREG32(x)|(y)) ++#define CLRREG32(x, y) OUTREG32(x, INREG32(x)&~(y)) ++#define MASKREG32(x, y, z) OUTREG32(x, (INREG32(x)&~(y))|(z)) ++ ++ ++#define DRV_Reg8(addr) INREG8(addr) ++#define DRV_WriteReg8(addr, data) OUTREG8(addr, data) ++#define DRV_SetReg8(addr, data) SETREG8(addr, data) ++#define DRV_ClrReg8(addr, data) CLRREG8(addr, data) ++ ++#define DRV_Reg16(addr) INREG16(addr) ++#define DRV_WriteReg16(addr, data) OUTREG16(addr, data) ++#define DRV_SetReg16(addr, data) SETREG16(addr, data) ++#define DRV_ClrReg16(addr, data) CLRREG16(addr, data) ++ ++#define DRV_Reg32(addr) INREG32(addr) ++#define DRV_WriteReg32(addr, data) OUTREG32(addr, data) ++#define DRV_SetReg32(addr, data) SETREG32(addr, data) ++#define DRV_ClrReg32(addr, data) CLRREG32(addr, data) ++ ++// !!! DEPRECATED, WILL BE REMOVED LATER !!! ++#define DRV_Reg(addr) DRV_Reg16(addr) ++#define DRV_WriteReg(addr, data) DRV_WriteReg16(addr, data) ++#define DRV_SetReg(addr, data) DRV_SetReg16(addr, data) ++#define DRV_ClrReg(addr, data) DRV_ClrReg16(addr, data) ++ ++ ++// --------------------------------------------------------------------------- ++// Compiler Time Deduction Macros ++// --------------------------------------------------------------------------- ++ ++#define _MASK_OFFSET_1(x, n) ((x) & 0x1) ? (n) : ++#define _MASK_OFFSET_2(x, n) _MASK_OFFSET_1((x), (n)) _MASK_OFFSET_1((x) >> 1, (n) + 1) ++#define _MASK_OFFSET_4(x, n) _MASK_OFFSET_2((x), (n)) _MASK_OFFSET_2((x) >> 2, (n) + 2) ++#define _MASK_OFFSET_8(x, n) _MASK_OFFSET_4((x), (n)) _MASK_OFFSET_4((x) >> 4, (n) + 4) ++#define _MASK_OFFSET_16(x, n) _MASK_OFFSET_8((x), (n)) _MASK_OFFSET_8((x) >> 8, (n) + 8) ++#define _MASK_OFFSET_32(x, n) _MASK_OFFSET_16((x), (n)) _MASK_OFFSET_16((x) >> 16, (n) + 16) ++ ++#define MASK_OFFSET_ERROR (0xFFFFFFFF) ++ ++#define MASK_OFFSET(x) (_MASK_OFFSET_32(x, 0) MASK_OFFSET_ERROR) ++ ++ ++// --------------------------------------------------------------------------- ++// Assertions ++// --------------------------------------------------------------------------- ++ ++#ifndef ASSERT ++ #define ASSERT(expr) BUG_ON(!(expr)) ++#endif ++ ++#ifndef NOT_IMPLEMENTED ++ #define NOT_IMPLEMENTED() BUG_ON(1) ++#endif ++ ++#define STATIC_ASSERT(pred) STATIC_ASSERT_X(pred, __LINE__) ++#define STATIC_ASSERT_X(pred, line) STATIC_ASSERT_XX(pred, line) ++#define STATIC_ASSERT_XX(pred, line) \ ++ extern char assertion_failed_at_##line[(pred) ? 1 : -1] ++ ++// --------------------------------------------------------------------------- ++// Resolve Compiler Warnings ++// --------------------------------------------------------------------------- ++ ++#define NOT_REFERENCED(x) { (x) = (x); } ++ ++ ++// --------------------------------------------------------------------------- ++// Utilities ++// --------------------------------------------------------------------------- ++ ++#define MAXIMUM(A,B) (((A)>(B))?(A):(B)) ++#define MINIMUM(A,B) (((A)<(B))?(A):(B)) ++ ++#define ARY_SIZE(x) (sizeof((x)) / sizeof((x[0]))) ++#define DVT_DELAYMACRO(u4Num) \ ++{ \ ++ UINT32 u4Count = 0 ; \ ++ for (u4Count = 0; u4Count < u4Num; u4Count++ ); \ ++} \ ++ ++#define A68351B 0 ++#define B68351B 1 ++#define B68351D 2 ++#define B68351E 3 ++#define UNKNOWN_IC_VERSION 0xFF ++ ++/* NAND driver */ ++struct mtk_nand_host_hw { ++ unsigned int nfi_bus_width; /* NFI_BUS_WIDTH */ ++ unsigned int nfi_access_timing; /* NFI_ACCESS_TIMING */ ++ unsigned int nfi_cs_num; /* NFI_CS_NUM */ ++ unsigned int nand_sec_size; /* NAND_SECTOR_SIZE */ ++ unsigned int nand_sec_shift; /* NAND_SECTOR_SHIFT */ ++ unsigned int nand_ecc_size; ++ unsigned int nand_ecc_bytes; ++ unsigned int nand_ecc_mode; ++}; ++extern struct mtk_nand_host_hw mt7621_nand_hw; ++extern unsigned int CFG_BLOCKSIZE; ++ ++#endif // _MT6575_TYPEDEFS_H ++ +--- /dev/null ++++ b/drivers/mtd/nand/mtk_nand.c +@@ -0,0 +1,2304 @@ ++/****************************************************************************** ++* mtk_nand.c - MTK NAND Flash Device Driver ++ * ++* Copyright 2009-2012 MediaTek Co.,Ltd. ++ * ++* DESCRIPTION: ++* This file provid the other drivers nand relative functions ++ * ++* modification history ++* ---------------------------------------- ++* v3.0, 11 Feb 2010, mtk ++* ---------------------------------------- ++******************************************************************************/ ++#include "nand_def.h" ++#include <linux/slab.h> ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/delay.h> ++#include <linux/errno.h> ++#include <linux/sched.h> ++#include <linux/types.h> ++#include <linux/wait.h> ++#include <linux/spinlock.h> ++#include <linux/interrupt.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/nand.h> ++#include <linux/mtd/partitions.h> ++#include <linux/mtd/nand_ecc.h> ++#include <linux/dma-mapping.h> ++#include <linux/jiffies.h> ++#include <linux/platform_device.h> ++#include <linux/proc_fs.h> ++#include <linux/time.h> ++#include <linux/mm.h> ++#include <asm/io.h> ++#include <asm/cacheflush.h> ++#include <asm/uaccess.h> ++#include <linux/miscdevice.h> ++#include "mtk_nand.h" ++#include "nand_device_list.h" ++ ++#include "bmt.h" ++#include "partition.h" ++ ++unsigned int CFG_BLOCKSIZE; ++ ++static int shift_on_bbt = 0; ++extern void nand_bbt_set(struct mtd_info *mtd, int page, int flag); ++extern int nand_bbt_get(struct mtd_info *mtd, int page); ++int mtk_nand_read_oob_hw(struct mtd_info *mtd, struct nand_chip *chip, int page); ++ ++static const char * const probe_types[] = { "cmdlinepart", "ofpart", NULL }; ++ ++#define NAND_CMD_STATUS_MULTI 0x71 ++ ++void show_stack(struct task_struct *tsk, unsigned long *sp); ++extern void mt_irq_set_sens(unsigned int irq, unsigned int sens); ++extern void mt_irq_set_polarity(unsigned int irq,unsigned int polarity); ++ ++struct mtk_nand_host mtk_nand_host; /* include mtd_info and nand_chip structs */ ++struct mtk_nand_host_hw mt7621_nand_hw = { ++ .nfi_bus_width = 8, ++ .nfi_access_timing = NFI_DEFAULT_ACCESS_TIMING, ++ .nfi_cs_num = NFI_CS_NUM, ++ .nand_sec_size = 512, ++ .nand_sec_shift = 9, ++ .nand_ecc_size = 2048, ++ .nand_ecc_bytes = 32, ++ .nand_ecc_mode = NAND_ECC_HW, ++}; ++ ++ ++/******************************************************************************* ++ * Gloable Varible Definition ++ *******************************************************************************/ ++ ++#define NFI_ISSUE_COMMAND(cmd, col_addr, row_addr, col_num, row_num) \ ++ do { \ ++ DRV_WriteReg(NFI_CMD_REG16,cmd);\ ++ while (DRV_Reg32(NFI_STA_REG32) & STA_CMD_STATE);\ ++ DRV_WriteReg32(NFI_COLADDR_REG32, col_addr);\ ++ DRV_WriteReg32(NFI_ROWADDR_REG32, row_addr);\ ++ DRV_WriteReg(NFI_ADDRNOB_REG16, col_num | (row_num<<ADDR_ROW_NOB_SHIFT));\ ++ while (DRV_Reg32(NFI_STA_REG32) & STA_ADDR_STATE);\ ++ }while(0); ++ ++//------------------------------------------------------------------------------- ++static struct NAND_CMD g_kCMD; ++static u32 g_u4ChipVer; ++bool g_bInitDone; ++static bool g_bcmdstatus; ++static u32 g_value = 0; ++static int g_page_size; ++ ++BOOL g_bHwEcc = true; ++ ++ ++static u8 *local_buffer_16_align; // 16 byte aligned buffer, for HW issue ++static u8 local_buffer[4096 + 512]; ++ ++extern void nand_release_device(struct mtd_info *mtd); ++extern int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state); ++ ++#if defined(MTK_NAND_BMT) ++static bmt_struct *g_bmt; ++#endif ++struct mtk_nand_host *host; ++extern struct mtd_partition g_pasStatic_Partition[]; ++int part_num = NUM_PARTITIONS; ++int manu_id; ++int dev_id; ++ ++static u8 local_oob_buf[NAND_MAX_OOBSIZE]; ++ ++static u8 nand_badblock_offset = 0; ++ ++void nand_enable_clock(void) ++{ ++ //enable_clock(MT65XX_PDN_PERI_NFI, "NAND"); ++} ++ ++void nand_disable_clock(void) ++{ ++ //disable_clock(MT65XX_PDN_PERI_NFI, "NAND"); ++} ++ ++static struct nand_ecclayout nand_oob_16 = { ++ .eccbytes = 8, ++ .eccpos = {8, 9, 10, 11, 12, 13, 14, 15}, ++ .oobfree = {{1, 6}, {0, 0}} ++}; ++ ++struct nand_ecclayout nand_oob_64 = { ++ .eccbytes = 32, ++ .eccpos = {32, 33, 34, 35, 36, 37, 38, 39, ++ 40, 41, 42, 43, 44, 45, 46, 47, ++ 48, 49, 50, 51, 52, 53, 54, 55, ++ 56, 57, 58, 59, 60, 61, 62, 63}, ++ .oobfree = {{1, 7}, {9, 7}, {17, 7}, {25, 6}, {0, 0}} ++}; ++ ++struct nand_ecclayout nand_oob_128 = { ++ .eccbytes = 64, ++ .eccpos = { ++ 64, 65, 66, 67, 68, 69, 70, 71, ++ 72, 73, 74, 75, 76, 77, 78, 79, ++ 80, 81, 82, 83, 84, 85, 86, 86, ++ 88, 89, 90, 91, 92, 93, 94, 95, ++ 96, 97, 98, 99, 100, 101, 102, 103, ++ 104, 105, 106, 107, 108, 109, 110, 111, ++ 112, 113, 114, 115, 116, 117, 118, 119, ++ 120, 121, 122, 123, 124, 125, 126, 127}, ++ .oobfree = {{1, 7}, {9, 7}, {17, 7}, {25, 7}, {33, 7}, {41, 7}, {49, 7}, {57, 6}} ++}; ++ ++flashdev_info devinfo; ++ ++void dump_nfi(void) ++{ ++} ++ ++void dump_ecc(void) ++{ ++} ++ ++u32 ++nand_virt_to_phys_add(u32 va) ++{ ++ u32 pageOffset = (va & (PAGE_SIZE - 1)); ++ pgd_t *pgd; ++ pmd_t *pmd; ++ pte_t *pte; ++ u32 pa; ++ ++ if (virt_addr_valid(va)) ++ return __virt_to_phys(va); ++ ++ if (NULL == current) { ++ printk(KERN_ERR "[nand_virt_to_phys_add] ERROR ,current is NULL! \n"); ++ return 0; ++ } ++ ++ if (NULL == current->mm) { ++ printk(KERN_ERR "[nand_virt_to_phys_add] ERROR current->mm is NULL! tgid=0x%x, name=%s \n", current->tgid, current->comm); ++ return 0; ++ } ++ ++ pgd = pgd_offset(current->mm, va); /* what is tsk->mm */ ++ if (pgd_none(*pgd) || pgd_bad(*pgd)) { ++ printk(KERN_ERR "[nand_virt_to_phys_add] ERROR, va=0x%x, pgd invalid! \n", va); ++ return 0; ++ } ++ ++ pmd = pmd_offset((pud_t *)pgd, va); ++ if (pmd_none(*pmd) || pmd_bad(*pmd)) { ++ printk(KERN_ERR "[nand_virt_to_phys_add] ERROR, va=0x%x, pmd invalid! \n", va); ++ return 0; ++ } ++ ++ pte = pte_offset_map(pmd, va); ++ if (pte_present(*pte)) { ++ pa = (pte_val(*pte) & (PAGE_MASK)) | pageOffset; ++ return pa; ++ } ++ ++ printk(KERN_ERR "[nand_virt_to_phys_add] ERROR va=0x%x, pte invalid! \n", va); ++ return 0; ++} ++EXPORT_SYMBOL(nand_virt_to_phys_add); ++ ++bool ++get_device_info(u16 id, u32 ext_id, flashdev_info * pdevinfo) ++{ ++ u32 index; ++ for (index = 0; gen_FlashTable[index].id != 0; index++) { ++ if (id == gen_FlashTable[index].id && ext_id == gen_FlashTable[index].ext_id) { ++ pdevinfo->id = gen_FlashTable[index].id; ++ pdevinfo->ext_id = gen_FlashTable[index].ext_id; ++ pdevinfo->blocksize = gen_FlashTable[index].blocksize; ++ pdevinfo->addr_cycle = gen_FlashTable[index].addr_cycle; ++ pdevinfo->iowidth = gen_FlashTable[index].iowidth; ++ pdevinfo->timmingsetting = gen_FlashTable[index].timmingsetting; ++ pdevinfo->advancedmode = gen_FlashTable[index].advancedmode; ++ pdevinfo->pagesize = gen_FlashTable[index].pagesize; ++ pdevinfo->sparesize = gen_FlashTable[index].sparesize; ++ pdevinfo->totalsize = gen_FlashTable[index].totalsize; ++ memcpy(pdevinfo->devciename, gen_FlashTable[index].devciename, sizeof(pdevinfo->devciename)); ++ printk(KERN_INFO "Device found in MTK table, ID: %x, EXT_ID: %x\n", id, ext_id); ++ ++ goto find; ++ } ++ } ++ ++find: ++ if (0 == pdevinfo->id) { ++ printk(KERN_INFO "Device not found, ID: %x\n", id); ++ return false; ++ } else { ++ return true; ++ } ++} ++ ++static void ++ECC_Config(struct mtk_nand_host_hw *hw,u32 ecc_bit) ++{ ++ u32 u4ENCODESize; ++ u32 u4DECODESize; ++ u32 ecc_bit_cfg = ECC_CNFG_ECC4; ++ ++ switch(ecc_bit){ ++ case 4: ++ ecc_bit_cfg = ECC_CNFG_ECC4; ++ break; ++ case 8: ++ ecc_bit_cfg = ECC_CNFG_ECC8; ++ break; ++ case 10: ++ ecc_bit_cfg = ECC_CNFG_ECC10; ++ break; ++ case 12: ++ ecc_bit_cfg = ECC_CNFG_ECC12; ++ break; ++ default: ++ break; ++ } ++ DRV_WriteReg16(ECC_DECCON_REG16, DEC_DE); ++ do { ++ } while (!DRV_Reg16(ECC_DECIDLE_REG16)); ++ ++ DRV_WriteReg16(ECC_ENCCON_REG16, ENC_DE); ++ do { ++ } while (!DRV_Reg32(ECC_ENCIDLE_REG32)); ++ ++ /* setup FDM register base */ ++ DRV_WriteReg32(ECC_FDMADDR_REG32, NFI_FDM0L_REG32); ++ ++ /* Sector + FDM */ ++ u4ENCODESize = (hw->nand_sec_size + 8) << 3; ++ /* Sector + FDM + YAFFS2 meta data bits */ ++ u4DECODESize = ((hw->nand_sec_size + 8) << 3) + ecc_bit * 13; ++ ++ /* configure ECC decoder && encoder */ ++ DRV_WriteReg32(ECC_DECCNFG_REG32, ecc_bit_cfg | DEC_CNFG_NFI | DEC_CNFG_EMPTY_EN | (u4DECODESize << DEC_CNFG_CODE_SHIFT)); ++ ++ DRV_WriteReg32(ECC_ENCCNFG_REG32, ecc_bit_cfg | ENC_CNFG_NFI | (u4ENCODESize << ENC_CNFG_MSG_SHIFT)); ++ NFI_SET_REG32(ECC_DECCNFG_REG32, DEC_CNFG_EL); ++} ++ ++static void ++ECC_Decode_Start(void) ++{ ++ while (!(DRV_Reg16(ECC_DECIDLE_REG16) & DEC_IDLE)) ++ ; ++ DRV_WriteReg16(ECC_DECCON_REG16, DEC_EN); ++} ++ ++static void ++ECC_Decode_End(void) ++{ ++ while (!(DRV_Reg16(ECC_DECIDLE_REG16) & DEC_IDLE)) ++ ; ++ DRV_WriteReg16(ECC_DECCON_REG16, DEC_DE); ++} ++ ++static void ++ECC_Encode_Start(void) ++{ ++ while (!(DRV_Reg32(ECC_ENCIDLE_REG32) & ENC_IDLE)) ++ ; ++ mb(); ++ DRV_WriteReg16(ECC_ENCCON_REG16, ENC_EN); ++} ++ ++static void ++ECC_Encode_End(void) ++{ ++ /* wait for device returning idle */ ++ while (!(DRV_Reg32(ECC_ENCIDLE_REG32) & ENC_IDLE)) ; ++ mb(); ++ DRV_WriteReg16(ECC_ENCCON_REG16, ENC_DE); ++} ++ ++static bool ++mtk_nand_check_bch_error(struct mtd_info *mtd, u8 * pDataBuf, u32 u4SecIndex, u32 u4PageAddr) ++{ ++ bool bRet = true; ++ u16 u2SectorDoneMask = 1 << u4SecIndex; ++ u32 u4ErrorNumDebug, i, u4ErrNum; ++ u32 timeout = 0xFFFF; ++ // int el; ++ u32 au4ErrBitLoc[6]; ++ u32 u4ErrByteLoc, u4BitOffset; ++ u32 u4ErrBitLoc1th, u4ErrBitLoc2nd; ++ ++ //4 // Wait for Decode Done ++ while (0 == (u2SectorDoneMask & DRV_Reg16(ECC_DECDONE_REG16))) { ++ timeout--; ++ if (0 == timeout) ++ return false; ++ } ++ /* We will manually correct the error bits in the last sector, not all the sectors of the page! */ ++ memset(au4ErrBitLoc, 0x0, sizeof(au4ErrBitLoc)); ++ u4ErrorNumDebug = DRV_Reg32(ECC_DECENUM_REG32); ++ u4ErrNum = DRV_Reg32(ECC_DECENUM_REG32) >> (u4SecIndex << 2); ++ u4ErrNum &= 0xF; ++ ++ if (u4ErrNum) { ++ if (0xF == u4ErrNum) { ++ mtd->ecc_stats.failed++; ++ bRet = false; ++ //printk(KERN_ERR"UnCorrectable at PageAddr=%d\n", u4PageAddr); ++ } else { ++ for (i = 0; i < ((u4ErrNum + 1) >> 1); ++i) { ++ au4ErrBitLoc[i] = DRV_Reg32(ECC_DECEL0_REG32 + i); ++ u4ErrBitLoc1th = au4ErrBitLoc[i] & 0x1FFF; ++ if (u4ErrBitLoc1th < 0x1000) { ++ u4ErrByteLoc = u4ErrBitLoc1th / 8; ++ u4BitOffset = u4ErrBitLoc1th % 8; ++ pDataBuf[u4ErrByteLoc] = pDataBuf[u4ErrByteLoc] ^ (1 << u4BitOffset); ++ mtd->ecc_stats.corrected++; ++ } else { ++ mtd->ecc_stats.failed++; ++ } ++ u4ErrBitLoc2nd = (au4ErrBitLoc[i] >> 16) & 0x1FFF; ++ if (0 != u4ErrBitLoc2nd) { ++ if (u4ErrBitLoc2nd < 0x1000) { ++ u4ErrByteLoc = u4ErrBitLoc2nd / 8; ++ u4BitOffset = u4ErrBitLoc2nd % 8; ++ pDataBuf[u4ErrByteLoc] = pDataBuf[u4ErrByteLoc] ^ (1 << u4BitOffset); ++ mtd->ecc_stats.corrected++; ++ } else { ++ mtd->ecc_stats.failed++; ++ //printk(KERN_ERR"UnCorrectable High ErrLoc=%d\n", au4ErrBitLoc[i]); ++ } ++ } ++ } ++ } ++ if (0 == (DRV_Reg16(ECC_DECFER_REG16) & (1 << u4SecIndex))) ++ bRet = false; ++ } ++ return bRet; ++} ++ ++static bool ++mtk_nand_RFIFOValidSize(u16 u2Size) ++{ ++ u32 timeout = 0xFFFF; ++ while (FIFO_RD_REMAIN(DRV_Reg16(NFI_FIFOSTA_REG16)) < u2Size) { ++ timeout--; ++ if (0 == timeout) ++ return false; ++ } ++ return true; ++} ++ ++static bool ++mtk_nand_WFIFOValidSize(u16 u2Size) ++{ ++ u32 timeout = 0xFFFF; ++ ++ while (FIFO_WR_REMAIN(DRV_Reg16(NFI_FIFOSTA_REG16)) > u2Size) { ++ timeout--; ++ if (0 == timeout) ++ return false; ++ } ++ return true; ++} ++ ++static bool ++mtk_nand_status_ready(u32 u4Status) ++{ ++ u32 timeout = 0xFFFF; ++ ++ while ((DRV_Reg32(NFI_STA_REG32) & u4Status) != 0) { ++ timeout--; ++ if (0 == timeout) ++ return false; ++ } ++ return true; ++} ++ ++static bool ++mtk_nand_reset(void) ++{ ++ int timeout = 0xFFFF; ++ if (DRV_Reg16(NFI_MASTERSTA_REG16)) { ++ mb(); ++ DRV_WriteReg16(NFI_CON_REG16, CON_FIFO_FLUSH | CON_NFI_RST); ++ while (DRV_Reg16(NFI_MASTERSTA_REG16)) { ++ timeout--; ++ if (!timeout) ++ MSG(INIT, "Wait for NFI_MASTERSTA timeout\n"); ++ } ++ } ++ /* issue reset operation */ ++ mb(); ++ DRV_WriteReg16(NFI_CON_REG16, CON_FIFO_FLUSH | CON_NFI_RST); ++ ++ return mtk_nand_status_ready(STA_NFI_FSM_MASK | STA_NAND_BUSY) && mtk_nand_RFIFOValidSize(0) && mtk_nand_WFIFOValidSize(0); ++} ++ ++static void ++mtk_nand_set_mode(u16 u2OpMode) ++{ ++ u16 u2Mode = DRV_Reg16(NFI_CNFG_REG16); ++ u2Mode &= ~CNFG_OP_MODE_MASK; ++ u2Mode |= u2OpMode; ++ DRV_WriteReg16(NFI_CNFG_REG16, u2Mode); ++} ++ ++static void ++mtk_nand_set_autoformat(bool bEnable) ++{ ++ if (bEnable) ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_AUTO_FMT_EN); ++ else ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AUTO_FMT_EN); ++} ++ ++static void ++mtk_nand_configure_fdm(u16 u2FDMSize) ++{ ++ NFI_CLN_REG16(NFI_PAGEFMT_REG16, PAGEFMT_FDM_MASK | PAGEFMT_FDM_ECC_MASK); ++ NFI_SET_REG16(NFI_PAGEFMT_REG16, u2FDMSize << PAGEFMT_FDM_SHIFT); ++ NFI_SET_REG16(NFI_PAGEFMT_REG16, u2FDMSize << PAGEFMT_FDM_ECC_SHIFT); ++} ++ ++static void ++mtk_nand_configure_lock(void) ++{ ++ u32 u4WriteColNOB = 2; ++ u32 u4WriteRowNOB = 3; ++ u32 u4EraseColNOB = 0; ++ u32 u4EraseRowNOB = 3; ++ DRV_WriteReg16(NFI_LOCKANOB_REG16, ++ (u4WriteColNOB << PROG_CADD_NOB_SHIFT) | (u4WriteRowNOB << PROG_RADD_NOB_SHIFT) | (u4EraseColNOB << ERASE_CADD_NOB_SHIFT) | (u4EraseRowNOB << ERASE_RADD_NOB_SHIFT)); ++ ++ if (CHIPVER_ECO_1 == g_u4ChipVer) { ++ int i; ++ for (i = 0; i < 16; ++i) { ++ DRV_WriteReg32(NFI_LOCK00ADD_REG32 + (i << 1), 0xFFFFFFFF); ++ DRV_WriteReg32(NFI_LOCK00FMT_REG32 + (i << 1), 0xFFFFFFFF); ++ } ++ //DRV_WriteReg16(NFI_LOCKANOB_REG16, 0x0); ++ DRV_WriteReg32(NFI_LOCKCON_REG32, 0xFFFFFFFF); ++ DRV_WriteReg16(NFI_LOCK_REG16, NFI_LOCK_ON); ++ } ++} ++ ++static bool ++mtk_nand_pio_ready(void) ++{ ++ int count = 0; ++ while (!(DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1)) { ++ count++; ++ if (count > 0xffff) { ++ printk("PIO_DIRDY timeout\n"); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ ++static bool ++mtk_nand_set_command(u16 command) ++{ ++ mb(); ++ DRV_WriteReg16(NFI_CMD_REG16, command); ++ return mtk_nand_status_ready(STA_CMD_STATE); ++} ++ ++static bool ++mtk_nand_set_address(u32 u4ColAddr, u32 u4RowAddr, u16 u2ColNOB, u16 u2RowNOB) ++{ ++ mb(); ++ DRV_WriteReg32(NFI_COLADDR_REG32, u4ColAddr); ++ DRV_WriteReg32(NFI_ROWADDR_REG32, u4RowAddr); ++ DRV_WriteReg16(NFI_ADDRNOB_REG16, u2ColNOB | (u2RowNOB << ADDR_ROW_NOB_SHIFT)); ++ return mtk_nand_status_ready(STA_ADDR_STATE); ++} ++ ++static bool ++mtk_nand_check_RW_count(u16 u2WriteSize) ++{ ++ u32 timeout = 0xFFFF; ++ u16 u2SecNum = u2WriteSize >> 9; ++ ++ while (ADDRCNTR_CNTR(DRV_Reg16(NFI_ADDRCNTR_REG16)) < u2SecNum) { ++ timeout--; ++ if (0 == timeout) { ++ printk(KERN_INFO "[%s] timeout\n", __FUNCTION__); ++ return false; ++ } ++ } ++ return true; ++} ++ ++static bool ++mtk_nand_ready_for_read(struct nand_chip *nand, u32 u4RowAddr, u32 u4ColAddr, bool full, u8 * buf) ++{ ++ /* Reset NFI HW internal state machine and flush NFI in/out FIFO */ ++ bool bRet = false; ++ u16 sec_num = 1 << (nand->page_shift - 9); ++ u32 col_addr = u4ColAddr; ++ u32 colnob = 2, rownob = devinfo.addr_cycle - 2; ++ if (nand->options & NAND_BUSWIDTH_16) ++ col_addr /= 2; ++ ++ if (!mtk_nand_reset()) ++ goto cleanup; ++ if (g_bHwEcc) { ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ } else { ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ } ++ ++ mtk_nand_set_mode(CNFG_OP_READ); ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_READ_EN); ++ DRV_WriteReg16(NFI_CON_REG16, sec_num << CON_NFI_SEC_SHIFT); ++ ++ if (full) { ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ ++ if (g_bHwEcc) ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ else ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ } else { ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ } ++ ++ mtk_nand_set_autoformat(full); ++ if (full) ++ if (g_bHwEcc) ++ ECC_Decode_Start(); ++ if (!mtk_nand_set_command(NAND_CMD_READ0)) ++ goto cleanup; ++ if (!mtk_nand_set_address(col_addr, u4RowAddr, colnob, rownob)) ++ goto cleanup; ++ if (!mtk_nand_set_command(NAND_CMD_READSTART)) ++ goto cleanup; ++ if (!mtk_nand_status_ready(STA_NAND_BUSY)) ++ goto cleanup; ++ ++ bRet = true; ++ ++cleanup: ++ return bRet; ++} ++ ++static bool ++mtk_nand_ready_for_write(struct nand_chip *nand, u32 u4RowAddr, u32 col_addr, bool full, u8 * buf) ++{ ++ bool bRet = false; ++ u32 sec_num = 1 << (nand->page_shift - 9); ++ u32 colnob = 2, rownob = devinfo.addr_cycle - 2; ++ if (nand->options & NAND_BUSWIDTH_16) ++ col_addr /= 2; ++ ++ /* Reset NFI HW internal state machine and flush NFI in/out FIFO */ ++ if (!mtk_nand_reset()) ++ return false; ++ ++ mtk_nand_set_mode(CNFG_OP_PRGM); ++ ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_READ_EN); ++ ++ DRV_WriteReg16(NFI_CON_REG16, sec_num << CON_NFI_SEC_SHIFT); ++ ++ if (full) { ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ if (g_bHwEcc) ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ else ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ } else { ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ } ++ ++ mtk_nand_set_autoformat(full); ++ ++ if (full) ++ if (g_bHwEcc) ++ ECC_Encode_Start(); ++ ++ if (!mtk_nand_set_command(NAND_CMD_SEQIN)) ++ goto cleanup; ++ //1 FIXED ME: For Any Kind of AddrCycle ++ if (!mtk_nand_set_address(col_addr, u4RowAddr, colnob, rownob)) ++ goto cleanup; ++ ++ if (!mtk_nand_status_ready(STA_NAND_BUSY)) ++ goto cleanup; ++ ++ bRet = true; ++ ++cleanup: ++ return bRet; ++} ++ ++static bool ++mtk_nand_check_dececc_done(u32 u4SecNum) ++{ ++ u32 timeout, dec_mask; ++ ++ timeout = 0xffff; ++ dec_mask = (1 << u4SecNum) - 1; ++ while ((dec_mask != DRV_Reg(ECC_DECDONE_REG16)) && timeout > 0) ++ timeout--; ++ if (timeout == 0) { ++ MSG(VERIFY, "ECC_DECDONE: timeout\n"); ++ return false; ++ } ++ return true; ++} ++ ++static bool ++mtk_nand_mcu_read_data(u8 * buf, u32 length) ++{ ++ int timeout = 0xffff; ++ u32 i; ++ u32 *buf32 = (u32 *) buf; ++ if ((u32) buf % 4 || length % 4) ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); ++ else ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); ++ ++ //DRV_WriteReg32(NFI_STRADDR_REG32, 0); ++ mb(); ++ NFI_SET_REG16(NFI_CON_REG16, CON_NFI_BRD); ++ ++ if ((u32) buf % 4 || length % 4) { ++ for (i = 0; (i < (length)) && (timeout > 0);) { ++ if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1) { ++ *buf++ = (u8) DRV_Reg32(NFI_DATAR_REG32); ++ i++; ++ } else { ++ timeout--; ++ } ++ if (0 == timeout) { ++ printk(KERN_ERR "[%s] timeout\n", __FUNCTION__); ++ dump_nfi(); ++ return false; ++ } ++ } ++ } else { ++ for (i = 0; (i < (length >> 2)) && (timeout > 0);) { ++ if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1) { ++ *buf32++ = DRV_Reg32(NFI_DATAR_REG32); ++ i++; ++ } else { ++ timeout--; ++ } ++ if (0 == timeout) { ++ printk(KERN_ERR "[%s] timeout\n", __FUNCTION__); ++ dump_nfi(); ++ return false; ++ } ++ } ++ } ++ return true; ++} ++ ++static bool ++mtk_nand_read_page_data(struct mtd_info *mtd, u8 * pDataBuf, u32 u4Size) ++{ ++ return mtk_nand_mcu_read_data(pDataBuf, u4Size); ++} ++ ++static bool ++mtk_nand_mcu_write_data(struct mtd_info *mtd, const u8 * buf, u32 length) ++{ ++ u32 timeout = 0xFFFF; ++ u32 i; ++ u32 *pBuf32; ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); ++ mb(); ++ NFI_SET_REG16(NFI_CON_REG16, CON_NFI_BWR); ++ pBuf32 = (u32 *) buf; ++ ++ if ((u32) buf % 4 || length % 4) ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); ++ else ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); ++ ++ if ((u32) buf % 4 || length % 4) { ++ for (i = 0; (i < (length)) && (timeout > 0);) { ++ if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1) { ++ DRV_WriteReg32(NFI_DATAW_REG32, *buf++); ++ i++; ++ } else { ++ timeout--; ++ } ++ if (0 == timeout) { ++ printk(KERN_ERR "[%s] timeout\n", __FUNCTION__); ++ dump_nfi(); ++ return false; ++ } ++ } ++ } else { ++ for (i = 0; (i < (length >> 2)) && (timeout > 0);) { ++ if (DRV_Reg16(NFI_PIO_DIRDY_REG16) & 1) { ++ DRV_WriteReg32(NFI_DATAW_REG32, *pBuf32++); ++ i++; ++ } else { ++ timeout--; ++ } ++ if (0 == timeout) { ++ printk(KERN_ERR "[%s] timeout\n", __FUNCTION__); ++ dump_nfi(); ++ return false; ++ } ++ } ++ } ++ ++ return true; ++} ++ ++static bool ++mtk_nand_write_page_data(struct mtd_info *mtd, u8 * buf, u32 size) ++{ ++ return mtk_nand_mcu_write_data(mtd, buf, size); ++} ++ ++static void ++mtk_nand_read_fdm_data(u8 * pDataBuf, u32 u4SecNum) ++{ ++ u32 i; ++ u32 *pBuf32 = (u32 *) pDataBuf; ++ ++ if (pBuf32) { ++ for (i = 0; i < u4SecNum; ++i) { ++ *pBuf32++ = DRV_Reg32(NFI_FDM0L_REG32 + (i << 1)); ++ *pBuf32++ = DRV_Reg32(NFI_FDM0M_REG32 + (i << 1)); ++ } ++ } ++} ++ ++static u8 fdm_buf[64]; ++static void ++mtk_nand_write_fdm_data(struct nand_chip *chip, u8 * pDataBuf, u32 u4SecNum) ++{ ++ u32 i, j; ++ u8 checksum = 0; ++ bool empty = true; ++ struct nand_oobfree *free_entry; ++ u32 *pBuf32; ++ ++ memcpy(fdm_buf, pDataBuf, u4SecNum * 8); ++ ++ free_entry = chip->ecc.layout->oobfree; ++ for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES && free_entry[i].length; i++) { ++ for (j = 0; j < free_entry[i].length; j++) { ++ if (pDataBuf[free_entry[i].offset + j] != 0xFF) ++ empty = false; ++ checksum ^= pDataBuf[free_entry[i].offset + j]; ++ } ++ } ++ ++ if (!empty) { ++ fdm_buf[free_entry[i - 1].offset + free_entry[i - 1].length] = checksum; ++ } ++ ++ pBuf32 = (u32 *) fdm_buf; ++ for (i = 0; i < u4SecNum; ++i) { ++ DRV_WriteReg32(NFI_FDM0L_REG32 + (i << 1), *pBuf32++); ++ DRV_WriteReg32(NFI_FDM0M_REG32 + (i << 1), *pBuf32++); ++ } ++} ++ ++static void ++mtk_nand_stop_read(void) ++{ ++ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_BRD); ++ mtk_nand_reset(); ++ if (g_bHwEcc) ++ ECC_Decode_End(); ++ DRV_WriteReg16(NFI_INTR_EN_REG16, 0); ++} ++ ++static void ++mtk_nand_stop_write(void) ++{ ++ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_BWR); ++ if (g_bHwEcc) ++ ECC_Encode_End(); ++ DRV_WriteReg16(NFI_INTR_EN_REG16, 0); ++} ++ ++bool ++mtk_nand_exec_read_page(struct mtd_info *mtd, u32 u4RowAddr, u32 u4PageSize, u8 * pPageBuf, u8 * pFDMBuf) ++{ ++ u8 *buf; ++ bool bRet = true; ++ struct nand_chip *nand = mtd->priv; ++ u32 u4SecNum = u4PageSize >> 9; ++ ++ if (((u32) pPageBuf % 16) && local_buffer_16_align) ++ buf = local_buffer_16_align; ++ else ++ buf = pPageBuf; ++ if (mtk_nand_ready_for_read(nand, u4RowAddr, 0, true, buf)) { ++ int j; ++ for (j = 0 ; j < u4SecNum; j++) { ++ if (!mtk_nand_read_page_data(mtd, buf+j*512, 512)) ++ bRet = false; ++ if(g_bHwEcc && !mtk_nand_check_dececc_done(j+1)) ++ bRet = false; ++ if(g_bHwEcc && !mtk_nand_check_bch_error(mtd, buf+j*512, j, u4RowAddr)) ++ bRet = false; ++ } ++ if (!mtk_nand_status_ready(STA_NAND_BUSY)) ++ bRet = false; ++ ++ mtk_nand_read_fdm_data(pFDMBuf, u4SecNum); ++ mtk_nand_stop_read(); ++ } ++ ++ if (buf == local_buffer_16_align) ++ memcpy(pPageBuf, buf, u4PageSize); ++ ++ return bRet; ++} ++ ++int ++mtk_nand_exec_write_page(struct mtd_info *mtd, u32 u4RowAddr, u32 u4PageSize, u8 * pPageBuf, u8 * pFDMBuf) ++{ ++ struct nand_chip *chip = mtd->priv; ++ u32 u4SecNum = u4PageSize >> 9; ++ u8 *buf; ++ u8 status; ++ ++ MSG(WRITE, "mtk_nand_exec_write_page, page: 0x%x\n", u4RowAddr); ++ ++ if (((u32) pPageBuf % 16) && local_buffer_16_align) { ++ printk(KERN_INFO "Data buffer not 16 bytes aligned: %p\n", pPageBuf); ++ memcpy(local_buffer_16_align, pPageBuf, mtd->writesize); ++ buf = local_buffer_16_align; ++ } else ++ buf = pPageBuf; ++ ++ if (mtk_nand_ready_for_write(chip, u4RowAddr, 0, true, buf)) { ++ mtk_nand_write_fdm_data(chip, pFDMBuf, u4SecNum); ++ (void)mtk_nand_write_page_data(mtd, buf, u4PageSize); ++ (void)mtk_nand_check_RW_count(u4PageSize); ++ mtk_nand_stop_write(); ++ (void)mtk_nand_set_command(NAND_CMD_PAGEPROG); ++ while (DRV_Reg32(NFI_STA_REG32) & STA_NAND_BUSY) ; ++ } ++ ++ status = chip->waitfunc(mtd, chip); ++ if (status & NAND_STATUS_FAIL) ++ return -EIO; ++ return 0; ++} ++ ++static int ++get_start_end_block(struct mtd_info *mtd, int block, int *start_blk, int *end_blk) ++{ ++ struct nand_chip *chip = mtd->priv; ++ int i; ++ ++ *start_blk = 0; ++ for (i = 0; i <= part_num; i++) ++ { ++ if (i == part_num) ++ { ++ // try the last reset partition ++ *end_blk = (chip->chipsize >> chip->phys_erase_shift) - 1; ++ if (*start_blk <= *end_blk) ++ { ++ if ((block >= *start_blk) && (block <= *end_blk)) ++ break; ++ } ++ } ++ // skip All partition entry ++ else if (g_pasStatic_Partition[i].size == MTDPART_SIZ_FULL) ++ { ++ continue; ++ } ++ *end_blk = *start_blk + (g_pasStatic_Partition[i].size >> chip->phys_erase_shift) - 1; ++ if ((block >= *start_blk) && (block <= *end_blk)) ++ break; ++ *start_blk = *end_blk + 1; ++ } ++ if (*start_blk > *end_blk) ++ { ++ return -1; ++ } ++ return 0; ++} ++ ++static int ++block_remap(struct mtd_info *mtd, int block) ++{ ++ struct nand_chip *chip = mtd->priv; ++ int start_blk, end_blk; ++ int j, block_offset; ++ int bad_block = 0; ++ ++ if (chip->bbt == NULL) { ++ printk("ERROR!! no bbt table for block_remap\n"); ++ return -1; ++ } ++ ++ if (get_start_end_block(mtd, block, &start_blk, &end_blk) < 0) { ++ printk("ERROR!! can not find start_blk and end_blk\n"); ++ return -1; ++ } ++ ++ block_offset = block - start_blk; ++ for (j = start_blk; j <= end_blk;j++) { ++ if (((chip->bbt[j >> 2] >> ((j<<1) & 0x6)) & 0x3) == 0x0) { ++ if (!block_offset) ++ break; ++ block_offset--; ++ } else { ++ bad_block++; ++ } ++ } ++ if (j <= end_blk) { ++ return j; ++ } else { ++ // remap to the bad block ++ for (j = end_blk; bad_block > 0; j--) ++ { ++ if (((chip->bbt[j >> 2] >> ((j<<1) & 0x6)) & 0x3) != 0x0) ++ { ++ bad_block--; ++ if (bad_block <= block_offset) ++ return j; ++ } ++ } ++ } ++ ++ printk("Error!! block_remap error\n"); ++ return -1; ++} ++ ++int ++check_block_remap(struct mtd_info *mtd, int block) ++{ ++ if (shift_on_bbt) ++ return block_remap(mtd, block); ++ else ++ return block; ++} ++EXPORT_SYMBOL(check_block_remap); ++ ++ ++static int ++write_next_on_fail(struct mtd_info *mtd, char *write_buf, int page, int * to_blk) ++{ ++ struct nand_chip *chip = mtd->priv; ++ int i, j, to_page = 0, first_page; ++ char *buf, *oob; ++ int start_blk = 0, end_blk; ++ int mapped_block; ++ int page_per_block_bit = chip->phys_erase_shift - chip->page_shift; ++ int block = page >> page_per_block_bit; ++ ++ // find next available block in the same MTD partition ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ ++ get_start_end_block(mtd, block, &start_blk, &end_blk); ++ ++ buf = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL | GFP_DMA); ++ if (buf == NULL) ++ return -1; ++ ++ oob = buf + mtd->writesize; ++ for ((*to_blk) = block + 1; (*to_blk) <= end_blk ; (*to_blk)++) { ++ if (nand_bbt_get(mtd, (*to_blk) << page_per_block_bit) == 0) { ++ int status; ++ status = mtk_nand_erase_hw(mtd, (*to_blk) << page_per_block_bit); ++ if (status & NAND_STATUS_FAIL) { ++ mtk_nand_block_markbad_hw(mtd, (*to_blk) << chip->phys_erase_shift); ++ nand_bbt_set(mtd, (*to_blk) << page_per_block_bit, 0x3); ++ } else { ++ /* good block */ ++ to_page = (*to_blk) << page_per_block_bit; ++ break; ++ } ++ } ++ } ++ ++ if (!to_page) { ++ kfree(buf); ++ return -1; ++ } ++ ++ first_page = (page >> page_per_block_bit) << page_per_block_bit; ++ for (i = 0; i < (1 << page_per_block_bit); i++) { ++ if ((first_page + i) != page) { ++ mtk_nand_read_oob_hw(mtd, chip, (first_page+i)); ++ for (j = 0; j < mtd->oobsize; j++) ++ if (chip->oob_poi[j] != (unsigned char)0xff) ++ break; ++ if (j < mtd->oobsize) { ++ mtk_nand_exec_read_page(mtd, (first_page+i), mtd->writesize, buf, oob); ++ memset(oob, 0xff, mtd->oobsize); ++ if (mtk_nand_exec_write_page(mtd, to_page + i, mtd->writesize, (u8 *)buf, oob) != 0) { ++ int ret, new_blk = 0; ++ nand_bbt_set(mtd, to_page, 0x3); ++ ret = write_next_on_fail(mtd, buf, to_page + i, &new_blk); ++ if (ret) { ++ kfree(buf); ++ mtk_nand_block_markbad_hw(mtd, to_page << chip->page_shift); ++ return ret; ++ } ++ mtk_nand_block_markbad_hw(mtd, to_page << chip->page_shift); ++ *to_blk = new_blk; ++ to_page = ((*to_blk) << page_per_block_bit); ++ } ++ } ++ } else { ++ memset(chip->oob_poi, 0xff, mtd->oobsize); ++ if (mtk_nand_exec_write_page(mtd, to_page + i, mtd->writesize, (u8 *)write_buf, chip->oob_poi) != 0) { ++ int ret, new_blk = 0; ++ nand_bbt_set(mtd, to_page, 0x3); ++ ret = write_next_on_fail(mtd, write_buf, to_page + i, &new_blk); ++ if (ret) { ++ kfree(buf); ++ mtk_nand_block_markbad_hw(mtd, to_page << chip->page_shift); ++ return ret; ++ } ++ mtk_nand_block_markbad_hw(mtd, to_page << chip->page_shift); ++ *to_blk = new_blk; ++ to_page = ((*to_blk) << page_per_block_bit); ++ } ++ } ++ } ++ ++ kfree(buf); ++ ++ return 0; ++} ++ ++static int ++mtk_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, uint32_t offset, ++ int data_len, const u8 * buf, int oob_required, int page, int cached, int raw) ++{ ++ int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); ++ int block = page / page_per_block; ++ u16 page_in_block = page % page_per_block; ++ int mapped_block = block; ++ ++#if defined(MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++ // write bad index into oob ++ if (mapped_block != block) ++ set_bad_index_to_oob(chip->oob_poi, block); ++ else ++ set_bad_index_to_oob(chip->oob_poi, FAKE_INDEX); ++#else ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) ++ return NAND_STATUS_FAIL; ++ } ++#endif ++ do { ++ if (mtk_nand_exec_write_page(mtd, page_in_block + mapped_block * page_per_block, mtd->writesize, (u8 *)buf, chip->oob_poi)) { ++ MSG(INIT, "write fail at block: 0x%x, page: 0x%x\n", mapped_block, page_in_block); ++#if defined(MTK_NAND_BMT) ++ if (update_bmt((page_in_block + mapped_block * page_per_block) << chip->page_shift, UPDATE_WRITE_FAIL, (u8 *) buf, chip->oob_poi)) { ++ MSG(INIT, "Update BMT success\n"); ++ return 0; ++ } else { ++ MSG(INIT, "Update BMT fail\n"); ++ return -EIO; ++ } ++#else ++ { ++ int new_blk; ++ nand_bbt_set(mtd, page_in_block + mapped_block * page_per_block, 0x3); ++ if (write_next_on_fail(mtd, (char *)buf, page_in_block + mapped_block * page_per_block, &new_blk) != 0) ++ { ++ mtk_nand_block_markbad_hw(mtd, (page_in_block + mapped_block * page_per_block) << chip->page_shift); ++ return NAND_STATUS_FAIL; ++ } ++ mtk_nand_block_markbad_hw(mtd, (page_in_block + mapped_block * page_per_block) << chip->page_shift); ++ break; ++ } ++#endif ++ } else ++ break; ++ } while(1); ++ ++ return 0; ++} ++ ++static void ++mtk_nand_command_bp(struct mtd_info *mtd, unsigned int command, int column, int page_addr) ++{ ++ struct nand_chip *nand = mtd->priv; ++ ++ switch (command) { ++ case NAND_CMD_SEQIN: ++ memset(g_kCMD.au1OOB, 0xFF, sizeof(g_kCMD.au1OOB)); ++ g_kCMD.pDataBuf = NULL; ++ g_kCMD.u4RowAddr = page_addr; ++ g_kCMD.u4ColAddr = column; ++ break; ++ ++ case NAND_CMD_PAGEPROG: ++ if (g_kCMD.pDataBuf || (0xFF != g_kCMD.au1OOB[nand_badblock_offset])) { ++ u8 *pDataBuf = g_kCMD.pDataBuf ? g_kCMD.pDataBuf : nand->buffers->databuf; ++ mtk_nand_exec_write_page(mtd, g_kCMD.u4RowAddr, mtd->writesize, pDataBuf, g_kCMD.au1OOB); ++ g_kCMD.u4RowAddr = (u32) - 1; ++ g_kCMD.u4OOBRowAddr = (u32) - 1; ++ } ++ break; ++ ++ case NAND_CMD_READOOB: ++ g_kCMD.u4RowAddr = page_addr; ++ g_kCMD.u4ColAddr = column + mtd->writesize; ++ break; ++ ++ case NAND_CMD_READ0: ++ g_kCMD.u4RowAddr = page_addr; ++ g_kCMD.u4ColAddr = column; ++ break; ++ ++ case NAND_CMD_ERASE1: ++ nand->state=FL_ERASING; ++ (void)mtk_nand_reset(); ++ mtk_nand_set_mode(CNFG_OP_ERASE); ++ (void)mtk_nand_set_command(NAND_CMD_ERASE1); ++ (void)mtk_nand_set_address(0, page_addr, 0, devinfo.addr_cycle - 2); ++ break; ++ ++ case NAND_CMD_ERASE2: ++ (void)mtk_nand_set_command(NAND_CMD_ERASE2); ++ while (DRV_Reg32(NFI_STA_REG32) & STA_NAND_BUSY) ++ ; ++ break; ++ ++ case NAND_CMD_STATUS: ++ (void)mtk_nand_reset(); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_BYTE_RW); ++ mtk_nand_set_mode(CNFG_OP_SRD); ++ mtk_nand_set_mode(CNFG_READ_EN); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ (void)mtk_nand_set_command(NAND_CMD_STATUS); ++ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_NOB_MASK); ++ mb(); ++ DRV_WriteReg16(NFI_CON_REG16, CON_NFI_SRD | (1 << CON_NFI_NOB_SHIFT)); ++ g_bcmdstatus = true; ++ break; ++ ++ case NAND_CMD_RESET: ++ (void)mtk_nand_reset(); ++ DRV_WriteReg16(NFI_INTR_EN_REG16, INTR_RST_DONE_EN); ++ (void)mtk_nand_set_command(NAND_CMD_RESET); ++ DRV_WriteReg16(NFI_BASE+0x44, 0xF1); ++ while(!(DRV_Reg16(NFI_INTR_REG16)&INTR_RST_DONE_EN)) ++ ; ++ break; ++ ++ case NAND_CMD_READID: ++ mtk_nand_reset(); ++ /* Disable HW ECC */ ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_READ_EN | CNFG_BYTE_RW); ++ (void)mtk_nand_reset(); ++ mb(); ++ mtk_nand_set_mode(CNFG_OP_SRD); ++ (void)mtk_nand_set_command(NAND_CMD_READID); ++ (void)mtk_nand_set_address(0, 0, 1, 0); ++ DRV_WriteReg16(NFI_CON_REG16, CON_NFI_SRD); ++ while (DRV_Reg32(NFI_STA_REG32) & STA_DATAR_STATE) ++ ; ++ break; ++ ++ default: ++ BUG(); ++ break; ++ } ++} ++ ++static void ++mtk_nand_select_chip(struct mtd_info *mtd, int chip) ++{ ++ if ((chip == -1) && (false == g_bInitDone)) { ++ struct nand_chip *nand = mtd->priv; ++ struct mtk_nand_host *host = nand->priv; ++ struct mtk_nand_host_hw *hw = host->hw; ++ u32 spare_per_sector = mtd->oobsize / (mtd->writesize / 512); ++ u32 ecc_bit = 4; ++ u32 spare_bit = PAGEFMT_SPARE_16; ++ ++ if (spare_per_sector >= 28) { ++ spare_bit = PAGEFMT_SPARE_28; ++ ecc_bit = 12; ++ spare_per_sector = 28; ++ } else if (spare_per_sector >= 27) { ++ spare_bit = PAGEFMT_SPARE_27; ++ ecc_bit = 8; ++ spare_per_sector = 27; ++ } else if (spare_per_sector >= 26) { ++ spare_bit = PAGEFMT_SPARE_26; ++ ecc_bit = 8; ++ spare_per_sector = 26; ++ } else if (spare_per_sector >= 16) { ++ spare_bit = PAGEFMT_SPARE_16; ++ ecc_bit = 4; ++ spare_per_sector = 16; ++ } else { ++ MSG(INIT, "[NAND]: NFI not support oobsize: %x\n", spare_per_sector); ++ ASSERT(0); ++ } ++ mtd->oobsize = spare_per_sector*(mtd->writesize/512); ++ MSG(INIT, "[NAND]select ecc bit:%d, sparesize :%d spare_per_sector=%d\n",ecc_bit,mtd->oobsize,spare_per_sector); ++ /* Setup PageFormat */ ++ if (4096 == mtd->writesize) { ++ NFI_SET_REG16(NFI_PAGEFMT_REG16, (spare_bit << PAGEFMT_SPARE_SHIFT) | PAGEFMT_4K); ++ nand->cmdfunc = mtk_nand_command_bp; ++ } else if (2048 == mtd->writesize) { ++ NFI_SET_REG16(NFI_PAGEFMT_REG16, (spare_bit << PAGEFMT_SPARE_SHIFT) | PAGEFMT_2K); ++ nand->cmdfunc = mtk_nand_command_bp; ++ } ++ ECC_Config(hw,ecc_bit); ++ g_bInitDone = true; ++ } ++ switch (chip) { ++ case -1: ++ break; ++ case 0: ++ case 1: ++ /* Jun Shen, 2011.04.13 */ ++ /* Note: MT6577 EVB NAND is mounted on CS0, but FPGA is CS1 */ ++ DRV_WriteReg16(NFI_CSEL_REG16, chip); ++ /* Jun Shen, 2011.04.13 */ ++ break; ++ } ++} ++ ++static uint8_t ++mtk_nand_read_byte(struct mtd_info *mtd) ++{ ++ uint8_t retval = 0; ++ ++ if (!mtk_nand_pio_ready()) { ++ printk("pio ready timeout\n"); ++ retval = false; ++ } ++ ++ if (g_bcmdstatus) { ++ retval = DRV_Reg8(NFI_DATAR_REG32); ++ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_NOB_MASK); ++ mtk_nand_reset(); ++ if (g_bHwEcc) { ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ } else { ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ } ++ g_bcmdstatus = false; ++ } else ++ retval = DRV_Reg8(NFI_DATAR_REG32); ++ ++ return retval; ++} ++ ++static void ++mtk_nand_read_buf(struct mtd_info *mtd, uint8_t * buf, int len) ++{ ++ struct nand_chip *nand = (struct nand_chip *)mtd->priv; ++ struct NAND_CMD *pkCMD = &g_kCMD; ++ u32 u4ColAddr = pkCMD->u4ColAddr; ++ u32 u4PageSize = mtd->writesize; ++ ++ if (u4ColAddr < u4PageSize) { ++ if ((u4ColAddr == 0) && (len >= u4PageSize)) { ++ mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, buf, pkCMD->au1OOB); ++ if (len > u4PageSize) { ++ u32 u4Size = min(len - u4PageSize, sizeof(pkCMD->au1OOB)); ++ memcpy(buf + u4PageSize, pkCMD->au1OOB, u4Size); ++ } ++ } else { ++ mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, nand->buffers->databuf, pkCMD->au1OOB); ++ memcpy(buf, nand->buffers->databuf + u4ColAddr, len); ++ } ++ pkCMD->u4OOBRowAddr = pkCMD->u4RowAddr; ++ } else { ++ u32 u4Offset = u4ColAddr - u4PageSize; ++ u32 u4Size = min(len - u4Offset, sizeof(pkCMD->au1OOB)); ++ if (pkCMD->u4OOBRowAddr != pkCMD->u4RowAddr) { ++ mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, nand->buffers->databuf, pkCMD->au1OOB); ++ pkCMD->u4OOBRowAddr = pkCMD->u4RowAddr; ++ } ++ memcpy(buf, pkCMD->au1OOB + u4Offset, u4Size); ++ } ++ pkCMD->u4ColAddr += len; ++} ++ ++static void ++mtk_nand_write_buf(struct mtd_info *mtd, const uint8_t * buf, int len) ++{ ++ struct NAND_CMD *pkCMD = &g_kCMD; ++ u32 u4ColAddr = pkCMD->u4ColAddr; ++ u32 u4PageSize = mtd->writesize; ++ int i4Size, i; ++ ++ if (u4ColAddr >= u4PageSize) { ++ u32 u4Offset = u4ColAddr - u4PageSize; ++ u8 *pOOB = pkCMD->au1OOB + u4Offset; ++ i4Size = min(len, (int)(sizeof(pkCMD->au1OOB) - u4Offset)); ++ for (i = 0; i < i4Size; i++) { ++ pOOB[i] &= buf[i]; ++ } ++ } else { ++ pkCMD->pDataBuf = (u8 *) buf; ++ } ++ ++ pkCMD->u4ColAddr += len; ++} ++ ++static int ++mtk_nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t * buf, int oob_required) ++{ ++ mtk_nand_write_buf(mtd, buf, mtd->writesize); ++ mtk_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize); ++ return 0; ++} ++ ++static int ++mtk_nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t * buf, int oob_required, int page) ++{ ++ struct NAND_CMD *pkCMD = &g_kCMD; ++ u32 u4ColAddr = pkCMD->u4ColAddr; ++ u32 u4PageSize = mtd->writesize; ++ ++ if (u4ColAddr == 0) { ++ mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, buf, chip->oob_poi); ++ pkCMD->u4ColAddr += u4PageSize + mtd->oobsize; ++ } ++ ++ return 0; ++} ++ ++static int ++mtk_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, u8 * buf, int page) ++{ ++ int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); ++ int block = page / page_per_block; ++ u16 page_in_block = page % page_per_block; ++ int mapped_block = block; ++ ++#if defined (MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++ if (mtk_nand_exec_read_page(mtd, page_in_block + mapped_block * page_per_block, ++ mtd->writesize, buf, chip->oob_poi)) ++ return 0; ++#else ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) ++ return NAND_STATUS_FAIL; ++ } ++ ++ if (mtk_nand_exec_read_page(mtd, page_in_block + mapped_block * page_per_block, mtd->writesize, buf, chip->oob_poi)) ++ return 0; ++ else ++ return -EIO; ++#endif ++} ++ ++int ++mtk_nand_erase_hw(struct mtd_info *mtd, int page) ++{ ++ struct nand_chip *chip = (struct nand_chip *)mtd->priv; ++ ++ chip->erase_cmd(mtd, page); ++ ++ return chip->waitfunc(mtd, chip); ++} ++ ++static int ++mtk_nand_erase(struct mtd_info *mtd, int page) ++{ ++ // get mapping ++ struct nand_chip *chip = mtd->priv; ++ int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); ++ int page_in_block = page % page_per_block; ++ int block = page / page_per_block; ++ int mapped_block = block; ++ ++#if defined(MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++#else ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) ++ return NAND_STATUS_FAIL; ++ } ++#endif ++ ++ do { ++ int status = mtk_nand_erase_hw(mtd, page_in_block + page_per_block * mapped_block); ++ ++ if (status & NAND_STATUS_FAIL) { ++#if defined (MTK_NAND_BMT) ++ if (update_bmt( (page_in_block + mapped_block * page_per_block) << chip->page_shift, ++ UPDATE_ERASE_FAIL, NULL, NULL)) ++ { ++ MSG(INIT, "Erase fail at block: 0x%x, update BMT success\n", mapped_block); ++ return 0; ++ } else { ++ MSG(INIT, "Erase fail at block: 0x%x, update BMT fail\n", mapped_block); ++ return NAND_STATUS_FAIL; ++ } ++#else ++ mtk_nand_block_markbad_hw(mtd, (page_in_block + mapped_block * page_per_block) << chip->page_shift); ++ nand_bbt_set(mtd, page_in_block + mapped_block * page_per_block, 0x3); ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) ++ return NAND_STATUS_FAIL; ++ } else ++ return NAND_STATUS_FAIL; ++#endif ++ } else ++ break; ++ } while(1); ++ ++ return 0; ++} ++ ++static int ++mtk_nand_read_oob_raw(struct mtd_info *mtd, uint8_t * buf, int page_addr, int len) ++{ ++ struct nand_chip *chip = (struct nand_chip *)mtd->priv; ++ u32 col_addr = 0; ++ u32 sector = 0; ++ int res = 0; ++ u32 colnob = 2, rawnob = devinfo.addr_cycle - 2; ++ int randomread = 0; ++ int read_len = 0; ++ int sec_num = 1<<(chip->page_shift-9); ++ int spare_per_sector = mtd->oobsize/sec_num; ++ ++ if (len > NAND_MAX_OOBSIZE || len % OOB_AVAI_PER_SECTOR || !buf) { ++ printk(KERN_WARNING "[%s] invalid parameter, len: %d, buf: %p\n", __FUNCTION__, len, buf); ++ return -EINVAL; ++ } ++ if (len > spare_per_sector) ++ randomread = 1; ++ if (!randomread || !(devinfo.advancedmode & RAMDOM_READ)) { ++ while (len > 0) { ++ read_len = min(len, spare_per_sector); ++ col_addr = NAND_SECTOR_SIZE + sector * (NAND_SECTOR_SIZE + spare_per_sector); // TODO: Fix this hard-code 16 ++ if (!mtk_nand_ready_for_read(chip, page_addr, col_addr, false, NULL)) { ++ printk(KERN_WARNING "mtk_nand_ready_for_read return failed\n"); ++ res = -EIO; ++ goto error; ++ } ++ if (!mtk_nand_mcu_read_data(buf + spare_per_sector * sector, read_len)) { ++ printk(KERN_WARNING "mtk_nand_mcu_read_data return failed\n"); ++ res = -EIO; ++ goto error; ++ } ++ mtk_nand_check_RW_count(read_len); ++ mtk_nand_stop_read(); ++ sector++; ++ len -= read_len; ++ } ++ } else { ++ col_addr = NAND_SECTOR_SIZE; ++ if (chip->options & NAND_BUSWIDTH_16) ++ col_addr /= 2; ++ if (!mtk_nand_reset()) ++ goto error; ++ mtk_nand_set_mode(0x6000); ++ NFI_SET_REG16(NFI_CNFG_REG16, CNFG_READ_EN); ++ DRV_WriteReg16(NFI_CON_REG16, 4 << CON_NFI_SEC_SHIFT); ++ ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_AHB); ++ NFI_CLN_REG16(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ ++ mtk_nand_set_autoformat(false); ++ ++ if (!mtk_nand_set_command(NAND_CMD_READ0)) ++ goto error; ++ //1 FIXED ME: For Any Kind of AddrCycle ++ if (!mtk_nand_set_address(col_addr, page_addr, colnob, rawnob)) ++ goto error; ++ if (!mtk_nand_set_command(NAND_CMD_READSTART)) ++ goto error; ++ if (!mtk_nand_status_ready(STA_NAND_BUSY)) ++ goto error; ++ read_len = min(len, spare_per_sector); ++ if (!mtk_nand_mcu_read_data(buf + spare_per_sector * sector, read_len)) { ++ printk(KERN_WARNING "mtk_nand_mcu_read_data return failed first 16\n"); ++ res = -EIO; ++ goto error; ++ } ++ sector++; ++ len -= read_len; ++ mtk_nand_stop_read(); ++ while (len > 0) { ++ read_len = min(len, spare_per_sector); ++ if (!mtk_nand_set_command(0x05)) ++ goto error; ++ col_addr = NAND_SECTOR_SIZE + sector * (NAND_SECTOR_SIZE + spare_per_sector); ++ if (chip->options & NAND_BUSWIDTH_16) ++ col_addr /= 2; ++ DRV_WriteReg32(NFI_COLADDR_REG32, col_addr); ++ DRV_WriteReg16(NFI_ADDRNOB_REG16, 2); ++ DRV_WriteReg16(NFI_CON_REG16, 4 << CON_NFI_SEC_SHIFT); ++ if (!mtk_nand_status_ready(STA_ADDR_STATE)) ++ goto error; ++ if (!mtk_nand_set_command(0xE0)) ++ goto error; ++ if (!mtk_nand_status_ready(STA_NAND_BUSY)) ++ goto error; ++ if (!mtk_nand_mcu_read_data(buf + spare_per_sector * sector, read_len)) { ++ printk(KERN_WARNING "mtk_nand_mcu_read_data return failed first 16\n"); ++ res = -EIO; ++ goto error; ++ } ++ mtk_nand_stop_read(); ++ sector++; ++ len -= read_len; ++ } ++ } ++error: ++ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_BRD); ++ return res; ++} ++ ++static int ++mtk_nand_write_oob_raw(struct mtd_info *mtd, const uint8_t * buf, int page_addr, int len) ++{ ++ struct nand_chip *chip = mtd->priv; ++ u32 col_addr = 0; ++ u32 sector = 0; ++ int write_len = 0; ++ int status; ++ int sec_num = 1<<(chip->page_shift-9); ++ int spare_per_sector = mtd->oobsize/sec_num; ++ ++ if (len > NAND_MAX_OOBSIZE || len % OOB_AVAI_PER_SECTOR || !buf) { ++ printk(KERN_WARNING "[%s] invalid parameter, len: %d, buf: %p\n", __FUNCTION__, len, buf); ++ return -EINVAL; ++ } ++ ++ while (len > 0) { ++ write_len = min(len, spare_per_sector); ++ col_addr = sector * (NAND_SECTOR_SIZE + spare_per_sector) + NAND_SECTOR_SIZE; ++ if (!mtk_nand_ready_for_write(chip, page_addr, col_addr, false, NULL)) ++ return -EIO; ++ if (!mtk_nand_mcu_write_data(mtd, buf + sector * spare_per_sector, write_len)) ++ return -EIO; ++ (void)mtk_nand_check_RW_count(write_len); ++ NFI_CLN_REG16(NFI_CON_REG16, CON_NFI_BWR); ++ (void)mtk_nand_set_command(NAND_CMD_PAGEPROG); ++ while (DRV_Reg32(NFI_STA_REG32) & STA_NAND_BUSY) ++ ; ++ status = chip->waitfunc(mtd, chip); ++ if (status & NAND_STATUS_FAIL) { ++ printk(KERN_INFO "status: %d\n", status); ++ return -EIO; ++ } ++ len -= write_len; ++ sector++; ++ } ++ ++ return 0; ++} ++ ++static int ++mtk_nand_write_oob_hw(struct mtd_info *mtd, struct nand_chip *chip, int page) ++{ ++ int i, iter; ++ int sec_num = 1<<(chip->page_shift-9); ++ int spare_per_sector = mtd->oobsize/sec_num; ++ ++ memcpy(local_oob_buf, chip->oob_poi, mtd->oobsize); ++ ++ // copy ecc data ++ for (i = 0; i < chip->ecc.layout->eccbytes; i++) { ++ iter = (i / (spare_per_sector-OOB_AVAI_PER_SECTOR)) * spare_per_sector + OOB_AVAI_PER_SECTOR + i % (spare_per_sector-OOB_AVAI_PER_SECTOR); ++ local_oob_buf[iter] = chip->oob_poi[chip->ecc.layout->eccpos[i]]; ++ } ++ ++ // copy FDM data ++ for (i = 0; i < sec_num; i++) ++ memcpy(&local_oob_buf[i * spare_per_sector], &chip->oob_poi[i * OOB_AVAI_PER_SECTOR], OOB_AVAI_PER_SECTOR); ++ ++ return mtk_nand_write_oob_raw(mtd, local_oob_buf, page, mtd->oobsize); ++} ++ ++static int mtk_nand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) ++{ ++ int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); ++ int block = page / page_per_block; ++ u16 page_in_block = page % page_per_block; ++ int mapped_block = block; ++ ++#if defined(MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++ // write bad index into oob ++ if (mapped_block != block) ++ set_bad_index_to_oob(chip->oob_poi, block); ++ else ++ set_bad_index_to_oob(chip->oob_poi, FAKE_INDEX); ++#else ++ if (shift_on_bbt) ++ { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) ++ return NAND_STATUS_FAIL; ++ } ++#endif ++ do { ++ if (mtk_nand_write_oob_hw(mtd, chip, page_in_block + mapped_block * page_per_block /* page */)) { ++ MSG(INIT, "write oob fail at block: 0x%x, page: 0x%x\n", mapped_block, page_in_block); ++#if defined(MTK_NAND_BMT) ++ if (update_bmt((page_in_block + mapped_block * page_per_block) << chip->page_shift, ++ UPDATE_WRITE_FAIL, NULL, chip->oob_poi)) ++ { ++ MSG(INIT, "Update BMT success\n"); ++ return 0; ++ } else { ++ MSG(INIT, "Update BMT fail\n"); ++ return -EIO; ++ } ++#else ++ mtk_nand_block_markbad_hw(mtd, (page_in_block + mapped_block * page_per_block) << chip->page_shift); ++ nand_bbt_set(mtd, page_in_block + mapped_block * page_per_block, 0x3); ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, mapped_block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ if (nand_bbt_get(mtd, mapped_block << (chip->phys_erase_shift - chip->page_shift)) != 0x0) ++ return NAND_STATUS_FAIL; ++ } else { ++ return NAND_STATUS_FAIL; ++ } ++#endif ++ } else ++ break; ++ } while (1); ++ ++ return 0; ++} ++ ++int ++mtk_nand_block_markbad_hw(struct mtd_info *mtd, loff_t offset) ++{ ++ struct nand_chip *chip = mtd->priv; ++ int block = (int)offset >> chip->phys_erase_shift; ++ int page = block * (1 << (chip->phys_erase_shift - chip->page_shift)); ++ u8 buf[8]; ++ ++ memset(buf, 0xFF, 8); ++ buf[0] = 0; ++ return mtk_nand_write_oob_raw(mtd, buf, page, 8); ++} ++ ++static int ++mtk_nand_block_markbad(struct mtd_info *mtd, loff_t offset) ++{ ++ struct nand_chip *chip = mtd->priv; ++ int block = (int)offset >> chip->phys_erase_shift; ++ int ret; ++ int mapped_block = block; ++ ++ nand_get_device(chip, mtd, FL_WRITING); ++ ++#if defined(MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++ ret = mtk_nand_block_markbad_hw(mtd, mapped_block << chip->phys_erase_shift); ++#else ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) { ++ printk("NAND mark bad failed\n"); ++ nand_release_device(mtd); ++ return NAND_STATUS_FAIL; ++ } ++ } ++ ret = mtk_nand_block_markbad_hw(mtd, mapped_block << chip->phys_erase_shift); ++#endif ++ nand_release_device(mtd); ++ ++ return ret; ++} ++ ++int ++mtk_nand_read_oob_hw(struct mtd_info *mtd, struct nand_chip *chip, int page) ++{ ++ int i; ++ u8 iter = 0; ++ ++ int sec_num = 1<<(chip->page_shift-9); ++ int spare_per_sector = mtd->oobsize/sec_num; ++ ++ if (mtk_nand_read_oob_raw(mtd, chip->oob_poi, page, mtd->oobsize)) { ++ printk(KERN_ERR "[%s]mtk_nand_read_oob_raw return failed\n", __FUNCTION__); ++ return -EIO; ++ } ++ ++ // adjust to ecc physical layout to memory layout ++ /*********************************************************/ ++ /* FDM0 | ECC0 | FDM1 | ECC1 | FDM2 | ECC2 | FDM3 | ECC3 */ ++ /* 8B | 8B | 8B | 8B | 8B | 8B | 8B | 8B */ ++ /*********************************************************/ ++ ++ memcpy(local_oob_buf, chip->oob_poi, mtd->oobsize); ++ // copy ecc data ++ for (i = 0; i < chip->ecc.layout->eccbytes; i++) { ++ iter = (i / (spare_per_sector-OOB_AVAI_PER_SECTOR)) * spare_per_sector + OOB_AVAI_PER_SECTOR + i % (spare_per_sector-OOB_AVAI_PER_SECTOR); ++ chip->oob_poi[chip->ecc.layout->eccpos[i]] = local_oob_buf[iter]; ++ } ++ ++ // copy FDM data ++ for (i = 0; i < sec_num; i++) { ++ memcpy(&chip->oob_poi[i * OOB_AVAI_PER_SECTOR], &local_oob_buf[i * spare_per_sector], OOB_AVAI_PER_SECTOR); ++ } ++ ++ return 0; ++} ++ ++static int ++mtk_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) ++{ ++ int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); ++ int block = page / page_per_block; ++ u16 page_in_block = page % page_per_block; ++ int mapped_block = block; ++ ++#if defined (MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++ mtk_nand_read_oob_hw(mtd, chip, page_in_block + mapped_block * page_per_block); ++#else ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) ++ return NAND_STATUS_FAIL; ++ // allow to read oob even if the block is bad ++ } ++ if (mtk_nand_read_oob_hw(mtd, chip, page_in_block + mapped_block * page_per_block)!=0) ++ return -1; ++#endif ++ return 0; ++} ++ ++int ++mtk_nand_block_bad_hw(struct mtd_info *mtd, loff_t ofs) ++{ ++ struct nand_chip *chip = (struct nand_chip *)mtd->priv; ++ int page_addr = (int)(ofs >> chip->page_shift); ++ unsigned int page_per_block = 1 << (chip->phys_erase_shift - chip->page_shift); ++ unsigned char oob_buf[8]; ++ ++ page_addr &= ~(page_per_block - 1); ++ if (mtk_nand_read_oob_raw(mtd, oob_buf, page_addr, sizeof(oob_buf))) { ++ printk(KERN_WARNING "mtk_nand_read_oob_raw return error\n"); ++ return 1; ++ } ++ ++ if (oob_buf[0] != 0xff) { ++ printk(KERN_WARNING "Bad block detected at 0x%x, oob_buf[0] is 0x%x\n", page_addr, oob_buf[0]); ++ // dump_nfi(); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int ++mtk_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) ++{ ++ int chipnr = 0; ++ struct nand_chip *chip = (struct nand_chip *)mtd->priv; ++ int block = (int)ofs >> chip->phys_erase_shift; ++ int mapped_block = block; ++ int ret; ++ ++ if (getchip) { ++ chipnr = (int)(ofs >> chip->chip_shift); ++ nand_get_device(chip, mtd, FL_READING); ++ /* Select the NAND device */ ++ chip->select_chip(mtd, chipnr); ++ } ++ ++#if defined(MTK_NAND_BMT) ++ mapped_block = get_mapping_block_index(block); ++#else ++ if (shift_on_bbt) { ++ mapped_block = block_remap(mtd, block); ++ if (mapped_block == -1) { ++ if (getchip) ++ nand_release_device(mtd); ++ return NAND_STATUS_FAIL; ++ } ++ } ++#endif ++ ++ ret = mtk_nand_block_bad_hw(mtd, mapped_block << chip->phys_erase_shift); ++#if defined (MTK_NAND_BMT) ++ if (ret) { ++ MSG(INIT, "Unmapped bad block: 0x%x\n", mapped_block); ++ if (update_bmt(mapped_block << chip->phys_erase_shift, UPDATE_UNMAPPED_BLOCK, NULL, NULL)) { ++ MSG(INIT, "Update BMT success\n"); ++ ret = 0; ++ } else { ++ MSG(INIT, "Update BMT fail\n"); ++ ret = 1; ++ } ++ } ++#endif ++ ++ if (getchip) ++ nand_release_device(mtd); ++ ++ return ret; ++} ++ ++#ifdef CONFIG_MTD_NAND_VERIFY_WRITE ++char gacBuf[4096 + 288]; ++ ++static int ++mtk_nand_verify_buf(struct mtd_info *mtd, const uint8_t * buf, int len) ++{ ++ struct nand_chip *chip = (struct nand_chip *)mtd->priv; ++ struct NAND_CMD *pkCMD = &g_kCMD; ++ u32 u4PageSize = mtd->writesize; ++ u32 *pSrc, *pDst; ++ int i; ++ ++ mtk_nand_exec_read_page(mtd, pkCMD->u4RowAddr, u4PageSize, gacBuf, gacBuf + u4PageSize); ++ ++ pSrc = (u32 *) buf; ++ pDst = (u32 *) gacBuf; ++ len = len / sizeof(u32); ++ for (i = 0; i < len; ++i) { ++ if (*pSrc != *pDst) { ++ MSG(VERIFY, "mtk_nand_verify_buf page fail at page %d\n", pkCMD->u4RowAddr); ++ return -1; ++ } ++ pSrc++; ++ pDst++; ++ } ++ ++ pSrc = (u32 *) chip->oob_poi; ++ pDst = (u32 *) (gacBuf + u4PageSize); ++ ++ if ((pSrc[0] != pDst[0]) || (pSrc[1] != pDst[1]) || (pSrc[2] != pDst[2]) || (pSrc[3] != pDst[3]) || (pSrc[4] != pDst[4]) || (pSrc[5] != pDst[5])) { ++ // TODO: Ask Designer Why? ++ //(pSrc[6] != pDst[6]) || (pSrc[7] != pDst[7])) ++ MSG(VERIFY, "mtk_nand_verify_buf oob fail at page %d\n", pkCMD->u4RowAddr); ++ MSG(VERIFY, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", pSrc[0], pSrc[1], pSrc[2], pSrc[3], pSrc[4], pSrc[5], pSrc[6], pSrc[7]); ++ MSG(VERIFY, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", pDst[0], pDst[1], pDst[2], pDst[3], pDst[4], pDst[5], pDst[6], pDst[7]); ++ return -1; ++ } ++ return 0; ++} ++#endif ++ ++static void ++mtk_nand_init_hw(struct mtk_nand_host *host) { ++ struct mtk_nand_host_hw *hw = host->hw; ++ u32 data; ++ ++ data = DRV_Reg32(RALINK_SYSCTL_BASE+0x60); ++ data &= ~((0x3<<18)|(0x3<<16)); ++ data |= ((0x2<<18) |(0x2<<16)); ++ DRV_WriteReg32(RALINK_SYSCTL_BASE+0x60, data); ++ ++ MSG(INIT, "Enable NFI Clock\n"); ++ nand_enable_clock(); ++ ++ g_bInitDone = false; ++ g_kCMD.u4OOBRowAddr = (u32) - 1; ++ ++ /* Set default NFI access timing control */ ++ DRV_WriteReg32(NFI_ACCCON_REG32, hw->nfi_access_timing); ++ DRV_WriteReg16(NFI_CNFG_REG16, 0); ++ DRV_WriteReg16(NFI_PAGEFMT_REG16, 0); ++ ++ /* Reset the state machine and data FIFO, because flushing FIFO */ ++ (void)mtk_nand_reset(); ++ ++ /* Set the ECC engine */ ++ if (hw->nand_ecc_mode == NAND_ECC_HW) { ++ MSG(INIT, "%s : Use HW ECC\n", MODULE_NAME); ++ if (g_bHwEcc) ++ NFI_SET_REG32(NFI_CNFG_REG16, CNFG_HW_ECC_EN); ++ ECC_Config(host->hw,4); ++ mtk_nand_configure_fdm(8); ++ mtk_nand_configure_lock(); ++ } ++ ++ NFI_SET_REG16(NFI_IOCON_REG16, 0x47); ++} ++ ++static int mtk_nand_dev_ready(struct mtd_info *mtd) ++{ ++ return !(DRV_Reg32(NFI_STA_REG32) & STA_NAND_BUSY); ++} ++ ++#define FACT_BBT_BLOCK_NUM 32 // use the latest 32 BLOCK for factory bbt table ++#define FACT_BBT_OOB_SIGNATURE 1 ++#define FACT_BBT_SIGNATURE_LEN 7 ++const u8 oob_signature[] = "mtknand"; ++static u8 *fact_bbt = 0; ++static u32 bbt_size = 0; ++ ++static int ++read_fact_bbt(struct mtd_info *mtd, unsigned int page) ++{ ++ struct nand_chip *chip = mtd->priv; ++ ++ // read oob ++ if (mtk_nand_read_oob_hw(mtd, chip, page)==0) ++ { ++ if (chip->oob_poi[nand_badblock_offset] != 0xFF) ++ { ++ printk("Bad Block on Page %x\n", page); ++ return -1; ++ } ++ if (memcmp(&chip->oob_poi[FACT_BBT_OOB_SIGNATURE], oob_signature, FACT_BBT_SIGNATURE_LEN) != 0) ++ { ++ printk("compare signature failed %x\n", page); ++ return -1; ++ } ++ if (mtk_nand_exec_read_page(mtd, page, mtd->writesize, chip->buffers->databuf, chip->oob_poi)) ++ { ++ printk("Signature matched and data read!\n"); ++ memcpy(fact_bbt, chip->buffers->databuf, (bbt_size <= mtd->writesize)? bbt_size:mtd->writesize); ++ return 0; ++ } ++ ++ } ++ printk("failed at page %x\n", page); ++ return -1; ++} ++ ++static int ++load_fact_bbt(struct mtd_info *mtd) ++{ ++ struct nand_chip *chip = mtd->priv; ++ int i; ++ u32 total_block; ++ ++ total_block = 1 << (chip->chip_shift - chip->phys_erase_shift); ++ bbt_size = total_block >> 2; ++ ++ if ((!fact_bbt) && (bbt_size)) ++ fact_bbt = (u8 *)kmalloc(bbt_size, GFP_KERNEL); ++ if (!fact_bbt) ++ return -1; ++ ++ for (i = total_block - 1; i >= (total_block - FACT_BBT_BLOCK_NUM); i--) ++ { ++ if (read_fact_bbt(mtd, i << (chip->phys_erase_shift - chip->page_shift)) == 0) ++ { ++ printk("load_fact_bbt success %d\n", i); ++ return 0; ++ } ++ ++ } ++ printk("load_fact_bbt failed\n"); ++ return -1; ++} ++ ++static int ++mtk_nand_probe(struct platform_device *pdev) ++{ ++ struct mtd_part_parser_data ppdata; ++ struct mtk_nand_host_hw *hw; ++ struct mtd_info *mtd; ++ struct nand_chip *nand_chip; ++ u8 ext_id1, ext_id2, ext_id3; ++ int err = 0; ++ int id; ++ u32 ext_id; ++ int i; ++ u32 data; ++ ++ data = DRV_Reg32(RALINK_SYSCTL_BASE+0x60); ++ data &= ~((0x3<<18)|(0x3<<16)); ++ data |= ((0x2<<18) |(0x2<<16)); ++ DRV_WriteReg32(RALINK_SYSCTL_BASE+0x60, data); ++ ++ hw = &mt7621_nand_hw, ++ BUG_ON(!hw); ++ /* Allocate memory for the device structure (and zero it) */ ++ host = kzalloc(sizeof(struct mtk_nand_host), GFP_KERNEL); ++ if (!host) { ++ MSG(INIT, "mtk_nand: failed to allocate device structure.\n"); ++ return -ENOMEM; ++ } ++ ++ /* Allocate memory for 16 byte aligned buffer */ ++ local_buffer_16_align = local_buffer + 16 - ((u32) local_buffer % 16); ++ printk(KERN_INFO "Allocate 16 byte aligned buffer: %p\n", local_buffer_16_align); ++ host->hw = hw; ++ ++ /* init mtd data structure */ ++ nand_chip = &host->nand_chip; ++ nand_chip->priv = host; /* link the private data structures */ ++ ++ mtd = &host->mtd; ++ mtd->priv = nand_chip; ++ mtd->owner = THIS_MODULE; ++ mtd->name = "MT7621-NAND"; ++ ++ hw->nand_ecc_mode = NAND_ECC_HW; ++ ++ /* Set address of NAND IO lines */ ++ nand_chip->IO_ADDR_R = (void __iomem *)NFI_DATAR_REG32; ++ nand_chip->IO_ADDR_W = (void __iomem *)NFI_DATAW_REG32; ++ nand_chip->chip_delay = 20; /* 20us command delay time */ ++ nand_chip->ecc.mode = hw->nand_ecc_mode; /* enable ECC */ ++ nand_chip->ecc.strength = 1; ++ nand_chip->read_byte = mtk_nand_read_byte; ++ nand_chip->read_buf = mtk_nand_read_buf; ++ nand_chip->write_buf = mtk_nand_write_buf; ++#ifdef CONFIG_MTD_NAND_VERIFY_WRITE ++ nand_chip->verify_buf = mtk_nand_verify_buf; ++#endif ++ nand_chip->select_chip = mtk_nand_select_chip; ++ nand_chip->dev_ready = mtk_nand_dev_ready; ++ nand_chip->cmdfunc = mtk_nand_command_bp; ++ nand_chip->ecc.read_page = mtk_nand_read_page_hwecc; ++ nand_chip->ecc.write_page = mtk_nand_write_page_hwecc; ++ ++ nand_chip->ecc.layout = &nand_oob_64; ++ nand_chip->ecc.size = hw->nand_ecc_size; //2048 ++ nand_chip->ecc.bytes = hw->nand_ecc_bytes; //32 ++ ++ // For BMT, we need to revise driver architecture ++ nand_chip->write_page = mtk_nand_write_page; ++ nand_chip->ecc.write_oob = mtk_nand_write_oob; ++ nand_chip->block_markbad = mtk_nand_block_markbad; // need to add nand_get_device()/nand_release_device(). ++ // nand_chip->erase = mtk_nand_erase; ++ // nand_chip->read_page = mtk_nand_read_page; ++ nand_chip->ecc.read_oob = mtk_nand_read_oob; ++ nand_chip->block_bad = mtk_nand_block_bad; ++ ++ //Qwert:Add for Uboot ++ mtk_nand_init_hw(host); ++ /* Select the device */ ++ nand_chip->select_chip(mtd, NFI_DEFAULT_CS); ++ ++ /* ++ * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx) ++ * after power-up ++ */ ++ nand_chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); ++ ++ memset(&devinfo, 0 , sizeof(flashdev_info)); ++ ++ /* Send the command for reading device ID */ ++ ++ nand_chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); ++ ++ /* Read manufacturer and device IDs */ ++ manu_id = nand_chip->read_byte(mtd); ++ dev_id = nand_chip->read_byte(mtd); ++ id = dev_id | (manu_id << 8); ++ ext_id1 = nand_chip->read_byte(mtd); ++ ext_id2 = nand_chip->read_byte(mtd); ++ ext_id3 = nand_chip->read_byte(mtd); ++ ext_id = ext_id1 << 16 | ext_id2 << 8 | ext_id3; ++ if (!get_device_info(id, ext_id, &devinfo)) { ++ u32 chip_mode = RALINK_REG(RALINK_SYSCTL_BASE+0x010)&0x0F; ++ MSG(INIT, "Not Support this Device! \r\n"); ++ memset(&devinfo, 0 , sizeof(flashdev_info)); ++ MSG(INIT, "chip_mode=%08X\n",chip_mode); ++ ++ /* apply bootstrap first */ ++ devinfo.addr_cycle = 5; ++ devinfo.iowidth = 8; ++ ++ switch (chip_mode) { ++ case 10: ++ devinfo.pagesize = 2048; ++ devinfo.sparesize = 128; ++ devinfo.totalsize = 128; ++ devinfo.blocksize = 128; ++ break; ++ case 11: ++ devinfo.pagesize = 4096; ++ devinfo.sparesize = 128; ++ devinfo.totalsize = 1024; ++ devinfo.blocksize = 256; ++ break; ++ case 12: ++ devinfo.pagesize = 4096; ++ devinfo.sparesize = 224; ++ devinfo.totalsize = 2048; ++ devinfo.blocksize = 512; ++ break; ++ default: ++ case 1: ++ devinfo.pagesize = 2048; ++ devinfo.sparesize = 64; ++ devinfo.totalsize = 128; ++ devinfo.blocksize = 128; ++ break; ++ } ++ ++ devinfo.timmingsetting = NFI_DEFAULT_ACCESS_TIMING; ++ devinfo.devciename[0] = 'U'; ++ devinfo.advancedmode = 0; ++ } ++ mtd->writesize = devinfo.pagesize; ++ mtd->erasesize = (devinfo.blocksize<<10); ++ mtd->oobsize = devinfo.sparesize; ++ ++ nand_chip->chipsize = (devinfo.totalsize<<20); ++ nand_chip->page_shift = ffs(mtd->writesize) - 1; ++ nand_chip->pagemask = (nand_chip->chipsize >> nand_chip->page_shift) - 1; ++ nand_chip->phys_erase_shift = ffs(mtd->erasesize) - 1; ++ nand_chip->chip_shift = ffs(nand_chip->chipsize) - 1;//0x1C;//ffs(nand_chip->chipsize) - 1; ++ nand_chip->oob_poi = nand_chip->buffers->databuf + mtd->writesize; ++ nand_chip->badblockpos = 0; ++ ++ if (devinfo.pagesize == 4096) ++ nand_chip->ecc.layout = &nand_oob_128; ++ else if (devinfo.pagesize == 2048) ++ nand_chip->ecc.layout = &nand_oob_64; ++ else if (devinfo.pagesize == 512) ++ nand_chip->ecc.layout = &nand_oob_16; ++ ++ nand_chip->ecc.layout->eccbytes = devinfo.sparesize-OOB_AVAI_PER_SECTOR*(devinfo.pagesize/NAND_SECTOR_SIZE); ++ for (i = 0; i < nand_chip->ecc.layout->eccbytes; i++) ++ nand_chip->ecc.layout->eccpos[i]=OOB_AVAI_PER_SECTOR*(devinfo.pagesize/NAND_SECTOR_SIZE)+i; ++ ++ MSG(INIT, "Support this Device in MTK table! %x \r\n", id); ++ hw->nfi_bus_width = devinfo.iowidth; ++ DRV_WriteReg32(NFI_ACCCON_REG32, devinfo.timmingsetting); ++ ++ /* 16-bit bus width */ ++ if (hw->nfi_bus_width == 16) { ++ MSG(INIT, "%s : Set the 16-bit I/O settings!\n", MODULE_NAME); ++ nand_chip->options |= NAND_BUSWIDTH_16; ++ } ++ mtd->oobsize = devinfo.sparesize; ++ hw->nfi_cs_num = 1; ++ ++ /* Scan to find existance of the device */ ++ if (nand_scan(mtd, hw->nfi_cs_num)) { ++ MSG(INIT, "%s : nand_scan fail.\n", MODULE_NAME); ++ err = -ENXIO; ++ goto out; ++ } ++ ++ g_page_size = mtd->writesize; ++ platform_set_drvdata(pdev, host); ++ if (hw->nfi_bus_width == 16) { ++ NFI_SET_REG16(NFI_PAGEFMT_REG16, PAGEFMT_DBYTE_EN); ++ } ++ ++ nand_chip->select_chip(mtd, 0); ++#if defined(MTK_NAND_BMT) ++ nand_chip->chipsize -= (BMT_POOL_SIZE) << nand_chip->phys_erase_shift; ++#endif ++ mtd->size = nand_chip->chipsize; ++ ++ CFG_BLOCKSIZE = mtd->erasesize; ++ ++#if defined(MTK_NAND_BMT) ++ if (!g_bmt) { ++ if (!(g_bmt = init_bmt(nand_chip, BMT_POOL_SIZE))) { ++ MSG(INIT, "Error: init bmt failed\n"); ++ return 0; ++ } ++ } ++#endif ++ ++ ppdata.of_node = pdev->dev.of_node; ++ err = mtd_device_parse_register(mtd, probe_types, &ppdata, ++ NULL, 0); ++ if (!err) { ++ MSG(INIT, "[mtk_nand] probe successfully!\n"); ++ nand_disable_clock(); ++ shift_on_bbt = 1; ++ if (load_fact_bbt(mtd) == 0) { ++ int i; ++ for (i = 0; i < 0x100; i++) ++ nand_chip->bbt[i] |= fact_bbt[i]; ++ } ++ ++ return err; ++ } ++ ++out: ++ MSG(INIT, "[NFI] mtk_nand_probe fail, err = %d!\n", err); ++ nand_release(mtd); ++ platform_set_drvdata(pdev, NULL); ++ kfree(host); ++ nand_disable_clock(); ++ return err; ++} ++ ++static int ++mtk_nand_remove(struct platform_device *pdev) ++{ ++ struct mtk_nand_host *host = platform_get_drvdata(pdev); ++ struct mtd_info *mtd = &host->mtd; ++ ++ nand_release(mtd); ++ kfree(host); ++ nand_disable_clock(); ++ ++ return 0; ++} ++ ++static const struct of_device_id mt7621_nand_match[] = { ++ { .compatible = "mtk,mt7621-nand" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mt7621_nand_match); ++ ++static struct platform_driver mtk_nand_driver = { ++ .probe = mtk_nand_probe, ++ .remove = mtk_nand_remove, ++ .driver = { ++ .name = "MT7621-NAND", ++ .owner = THIS_MODULE, ++ .of_match_table = mt7621_nand_match, ++ }, ++}; ++ ++static int __init ++mtk_nand_init(void) ++{ ++ printk("MediaTek Nand driver init, version %s\n", VERSION); ++ ++ return platform_driver_register(&mtk_nand_driver); ++} ++ ++static void __exit ++mtk_nand_exit(void) ++{ ++ platform_driver_unregister(&mtk_nand_driver); ++} ++ ++module_init(mtk_nand_init); ++module_exit(mtk_nand_exit); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/mtd/nand/mtk_nand.h +@@ -0,0 +1,452 @@ ++#ifndef __MTK_NAND_H ++#define __MTK_NAND_H ++ ++#define RALINK_NAND_CTRL_BASE 0xBE003000 ++#define RALINK_SYSCTL_BASE 0xBE000000 ++#define RALINK_NANDECC_CTRL_BASE 0xBE003800 ++/******************************************************************************* ++ * NFI Register Definition ++ *******************************************************************************/ ++ ++#define NFI_CNFG_REG16 ((volatile P_U16)(NFI_BASE+0x0000)) ++#define NFI_PAGEFMT_REG16 ((volatile P_U16)(NFI_BASE+0x0004)) ++#define NFI_CON_REG16 ((volatile P_U16)(NFI_BASE+0x0008)) ++#define NFI_ACCCON_REG32 ((volatile P_U32)(NFI_BASE+0x000C)) ++#define NFI_INTR_EN_REG16 ((volatile P_U16)(NFI_BASE+0x0010)) ++#define NFI_INTR_REG16 ((volatile P_U16)(NFI_BASE+0x0014)) ++ ++#define NFI_CMD_REG16 ((volatile P_U16)(NFI_BASE+0x0020)) ++ ++#define NFI_ADDRNOB_REG16 ((volatile P_U16)(NFI_BASE+0x0030)) ++#define NFI_COLADDR_REG32 ((volatile P_U32)(NFI_BASE+0x0034)) ++#define NFI_ROWADDR_REG32 ((volatile P_U32)(NFI_BASE+0x0038)) ++ ++#define NFI_STRDATA_REG16 ((volatile P_U16)(NFI_BASE+0x0040)) ++ ++#define NFI_DATAW_REG32 ((volatile P_U32)(NFI_BASE+0x0050)) ++#define NFI_DATAR_REG32 ((volatile P_U32)(NFI_BASE+0x0054)) ++#define NFI_PIO_DIRDY_REG16 ((volatile P_U16)(NFI_BASE+0x0058)) ++ ++#define NFI_STA_REG32 ((volatile P_U32)(NFI_BASE+0x0060)) ++#define NFI_FIFOSTA_REG16 ((volatile P_U16)(NFI_BASE+0x0064)) ++#define NFI_LOCKSTA_REG16 ((volatile P_U16)(NFI_BASE+0x0068)) ++ ++#define NFI_ADDRCNTR_REG16 ((volatile P_U16)(NFI_BASE+0x0070)) ++ ++#define NFI_STRADDR_REG32 ((volatile P_U32)(NFI_BASE+0x0080)) ++#define NFI_BYTELEN_REG16 ((volatile P_U16)(NFI_BASE+0x0084)) ++ ++#define NFI_CSEL_REG16 ((volatile P_U16)(NFI_BASE+0x0090)) ++#define NFI_IOCON_REG16 ((volatile P_U16)(NFI_BASE+0x0094)) ++ ++#define NFI_FDM0L_REG32 ((volatile P_U32)(NFI_BASE+0x00A0)) ++#define NFI_FDM0M_REG32 ((volatile P_U32)(NFI_BASE+0x00A4)) ++ ++#define NFI_LOCK_REG16 ((volatile P_U16)(NFI_BASE+0x0100)) ++#define NFI_LOCKCON_REG32 ((volatile P_U32)(NFI_BASE+0x0104)) ++#define NFI_LOCKANOB_REG16 ((volatile P_U16)(NFI_BASE+0x0108)) ++#define NFI_LOCK00ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0110)) ++#define NFI_LOCK00FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0114)) ++#define NFI_LOCK01ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0118)) ++#define NFI_LOCK01FMT_REG32 ((volatile P_U32)(NFI_BASE+0x011C)) ++#define NFI_LOCK02ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0120)) ++#define NFI_LOCK02FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0124)) ++#define NFI_LOCK03ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0128)) ++#define NFI_LOCK03FMT_REG32 ((volatile P_U32)(NFI_BASE+0x012C)) ++#define NFI_LOCK04ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0130)) ++#define NFI_LOCK04FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0134)) ++#define NFI_LOCK05ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0138)) ++#define NFI_LOCK05FMT_REG32 ((volatile P_U32)(NFI_BASE+0x013C)) ++#define NFI_LOCK06ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0140)) ++#define NFI_LOCK06FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0144)) ++#define NFI_LOCK07ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0148)) ++#define NFI_LOCK07FMT_REG32 ((volatile P_U32)(NFI_BASE+0x014C)) ++#define NFI_LOCK08ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0150)) ++#define NFI_LOCK08FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0154)) ++#define NFI_LOCK09ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0158)) ++#define NFI_LOCK09FMT_REG32 ((volatile P_U32)(NFI_BASE+0x015C)) ++#define NFI_LOCK10ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0160)) ++#define NFI_LOCK10FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0164)) ++#define NFI_LOCK11ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0168)) ++#define NFI_LOCK11FMT_REG32 ((volatile P_U32)(NFI_BASE+0x016C)) ++#define NFI_LOCK12ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0170)) ++#define NFI_LOCK12FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0174)) ++#define NFI_LOCK13ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0178)) ++#define NFI_LOCK13FMT_REG32 ((volatile P_U32)(NFI_BASE+0x017C)) ++#define NFI_LOCK14ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0180)) ++#define NFI_LOCK14FMT_REG32 ((volatile P_U32)(NFI_BASE+0x0184)) ++#define NFI_LOCK15ADD_REG32 ((volatile P_U32)(NFI_BASE+0x0188)) ++#define NFI_LOCK15FMT_REG32 ((volatile P_U32)(NFI_BASE+0x018C)) ++ ++#define NFI_FIFODATA0_REG32 ((volatile P_U32)(NFI_BASE+0x0190)) ++#define NFI_FIFODATA1_REG32 ((volatile P_U32)(NFI_BASE+0x0194)) ++#define NFI_FIFODATA2_REG32 ((volatile P_U32)(NFI_BASE+0x0198)) ++#define NFI_FIFODATA3_REG32 ((volatile P_U32)(NFI_BASE+0x019C)) ++#define NFI_MASTERSTA_REG16 ((volatile P_U16)(NFI_BASE+0x0210)) ++ ++ ++/******************************************************************************* ++ * NFI Register Field Definition ++ *******************************************************************************/ ++ ++/* NFI_CNFG */ ++#define CNFG_AHB (0x0001) ++#define CNFG_READ_EN (0x0002) ++#define CNFG_DMA_BURST_EN (0x0004) ++#define CNFG_BYTE_RW (0x0040) ++#define CNFG_HW_ECC_EN (0x0100) ++#define CNFG_AUTO_FMT_EN (0x0200) ++#define CNFG_OP_IDLE (0x0000) ++#define CNFG_OP_READ (0x1000) ++#define CNFG_OP_SRD (0x2000) ++#define CNFG_OP_PRGM (0x3000) ++#define CNFG_OP_ERASE (0x4000) ++#define CNFG_OP_RESET (0x5000) ++#define CNFG_OP_CUST (0x6000) ++#define CNFG_OP_MODE_MASK (0x7000) ++#define CNFG_OP_MODE_SHIFT (12) ++ ++/* NFI_PAGEFMT */ ++#define PAGEFMT_512 (0x0000) ++#define PAGEFMT_2K (0x0001) ++#define PAGEFMT_4K (0x0002) ++ ++#define PAGEFMT_PAGE_MASK (0x0003) ++ ++#define PAGEFMT_DBYTE_EN (0x0008) ++ ++#define PAGEFMT_SPARE_16 (0x0000) ++#define PAGEFMT_SPARE_26 (0x0001) ++#define PAGEFMT_SPARE_27 (0x0002) ++#define PAGEFMT_SPARE_28 (0x0003) ++#define PAGEFMT_SPARE_MASK (0x0030) ++#define PAGEFMT_SPARE_SHIFT (4) ++ ++#define PAGEFMT_FDM_MASK (0x0F00) ++#define PAGEFMT_FDM_SHIFT (8) ++ ++#define PAGEFMT_FDM_ECC_MASK (0xF000) ++#define PAGEFMT_FDM_ECC_SHIFT (12) ++ ++/* NFI_CON */ ++#define CON_FIFO_FLUSH (0x0001) ++#define CON_NFI_RST (0x0002) ++#define CON_NFI_SRD (0x0010) ++ ++#define CON_NFI_NOB_MASK (0x0060) ++#define CON_NFI_NOB_SHIFT (5) ++ ++#define CON_NFI_BRD (0x0100) ++#define CON_NFI_BWR (0x0200) ++ ++#define CON_NFI_SEC_MASK (0xF000) ++#define CON_NFI_SEC_SHIFT (12) ++ ++/* NFI_ACCCON */ ++#define ACCCON_SETTING () ++ ++/* NFI_INTR_EN */ ++#define INTR_RD_DONE_EN (0x0001) ++#define INTR_WR_DONE_EN (0x0002) ++#define INTR_RST_DONE_EN (0x0004) ++#define INTR_ERASE_DONE_EN (0x0008) ++#define INTR_BSY_RTN_EN (0x0010) ++#define INTR_ACC_LOCK_EN (0x0020) ++#define INTR_AHB_DONE_EN (0x0040) ++#define INTR_ALL_INTR_DE (0x0000) ++#define INTR_ALL_INTR_EN (0x007F) ++ ++/* NFI_INTR */ ++#define INTR_RD_DONE (0x0001) ++#define INTR_WR_DONE (0x0002) ++#define INTR_RST_DONE (0x0004) ++#define INTR_ERASE_DONE (0x0008) ++#define INTR_BSY_RTN (0x0010) ++#define INTR_ACC_LOCK (0x0020) ++#define INTR_AHB_DONE (0x0040) ++ ++/* NFI_ADDRNOB */ ++#define ADDR_COL_NOB_MASK (0x0003) ++#define ADDR_COL_NOB_SHIFT (0) ++#define ADDR_ROW_NOB_MASK (0x0030) ++#define ADDR_ROW_NOB_SHIFT (4) ++ ++/* NFI_STA */ ++#define STA_READ_EMPTY (0x00001000) ++#define STA_ACC_LOCK (0x00000010) ++#define STA_CMD_STATE (0x00000001) ++#define STA_ADDR_STATE (0x00000002) ++#define STA_DATAR_STATE (0x00000004) ++#define STA_DATAW_STATE (0x00000008) ++ ++#define STA_NAND_FSM_MASK (0x1F000000) ++#define STA_NAND_BUSY (0x00000100) ++#define STA_NAND_BUSY_RETURN (0x00000200) ++#define STA_NFI_FSM_MASK (0x000F0000) ++#define STA_NFI_OP_MASK (0x0000000F) ++ ++/* NFI_FIFOSTA */ ++#define FIFO_RD_EMPTY (0x0040) ++#define FIFO_RD_FULL (0x0080) ++#define FIFO_WR_FULL (0x8000) ++#define FIFO_WR_EMPTY (0x4000) ++#define FIFO_RD_REMAIN(x) (0x1F&(x)) ++#define FIFO_WR_REMAIN(x) ((0x1F00&(x))>>8) ++ ++/* NFI_ADDRCNTR */ ++#define ADDRCNTR_CNTR(x) ((0xF000&(x))>>12) ++#define ADDRCNTR_OFFSET(x) (0x03FF&(x)) ++ ++/* NFI_LOCK */ ++#define NFI_LOCK_ON (0x0001) ++ ++/* NFI_LOCKANOB */ ++#define PROG_RADD_NOB_MASK (0x7000) ++#define PROG_RADD_NOB_SHIFT (12) ++#define PROG_CADD_NOB_MASK (0x0300) ++#define PROG_CADD_NOB_SHIFT (8) ++#define ERASE_RADD_NOB_MASK (0x0070) ++#define ERASE_RADD_NOB_SHIFT (4) ++#define ERASE_CADD_NOB_MASK (0x0007) ++#define ERASE_CADD_NOB_SHIFT (0) ++ ++/******************************************************************************* ++ * ECC Register Definition ++ *******************************************************************************/ ++ ++#define ECC_ENCCON_REG16 ((volatile P_U16)(NFIECC_BASE+0x0000)) ++#define ECC_ENCCNFG_REG32 ((volatile P_U32)(NFIECC_BASE+0x0004)) ++#define ECC_ENCDIADDR_REG32 ((volatile P_U32)(NFIECC_BASE+0x0008)) ++#define ECC_ENCIDLE_REG32 ((volatile P_U32)(NFIECC_BASE+0x000C)) ++#define ECC_ENCPAR0_REG32 ((volatile P_U32)(NFIECC_BASE+0x0010)) ++#define ECC_ENCPAR1_REG32 ((volatile P_U32)(NFIECC_BASE+0x0014)) ++#define ECC_ENCPAR2_REG32 ((volatile P_U32)(NFIECC_BASE+0x0018)) ++#define ECC_ENCPAR3_REG32 ((volatile P_U32)(NFIECC_BASE+0x001C)) ++#define ECC_ENCPAR4_REG32 ((volatile P_U32)(NFIECC_BASE+0x0020)) ++#define ECC_ENCSTA_REG32 ((volatile P_U32)(NFIECC_BASE+0x0024)) ++#define ECC_ENCIRQEN_REG16 ((volatile P_U16)(NFIECC_BASE+0x0028)) ++#define ECC_ENCIRQSTA_REG16 ((volatile P_U16)(NFIECC_BASE+0x002C)) ++ ++#define ECC_DECCON_REG16 ((volatile P_U16)(NFIECC_BASE+0x0100)) ++#define ECC_DECCNFG_REG32 ((volatile P_U32)(NFIECC_BASE+0x0104)) ++#define ECC_DECDIADDR_REG32 ((volatile P_U32)(NFIECC_BASE+0x0108)) ++#define ECC_DECIDLE_REG16 ((volatile P_U16)(NFIECC_BASE+0x010C)) ++#define ECC_DECFER_REG16 ((volatile P_U16)(NFIECC_BASE+0x0110)) ++#define ECC_DECENUM_REG32 ((volatile P_U32)(NFIECC_BASE+0x0114)) ++#define ECC_DECDONE_REG16 ((volatile P_U16)(NFIECC_BASE+0x0118)) ++#define ECC_DECEL0_REG32 ((volatile P_U32)(NFIECC_BASE+0x011C)) ++#define ECC_DECEL1_REG32 ((volatile P_U32)(NFIECC_BASE+0x0120)) ++#define ECC_DECEL2_REG32 ((volatile P_U32)(NFIECC_BASE+0x0124)) ++#define ECC_DECEL3_REG32 ((volatile P_U32)(NFIECC_BASE+0x0128)) ++#define ECC_DECEL4_REG32 ((volatile P_U32)(NFIECC_BASE+0x012C)) ++#define ECC_DECEL5_REG32 ((volatile P_U32)(NFIECC_BASE+0x0130)) ++#define ECC_DECIRQEN_REG16 ((volatile P_U16)(NFIECC_BASE+0x0134)) ++#define ECC_DECIRQSTA_REG16 ((volatile P_U16)(NFIECC_BASE+0x0138)) ++#define ECC_FDMADDR_REG32 ((volatile P_U32)(NFIECC_BASE+0x013C)) ++#define ECC_DECFSM_REG32 ((volatile P_U32)(NFIECC_BASE+0x0140)) ++#define ECC_SYNSTA_REG32 ((volatile P_U32)(NFIECC_BASE+0x0144)) ++#define ECC_DECNFIDI_REG32 ((volatile P_U32)(NFIECC_BASE+0x0148)) ++#define ECC_SYN0_REG32 ((volatile P_U32)(NFIECC_BASE+0x014C)) ++ ++/******************************************************************************* ++ * ECC register definition ++ *******************************************************************************/ ++/* ECC_ENCON */ ++#define ENC_EN (0x0001) ++#define ENC_DE (0x0000) ++ ++/* ECC_ENCCNFG */ ++#define ECC_CNFG_ECC4 (0x0000) ++#define ECC_CNFG_ECC6 (0x0001) ++#define ECC_CNFG_ECC8 (0x0002) ++#define ECC_CNFG_ECC10 (0x0003) ++#define ECC_CNFG_ECC12 (0x0004) ++#define ECC_CNFG_ECC_MASK (0x00000007) ++ ++#define ENC_CNFG_NFI (0x0010) ++#define ENC_CNFG_MODE_MASK (0x0010) ++ ++#define ENC_CNFG_META6 (0x10300000) ++#define ENC_CNFG_META8 (0x10400000) ++ ++#define ENC_CNFG_MSG_MASK (0x1FFF0000) ++#define ENC_CNFG_MSG_SHIFT (0x10) ++ ++/* ECC_ENCIDLE */ ++#define ENC_IDLE (0x0001) ++ ++/* ECC_ENCSTA */ ++#define STA_FSM (0x001F) ++#define STA_COUNT_PS (0xFF10) ++#define STA_COUNT_MS (0x3FFF0000) ++ ++/* ECC_ENCIRQEN */ ++#define ENC_IRQEN (0x0001) ++ ++/* ECC_ENCIRQSTA */ ++#define ENC_IRQSTA (0x0001) ++ ++/* ECC_DECCON */ ++#define DEC_EN (0x0001) ++#define DEC_DE (0x0000) ++ ++/* ECC_ENCCNFG */ ++#define DEC_CNFG_ECC4 (0x0000) ++//#define DEC_CNFG_ECC6 (0x0001) ++//#define DEC_CNFG_ECC12 (0x0002) ++#define DEC_CNFG_NFI (0x0010) ++//#define DEC_CNFG_META6 (0x10300000) ++//#define DEC_CNFG_META8 (0x10400000) ++ ++#define DEC_CNFG_FER (0x01000) ++#define DEC_CNFG_EL (0x02000) ++#define DEC_CNFG_CORRECT (0x03000) ++#define DEC_CNFG_TYPE_MASK (0x03000) ++ ++#define DEC_CNFG_EMPTY_EN (0x80000000) ++ ++#define DEC_CNFG_CODE_MASK (0x1FFF0000) ++#define DEC_CNFG_CODE_SHIFT (0x10) ++ ++/* ECC_DECIDLE */ ++#define DEC_IDLE (0x0001) ++ ++/* ECC_DECFER */ ++#define DEC_FER0 (0x0001) ++#define DEC_FER1 (0x0002) ++#define DEC_FER2 (0x0004) ++#define DEC_FER3 (0x0008) ++#define DEC_FER4 (0x0010) ++#define DEC_FER5 (0x0020) ++#define DEC_FER6 (0x0040) ++#define DEC_FER7 (0x0080) ++ ++/* ECC_DECENUM */ ++#define ERR_NUM0 (0x0000000F) ++#define ERR_NUM1 (0x000000F0) ++#define ERR_NUM2 (0x00000F00) ++#define ERR_NUM3 (0x0000F000) ++#define ERR_NUM4 (0x000F0000) ++#define ERR_NUM5 (0x00F00000) ++#define ERR_NUM6 (0x0F000000) ++#define ERR_NUM7 (0xF0000000) ++ ++/* ECC_DECDONE */ ++#define DEC_DONE0 (0x0001) ++#define DEC_DONE1 (0x0002) ++#define DEC_DONE2 (0x0004) ++#define DEC_DONE3 (0x0008) ++#define DEC_DONE4 (0x0010) ++#define DEC_DONE5 (0x0020) ++#define DEC_DONE6 (0x0040) ++#define DEC_DONE7 (0x0080) ++ ++/* ECC_DECIRQEN */ ++#define DEC_IRQEN (0x0001) ++ ++/* ECC_DECIRQSTA */ ++#define DEC_IRQSTA (0x0001) ++ ++#define CHIPVER_ECO_1 (0x8a00) ++#define CHIPVER_ECO_2 (0x8a01) ++ ++//#define NAND_PFM ++ ++/******************************************************************************* ++ * Data Structure Definition ++ *******************************************************************************/ ++struct mtk_nand_host ++{ ++ struct nand_chip nand_chip; ++ struct mtd_info mtd; ++ struct mtk_nand_host_hw *hw; ++}; ++ ++struct NAND_CMD ++{ ++ u32 u4ColAddr; ++ u32 u4RowAddr; ++ u32 u4OOBRowAddr; ++ u8 au1OOB[288]; ++ u8* pDataBuf; ++#ifdef NAND_PFM ++ u32 pureReadOOB; ++ u32 pureReadOOBNum; ++#endif ++}; ++ ++/* ++ * ECC layout control structure. Exported to userspace for ++ * diagnosis and to allow creation of raw images ++struct nand_ecclayout { ++ uint32_t eccbytes; ++ uint32_t eccpos[64]; ++ uint32_t oobavail; ++ struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES]; ++}; ++*/ ++#define __DEBUG_NAND 1 /* Debug information on/off */ ++ ++/* Debug message event */ ++#define DBG_EVT_NONE 0x00000000 /* No event */ ++#define DBG_EVT_INIT 0x00000001 /* Initial related event */ ++#define DBG_EVT_VERIFY 0x00000002 /* Verify buffer related event */ ++#define DBG_EVT_PERFORMANCE 0x00000004 /* Performance related event */ ++#define DBG_EVT_READ 0x00000008 /* Read related event */ ++#define DBG_EVT_WRITE 0x00000010 /* Write related event */ ++#define DBG_EVT_ERASE 0x00000020 /* Erase related event */ ++#define DBG_EVT_BADBLOCK 0x00000040 /* Badblock related event */ ++#define DBG_EVT_POWERCTL 0x00000080 /* Suspend/Resume related event */ ++ ++#define DBG_EVT_ALL 0xffffffff ++ ++#define DBG_EVT_MASK (DBG_EVT_INIT) ++ ++#if __DEBUG_NAND ++#define MSG(evt, fmt, args...) \ ++do { \ ++ if ((DBG_EVT_##evt) & DBG_EVT_MASK) { \ ++ printk(fmt, ##args); \ ++ } \ ++} while(0) ++ ++#define MSG_FUNC_ENTRY(f) MSG(FUC, "<FUN_ENT>: %s\n", __FUNCTION__) ++#else ++#define MSG(evt, fmt, args...) do{}while(0) ++#define MSG_FUNC_ENTRY(f) do{}while(0) ++#endif ++ ++#define RAMDOM_READ 1<<0 ++#define CACHE_READ 1<<1 ++ ++typedef struct ++{ ++ u16 id; //deviceid+menuid ++ u32 ext_id; ++ u8 addr_cycle; ++ u8 iowidth; ++ u16 totalsize; ++ u16 blocksize; ++ u16 pagesize; ++ u16 sparesize; ++ u32 timmingsetting; ++ char devciename[14]; ++ u32 advancedmode; // ++}flashdev_info,*pflashdev_info; ++ ++/* NAND driver */ ++#if 0 ++struct mtk_nand_host_hw { ++ unsigned int nfi_bus_width; /* NFI_BUS_WIDTH */ ++ unsigned int nfi_access_timing; /* NFI_ACCESS_TIMING */ ++ unsigned int nfi_cs_num; /* NFI_CS_NUM */ ++ unsigned int nand_sec_size; /* NAND_SECTOR_SIZE */ ++ unsigned int nand_sec_shift; /* NAND_SECTOR_SHIFT */ ++ unsigned int nand_ecc_size; ++ unsigned int nand_ecc_bytes; ++ unsigned int nand_ecc_mode; ++}; ++extern struct mtk_nand_host_hw mt7621_nand_hw; ++extern u32 CFG_BLOCKSIZE; ++#endif ++#endif +--- a/drivers/mtd/nand/nand_base.c ++++ b/drivers/mtd/nand/nand_base.c +@@ -93,7 +93,7 @@ static struct nand_ecclayout nand_oob_12 + .length = 78} } + }; + +-static int nand_get_device(struct mtd_info *mtd, int new_state); ++int nand_get_device(struct mtd_info *mtd, int new_state); + + static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, + struct mtd_oob_ops *ops); +@@ -131,7 +131,7 @@ static int check_offs_len(struct mtd_inf + * + * Release chip lock and wake up anyone waiting on the device. + */ +-static void nand_release_device(struct mtd_info *mtd) ++void nand_release_device(struct mtd_info *mtd) + { + struct nand_chip *chip = mtd->priv; + +@@ -803,7 +803,7 @@ static void panic_nand_get_device(struct + * + * Get the device and lock it for exclusive access + */ +-static int ++int + nand_get_device(struct mtd_info *mtd, int new_state) + { + struct nand_chip *chip = mtd->priv; +--- a/drivers/mtd/nand/nand_bbt.c ++++ b/drivers/mtd/nand/nand_bbt.c +@@ -1372,4 +1372,23 @@ int nand_markbad_bbt(struct mtd_info *mt + return ret; + } + ++void nand_bbt_set(struct mtd_info *mtd, int page, int flag) ++{ ++ struct nand_chip *this = mtd->priv; ++ int block; ++ ++ block = (int)(page >> (this->bbt_erase_shift - this->page_shift - 1)); ++ this->bbt[block >> 3] &= ~(0x03 << (block & 0x6)); ++ this->bbt[block >> 3] |= (flag & 0x3) << (block & 0x6); ++} ++ ++int nand_bbt_get(struct mtd_info *mtd, int page) ++{ ++ struct nand_chip *this = mtd->priv; ++ int block; ++ ++ block = (int)(page >> (this->bbt_erase_shift - this->page_shift - 1)); ++ return (this->bbt[block >> 3] >> (block & 0x06)) & 0x03; ++} ++ + EXPORT_SYMBOL(nand_scan_bbt); +--- /dev/null ++++ b/drivers/mtd/nand/nand_def.h +@@ -0,0 +1,123 @@ ++#ifndef __NAND_DEF_H__ ++#define __NAND_DEF_H__ ++ ++#define VERSION "v2.1 Fix AHB virt2phys error" ++#define MODULE_NAME "# MTK NAND #" ++#define PROCNAME "driver/nand" ++ ++#undef TESTTIME ++//#define __UBOOT_NAND__ 1 ++#define __KERNEL_NAND__ 1 ++//#define __PRELOADER_NAND__ 1 ++//#define PMT 1 ++//#define _MTK_NAND_DUMMY_DRIVER ++//#define CONFIG_BADBLOCK_CHECK 1 ++//#ifdef CONFIG_BADBLOCK_CHECK ++//#define MTK_NAND_BMT 1 ++//#endif ++#define ECC_ENABLE 1 ++#define MANUAL_CORRECT 1 ++//#define __INTERNAL_USE_AHB_MODE__ (0) ++#define SKIP_BAD_BLOCK ++#define FACT_BBT ++ ++#ifndef NAND_OTP_SUPPORT ++#define NAND_OTP_SUPPORT 0 ++#endif ++ ++/******************************************************************************* ++ * Macro definition ++ *******************************************************************************/ ++//#define NFI_SET_REG32(reg, value) (DRV_WriteReg32(reg, DRV_Reg32(reg) | (value))) ++//#define NFI_SET_REG16(reg, value) (DRV_WriteReg16(reg, DRV_Reg16(reg) | (value))) ++//#define NFI_CLN_REG32(reg, value) (DRV_WriteReg32(reg, DRV_Reg32(reg) & (~(value)))) ++//#define NFI_CLN_REG16(reg, value) (DRV_WriteReg16(reg, DRV_Reg16(reg) & (~(value)))) ++ ++#if defined (__KERNEL_NAND__) ++#define NFI_SET_REG32(reg, value) \ ++do { \ ++ g_value = (DRV_Reg32(reg) | (value));\ ++ DRV_WriteReg32(reg, g_value); \ ++} while(0) ++ ++#define NFI_SET_REG16(reg, value) \ ++do { \ ++ g_value = (DRV_Reg16(reg) | (value));\ ++ DRV_WriteReg16(reg, g_value); \ ++} while(0) ++ ++#define NFI_CLN_REG32(reg, value) \ ++do { \ ++ g_value = (DRV_Reg32(reg) & (~(value)));\ ++ DRV_WriteReg32(reg, g_value); \ ++} while(0) ++ ++#define NFI_CLN_REG16(reg, value) \ ++do { \ ++ g_value = (DRV_Reg16(reg) & (~(value)));\ ++ DRV_WriteReg16(reg, g_value); \ ++} while(0) ++#endif ++ ++#define NFI_WAIT_STATE_DONE(state) do{;}while (__raw_readl(NFI_STA_REG32) & state) ++#define NFI_WAIT_TO_READY() do{;}while (!(__raw_readl(NFI_STA_REG32) & STA_BUSY2READY)) ++ ++ ++#define NAND_SECTOR_SIZE (512) ++#define OOB_PER_SECTOR (16) ++#define OOB_AVAI_PER_SECTOR (8) ++ ++#ifndef PART_SIZE_BMTPOOL ++#define BMT_POOL_SIZE (80) ++#else ++#define BMT_POOL_SIZE (PART_SIZE_BMTPOOL) ++#endif ++ ++#define PMT_POOL_SIZE (2) ++ ++#define TIMEOUT_1 0x1fff ++#define TIMEOUT_2 0x8ff ++#define TIMEOUT_3 0xffff ++#define TIMEOUT_4 0xffff//5000 //PIO ++ ++ ++/* temporarity definiation */ ++#if !defined (__KERNEL_NAND__) ++#define KERN_INFO ++#define KERN_WARNING ++#define KERN_ERR ++#define PAGE_SIZE (4096) ++#endif ++#define AddStorageTrace //AddStorageTrace ++#define STORAGE_LOGGER_MSG_NAND 0 ++#define NFI_BASE RALINK_NAND_CTRL_BASE ++#define NFIECC_BASE RALINK_NANDECC_CTRL_BASE ++ ++#ifdef __INTERNAL_USE_AHB_MODE__ ++#define MT65xx_POLARITY_LOW 0 ++#define MT65XX_PDN_PERI_NFI 0 ++#define MT65xx_EDGE_SENSITIVE 0 ++#define MT6575_NFI_IRQ_ID (58) ++#endif ++ ++#if defined (__KERNEL_NAND__) ++#define RALINK_REG(x) (*((volatile u32 *)(x))) ++#define __virt_to_phys(x) virt_to_phys((volatile void*)x) ++#else ++#define CONFIG_MTD_NAND_VERIFY_WRITE (1) ++#define printk printf ++#define ra_dbg printf ++#define BUG() //BUG() ++#define BUG_ON(x) //BUG_ON() ++#define NUM_PARTITIONS 1 ++#endif ++ ++#define NFI_DEFAULT_ACCESS_TIMING (0x30C77fff) //(0x44333) ++ ++//uboot only support 1 cs ++#define NFI_CS_NUM (1) ++#define NFI_DEFAULT_CS (0) ++ ++#include "mt6575_typedefs.h" ++ ++#endif /* __NAND_DEF_H__ */ +--- /dev/null ++++ b/drivers/mtd/nand/nand_device_list.h +@@ -0,0 +1,55 @@ ++/* Copyright Statement: ++ * ++ * This software/firmware and related documentation ("MediaTek Software") are ++ * protected under relevant copyright laws. The information contained herein ++ * is confidential and proprietary to MediaTek Inc. and/or its licensors. ++ * Without the prior written permission of MediaTek inc. and/or its licensors, ++ * any reproduction, modification, use or disclosure of MediaTek Software, ++ * and information contained herein, in whole or in part, shall be strictly prohibited. ++ */ ++/* MediaTek Inc. (C) 2010. All rights reserved. ++ * ++ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES ++ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") ++ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON ++ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. ++ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ++ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR ++ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH ++ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES ++ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES ++ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK ++ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR ++ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND ++ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, ++ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, ++ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO ++ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. ++ * ++ * The following software/firmware and/or related documentation ("MediaTek Software") ++ * have been modified by MediaTek Inc. All revisions are subject to any receiver's ++ * applicable license agreements with MediaTek Inc. ++ */ ++ ++#ifndef __NAND_DEVICE_LIST_H__ ++#define __NAND_DEVICE_LIST_H__ ++ ++static const flashdev_info gen_FlashTable[]={ ++ {0x20BC, 0x105554, 5, 16, 512, 128, 2048, 64, 0x1123, "EHD013151MA_5", 0}, ++ {0xECBC, 0x005554, 5, 16, 512, 128, 2048, 64, 0x1123, "K524G2GACB_A0", 0}, ++ {0x2CBC, 0x905556, 5, 16, 512, 128, 2048, 64, 0x21044333, "MT29C4G96MAZA", 0}, ++ {0xADBC, 0x905554, 5, 16, 512, 128, 2048, 64, 0x10801011, "H9DA4GH4JJAMC", 0}, ++ {0x01F1, 0x801D01, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "S34ML01G100TF", 0}, ++ {0x92F1, 0x8095FF, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "F59L1G81A", 0}, ++ {0xECD3, 0x519558, 5, 8, 1024, 128, 2048, 64, 0x44333, "K9K8G8000", 0}, ++ {0xC2F1, 0x801DC2, 4, 8, 128, 128, 2048, 64, 0x30C77fff, "MX30LF1G08AA", 0}, ++ {0x98D3, 0x902676, 5, 8, 1024, 256, 4096, 224, 0x00C25332, "TC58NVG3S0F", 0}, ++ {0x01DA, 0x909546, 5, 8, 256, 128, 2048, 128, 0x30C77fff, "S34ML02G200TF", 0}, ++ {0x01DC, 0x909556, 5, 8, 512, 128, 2048, 128, 0x30C77fff, "S34ML04G200TF", 0}, ++ {0x0000, 0x000000, 0, 0, 0, 0, 0, 0, 0, "xxxxxxxxxx", 0}, ++}; ++ ++ ++#endif +--- /dev/null ++++ b/drivers/mtd/nand/partition.h +@@ -0,0 +1,115 @@ ++/* Copyright Statement: ++ * ++ * This software/firmware and related documentation ("MediaTek Software") are ++ * protected under relevant copyright laws. The information contained herein ++ * is confidential and proprietary to MediaTek Inc. and/or its licensors. ++ * Without the prior written permission of MediaTek inc. and/or its licensors, ++ * any reproduction, modification, use or disclosure of MediaTek Software, ++ * and information contained herein, in whole or in part, shall be strictly prohibited. ++ */ ++/* MediaTek Inc. (C) 2010. All rights reserved. ++ * ++ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES ++ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") ++ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON ++ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. ++ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ++ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR ++ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH ++ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES ++ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES ++ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK ++ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR ++ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND ++ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, ++ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, ++ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO ++ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. ++ * ++ * The following software/firmware and/or related documentation ("MediaTek Software") ++ * have been modified by MediaTek Inc. All revisions are subject to any receiver's ++ * applicable license agreements with MediaTek Inc. ++ */ ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/nand.h> ++#include <linux/mtd/partitions.h> ++ ++#define RECONFIG_PARTITION_SIZE 1 ++ ++#define MTD_BOOT_PART_SIZE 0x80000 ++#define MTD_CONFIG_PART_SIZE 0x20000 ++#define MTD_FACTORY_PART_SIZE 0x20000 ++ ++extern unsigned int CFG_BLOCKSIZE; ++#define LARGE_MTD_BOOT_PART_SIZE (CFG_BLOCKSIZE<<2) ++#define LARGE_MTD_CONFIG_PART_SIZE (CFG_BLOCKSIZE<<2) ++#define LARGE_MTD_FACTORY_PART_SIZE (CFG_BLOCKSIZE<<1) ++ ++/*=======================================================================*/ ++/* NAND PARTITION Mapping */ ++/*=======================================================================*/ ++//#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition g_pasStatic_Partition[] = { ++ { ++ name: "ALL", ++ size: MTDPART_SIZ_FULL, ++ offset: 0, ++ }, ++ /* Put your own partition definitions here */ ++ { ++ name: "Bootloader", ++ size: MTD_BOOT_PART_SIZE, ++ offset: 0, ++ }, { ++ name: "Config", ++ size: MTD_CONFIG_PART_SIZE, ++ offset: MTDPART_OFS_APPEND ++ }, { ++ name: "Factory", ++ size: MTD_FACTORY_PART_SIZE, ++ offset: MTDPART_OFS_APPEND ++#ifdef CONFIG_RT2880_ROOTFS_IN_FLASH ++ }, { ++ name: "Kernel", ++ size: MTD_KERN_PART_SIZE, ++ offset: MTDPART_OFS_APPEND, ++ }, { ++ name: "RootFS", ++ size: MTD_ROOTFS_PART_SIZE, ++ offset: MTDPART_OFS_APPEND, ++#ifdef CONFIG_ROOTFS_IN_FLASH_NO_PADDING ++ }, { ++ name: "Kernel_RootFS", ++ size: MTD_KERN_PART_SIZE + MTD_ROOTFS_PART_SIZE, ++ offset: MTD_BOOT_PART_SIZE + MTD_CONFIG_PART_SIZE + MTD_FACTORY_PART_SIZE, ++#endif ++#else //CONFIG_RT2880_ROOTFS_IN_RAM ++ }, { ++ name: "Kernel", ++ size: 0x10000, ++ offset: MTDPART_OFS_APPEND, ++#endif ++#ifdef CONFIG_DUAL_IMAGE ++ }, { ++ name: "Kernel2", ++ size: MTD_KERN2_PART_SIZE, ++ offset: MTD_KERN2_PART_OFFSET, ++#ifdef CONFIG_RT2880_ROOTFS_IN_FLASH ++ }, { ++ name: "RootFS2", ++ size: MTD_ROOTFS2_PART_SIZE, ++ offset: MTD_ROOTFS2_PART_OFFSET, ++#endif ++#endif ++ } ++ ++}; ++ ++#define NUM_PARTITIONS ARRAY_SIZE(g_pasStatic_Partition) ++extern int part_num; // = NUM_PARTITIONS; ++//#endif ++#undef RECONFIG_PARTITION_SIZE ++ diff --git a/target/linux/ramips/patches-3.18/0046-DT-Add-documentation-for-gpio-ralink.patch b/target/linux/ramips/patches-3.18/0046-DT-Add-documentation-for-gpio-ralink.patch new file mode 100644 index 0000000..4c869eb --- /dev/null +++ b/target/linux/ramips/patches-3.18/0046-DT-Add-documentation-for-gpio-ralink.patch @@ -0,0 +1,59 @@ +From 6827bd971fc4f323fc91e4506771a13b827c49a3 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 28 Jul 2013 19:45:30 +0200 +Subject: [PATCH 46/57] DT: Add documentation for gpio-ralink + +Describe gpio-ralink binding. + +Signed-off-by: John Crispin <blogic@openwrt.org> +Cc: linux-mips@linux-mips.org +Cc: devicetree@vger.kernel.org +Cc: linux-gpio@vger.kernel.org +--- + .../devicetree/bindings/gpio/gpio-ralink.txt | 40 ++++++++++++++++++++ + 1 file changed, 40 insertions(+) + create mode 100644 Documentation/devicetree/bindings/gpio/gpio-ralink.txt + +--- /dev/null ++++ b/Documentation/devicetree/bindings/gpio/gpio-ralink.txt +@@ -0,0 +1,40 @@ ++Ralink SoC GPIO controller bindings ++ ++Required properties: ++- compatible: ++ - "ralink,rt2880-gpio" for Ralink controllers ++- #gpio-cells : Should be two. ++ - first cell is the pin number ++ - second cell is used to specify optional parameters (unused) ++- gpio-controller : Marks the device node as a GPIO controller ++- reg : Physical base address and length of the controller's registers ++- interrupt-parent: phandle to the INTC device node ++- interrupts : Specify the INTC interrupt number ++- ralink,num-gpios : Specify the number of GPIOs ++- ralink,register-map : The register layout depends on the GPIO bank and actual ++ SoC type. Register offsets need to be in this order. ++ [ INT, EDGE, RENA, FENA, DATA, DIR, POL, SET, RESET, TOGGLE ] ++ ++Optional properties: ++- ralink,gpio-base : Specify the GPIO chips base number ++ ++Example: ++ ++ gpio0: gpio@600 { ++ compatible = "ralink,rt5350-gpio", "ralink,rt2880-gpio"; ++ ++ #gpio-cells = <2>; ++ gpio-controller; ++ ++ reg = <0x600 0x34>; ++ ++ interrupt-parent = <&intc>; ++ interrupts = <6>; ++ ++ ralink,gpio-base = <0>; ++ ralink,num-gpios = <24>; ++ ralink,register-map = [ 00 04 08 0c ++ 20 24 28 2c ++ 30 34 ]; ++ ++ }; diff --git a/target/linux/ramips/patches-3.18/0047-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch b/target/linux/ramips/patches-3.18/0047-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch new file mode 100644 index 0000000..a742e0b --- /dev/null +++ b/target/linux/ramips/patches-3.18/0047-GPIO-MIPS-ralink-add-gpio-driver-for-ralink-SoC.patch @@ -0,0 +1,430 @@ +From 4b23ed96930650076caa524ffdde898cb937bdaa Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Mon, 4 Aug 2014 20:36:29 +0200 +Subject: [PATCH 47/57] GPIO: MIPS: ralink: add gpio driver for ralink SoC + +Add gpio driver for Ralink SoC. This driver makes the gpio core on +RT2880, RT305x, rt3352, rt3662, rt3883, rt5350 and mt7620 work. + +Signed-off-by: John Crispin <blogic@openwrt.org> +Cc: linux-mips@linux-mips.org +Cc: linux-gpio@vger.kernel.org +--- + arch/mips/include/asm/mach-ralink/gpio.h | 24 +++ + drivers/gpio/Kconfig | 6 + + drivers/gpio/Makefile | 1 + + drivers/gpio/gpio-ralink.c | 345 ++++++++++++++++++++++++++++++ + 4 files changed, 376 insertions(+) + create mode 100644 arch/mips/include/asm/mach-ralink/gpio.h + create mode 100644 drivers/gpio/gpio-ralink.c + +--- /dev/null ++++ b/arch/mips/include/asm/mach-ralink/gpio.h +@@ -0,0 +1,24 @@ ++/* ++ * Ralink SoC GPIO API support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ */ ++ ++#ifndef __ASM_MACH_RALINK_GPIO_H ++#define __ASM_MACH_RALINK_GPIO_H ++ ++#define ARCH_NR_GPIOS 128 ++#include <asm-generic/gpio.h> ++ ++#define gpio_get_value __gpio_get_value ++#define gpio_set_value __gpio_set_value ++#define gpio_cansleep __gpio_cansleep ++#define gpio_to_irq __gpio_to_irq ++ ++#endif /* __ASM_MACH_RALINK_GPIO_H */ +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -288,6 +288,12 @@ config GPIO_SCH311X + To compile this driver as a module, choose M here: the module will + be called gpio-sch311x. + ++config GPIO_RALINK ++ bool "Ralink GPIO Support" ++ depends on RALINK ++ help ++ Say yes here to support the Ralink SoC GPIO device ++ + config GPIO_SPEAR_SPICS + bool "ST SPEAr13xx SPI Chip Select as GPIO support" + depends on PLAT_SPEAR +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -67,6 +67,7 @@ obj-$(CONFIG_GPIO_PCF857X) += gpio-pcf85 + obj-$(CONFIG_GPIO_PCH) += gpio-pch.o + obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o + obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o ++obj-$(CONFIG_GPIO_RALINK) += gpio-ralink.o + obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o + obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o + obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o +--- /dev/null ++++ b/drivers/gpio/gpio-ralink.c +@@ -0,0 +1,355 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2013 John Crispin <blogic@openwrt.org> ++ */ ++ ++#include <linux/module.h> ++#include <linux/io.h> ++#include <linux/gpio.h> ++#include <linux/spinlock.h> ++#include <linux/platform_device.h> ++#include <linux/of_irq.h> ++#include <linux/irqdomain.h> ++#include <linux/interrupt.h> ++ ++enum ralink_gpio_reg { ++ GPIO_REG_INT = 0, ++ GPIO_REG_EDGE, ++ GPIO_REG_RENA, ++ GPIO_REG_FENA, ++ GPIO_REG_DATA, ++ GPIO_REG_DIR, ++ GPIO_REG_POL, ++ GPIO_REG_SET, ++ GPIO_REG_RESET, ++ GPIO_REG_TOGGLE, ++ GPIO_REG_MAX ++}; ++ ++struct ralink_gpio_chip { ++ struct gpio_chip chip; ++ u8 regs[GPIO_REG_MAX]; ++ ++ spinlock_t lock; ++ void __iomem *membase; ++ struct irq_domain *domain; ++ int irq; ++ ++ u32 rising; ++ u32 falling; ++}; ++ ++#define MAP_MAX 4 ++static struct irq_domain *irq_map[MAP_MAX]; ++static int irq_map_count; ++static atomic_t irq_refcount = ATOMIC_INIT(0); ++ ++static inline struct ralink_gpio_chip *to_ralink_gpio(struct gpio_chip *chip) ++{ ++ struct ralink_gpio_chip *rg; ++ ++ rg = container_of(chip, struct ralink_gpio_chip, chip); ++ ++ return rg; ++} ++ ++static inline void rt_gpio_w32(struct ralink_gpio_chip *rg, u8 reg, u32 val) ++{ ++ iowrite32(val, rg->membase + rg->regs[reg]); ++} ++ ++static inline u32 rt_gpio_r32(struct ralink_gpio_chip *rg, u8 reg) ++{ ++ return ioread32(rg->membase + rg->regs[reg]); ++} ++ ++static void ralink_gpio_set(struct gpio_chip *chip, unsigned offset, int value) ++{ ++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); ++ ++ rt_gpio_w32(rg, (value) ? GPIO_REG_SET : GPIO_REG_RESET, BIT(offset)); ++} ++ ++static int ralink_gpio_get(struct gpio_chip *chip, unsigned offset) ++{ ++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); ++ ++ return !!(rt_gpio_r32(rg, GPIO_REG_DATA) & BIT(offset)); ++} ++ ++static int ralink_gpio_direction_input(struct gpio_chip *chip, unsigned offset) ++{ ++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); ++ unsigned long flags; ++ u32 t; ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ t = rt_gpio_r32(rg, GPIO_REG_DIR); ++ t &= ~BIT(offset); ++ rt_gpio_w32(rg, GPIO_REG_DIR, t); ++ spin_unlock_irqrestore(&rg->lock, flags); ++ ++ return 0; ++} ++ ++static int ralink_gpio_direction_output(struct gpio_chip *chip, ++ unsigned offset, int value) ++{ ++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); ++ unsigned long flags; ++ u32 t; ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ ralink_gpio_set(chip, offset, value); ++ t = rt_gpio_r32(rg, GPIO_REG_DIR); ++ t |= BIT(offset); ++ rt_gpio_w32(rg, GPIO_REG_DIR, t); ++ spin_unlock_irqrestore(&rg->lock, flags); ++ ++ return 0; ++} ++ ++static int ralink_gpio_to_irq(struct gpio_chip *chip, unsigned pin) ++{ ++ struct ralink_gpio_chip *rg = to_ralink_gpio(chip); ++ ++ if (rg->irq < 1) ++ return -1; ++ ++ return irq_create_mapping(rg->domain, pin); ++} ++ ++static void ralink_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) ++{ ++ int i; ++ ++ for (i = 0; i < irq_map_count; i++) { ++ struct irq_domain *domain = irq_map[i]; ++ struct ralink_gpio_chip *rg; ++ unsigned long pending; ++ int bit; ++ ++ rg = (struct ralink_gpio_chip *) domain->host_data; ++ pending = rt_gpio_r32(rg, GPIO_REG_INT); ++ ++ for_each_set_bit(bit, &pending, rg->chip.ngpio) { ++ u32 map = irq_find_mapping(domain, bit); ++ generic_handle_irq(map); ++ rt_gpio_w32(rg, GPIO_REG_INT, BIT(bit)); ++ } ++ } ++} ++ ++static void ralink_gpio_irq_unmask(struct irq_data *d) ++{ ++ struct ralink_gpio_chip *rg; ++ unsigned long flags; ++ u32 rise, fall; ++ ++ rg = (struct ralink_gpio_chip *) d->domain->host_data; ++ rise = rt_gpio_r32(rg, GPIO_REG_RENA); ++ fall = rt_gpio_r32(rg, GPIO_REG_FENA); ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ rt_gpio_w32(rg, GPIO_REG_RENA, rise | (BIT(d->hwirq) & rg->rising)); ++ rt_gpio_w32(rg, GPIO_REG_FENA, fall | (BIT(d->hwirq) & rg->falling)); ++ spin_unlock_irqrestore(&rg->lock, flags); ++} ++ ++static void ralink_gpio_irq_mask(struct irq_data *d) ++{ ++ struct ralink_gpio_chip *rg; ++ unsigned long flags; ++ u32 rise, fall; ++ ++ rg = (struct ralink_gpio_chip *) d->domain->host_data; ++ rise = rt_gpio_r32(rg, GPIO_REG_RENA); ++ fall = rt_gpio_r32(rg, GPIO_REG_FENA); ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ rt_gpio_w32(rg, GPIO_REG_FENA, fall & ~BIT(d->hwirq)); ++ rt_gpio_w32(rg, GPIO_REG_RENA, rise & ~BIT(d->hwirq)); ++ spin_unlock_irqrestore(&rg->lock, flags); ++} ++ ++static int ralink_gpio_irq_type(struct irq_data *d, unsigned int type) ++{ ++ struct ralink_gpio_chip *rg; ++ u32 mask = BIT(d->hwirq); ++ ++ rg = (struct ralink_gpio_chip *) d->domain->host_data; ++ ++ if (type == IRQ_TYPE_PROBE) { ++ if ((rg->rising | rg->falling) & mask) ++ return 0; ++ ++ type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; ++ } ++ ++ if (type & IRQ_TYPE_EDGE_RISING) ++ rg->rising |= mask; ++ else ++ rg->rising &= ~mask; ++ ++ if (type & IRQ_TYPE_EDGE_FALLING) ++ rg->falling |= mask; ++ else ++ rg->falling &= ~mask; ++ ++ return 0; ++} ++ ++static struct irq_chip ralink_gpio_irq_chip = { ++ .name = "GPIO", ++ .irq_unmask = ralink_gpio_irq_unmask, ++ .irq_mask = ralink_gpio_irq_mask, ++ .irq_mask_ack = ralink_gpio_irq_mask, ++ .irq_set_type = ralink_gpio_irq_type, ++}; ++ ++static int gpio_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) ++{ ++ irq_set_chip_and_handler(irq, &ralink_gpio_irq_chip, handle_level_irq); ++ irq_set_handler_data(irq, d); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops irq_domain_ops = { ++ .xlate = irq_domain_xlate_onecell, ++ .map = gpio_map, ++}; ++ ++static void ralink_gpio_irq_init(struct device_node *np, ++ struct ralink_gpio_chip *rg) ++{ ++ if (irq_map_count >= MAP_MAX) ++ return; ++ ++ rg->irq = irq_of_parse_and_map(np, 0); ++ if (!rg->irq) ++ return; ++ ++ rg->domain = irq_domain_add_linear(np, rg->chip.ngpio, ++ &irq_domain_ops, rg); ++ if (!rg->domain) { ++ dev_err(rg->chip.dev, "irq_domain_add_linear failed\n"); ++ return; ++ } ++ ++ irq_map[irq_map_count++] = rg->domain; ++ ++ rt_gpio_w32(rg, GPIO_REG_RENA, 0x0); ++ rt_gpio_w32(rg, GPIO_REG_FENA, 0x0); ++ ++ if (!atomic_read(&irq_refcount)) ++ irq_set_chained_handler(rg->irq, ralink_gpio_irq_handler); ++ atomic_inc(&irq_refcount); ++ ++ dev_info(rg->chip.dev, "registering %d irq handlers\n", rg->chip.ngpio); ++} ++ ++static int ralink_gpio_request(struct gpio_chip *chip, unsigned offset) ++{ ++ int gpio = chip->base + offset; ++ ++ return pinctrl_request_gpio(gpio); ++} ++ ++static void ralink_gpio_free(struct gpio_chip *chip, unsigned offset) ++{ ++ int gpio = chip->base + offset; ++ ++ pinctrl_free_gpio(gpio); ++} ++ ++static int ralink_gpio_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ struct ralink_gpio_chip *rg; ++ const __be32 *ngpio, *gpiobase; ++ ++ if (!res) { ++ dev_err(&pdev->dev, "failed to find resource\n"); ++ return -ENOMEM; ++ } ++ ++ rg = devm_kzalloc(&pdev->dev, ++ sizeof(struct ralink_gpio_chip), GFP_KERNEL); ++ if (!rg) ++ return -ENOMEM; ++ ++ rg->membase = devm_ioremap_resource(&pdev->dev, res); ++ if (!rg->membase) { ++ dev_err(&pdev->dev, "cannot remap I/O memory region\n"); ++ return -ENOMEM; ++ } ++ ++ if (of_property_read_u8_array(np, "ralink,register-map", ++ rg->regs, GPIO_REG_MAX)) { ++ dev_err(&pdev->dev, "failed to read register definition\n"); ++ return -EINVAL; ++ } ++ ++ ngpio = of_get_property(np, "ralink,num-gpios", NULL); ++ if (!ngpio) { ++ dev_err(&pdev->dev, "failed to read number of pins\n"); ++ return -EINVAL; ++ } ++ ++ gpiobase = of_get_property(np, "ralink,gpio-base", NULL); ++ if (gpiobase) ++ rg->chip.base = be32_to_cpu(*gpiobase); ++ else ++ rg->chip.base = -1; ++ ++ spin_lock_init(&rg->lock); ++ ++ rg->chip.dev = &pdev->dev; ++ rg->chip.label = dev_name(&pdev->dev); ++ rg->chip.of_node = np; ++ rg->chip.ngpio = be32_to_cpu(*ngpio); ++ rg->chip.direction_input = ralink_gpio_direction_input; ++ rg->chip.direction_output = ralink_gpio_direction_output; ++ rg->chip.get = ralink_gpio_get; ++ rg->chip.set = ralink_gpio_set; ++ rg->chip.request = ralink_gpio_request; ++ rg->chip.to_irq = ralink_gpio_to_irq; ++ rg->chip.free = ralink_gpio_free; ++ ++ /* set polarity to low for all lines */ ++ rt_gpio_w32(rg, GPIO_REG_POL, 0); ++ ++ dev_info(&pdev->dev, "registering %d gpios\n", rg->chip.ngpio); ++ ++ ralink_gpio_irq_init(np, rg); ++ ++ return gpiochip_add(&rg->chip); ++} ++ ++static const struct of_device_id ralink_gpio_match[] = { ++ { .compatible = "ralink,rt2880-gpio" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, ralink_gpio_match); ++ ++static struct platform_driver ralink_gpio_driver = { ++ .probe = ralink_gpio_probe, ++ .driver = { ++ .name = "rt2880_gpio", ++ .owner = THIS_MODULE, ++ .of_match_table = ralink_gpio_match, ++ }, ++}; ++ ++static int __init ralink_gpio_init(void) ++{ ++ return platform_driver_register(&ralink_gpio_driver); ++} ++ ++subsys_initcall(ralink_gpio_init); diff --git a/target/linux/ramips/patches-3.18/0048-GPIO-ralink-add-mt7621-gpio-controller.patch b/target/linux/ramips/patches-3.18/0048-GPIO-ralink-add-mt7621-gpio-controller.patch new file mode 100644 index 0000000..429af73 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0048-GPIO-ralink-add-mt7621-gpio-controller.patch @@ -0,0 +1,406 @@ +From 8481cdf6f96dc16cbcc129d046c021d17a891274 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 27 Jul 2014 11:00:32 +0100 +Subject: [PATCH 48/57] GPIO: ralink: add mt7621 gpio controller + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/Kconfig | 3 + + drivers/gpio/Kconfig | 6 ++ + drivers/gpio/Makefile | 1 + + drivers/gpio/gpio-mt7621.c | 177 ++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 187 insertions(+) + create mode 100644 drivers/gpio/gpio-mt7621.c + +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -455,6 +455,9 @@ config RALINK + select RESET_CONTROLLER + select PINCTRL + select PINCTRL_RT2880 ++ select ARCH_HAS_RESET_CONTROLLER ++ select RESET_CONTROLLER ++ select ARCH_REQUIRE_GPIOLIB + + config SGI_IP22 + bool "SGI IP22 (Indy/Indigo2)" +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -898,6 +898,12 @@ config GPIO_BCM_KONA + help + Turn on GPIO support for Broadcom "Kona" chips. + ++config GPIO_MT7621 ++ bool "Mediatek GPIO Support" ++ depends on SOC_MT7620 || SOC_MT7621 ++ help ++ Say yes here to support the Mediatek SoC GPIO device ++ + comment "USB GPIO expanders:" + + config GPIO_VIPERBOARD +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -107,3 +107,5 @@ obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx + obj-$(CONFIG_GPIO_XTENSA) += gpio-xtensa.o + obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o + obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o ++obj-$(CONFIG_GPIO_MT7621) += gpio-mt7621.o ++ +--- /dev/null ++++ b/drivers/gpio/gpio-mt7621.c +@@ -0,0 +1,354 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2013 John Crispin <blogic@openwrt.org> ++ */ ++ ++#include <linux/io.h> ++#include <linux/err.h> ++#include <linux/gpio.h> ++#include <linux/module.h> ++#include <linux/of_irq.h> ++#include <linux/spinlock.h> ++#include <linux/irqdomain.h> ++#include <linux/interrupt.h> ++#include <linux/platform_device.h> ++ ++#define MTK_MAX_BANK 3 ++#define MTK_BANK_WIDTH 32 ++ ++enum mediatek_gpio_reg { ++ GPIO_REG_CTRL = 0, ++ GPIO_REG_POL, ++ GPIO_REG_DATA, ++ GPIO_REG_DSET, ++ GPIO_REG_DCLR, ++ GPIO_REG_REDGE, ++ GPIO_REG_FEDGE, ++ GPIO_REG_HLVL, ++ GPIO_REG_LLVL, ++ GPIO_REG_STAT, ++ GPIO_REG_EDGE, ++}; ++ ++static void __iomem *mediatek_gpio_membase; ++static int mediatek_gpio_irq; ++static struct irq_domain *mediatek_gpio_irq_domain; ++static atomic_t irq_refcount = ATOMIC_INIT(0); ++ ++struct mtk_gc { ++ struct gpio_chip chip; ++ spinlock_t lock; ++ int bank; ++ u32 rising; ++ u32 falling; ++} *gc_map[MTK_MAX_BANK]; ++ ++static inline struct mtk_gc ++*to_mediatek_gpio(struct gpio_chip *chip) ++{ ++ struct mtk_gc *mgc; ++ ++ mgc = container_of(chip, struct mtk_gc, chip); ++ ++ return mgc; ++} ++ ++static inline void ++mtk_gpio_w32(struct mtk_gc *rg, u8 reg, u32 val) ++{ ++ iowrite32(val, mediatek_gpio_membase + (reg * 0x10) + (rg->bank * 0x4)); ++} ++ ++static inline u32 ++mtk_gpio_r32(struct mtk_gc *rg, u8 reg) ++{ ++ return ioread32(mediatek_gpio_membase + (reg * 0x10) + (rg->bank * 0x4)); ++} ++ ++static void ++mediatek_gpio_set(struct gpio_chip *chip, unsigned offset, int value) ++{ ++ struct mtk_gc *rg = to_mediatek_gpio(chip); ++ ++ mtk_gpio_w32(rg, (value) ? GPIO_REG_DSET : GPIO_REG_DCLR, BIT(offset)); ++} ++ ++static int ++mediatek_gpio_get(struct gpio_chip *chip, unsigned offset) ++{ ++ struct mtk_gc *rg = to_mediatek_gpio(chip); ++ ++ return !!(mtk_gpio_r32(rg, GPIO_REG_DATA) & BIT(offset)); ++} ++ ++static int ++mediatek_gpio_direction_input(struct gpio_chip *chip, unsigned offset) ++{ ++ struct mtk_gc *rg = to_mediatek_gpio(chip); ++ unsigned long flags; ++ u32 t; ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ t = mtk_gpio_r32(rg, GPIO_REG_CTRL); ++ t &= ~BIT(offset); ++ mtk_gpio_w32(rg, GPIO_REG_CTRL, t); ++ spin_unlock_irqrestore(&rg->lock, flags); ++ ++ return 0; ++} ++ ++static int ++mediatek_gpio_direction_output(struct gpio_chip *chip, ++ unsigned offset, int value) ++{ ++ struct mtk_gc *rg = to_mediatek_gpio(chip); ++ unsigned long flags; ++ u32 t; ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ t = mtk_gpio_r32(rg, GPIO_REG_CTRL); ++ t |= BIT(offset); ++ mtk_gpio_w32(rg, GPIO_REG_CTRL, t); ++ mediatek_gpio_set(chip, offset, value); ++ spin_unlock_irqrestore(&rg->lock, flags); ++ ++ return 0; ++} ++ ++static int ++mediatek_gpio_get_direction(struct gpio_chip *chip, unsigned offset) ++{ ++ struct mtk_gc *rg = to_mediatek_gpio(chip); ++ unsigned long flags; ++ u32 t; ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ t = mtk_gpio_r32(rg, GPIO_REG_CTRL); ++ spin_unlock_irqrestore(&rg->lock, flags); ++ ++ if (t & BIT(offset)) ++ return 0; ++ ++ return 1; ++} ++ ++static int ++mediatek_gpio_to_irq(struct gpio_chip *chip, unsigned pin) ++{ ++ struct mtk_gc *rg = to_mediatek_gpio(chip); ++ ++ return irq_create_mapping(mediatek_gpio_irq_domain, pin + (rg->bank * MTK_BANK_WIDTH)); ++} ++ ++static int ++mediatek_gpio_bank_probe(struct platform_device *pdev, struct device_node *bank) ++{ ++ const __be32 *id = of_get_property(bank, "reg", NULL); ++ struct mtk_gc *rg = devm_kzalloc(&pdev->dev, ++ sizeof(struct mtk_gc), GFP_KERNEL); ++ ++ if (!rg || !id || be32_to_cpu(*id) > MTK_MAX_BANK) ++ return -ENOMEM; ++ ++ gc_map[be32_to_cpu(*id)] = rg; ++ ++ memset(rg, 0, sizeof(struct mtk_gc)); ++ ++ spin_lock_init(&rg->lock); ++ ++ rg->chip.dev = &pdev->dev; ++ rg->chip.label = dev_name(&pdev->dev); ++ rg->chip.of_node = bank; ++ rg->chip.base = MTK_BANK_WIDTH * be32_to_cpu(*id); ++ rg->chip.ngpio = MTK_BANK_WIDTH; ++ rg->chip.direction_input = mediatek_gpio_direction_input; ++ rg->chip.direction_output = mediatek_gpio_direction_output; ++ rg->chip.get_direction = mediatek_gpio_get_direction; ++ rg->chip.get = mediatek_gpio_get; ++ rg->chip.set = mediatek_gpio_set; ++ if (mediatek_gpio_irq_domain) ++ rg->chip.to_irq = mediatek_gpio_to_irq; ++ rg->bank = be32_to_cpu(*id); ++ ++ /* set polarity to low for all gpios */ ++ mtk_gpio_w32(rg, GPIO_REG_POL, 0); ++ ++ dev_info(&pdev->dev, "registering %d gpios\n", rg->chip.ngpio); ++ ++ return gpiochip_add(&rg->chip); ++} ++ ++static void ++mediatek_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) ++{ ++ int i; ++ ++ for (i = 0; i < MTK_MAX_BANK; i++) { ++ struct mtk_gc *rg = gc_map[i]; ++ unsigned long pending; ++ int bit; ++ ++ if (!rg) ++ continue; ++ ++ pending = mtk_gpio_r32(rg, GPIO_REG_STAT); ++ ++ for_each_set_bit(bit, &pending, MTK_BANK_WIDTH) { ++ u32 map = irq_find_mapping(mediatek_gpio_irq_domain, (MTK_BANK_WIDTH * i) + bit); ++ ++ generic_handle_irq(map); ++ mtk_gpio_w32(rg, GPIO_REG_STAT, BIT(bit)); ++ } ++ } ++} ++ ++static void ++mediatek_gpio_irq_unmask(struct irq_data *d) ++{ ++ int pin = d->hwirq; ++ int bank = pin / 32; ++ struct mtk_gc *rg = gc_map[bank]; ++ unsigned long flags; ++ u32 rise, fall; ++ ++ if (!rg) ++ return; ++ ++ rise = mtk_gpio_r32(rg, GPIO_REG_REDGE); ++ fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE); ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ mtk_gpio_w32(rg, GPIO_REG_REDGE, rise | (BIT(d->hwirq) & rg->rising)); ++ mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall | (BIT(d->hwirq) & rg->falling)); ++ spin_unlock_irqrestore(&rg->lock, flags); ++} ++ ++static void ++mediatek_gpio_irq_mask(struct irq_data *d) ++{ ++ int pin = d->hwirq; ++ int bank = pin / 32; ++ struct mtk_gc *rg = gc_map[bank]; ++ unsigned long flags; ++ u32 rise, fall; ++ ++ if (!rg) ++ return; ++ ++ rise = mtk_gpio_r32(rg, GPIO_REG_REDGE); ++ fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE); ++ ++ spin_lock_irqsave(&rg->lock, flags); ++ mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall & ~BIT(d->hwirq)); ++ mtk_gpio_w32(rg, GPIO_REG_REDGE, rise & ~BIT(d->hwirq)); ++ spin_unlock_irqrestore(&rg->lock, flags); ++} ++ ++static int ++mediatek_gpio_irq_type(struct irq_data *d, unsigned int type) ++{ ++ int pin = d->hwirq; ++ int bank = pin / 32; ++ struct mtk_gc *rg = gc_map[bank]; ++ u32 mask = BIT(d->hwirq); ++ ++ if (!rg) ++ return -1; ++ ++ if (type == IRQ_TYPE_PROBE) { ++ if ((rg->rising | rg->falling) & mask) ++ return 0; ++ ++ type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; ++ } ++ ++ if (type & IRQ_TYPE_EDGE_RISING) ++ rg->rising |= mask; ++ else ++ rg->rising &= ~mask; ++ ++ if (type & IRQ_TYPE_EDGE_FALLING) ++ rg->falling |= mask; ++ else ++ rg->falling &= ~mask; ++ ++ return 0; ++} ++ ++static struct irq_chip mediatek_gpio_irq_chip = { ++ .name = "GPIO", ++ .irq_unmask = mediatek_gpio_irq_unmask, ++ .irq_mask = mediatek_gpio_irq_mask, ++ .irq_mask_ack = mediatek_gpio_irq_mask, ++ .irq_set_type = mediatek_gpio_irq_type, ++}; ++ ++static int ++mediatek_gpio_gpio_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) ++{ ++ irq_set_chip_and_handler(irq, &mediatek_gpio_irq_chip, handle_level_irq); ++ irq_set_handler_data(irq, d); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops irq_domain_ops = { ++ .xlate = irq_domain_xlate_onecell, ++ .map = mediatek_gpio_gpio_map, ++}; ++ ++static int ++mediatek_gpio_probe(struct platform_device *pdev) ++{ ++ struct device_node *bank, *np = pdev->dev.of_node; ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ mediatek_gpio_membase = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(mediatek_gpio_membase)) ++ return PTR_ERR(mediatek_gpio_membase); ++ ++ mediatek_gpio_irq = irq_of_parse_and_map(np, 0); ++ if (mediatek_gpio_irq) { ++ mediatek_gpio_irq_domain = irq_domain_add_linear(np, ++ MTK_MAX_BANK * MTK_BANK_WIDTH, ++ &irq_domain_ops, NULL); ++ if (!mediatek_gpio_irq_domain) ++ dev_err(&pdev->dev, "irq_domain_add_linear failed\n"); ++ } ++ ++ for_each_child_of_node(np, bank) ++ if (of_device_is_compatible(bank, "mtk,mt7621-gpio-bank")) ++ mediatek_gpio_bank_probe(pdev, bank); ++ ++ if (mediatek_gpio_irq_domain) ++ irq_set_chained_handler(mediatek_gpio_irq, mediatek_gpio_irq_handler); ++ ++ return 0; ++} ++ ++static const struct of_device_id mediatek_gpio_match[] = { ++ { .compatible = "mtk,mt7621-gpio" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mediatek_gpio_match); ++ ++static struct platform_driver mediatek_gpio_driver = { ++ .probe = mediatek_gpio_probe, ++ .driver = { ++ .name = "mt7621_gpio", ++ .owner = THIS_MODULE, ++ .of_match_table = mediatek_gpio_match, ++ }, ++}; ++ ++static int __init ++mediatek_gpio_init(void) ++{ ++ return platform_driver_register(&mediatek_gpio_driver); ++} ++ ++subsys_initcall(mediatek_gpio_init); diff --git a/target/linux/ramips/patches-3.18/0049-DT-Add-documentation-for-spi-rt2880.patch b/target/linux/ramips/patches-3.18/0049-DT-Add-documentation-for-spi-rt2880.patch new file mode 100644 index 0000000..23a6b3e --- /dev/null +++ b/target/linux/ramips/patches-3.18/0049-DT-Add-documentation-for-spi-rt2880.patch @@ -0,0 +1,44 @@ +From 6ed8d03e5f4283b60dffea5c10ff1484141824e7 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Fri, 9 Aug 2013 20:12:59 +0200 +Subject: [PATCH 49/57] DT: Add documentation for spi-rt2880 + +Describe the SPI master found on the MIPS based Ralink RT2880 SoC. + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + .../devicetree/bindings/spi/spi-rt2880.txt | 28 ++++++++++++++++++++ + 1 file changed, 28 insertions(+) + create mode 100644 Documentation/devicetree/bindings/spi/spi-rt2880.txt + +--- /dev/null ++++ b/Documentation/devicetree/bindings/spi/spi-rt2880.txt +@@ -0,0 +1,28 @@ ++Ralink SoC RT2880 SPI master controller. ++ ++This SPI controller is found on most wireless SoCs made by ralink. ++ ++Required properties: ++- compatible : "ralink,rt2880-spi" ++- reg : The register base for the controller. ++- #address-cells : <1>, as required by generic SPI binding. ++- #size-cells : <0>, also as required by generic SPI binding. ++ ++Child nodes as per the generic SPI binding. ++ ++Example: ++ ++ spi@b00 { ++ compatible = "ralink,rt2880-spi"; ++ reg = <0xb00 0x100>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ m25p80@0 { ++ compatible = "m25p80"; ++ reg = <0>; ++ spi-max-frequency = <10000000>; ++ }; ++ }; ++ diff --git a/target/linux/ramips/patches-3.18/0050-SPI-ralink-add-Ralink-SoC-spi-driver.patch b/target/linux/ramips/patches-3.18/0050-SPI-ralink-add-Ralink-SoC-spi-driver.patch new file mode 100644 index 0000000..cb691f3 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0050-SPI-ralink-add-Ralink-SoC-spi-driver.patch @@ -0,0 +1,476 @@ +From fc006d0622ab8c43086b2c9018c03012db332033 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 27 Jul 2014 11:15:12 +0100 +Subject: [PATCH 50/57] SPI: ralink: add Ralink SoC spi driver + +Add the driver needed to make SPI work on Ralink SoC. + +Signed-off-by: Gabor Juhos <juhosg@openwrt.org> +Acked-by: John Crispin <blogic@openwrt.org> +--- + drivers/spi/Kconfig | 6 + + drivers/spi/Makefile | 1 + + drivers/spi/spi-rt2880.c | 432 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 439 insertions(+) + create mode 100644 drivers/spi/spi-rt2880.c + +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -433,6 +433,12 @@ config SPI_QUP + This driver can also be built as a module. If so, the module + will be called spi_qup. + ++config SPI_RT2880 ++ tristate "Ralink RT288x SPI Controller" ++ depends on RALINK ++ help ++ This selects a driver for the Ralink RT288x/RT305x SPI Controller. ++ + config SPI_S3C24XX + tristate "Samsung S3C24XX series SPI" + depends on ARCH_S3C24XX +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -65,6 +65,7 @@ obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa + obj-$(CONFIG_SPI_QUP) += spi-qup.o + obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o + obj-$(CONFIG_SPI_RSPI) += spi-rspi.o ++obj-$(CONFIG_SPI_RT2880) += spi-rt2880.o + obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o + spi-s3c24xx-hw-y := spi-s3c24xx.o + spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o +--- /dev/null ++++ b/drivers/spi/spi-rt2880.c +@@ -0,0 +1,432 @@ ++/* ++ * spi-rt2880.c -- Ralink RT288x/RT305x SPI controller driver ++ * ++ * Copyright (C) 2011 Sergiy <piratfm@gmail.com> ++ * Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * Some parts are based on spi-orion.c: ++ * Author: Shadi Ammouri <shadi@marvell.com> ++ * Copyright (C) 2007-2008 Marvell Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/clk.h> ++#include <linux/err.h> ++#include <linux/delay.h> ++#include <linux/io.h> ++#include <linux/reset.h> ++#include <linux/spi/spi.h> ++#include <linux/platform_device.h> ++ ++#define DRIVER_NAME "spi-rt2880" ++/* only one slave is supported*/ ++#define RALINK_NUM_CHIPSELECTS 1 ++/* in usec */ ++#define RALINK_SPI_WAIT_MAX_LOOP 2000 ++ ++#define RAMIPS_SPI_STAT 0x00 ++#define RAMIPS_SPI_CFG 0x10 ++#define RAMIPS_SPI_CTL 0x14 ++#define RAMIPS_SPI_DATA 0x20 ++#define RAMIPS_SPI_FIFO_STAT 0x38 ++ ++/* SPISTAT register bit field */ ++#define SPISTAT_BUSY BIT(0) ++ ++/* SPICFG register bit field */ ++#define SPICFG_LSBFIRST 0 ++#define SPICFG_MSBFIRST BIT(8) ++#define SPICFG_SPICLKPOL BIT(6) ++#define SPICFG_RXCLKEDGE_FALLING BIT(5) ++#define SPICFG_TXCLKEDGE_FALLING BIT(4) ++#define SPICFG_SPICLK_PRESCALE_MASK 0x7 ++#define SPICFG_SPICLK_DIV2 0 ++#define SPICFG_SPICLK_DIV4 1 ++#define SPICFG_SPICLK_DIV8 2 ++#define SPICFG_SPICLK_DIV16 3 ++#define SPICFG_SPICLK_DIV32 4 ++#define SPICFG_SPICLK_DIV64 5 ++#define SPICFG_SPICLK_DIV128 6 ++#define SPICFG_SPICLK_DISABLE 7 ++ ++/* SPICTL register bit field */ ++#define SPICTL_HIZSDO BIT(3) ++#define SPICTL_STARTWR BIT(2) ++#define SPICTL_STARTRD BIT(1) ++#define SPICTL_SPIENA BIT(0) ++ ++/* SPIFIFOSTAT register bit field */ ++#define SPIFIFOSTAT_TXFULL BIT(17) ++ ++struct rt2880_spi { ++ struct spi_master *master; ++ void __iomem *base; ++ unsigned int sys_freq; ++ unsigned int speed; ++ struct clk *clk; ++ spinlock_t lock; ++}; ++ ++static inline struct rt2880_spi *spidev_to_rt2880_spi(struct spi_device *spi) ++{ ++ return spi_master_get_devdata(spi->master); ++} ++ ++static inline u32 rt2880_spi_read(struct rt2880_spi *rs, u32 reg) ++{ ++ return ioread32(rs->base + reg); ++} ++ ++static inline void rt2880_spi_write(struct rt2880_spi *rs, u32 reg, u32 val) ++{ ++ iowrite32(val, rs->base + reg); ++} ++ ++static inline void rt2880_spi_setbits(struct rt2880_spi *rs, u32 reg, u32 mask) ++{ ++ void __iomem *addr = rs->base + reg; ++ unsigned long flags; ++ u32 val; ++ ++ spin_lock_irqsave(&rs->lock, flags); ++ val = ioread32(addr); ++ val |= mask; ++ iowrite32(val, addr); ++ spin_unlock_irqrestore(&rs->lock, flags); ++} ++ ++static inline void rt2880_spi_clrbits(struct rt2880_spi *rs, u32 reg, u32 mask) ++{ ++ void __iomem *addr = rs->base + reg; ++ unsigned long flags; ++ u32 val; ++ ++ spin_lock_irqsave(&rs->lock, flags); ++ val = ioread32(addr); ++ val &= ~mask; ++ iowrite32(val, addr); ++ spin_unlock_irqrestore(&rs->lock, flags); ++} ++ ++static int rt2880_spi_baudrate_set(struct spi_device *spi, unsigned int speed) ++{ ++ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi); ++ u32 rate; ++ u32 prescale; ++ u32 reg; ++ ++ dev_dbg(&spi->dev, "speed:%u\n", speed); ++ ++ /* ++ * the supported rates are: 2, 4, 8, ... 128 ++ * round up as we look for equal or less speed ++ */ ++ rate = DIV_ROUND_UP(rs->sys_freq, speed); ++ dev_dbg(&spi->dev, "rate-1:%u\n", rate); ++ rate = roundup_pow_of_two(rate); ++ dev_dbg(&spi->dev, "rate-2:%u\n", rate); ++ ++ /* check if requested speed is too small */ ++ if (rate > 128) ++ return -EINVAL; ++ ++ if (rate < 2) ++ rate = 2; ++ ++ /* Convert the rate to SPI clock divisor value. */ ++ prescale = ilog2(rate / 2); ++ dev_dbg(&spi->dev, "prescale:%u\n", prescale); ++ ++ reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG); ++ reg = ((reg & ~SPICFG_SPICLK_PRESCALE_MASK) | prescale); ++ rt2880_spi_write(rs, RAMIPS_SPI_CFG, reg); ++ rs->speed = speed; ++ return 0; ++} ++ ++/* ++ * called only when no transfer is active on the bus ++ */ ++static int ++rt2880_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) ++{ ++ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi); ++ unsigned int speed = spi->max_speed_hz; ++ int rc; ++ ++ if ((t != NULL) && t->speed_hz) ++ speed = t->speed_hz; ++ ++ if (rs->speed != speed) { ++ dev_dbg(&spi->dev, "speed_hz:%u\n", speed); ++ rc = rt2880_spi_baudrate_set(spi, speed); ++ if (rc) ++ return rc; ++ } ++ ++ return 0; ++} ++ ++static void rt2880_spi_set_cs(struct rt2880_spi *rs, int enable) ++{ ++ if (enable) ++ rt2880_spi_clrbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA); ++ else ++ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA); ++} ++ ++static inline int rt2880_spi_wait_till_ready(struct rt2880_spi *rs) ++{ ++ int i; ++ ++ for (i = 0; i < RALINK_SPI_WAIT_MAX_LOOP; i++) { ++ u32 status; ++ ++ status = rt2880_spi_read(rs, RAMIPS_SPI_STAT); ++ if ((status & SPISTAT_BUSY) == 0) ++ return 0; ++ ++ cpu_relax(); ++ udelay(1); ++ } ++ ++ return -ETIMEDOUT; ++} ++ ++static unsigned int ++rt2880_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer) ++{ ++ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi); ++ unsigned count = 0; ++ u8 *rx = xfer->rx_buf; ++ const u8 *tx = xfer->tx_buf; ++ int err; ++ ++ dev_dbg(&spi->dev, "read (%d): %s %s\n", xfer->len, ++ (tx != NULL) ? "tx" : " ", ++ (rx != NULL) ? "rx" : " "); ++ ++ if (tx) { ++ for (count = 0; count < xfer->len; count++) { ++ rt2880_spi_write(rs, RAMIPS_SPI_DATA, tx[count]); ++ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTWR); ++ err = rt2880_spi_wait_till_ready(rs); ++ if (err) { ++ dev_err(&spi->dev, "TX failed, err=%d\n", err); ++ goto out; ++ } ++ } ++ } ++ ++ if (rx) { ++ for (count = 0; count < xfer->len; count++) { ++ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTRD); ++ err = rt2880_spi_wait_till_ready(rs); ++ if (err) { ++ dev_err(&spi->dev, "RX failed, err=%d\n", err); ++ goto out; ++ } ++ rx[count] = (u8) rt2880_spi_read(rs, RAMIPS_SPI_DATA); ++ } ++ } ++ ++out: ++ return count; ++} ++ ++static int rt2880_spi_transfer_one_message(struct spi_master *master, ++ struct spi_message *m) ++{ ++ struct rt2880_spi *rs = spi_master_get_devdata(master); ++ struct spi_device *spi = m->spi; ++ struct spi_transfer *t = NULL; ++ int par_override = 0; ++ int status = 0; ++ int cs_active = 0; ++ ++ /* Load defaults */ ++ status = rt2880_spi_setup_transfer(spi, NULL); ++ if (status < 0) ++ goto msg_done; ++ ++ list_for_each_entry(t, &m->transfers, transfer_list) { ++ if (t->tx_buf == NULL && t->rx_buf == NULL && t->len) { ++ dev_err(&spi->dev, ++ "message rejected: invalid transfer data buffers\n"); ++ status = -EIO; ++ goto msg_done; ++ } ++ ++ if (t->speed_hz && t->speed_hz < (rs->sys_freq / 128)) { ++ dev_err(&spi->dev, ++ "message rejected: device min speed (%d Hz) exceeds required transfer speed (%d Hz)\n", ++ (rs->sys_freq / 128), t->speed_hz); ++ status = -EIO; ++ goto msg_done; ++ } ++ ++ if (par_override || t->speed_hz || t->bits_per_word) { ++ par_override = 1; ++ status = rt2880_spi_setup_transfer(spi, t); ++ if (status < 0) ++ goto msg_done; ++ if (!t->speed_hz && !t->bits_per_word) ++ par_override = 0; ++ } ++ ++ if (!cs_active) { ++ rt2880_spi_set_cs(rs, 1); ++ cs_active = 1; ++ } ++ ++ if (t->len) ++ m->actual_length += rt2880_spi_write_read(spi, t); ++ ++ if (t->delay_usecs) ++ udelay(t->delay_usecs); ++ ++ if (t->cs_change) { ++ rt2880_spi_set_cs(rs, 0); ++ cs_active = 0; ++ } ++ } ++ ++msg_done: ++ if (cs_active) ++ rt2880_spi_set_cs(rs, 0); ++ ++ m->status = status; ++ spi_finalize_current_message(master); ++ ++ return 0; ++} ++ ++static int rt2880_spi_setup(struct spi_device *spi) ++{ ++ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi); ++ ++ if ((spi->max_speed_hz == 0) || ++ (spi->max_speed_hz > (rs->sys_freq / 2))) ++ spi->max_speed_hz = (rs->sys_freq / 2); ++ ++ if (spi->max_speed_hz < (rs->sys_freq / 128)) { ++ dev_err(&spi->dev, "setup: requested speed is too low %d Hz\n", ++ spi->max_speed_hz); ++ return -EINVAL; ++ } ++ ++ /* ++ * baudrate & width will be set rt2880_spi_setup_transfer ++ */ ++ return 0; ++} ++ ++static void rt2880_spi_reset(struct rt2880_spi *rs) ++{ ++ rt2880_spi_write(rs, RAMIPS_SPI_CFG, ++ SPICFG_MSBFIRST | SPICFG_TXCLKEDGE_FALLING | ++ SPICFG_SPICLK_DIV16 | SPICFG_SPICLKPOL); ++ rt2880_spi_write(rs, RAMIPS_SPI_CTL, SPICTL_HIZSDO | SPICTL_SPIENA); ++} ++ ++static int rt2880_spi_probe(struct platform_device *pdev) ++{ ++ struct spi_master *master; ++ struct rt2880_spi *rs; ++ unsigned long flags; ++ void __iomem *base; ++ struct resource *r; ++ int status = 0; ++ struct clk *clk; ++ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(&pdev->dev, r); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(clk)) { ++ dev_err(&pdev->dev, "unable to get SYS clock, err=%d\n", ++ status); ++ return PTR_ERR(clk); ++ } ++ ++ status = clk_prepare_enable(clk); ++ if (status) ++ return status; ++ ++ master = spi_alloc_master(&pdev->dev, sizeof(*rs)); ++ if (master == NULL) { ++ dev_dbg(&pdev->dev, "master allocation failed\n"); ++ return -ENOMEM; ++ } ++ ++ /* we support only mode 0, and no options */ ++ master->mode_bits = 0; ++ ++ master->setup = rt2880_spi_setup; ++ master->transfer_one_message = rt2880_spi_transfer_one_message; ++ master->num_chipselect = RALINK_NUM_CHIPSELECTS; ++ master->bits_per_word_mask = SPI_BPW_MASK(8); ++ master->dev.of_node = pdev->dev.of_node; ++ ++ dev_set_drvdata(&pdev->dev, master); ++ ++ rs = spi_master_get_devdata(master); ++ rs->base = base; ++ rs->clk = clk; ++ rs->master = master; ++ rs->sys_freq = clk_get_rate(rs->clk); ++ dev_dbg(&pdev->dev, "sys_freq: %u\n", rs->sys_freq); ++ spin_lock_irqsave(&rs->lock, flags); ++ ++ device_reset(&pdev->dev); ++ ++ rt2880_spi_reset(rs); ++ ++ return spi_register_master(master); ++} ++ ++static int rt2880_spi_remove(struct platform_device *pdev) ++{ ++ struct spi_master *master; ++ struct rt2880_spi *rs; ++ ++ master = dev_get_drvdata(&pdev->dev); ++ rs = spi_master_get_devdata(master); ++ ++ clk_disable(rs->clk); ++ spi_unregister_master(master); ++ ++ return 0; ++} ++ ++MODULE_ALIAS("platform:" DRIVER_NAME); ++ ++static const struct of_device_id rt2880_spi_match[] = { ++ { .compatible = "ralink,rt2880-spi" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rt2880_spi_match); ++ ++static struct platform_driver rt2880_spi_driver = { ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = rt2880_spi_match, ++ }, ++ .probe = rt2880_spi_probe, ++ .remove = rt2880_spi_remove, ++}; ++ ++module_platform_driver(rt2880_spi_driver); ++ ++MODULE_DESCRIPTION("Ralink SPI driver"); ++MODULE_AUTHOR("Sergiy <piratfm@gmail.com>"); ++MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/ramips/patches-3.18/0051-rt5350-spi-second-device.patch b/target/linux/ramips/patches-3.18/0051-rt5350-spi-second-device.patch new file mode 100644 index 0000000..2da8151 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0051-rt5350-spi-second-device.patch @@ -0,0 +1,368 @@ +From 27b11d4f1888e1a3d6d75b46d4d5a4d86fc03891 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Wed, 6 Aug 2014 10:53:40 +0200 +Subject: [PATCH 51/57] SPI: MIPS: ralink: add rt5350 dual SPI support + +Signed-off-by: John Crispin <blogic@openwrt.org> +Signed-off-by: Felix Fietkau <nbd@openwrt.org> +--- + drivers/spi/spi-rt2880.c | 218 +++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 205 insertions(+), 13 deletions(-) + +--- a/drivers/spi/spi-rt2880.c ++++ b/drivers/spi/spi-rt2880.c +@@ -21,19 +21,25 @@ + #include <linux/io.h> + #include <linux/reset.h> + #include <linux/spi/spi.h> ++#include <linux/of_device.h> + #include <linux/platform_device.h> + ++#include <ralink_regs.h> ++ ++#define SPI_BPW_MASK(bits) BIT((bits) - 1) ++ + #define DRIVER_NAME "spi-rt2880" +-/* only one slave is supported*/ +-#define RALINK_NUM_CHIPSELECTS 1 + /* in usec */ + #define RALINK_SPI_WAIT_MAX_LOOP 2000 + +-#define RAMIPS_SPI_STAT 0x00 +-#define RAMIPS_SPI_CFG 0x10 +-#define RAMIPS_SPI_CTL 0x14 +-#define RAMIPS_SPI_DATA 0x20 +-#define RAMIPS_SPI_FIFO_STAT 0x38 ++#define RAMIPS_SPI_DEV_OFFSET 0x40 ++ ++#define RAMIPS_SPI_STAT(cs) (0x00 + (cs * RAMIPS_SPI_DEV_OFFSET)) ++#define RAMIPS_SPI_CFG(cs) (0x10 + (cs * RAMIPS_SPI_DEV_OFFSET)) ++#define RAMIPS_SPI_CTL(cs) (0x14 + (cs * RAMIPS_SPI_DEV_OFFSET)) ++#define RAMIPS_SPI_DATA(cs) (0x20 + (cs * RAMIPS_SPI_DEV_OFFSET)) ++#define RAMIPS_SPI_FIFO_STAT(cs) (0x38 + (cs * RAMIPS_SPI_DEV_OFFSET)) ++#define RAMIPS_SPI_ARBITER 0xF0 + + /* SPISTAT register bit field */ + #define SPISTAT_BUSY BIT(0) +@@ -63,6 +69,19 @@ + /* SPIFIFOSTAT register bit field */ + #define SPIFIFOSTAT_TXFULL BIT(17) + ++#define SPICTL_ARB_EN BIT(31) ++#define SPI1_POR BIT(1) ++#define SPI0_POR BIT(0) ++ ++#define RT2880_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH) ++ ++struct rt2880_spi; ++ ++struct rt2880_spi_ops { ++ void (*init_hw)(struct rt2880_spi *rs); ++ int num_cs; ++}; ++ + struct rt2880_spi { + struct spi_master *master; + void __iomem *base; +@@ -70,6 +89,8 @@ struct rt2880_spi { + unsigned int speed; + struct clk *clk; + spinlock_t lock; ++ ++ struct rt2880_spi_ops *ops; + }; + + static inline struct rt2880_spi *spidev_to_rt2880_spi(struct spi_device *spi) +@@ -115,6 +136,7 @@ static inline void rt2880_spi_clrbits(st + + static int rt2880_spi_baudrate_set(struct spi_device *spi, unsigned int speed) + { ++ int cs = spi->chip_select; + struct rt2880_spi *rs = spidev_to_rt2880_spi(spi); + u32 rate; + u32 prescale; +@@ -142,9 +164,9 @@ static int rt2880_spi_baudrate_set(struc + prescale = ilog2(rate / 2); + dev_dbg(&spi->dev, "prescale:%u\n", prescale); + +- reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG); ++ reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG(cs)); + reg = ((reg & ~SPICFG_SPICLK_PRESCALE_MASK) | prescale); +- rt2880_spi_write(rs, RAMIPS_SPI_CFG, reg); ++ rt2880_spi_write(rs, RAMIPS_SPI_CFG(cs), reg); + rs->speed = speed; + return 0; + } +@@ -157,7 +179,8 @@ rt2880_spi_setup_transfer(struct spi_dev + { + struct rt2880_spi *rs = spidev_to_rt2880_spi(spi); + unsigned int speed = spi->max_speed_hz; +- int rc; ++ int rc, cs = spi->chip_select; ++ u32 reg; + + if ((t != NULL) && t->speed_hz) + speed = t->speed_hz; +@@ -169,25 +192,68 @@ rt2880_spi_setup_transfer(struct spi_dev + return rc; + } + ++ reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG(cs)); ++ ++ reg = (reg & ~SPICFG_MSBFIRST); ++ if (!(spi->mode & SPI_LSB_FIRST)) ++ reg |= SPICFG_MSBFIRST; ++ ++ reg = (reg & ~(SPICFG_SPICLKPOL | SPICFG_RXCLKEDGE_FALLING |SPICFG_TXCLKEDGE_FALLING)); ++ switch(spi->mode & (SPI_CPOL | SPI_CPHA)) { ++ case SPI_MODE_0: ++ reg |= SPICFG_SPICLKPOL | SPICFG_TXCLKEDGE_FALLING; ++ break; ++ case SPI_MODE_1: ++ reg |= SPICFG_SPICLKPOL | SPICFG_RXCLKEDGE_FALLING; ++ break; ++ case SPI_MODE_2: ++ reg |= SPICFG_RXCLKEDGE_FALLING; ++ break; ++ case SPI_MODE_3: ++ reg |= SPICFG_TXCLKEDGE_FALLING; ++ break; ++ } ++ ++ rt2880_spi_write(rs, RAMIPS_SPI_CFG(cs), reg); ++ ++ reg = SPICTL_ARB_EN; ++ if (spi->mode & SPI_CS_HIGH) { ++ switch(cs) { ++ case 0: ++ reg |= SPI0_POR; ++ break; ++ case 1: ++ reg |= SPI1_POR; ++ break; ++ } ++ } ++ ++ rt2880_spi_write(rs, RAMIPS_SPI_ARBITER, reg); ++ + return 0; + } + +-static void rt2880_spi_set_cs(struct rt2880_spi *rs, int enable) ++static void rt2880_spi_set_cs(struct spi_device *spi, int enable) + { ++ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi); ++ int cs = spi->chip_select; ++ + if (enable) +- rt2880_spi_clrbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA); ++ rt2880_spi_clrbits(rs, RAMIPS_SPI_CTL(cs), SPICTL_SPIENA); + else +- rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA); ++ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL(cs), SPICTL_SPIENA); + } + +-static inline int rt2880_spi_wait_till_ready(struct rt2880_spi *rs) ++static inline int rt2880_spi_wait_till_ready(struct spi_device *spi) + { ++ struct rt2880_spi *rs = spidev_to_rt2880_spi(spi); ++ int cs = spi->chip_select; + int i; + + for (i = 0; i < RALINK_SPI_WAIT_MAX_LOOP; i++) { + u32 status; + +- status = rt2880_spi_read(rs, RAMIPS_SPI_STAT); ++ status = rt2880_spi_read(rs, RAMIPS_SPI_STAT(cs)); + if ((status & SPISTAT_BUSY) == 0) + return 0; + +@@ -199,9 +265,10 @@ static inline int rt2880_spi_wait_till_r + } + + static unsigned int +-rt2880_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer) ++rt2880_spi_write_read(struct spi_device *spi, struct list_head *list, struct spi_transfer *xfer) + { + struct rt2880_spi *rs = spidev_to_rt2880_spi(spi); ++ int cs = spi->chip_select; + unsigned count = 0; + u8 *rx = xfer->rx_buf; + const u8 *tx = xfer->tx_buf; +@@ -213,9 +280,9 @@ rt2880_spi_write_read(struct spi_device + + if (tx) { + for (count = 0; count < xfer->len; count++) { +- rt2880_spi_write(rs, RAMIPS_SPI_DATA, tx[count]); +- rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTWR); +- err = rt2880_spi_wait_till_ready(rs); ++ rt2880_spi_write(rs, RAMIPS_SPI_DATA(cs), tx[count]); ++ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL(cs), SPICTL_STARTWR); ++ err = rt2880_spi_wait_till_ready(spi); + if (err) { + dev_err(&spi->dev, "TX failed, err=%d\n", err); + goto out; +@@ -225,13 +292,13 @@ rt2880_spi_write_read(struct spi_device + + if (rx) { + for (count = 0; count < xfer->len; count++) { +- rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTRD); +- err = rt2880_spi_wait_till_ready(rs); ++ rt2880_spi_setbits(rs, RAMIPS_SPI_CTL(cs), SPICTL_STARTRD); ++ err = rt2880_spi_wait_till_ready(spi); + if (err) { + dev_err(&spi->dev, "RX failed, err=%d\n", err); + goto out; + } +- rx[count] = (u8) rt2880_spi_read(rs, RAMIPS_SPI_DATA); ++ rx[count] = (u8) rt2880_spi_read(rs, RAMIPS_SPI_DATA(cs)); + } + } + +@@ -280,25 +347,25 @@ static int rt2880_spi_transfer_one_messa + } + + if (!cs_active) { +- rt2880_spi_set_cs(rs, 1); ++ rt2880_spi_set_cs(spi, 1); + cs_active = 1; + } + + if (t->len) +- m->actual_length += rt2880_spi_write_read(spi, t); ++ m->actual_length += rt2880_spi_write_read(spi, &m->transfers, t); + + if (t->delay_usecs) + udelay(t->delay_usecs); + + if (t->cs_change) { +- rt2880_spi_set_cs(rs, 0); ++ rt2880_spi_set_cs(spi, 0); + cs_active = 0; + } + } + + msg_done: + if (cs_active) +- rt2880_spi_set_cs(rs, 0); ++ rt2880_spi_set_cs(spi, 0); + + m->status = status; + spi_finalize_current_message(master); +@@ -311,7 +378,7 @@ static int rt2880_spi_setup(struct spi_d + struct rt2880_spi *rs = spidev_to_rt2880_spi(spi); + + if ((spi->max_speed_hz == 0) || +- (spi->max_speed_hz > (rs->sys_freq / 2))) ++ (spi->max_speed_hz > (rs->sys_freq / 2))) + spi->max_speed_hz = (rs->sys_freq / 2); + + if (spi->max_speed_hz < (rs->sys_freq / 128)) { +@@ -328,14 +395,47 @@ static int rt2880_spi_setup(struct spi_d + + static void rt2880_spi_reset(struct rt2880_spi *rs) + { +- rt2880_spi_write(rs, RAMIPS_SPI_CFG, ++ rt2880_spi_write(rs, RAMIPS_SPI_CFG(0), + SPICFG_MSBFIRST | SPICFG_TXCLKEDGE_FALLING | + SPICFG_SPICLK_DIV16 | SPICFG_SPICLKPOL); +- rt2880_spi_write(rs, RAMIPS_SPI_CTL, SPICTL_HIZSDO | SPICTL_SPIENA); ++ rt2880_spi_write(rs, RAMIPS_SPI_CTL(0), SPICTL_HIZSDO | SPICTL_SPIENA); + } + ++static void rt5350_spi_reset(struct rt2880_spi *rs) ++{ ++ int cs; ++ ++ rt2880_spi_write(rs, RAMIPS_SPI_ARBITER, ++ SPICTL_ARB_EN); ++ ++ for (cs = 0; cs < rs->ops->num_cs; cs++) { ++ rt2880_spi_write(rs, RAMIPS_SPI_CFG(cs), ++ SPICFG_MSBFIRST | SPICFG_TXCLKEDGE_FALLING | ++ SPICFG_SPICLK_DIV16 | SPICFG_SPICLKPOL); ++ rt2880_spi_write(rs, RAMIPS_SPI_CTL(cs), SPICTL_HIZSDO | SPICTL_SPIENA); ++ } ++} ++ ++static struct rt2880_spi_ops spi_ops[] = { ++ { ++ .init_hw = rt2880_spi_reset, ++ .num_cs = 1, ++ }, { ++ .init_hw = rt5350_spi_reset, ++ .num_cs = 2, ++ }, ++}; ++ ++static const struct of_device_id rt2880_spi_match[] = { ++ { .compatible = "ralink,rt2880-spi", .data = &spi_ops[0]}, ++ { .compatible = "ralink,rt5350-spi", .data = &spi_ops[1]}, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rt2880_spi_match); ++ + static int rt2880_spi_probe(struct platform_device *pdev) + { ++ const struct of_device_id *match; + struct spi_master *master; + struct rt2880_spi *rs; + unsigned long flags; +@@ -343,6 +443,12 @@ static int rt2880_spi_probe(struct platf + struct resource *r; + int status = 0; + struct clk *clk; ++ struct rt2880_spi_ops *ops; ++ ++ match = of_match_device(rt2880_spi_match, &pdev->dev); ++ if (!match) ++ return -EINVAL; ++ ops = (struct rt2880_spi_ops *)match->data; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&pdev->dev, r); +@@ -366,14 +472,13 @@ static int rt2880_spi_probe(struct platf + return -ENOMEM; + } + +- /* we support only mode 0, and no options */ +- master->mode_bits = 0; ++ master->mode_bits = RT2880_SPI_MODE_BITS; + + master->setup = rt2880_spi_setup; + master->transfer_one_message = rt2880_spi_transfer_one_message; +- master->num_chipselect = RALINK_NUM_CHIPSELECTS; + master->bits_per_word_mask = SPI_BPW_MASK(8); + master->dev.of_node = pdev->dev.of_node; ++ master->num_chipselect = ops->num_cs; + + dev_set_drvdata(&pdev->dev, master); + +@@ -382,12 +487,13 @@ static int rt2880_spi_probe(struct platf + rs->clk = clk; + rs->master = master; + rs->sys_freq = clk_get_rate(rs->clk); ++ rs->ops = ops; + dev_dbg(&pdev->dev, "sys_freq: %u\n", rs->sys_freq); + spin_lock_irqsave(&rs->lock, flags); + + device_reset(&pdev->dev); + +- rt2880_spi_reset(rs); ++ rs->ops->init_hw(rs); + + return spi_register_master(master); + } +@@ -408,12 +514,6 @@ static int rt2880_spi_remove(struct plat + + MODULE_ALIAS("platform:" DRIVER_NAME); + +-static const struct of_device_id rt2880_spi_match[] = { +- { .compatible = "ralink,rt2880-spi" }, +- {}, +-}; +-MODULE_DEVICE_TABLE(of, rt2880_spi_match); +- + static struct platform_driver rt2880_spi_driver = { + .driver = { + .name = DRIVER_NAME, diff --git a/target/linux/ramips/patches-3.18/0052-i2c-MIPS-adds-ralink-I2C-driver.patch b/target/linux/ramips/patches-3.18/0052-i2c-MIPS-adds-ralink-I2C-driver.patch new file mode 100644 index 0000000..5618652 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0052-i2c-MIPS-adds-ralink-I2C-driver.patch @@ -0,0 +1,398 @@ +From 225f36695bb07dad9510f9affd79e63f1a44a195 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 27 Jul 2014 09:52:56 +0100 +Subject: [PATCH 52/57] i2c: MIPS: adds ralink I2C driver + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + .../devicetree/bindings/i2c/i2c-ralink.txt | 27 ++ + drivers/i2c/busses/Kconfig | 4 + + drivers/i2c/busses/Makefile | 1 + + drivers/i2c/busses/i2c-ralink.c | 274 ++++++++++++++++++++ + 4 files changed, 306 insertions(+) + create mode 100644 Documentation/devicetree/bindings/i2c/i2c-ralink.txt + create mode 100644 drivers/i2c/busses/i2c-ralink.c + +--- /dev/null ++++ b/Documentation/devicetree/bindings/i2c/i2c-ralink.txt +@@ -0,0 +1,27 @@ ++I2C for Ralink platforms ++ ++Required properties : ++- compatible : Must be "link,rt3052-i2c" ++- reg: physical base address of the controller and length of memory mapped ++ region. ++- #address-cells = <1>; ++- #size-cells = <0>; ++ ++Optional properties: ++- Child nodes conforming to i2c bus binding ++ ++Example : ++ ++palmbus@10000000 { ++ i2c@900 { ++ compatible = "link,rt3052-i2c"; ++ reg = <0x900 0x100>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ hwmon@4b { ++ compatible = "national,lm92"; ++ reg = <0x4b>; ++ }; ++ }; ++}; +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -711,6 +711,10 @@ config I2C_RK3X + This driver can also be built as a module. If so, the module will + be called i2c-rk3x. + ++config I2C_RALINK ++ tristate "Ralink I2C Controller" ++ select OF_I2C ++ + config HAVE_S3C2410_I2C + bool + help +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -66,6 +66,7 @@ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o + obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o + obj-$(CONFIG_I2C_PXA) += i2c-pxa.o + obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o ++obj-$(CONFIG_I2C_RALINK) += i2c-ralink.o + obj-$(CONFIG_I2C_QUP) += i2c-qup.o + obj-$(CONFIG_I2C_RIIC) += i2c-riic.o + obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o +--- /dev/null ++++ b/drivers/i2c/busses/i2c-ralink.c +@@ -0,0 +1,327 @@ ++/* ++ * drivers/i2c/busses/i2c-ralink.c ++ * ++ * Copyright (C) 2013 Steven Liu <steven_liu@mediatek.com> ++ * ++ * Improve driver for i2cdetect from i2c-tools to detect i2c devices on the bus. ++ * (C) 2014 Sittisak <sittisaks@hotmail.com> ++ * ++ * 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/interrupt.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/reset.h> ++#include <linux/delay.h> ++#include <linux/slab.h> ++#include <linux/init.h> ++#include <linux/errno.h> ++#include <linux/platform_device.h> ++#include <linux/of_platform.h> ++#include <linux/i2c.h> ++#include <linux/io.h> ++#include <linux/err.h> ++ ++#include <asm/mach-ralink/ralink_regs.h> ++ ++#define REG_CONFIG_REG 0x00 ++#define REG_CLKDIV_REG 0x04 ++#define REG_DEVADDR_REG 0x08 ++#define REG_ADDR_REG 0x0C ++#define REG_DATAOUT_REG 0x10 ++#define REG_DATAIN_REG 0x14 ++#define REG_STATUS_REG 0x18 ++#define REG_STARTXFR_REG 0x1C ++#define REG_BYTECNT_REG 0x20 ++#define REG_SM0CFG2 0x28 ++#define REG_SM0CTL0 0x40 ++ ++#define I2C_STARTERR BIT(4) ++#define I2C_ACKERR BIT(3) ++#define I2C_DATARDY BIT(2) ++#define I2C_SDOEMPTY BIT(1) ++#define I2C_BUSY BIT(0) ++ ++#define I2C_DEVADLEN_7 (6 << 2) ++#define I2C_ADDRDIS BIT(1) ++ ++#define CLKDIV_VALUE 200 // clock rate is 40M, 40M / (200*2) = 100k (standard i2c bus rate). ++//#define CLKDIV_VALUE 50 // clock rate is 40M, 40M / (50*2) = 400k (fast i2c bus rate). ++ ++#define READ_CMD 0x01 ++#define WRITE_CMD 0x00 ++#define READ_BLOCK 64 ++ ++#define SM0CTL0_OD BIT(31) ++#define SM0CTL0_VTRIG BIT(28) ++#define SM0CTL0_OUTHI BIT(6) ++#define SM0CTL0_STRETCH BIT(1) ++#define SM0CTL0_DEFAULT (SM0CTL0_OD | SM0CTL0_VTRIG | SM0CTL0_OUTHI | SM0CTL0_STRETCH) ++ ++/* timeout waiting for I2C devices to respond (clock streching) */ ++#define RT_I2C_TIMEOUT (msecs_to_jiffies(1000)) ++ ++enum { ++ I2C_TYPE_RALINK, ++ I2C_TYPE_MEDIATEK, ++}; ++ ++static void __iomem *membase; ++static struct i2c_adapter *adapter; ++static int hw_type; ++ ++static void rt_i2c_w32(u32 val, unsigned reg) ++{ ++ iowrite32(val, membase + reg); ++} ++ ++static u32 rt_i2c_r32(unsigned reg) ++{ ++ return ioread32(membase + reg); ++} ++ ++static inline int rt_i2c_get_ack(void) ++{ ++ return (rt_i2c_r32(REG_STATUS_REG) & I2C_ACKERR) ? -EIO : 0; ++} ++ ++static inline int rt_i2c_wait_rx_done(void) ++{ ++ unsigned long timeout; ++ ++ timeout = jiffies + RT_I2C_TIMEOUT; ++ ++ do { ++ if (time_after(jiffies, timeout)) ++ return (-ETIMEDOUT); ++ ++ } while (!(rt_i2c_r32(REG_STATUS_REG) & I2C_DATARDY)); ++ ++ return 0; ++} ++ ++static inline int rt_i2c_wait_idle(void) ++{ ++ unsigned long timeout; ++ ++ timeout = jiffies + RT_I2C_TIMEOUT; ++ ++ do { ++ if (time_after(jiffies, timeout)) { ++ printk("i2c-read line busy\n"); ++ return 1; ++ } ++ } while (rt_i2c_r32(REG_STATUS_REG) & I2C_BUSY); ++ ++ return 0; ++} ++ ++static inline int rt_i2c_wait_tx_done(void) ++{ ++ unsigned long timeout; ++ ++ timeout = jiffies + RT_I2C_TIMEOUT; ++ ++ do { ++ if (time_after(jiffies, timeout)) ++ return (-ETIMEDOUT); ++ ++ } while (!(rt_i2c_r32(REG_STATUS_REG) & I2C_SDOEMPTY)); ++ ++ return 0; ++} ++ ++static int rt_i2c_handle_msg(struct i2c_adapter *a, struct i2c_msg* msg) ++{ ++ int i = 0, j = 0, pos = 0; ++ int nblock = msg->len / READ_BLOCK; ++ int rem = msg->len % READ_BLOCK; ++ int ret = 0; ++ ++ if (msg->flags & I2C_M_TEN) { ++ printk("10 bits addr not supported\n"); ++ return -EINVAL; ++ } ++ ++ if (msg->flags & I2C_M_RD) { ++ for (i = 0; i < nblock; i++) { ++ if (rt_i2c_wait_idle()) ++ return -ETIMEDOUT; ++ rt_i2c_w32(READ_BLOCK - 1, REG_BYTECNT_REG); ++ rt_i2c_w32(READ_CMD, REG_STARTXFR_REG); ++ for (j = 0; j < READ_BLOCK; j++) { ++ if (rt_i2c_wait_rx_done() < 0) ++ ret = rt_i2c_wait_rx_done(); ++ if (rt_i2c_get_ack() < 0) ++ ret = rt_i2c_get_ack(); ++ msg->buf[pos++] = rt_i2c_r32(REG_DATAIN_REG); ++ } ++ } ++ ++ if (rt_i2c_wait_idle()) ++ return -ETIMEDOUT; ++ if (rem) { ++ rt_i2c_w32(rem - 1, REG_BYTECNT_REG); ++ rt_i2c_w32(READ_CMD, REG_STARTXFR_REG); ++ } ++ for (i = 0; i < rem; i++) { ++ if (rt_i2c_wait_rx_done() < 0) ++ ret = rt_i2c_wait_rx_done(); ++ if (rt_i2c_get_ack() < 0) ++ ret = rt_i2c_get_ack(); ++ ++ msg->buf[pos++] = rt_i2c_r32(REG_DATAIN_REG); ++ } ++ } else { ++ if (rt_i2c_wait_idle()) ++ return -ETIMEDOUT; ++ rt_i2c_w32(msg->len - 1, REG_BYTECNT_REG); ++ for (i = 0; i < msg->len; i++) { ++ rt_i2c_w32(msg->buf[i], REG_DATAOUT_REG); ++ rt_i2c_w32(WRITE_CMD, REG_STARTXFR_REG); ++ ++ if (rt_i2c_wait_tx_done() < 0) ++ ret = rt_i2c_wait_tx_done(); ++ if (rt_i2c_get_ack() < 0) ++ ret = rt_i2c_get_ack(); ++ } ++ } ++ ++ return ret; ++} ++ ++static int rt_i2c_master_xfer(struct i2c_adapter *a, struct i2c_msg *m, int n) ++{ ++ int i = 0; ++ int ret = 0; ++ ++ if (rt_i2c_wait_idle()) ++ return -ETIMEDOUT; ++ ++ device_reset(a->dev.parent); ++ ++ rt_i2c_w32(m->addr, REG_DEVADDR_REG); ++ rt_i2c_w32(I2C_DEVADLEN_7 | I2C_ADDRDIS, REG_CONFIG_REG); ++ if (hw_type == I2C_TYPE_RALINK) { ++ rt_i2c_w32(CLKDIV_VALUE, REG_CLKDIV_REG); ++ } else { ++ rt_i2c_w32((CLKDIV_VALUE << 16) | SM0CTL0_DEFAULT, REG_SM0CTL0); ++ rt_i2c_w32(1, REG_SM0CFG2); ++ } ++ ++ for (i = 0; i < n && !ret; i++) { ++ ret = rt_i2c_handle_msg(a, &m[i]); ++ ++ if (ret < 0) { ++ return ret; ++ } ++ } ++ ++ return n; ++} ++ ++static u32 rt_i2c_func(struct i2c_adapter *a) ++{ ++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; ++} ++ ++static const struct i2c_algorithm rt_i2c_algo = { ++ .master_xfer = rt_i2c_master_xfer, ++ .functionality = rt_i2c_func, ++}; ++ ++static const struct of_device_id i2c_rt_dt_ids[] = { ++ { .compatible = "ralink,rt2880-i2c", .data = (void *) I2C_TYPE_RALINK }, ++ { .compatible = "mediatek,mt7628-i2c", .data = (void *) I2C_TYPE_MEDIATEK }, ++ { /* sentinel */ } ++}; ++ ++MODULE_DEVICE_TABLE(of, i2c_rt_dt_ids); ++ ++static int rt_i2c_probe(struct platform_device *pdev) ++{ ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ const struct of_device_id *match; ++ int ret; ++ ++ match = of_match_device(i2c_rt_dt_ids, &pdev->dev); ++ hw_type = (int) match->data; ++ ++ if (!res) { ++ dev_err(&pdev->dev, "no memory resource found\n"); ++ return -ENODEV; ++ } ++ ++ adapter = devm_kzalloc(&pdev->dev, sizeof(struct i2c_adapter), GFP_KERNEL); ++ if (!adapter) { ++ dev_err(&pdev->dev, "failed to allocate i2c_adapter\n"); ++ return -ENOMEM; ++ } ++ ++ membase = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(membase)) ++ return PTR_ERR(membase); ++ ++ strlcpy(adapter->name, dev_name(&pdev->dev), sizeof(adapter->name)); ++ adapter->owner = THIS_MODULE; ++ adapter->nr = pdev->id; ++ adapter->timeout = HZ; ++ adapter->algo = &rt_i2c_algo; ++ adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; ++ adapter->dev.parent = &pdev->dev; ++ adapter->dev.of_node = pdev->dev.of_node; ++ ++ ret = i2c_add_numbered_adapter(adapter); ++ if (ret) ++ return ret; ++ ++ platform_set_drvdata(pdev, adapter); ++ ++ dev_info(&pdev->dev, "loaded\n"); ++ ++ return 0; ++} ++ ++static int rt_i2c_remove(struct platform_device *pdev) ++{ ++ platform_set_drvdata(pdev, NULL); ++ ++ return 0; ++} ++ ++static struct platform_driver rt_i2c_driver = { ++ .probe = rt_i2c_probe, ++ .remove = rt_i2c_remove, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "i2c-ralink", ++ .of_match_table = i2c_rt_dt_ids, ++ }, ++}; ++ ++static int __init i2c_rt_init (void) ++{ ++ return platform_driver_register(&rt_i2c_driver); ++} ++subsys_initcall(i2c_rt_init); ++ ++static void __exit i2c_rt_exit (void) ++{ ++ platform_driver_unregister(&rt_i2c_driver); ++} ++ ++module_exit (i2c_rt_exit); ++ ++MODULE_AUTHOR("Steven Liu <steven_liu@mediatek.com>"); ++MODULE_DESCRIPTION("Ralink I2c host driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:Ralink-I2C"); diff --git a/target/linux/ramips/patches-3.18/0053-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch b/target/linux/ramips/patches-3.18/0053-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch new file mode 100644 index 0000000..2932eb6 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0053-mmc-MIPS-ralink-add-sdhci-for-mt7620a-SoC.patch @@ -0,0 +1,4823 @@ +From f954801c6f48fc291c39ca8a888dbdfda1021415 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Thu, 13 Nov 2014 19:08:40 +0100 +Subject: [PATCH] mmc: MIPS: ralink: add sdhci for mt7620a SoC + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + drivers/mmc/host/Kconfig | 2 + + drivers/mmc/host/Makefile | 1 + + drivers/mmc/host/mtk-mmc/Kconfig | 16 + + drivers/mmc/host/mtk-mmc/Makefile | 42 + + drivers/mmc/host/mtk-mmc/board.h | 137 ++ + drivers/mmc/host/mtk-mmc/dbg.c | 347 ++++ + drivers/mmc/host/mtk-mmc/dbg.h | 153 ++ + drivers/mmc/host/mtk-mmc/mt6575_sd.h | 1001 +++++++++++ + drivers/mmc/host/mtk-mmc/sd.c | 3041 ++++++++++++++++++++++++++++++++++ + 9 files changed, 4740 insertions(+) + create mode 100644 drivers/mmc/host/mtk-mmc/Kconfig + create mode 100644 drivers/mmc/host/mtk-mmc/Makefile + create mode 100644 drivers/mmc/host/mtk-mmc/board.h + create mode 100644 drivers/mmc/host/mtk-mmc/dbg.c + create mode 100644 drivers/mmc/host/mtk-mmc/dbg.h + create mode 100644 drivers/mmc/host/mtk-mmc/mt6575_sd.h + create mode 100644 drivers/mmc/host/mtk-mmc/sd.c + +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -773,3 +773,5 @@ config MMC_SUNXI + help + This selects support for the SD/MMC Host Controller on + Allwinner sunxi SoCs. ++ ++source "drivers/mmc/host/mtk-mmc/Kconfig" +--- a/drivers/mmc/host/Makefile ++++ b/drivers/mmc/host/Makefile +@@ -2,6 +2,7 @@ + # Makefile for MMC/SD host controller drivers + # + ++obj-$(CONFIG_MTK_MMC) += mtk-mmc/ + obj-$(CONFIG_MMC_ARMMMCI) += mmci.o + obj-$(CONFIG_MMC_QCOM_DML) += mmci_qcom_dml.o + obj-$(CONFIG_MMC_PXA) += pxamci.o +--- /dev/null ++++ b/drivers/mmc/host/mtk-mmc/Kconfig +@@ -0,0 +1,16 @@ ++config MTK_MMC ++ tristate "MTK SD/MMC" ++ depends on !MTD_NAND_RALINK ++ ++config MTK_AEE_KDUMP ++ bool "MTK AEE KDUMP" ++ depends on MTK_MMC ++ ++config MTK_MMC_CD_POLL ++ bool "Card Detect with Polling" ++ depends on MTK_MMC ++ ++config MTK_MMC_EMMC_8BIT ++ bool "eMMC 8-bit support" ++ depends on MTK_MMC && RALINK_MT7628 ++ +--- /dev/null ++++ b/drivers/mmc/host/mtk-mmc/Makefile +@@ -0,0 +1,42 @@ ++# Copyright Statement: ++# ++# This software/firmware and related documentation ("MediaTek Software") are ++# protected under relevant copyright laws. The information contained herein ++# is confidential and proprietary to MediaTek Inc. and/or its licensors. ++# Without the prior written permission of MediaTek inc. and/or its licensors, ++# any reproduction, modification, use or disclosure of MediaTek Software, ++# and information contained herein, in whole or in part, shall be strictly prohibited. ++# ++# MediaTek Inc. (C) 2010. All rights reserved. ++# ++# BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES ++# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") ++# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON ++# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, ++# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF ++# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. ++# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ++# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR ++# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH ++# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES ++# THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES ++# CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK ++# SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR ++# STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND ++# CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, ++# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, ++# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO ++# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. ++# ++# The following software/firmware and/or related documentation ("MediaTek Software") ++# have been modified by MediaTek Inc. All revisions are subject to any receiver's ++# applicable license agreements with MediaTek Inc. ++ ++obj-$(CONFIG_MTK_MMC) += mtk_sd.o ++mtk_sd-objs := sd.o dbg.o ++ifeq ($(CONFIG_MTK_AEE_KDUMP),y) ++EXTRA_CFLAGS += -DMT6575_SD_DEBUG ++endif ++ ++clean: ++ @rm -f *.o modules.order .*.cmd +--- /dev/null ++++ b/drivers/mmc/host/mtk-mmc/board.h +@@ -0,0 +1,137 @@ ++/* Copyright Statement: ++ * ++ * This software/firmware and related documentation ("MediaTek Software") are ++ * protected under relevant copyright laws. The information contained herein ++ * is confidential and proprietary to MediaTek Inc. and/or its licensors. ++ * Without the prior written permission of MediaTek inc. and/or its licensors, ++ * any reproduction, modification, use or disclosure of MediaTek Software, ++ * and information contained herein, in whole or in part, shall be strictly prohibited. ++ */ ++/* MediaTek Inc. (C) 2010. All rights reserved. ++ * ++ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES ++ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") ++ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON ++ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. ++ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ++ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR ++ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH ++ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES ++ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES ++ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK ++ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR ++ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND ++ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, ++ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, ++ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO ++ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. ++ * ++ * The following software/firmware and/or related documentation ("MediaTek Software") ++ * have been modified by MediaTek Inc. All revisions are subject to any receiver's ++ * applicable license agreements with MediaTek Inc. ++ */ ++ ++#ifndef __ARCH_ARM_MACH_BOARD_H ++#define __ARCH_ARM_MACH_BOARD_H ++ ++#include <generated/autoconf.h> ++#include <linux/pm.h> ++/* --- chhung */ ++// #include <mach/mt6575.h> ++// #include <board-custom.h> ++/* end of chhung */ ++ ++typedef void (*sdio_irq_handler_t)(void*); /* external irq handler */ ++typedef void (*pm_callback_t)(pm_message_t state, void *data); ++ ++#define MSDC_CD_PIN_EN (1 << 0) /* card detection pin is wired */ ++#define MSDC_WP_PIN_EN (1 << 1) /* write protection pin is wired */ ++#define MSDC_RST_PIN_EN (1 << 2) /* emmc reset pin is wired */ ++#define MSDC_SDIO_IRQ (1 << 3) /* use internal sdio irq (bus) */ ++#define MSDC_EXT_SDIO_IRQ (1 << 4) /* use external sdio irq */ ++#define MSDC_REMOVABLE (1 << 5) /* removable slot */ ++#define MSDC_SYS_SUSPEND (1 << 6) /* suspended by system */ ++#define MSDC_HIGHSPEED (1 << 7) /* high-speed mode support */ ++#define MSDC_UHS1 (1 << 8) /* uhs-1 mode support */ ++#define MSDC_DDR (1 << 9) /* ddr mode support */ ++ ++ ++#define MSDC_SMPL_RISING (0) ++#define MSDC_SMPL_FALLING (1) ++ ++#define MSDC_CMD_PIN (0) ++#define MSDC_DAT_PIN (1) ++#define MSDC_CD_PIN (2) ++#define MSDC_WP_PIN (3) ++#define MSDC_RST_PIN (4) ++ ++enum { ++ MSDC_CLKSRC_48MHZ = 0, ++// MSDC_CLKSRC_26MHZ = 0, ++// MSDC_CLKSRC_197MHZ = 1, ++// MSDC_CLKSRC_208MHZ = 2 ++}; ++ ++struct msdc_hw { ++ unsigned char clk_src; /* host clock source */ ++ unsigned char cmd_edge; /* command latch edge */ ++ unsigned char data_edge; /* data latch edge */ ++ unsigned char clk_drv; /* clock pad driving */ ++ unsigned char cmd_drv; /* command pad driving */ ++ unsigned char dat_drv; /* data pad driving */ ++ unsigned long flags; /* hardware capability flags */ ++ unsigned long data_pins; /* data pins */ ++ unsigned long data_offset; /* data address offset */ ++ ++ /* config gpio pull mode */ ++ void (*config_gpio_pin)(int type, int pull); ++ ++ /* external power control for card */ ++ void (*ext_power_on)(void); ++ void (*ext_power_off)(void); ++ ++ /* external sdio irq operations */ ++ void (*request_sdio_eirq)(sdio_irq_handler_t sdio_irq_handler, void *data); ++ void (*enable_sdio_eirq)(void); ++ void (*disable_sdio_eirq)(void); ++ ++ /* external cd irq operations */ ++ void (*request_cd_eirq)(sdio_irq_handler_t cd_irq_handler, void *data); ++ void (*enable_cd_eirq)(void); ++ void (*disable_cd_eirq)(void); ++ int (*get_cd_status)(void); ++ ++ /* power management callback for external module */ ++ void (*register_pm)(pm_callback_t pm_cb, void *data); ++}; ++ ++extern struct msdc_hw msdc0_hw; ++extern struct msdc_hw msdc1_hw; ++extern struct msdc_hw msdc2_hw; ++extern struct msdc_hw msdc3_hw; ++ ++/*GPS driver*/ ++#define GPS_FLAG_FORCE_OFF 0x0001 ++struct mt3326_gps_hardware { ++ int (*ext_power_on)(int); ++ int (*ext_power_off)(int); ++}; ++extern struct mt3326_gps_hardware mt3326_gps_hw; ++ ++/* NAND driver */ ++struct mt6575_nand_host_hw { ++ unsigned int nfi_bus_width; /* NFI_BUS_WIDTH */ ++ unsigned int nfi_access_timing; /* NFI_ACCESS_TIMING */ ++ unsigned int nfi_cs_num; /* NFI_CS_NUM */ ++ unsigned int nand_sec_size; /* NAND_SECTOR_SIZE */ ++ unsigned int nand_sec_shift; /* NAND_SECTOR_SHIFT */ ++ unsigned int nand_ecc_size; ++ unsigned int nand_ecc_bytes; ++ unsigned int nand_ecc_mode; ++}; ++extern struct mt6575_nand_host_hw mt6575_nand_hw; ++ ++#endif /* __ARCH_ARM_MACH_BOARD_H */ ++ +--- /dev/null ++++ b/drivers/mmc/host/mtk-mmc/dbg.c +@@ -0,0 +1,347 @@ ++/* Copyright Statement: ++ * ++ * This software/firmware and related documentation ("MediaTek Software") are ++ * protected under relevant copyright laws. The information contained herein ++ * is confidential and proprietary to MediaTek Inc. and/or its licensors. ++ * Without the prior written permission of MediaTek inc. and/or its licensors, ++ * any reproduction, modification, use or disclosure of MediaTek Software, ++ * and information contained herein, in whole or in part, shall be strictly prohibited. ++ * ++ * MediaTek Inc. (C) 2010. All rights reserved. ++ * ++ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES ++ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") ++ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON ++ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. ++ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ++ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR ++ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH ++ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES ++ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES ++ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK ++ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR ++ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND ++ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, ++ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, ++ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO ++ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. ++ * ++ * The following software/firmware and/or related documentation ("MediaTek Software") ++ * have been modified by MediaTek Inc. All revisions are subject to any receiver's ++ * applicable license agreements with MediaTek Inc. ++ */ ++ ++#include <linux/version.h> ++#include <linux/kernel.h> ++#include <linux/sched.h> ++#include <linux/kthread.h> ++#include <linux/delay.h> ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/proc_fs.h> ++#include <linux/string.h> ++#include <linux/uaccess.h> ++// #include <mach/mt6575_gpt.h> /* --- by chhung */ ++#include "dbg.h" ++#include "mt6575_sd.h" ++#include <linux/seq_file.h> ++ ++static char cmd_buf[256]; ++ ++/* for debug zone */ ++unsigned int sd_debug_zone[4]={ ++ 0, ++ 0, ++ 0, ++ 0 ++}; ++ ++/* mode select */ ++u32 dma_size[4]={ ++ 512, ++ 512, ++ 512, ++ 512 ++}; ++msdc_mode drv_mode[4]={ ++ MODE_SIZE_DEP, /* using DMA or not depend on the size */ ++ MODE_SIZE_DEP, ++ MODE_SIZE_DEP, ++ MODE_SIZE_DEP ++}; ++ ++#if defined (MT6575_SD_DEBUG) ++/* for driver profile */ ++#define TICKS_ONE_MS (13000) ++u32 gpt_enable = 0; ++u32 sdio_pro_enable = 0; /* make sure gpt is enabled */ ++u32 sdio_pro_time = 0; /* no more than 30s */ ++struct sdio_profile sdio_perfomance = {0}; ++ ++#if 0 /* --- chhung */ ++void msdc_init_gpt(void) ++{ ++ GPT_CONFIG config; ++ ++ config.num = GPT6; ++ config.mode = GPT_FREE_RUN; ++ config.clkSrc = GPT_CLK_SRC_SYS; ++ config.clkDiv = GPT_CLK_DIV_1; /* 13MHz GPT6 */ ++ ++ if (GPT_Config(config) == FALSE ) ++ return; ++ ++ GPT_Start(GPT6); ++} ++#endif /* end of --- */ ++ ++u32 msdc_time_calc(u32 old_L32, u32 old_H32, u32 new_L32, u32 new_H32) ++{ ++ u32 ret = 0; ++ ++ if (new_H32 == old_H32) { ++ ret = new_L32 - old_L32; ++ } else if(new_H32 == (old_H32 + 1)) { ++ if (new_L32 > old_L32) { ++ printk("msdc old_L<0x%x> new_L<0x%x>\n", old_L32, new_L32); ++ } ++ ret = (0xffffffff - old_L32); ++ ret += new_L32; ++ } else { ++ printk("msdc old_H<0x%x> new_H<0x%x>\n", old_H32, new_H32); ++ } ++ ++ return ret; ++} ++ ++void msdc_sdio_profile(struct sdio_profile* result) ++{ ++ struct cmd_profile* cmd; ++ u32 i; ++ ++ printk("sdio === performance dump ===\n"); ++ printk("sdio === total execute tick<%d> time<%dms> Tx<%dB> Rx<%dB>\n", ++ result->total_tc, result->total_tc / TICKS_ONE_MS, ++ result->total_tx_bytes, result->total_rx_bytes); ++ ++ /* CMD52 Dump */ ++ cmd = &result->cmd52_rx; ++ printk("sdio === CMD52 Rx <%d>times tick<%d> Max<%d> Min<%d> Aver<%d>\n", cmd->count, cmd->tot_tc, ++ cmd->max_tc, cmd->min_tc, cmd->tot_tc/cmd->count); ++ cmd = &result->cmd52_tx; ++ printk("sdio === CMD52 Tx <%d>times tick<%d> Max<%d> Min<%d> Aver<%d>\n", cmd->count, cmd->tot_tc, ++ cmd->max_tc, cmd->min_tc, cmd->tot_tc/cmd->count); ++ ++ /* CMD53 Rx bytes + block mode */ ++ for (i=0; i<512; i++) { ++ cmd = &result->cmd53_rx_byte[i]; ++ if (cmd->count) { ++ printk("sdio<%6d><%3dB>_Rx_<%9d><%9d><%6d><%6d>_<%9dB><%2dM>\n", cmd->count, i, cmd->tot_tc, ++ cmd->max_tc, cmd->min_tc, cmd->tot_tc/cmd->count, ++ cmd->tot_bytes, (cmd->tot_bytes/10)*13 / (cmd->tot_tc/10)); ++ } ++ } ++ for (i=0; i<100; i++) { ++ cmd = &result->cmd53_rx_blk[i]; ++ if (cmd->count) { ++ printk("sdio<%6d><%3d>B_Rx_<%9d><%9d><%6d><%6d>_<%9dB><%2dM>\n", cmd->count, i, cmd->tot_tc, ++ cmd->max_tc, cmd->min_tc, cmd->tot_tc/cmd->count, ++ cmd->tot_bytes, (cmd->tot_bytes/10)*13 / (cmd->tot_tc/10)); ++ } ++ } ++ ++ /* CMD53 Tx bytes + block mode */ ++ for (i=0; i<512; i++) { ++ cmd = &result->cmd53_tx_byte[i]; ++ if (cmd->count) { ++ printk("sdio<%6d><%3dB>_Tx_<%9d><%9d><%6d><%6d>_<%9dB><%2dM>\n", cmd->count, i, cmd->tot_tc, ++ cmd->max_tc, cmd->min_tc, cmd->tot_tc/cmd->count, ++ cmd->tot_bytes, (cmd->tot_bytes/10)*13 / (cmd->tot_tc/10)); ++ } ++ } ++ for (i=0; i<100; i++) { ++ cmd = &result->cmd53_tx_blk[i]; ++ if (cmd->count) { ++ printk("sdio<%6d><%3d>B_Tx_<%9d><%9d><%6d><%6d>_<%9dB><%2dM>\n", cmd->count, i, cmd->tot_tc, ++ cmd->max_tc, cmd->min_tc, cmd->tot_tc/cmd->count, ++ cmd->tot_bytes, (cmd->tot_bytes/10)*13 / (cmd->tot_tc/10)); ++ } ++ } ++ ++ printk("sdio === performance dump done ===\n"); ++} ++ ++//========= sdio command table =========== ++void msdc_performance(u32 opcode, u32 sizes, u32 bRx, u32 ticks) ++{ ++ struct sdio_profile* result = &sdio_perfomance; ++ struct cmd_profile* cmd; ++ u32 block; ++ ++ if (sdio_pro_enable == 0) { ++ return; ++ } ++ ++ if (opcode == 52) { ++ cmd = bRx ? &result->cmd52_rx : &result->cmd52_tx; ++ } else if (opcode == 53) { ++ if (sizes < 512) { ++ cmd = bRx ? &result->cmd53_rx_byte[sizes] : &result->cmd53_tx_byte[sizes]; ++ } else { ++ block = sizes / 512; ++ if (block >= 99) { ++ printk("cmd53 error blocks\n"); ++ while(1); ++ } ++ cmd = bRx ? &result->cmd53_rx_blk[block] : &result->cmd53_tx_blk[block]; ++ } ++ } else { ++ return; ++ } ++ ++ /* update the members */ ++ if (ticks > cmd->max_tc){ ++ cmd->max_tc = ticks; ++ } ++ if (cmd->min_tc == 0 || ticks < cmd->min_tc) { ++ cmd->min_tc = ticks; ++ } ++ cmd->tot_tc += ticks; ++ cmd->tot_bytes += sizes; ++ cmd->count ++; ++ ++ if (bRx) { ++ result->total_rx_bytes += sizes; ++ } else { ++ result->total_tx_bytes += sizes; ++ } ++ result->total_tc += ticks; ++ ++ /* dump when total_tc > 30s */ ++ if (result->total_tc >= sdio_pro_time * TICKS_ONE_MS * 1000) { ++ msdc_sdio_profile(result); ++ memset(result, 0 , sizeof(struct sdio_profile)); ++ } ++} ++ ++//========== driver proc interface =========== ++static int msdc_debug_proc_read(struct seq_file *s, void *p) ++{ ++ seq_printf(s, "\n=========================================\n"); ++ seq_printf(s, "Index<0> + Id + Zone\n"); ++ seq_printf(s, "-> PWR<9> WRN<8> | FIO<7> OPS<6> FUN<5> CFG<4> | INT<3> RSP<2> CMD<1> DMA<0>\n"); ++ seq_printf(s, "-> echo 0 3 0x3ff >msdc_bebug -> host[3] debug zone set to 0x3ff\n"); ++ seq_printf(s, "-> MSDC[0] Zone: 0x%.8x\n", sd_debug_zone[0]); ++ seq_printf(s, "-> MSDC[1] Zone: 0x%.8x\n", sd_debug_zone[1]); ++ seq_printf(s, "-> MSDC[2] Zone: 0x%.8x\n", sd_debug_zone[2]); ++ seq_printf(s, "-> MSDC[3] Zone: 0x%.8x\n", sd_debug_zone[3]); ++ ++ seq_printf(s, "Index<1> + ID:4|Mode:4 + DMA_SIZE\n"); ++ seq_printf(s, "-> 0)PIO 1)DMA 2)SIZE\n"); ++ seq_printf(s, "-> echo 1 22 0x200 >msdc_bebug -> host[2] size mode, dma when >= 512\n"); ++ seq_printf(s, "-> MSDC[0] mode<%d> size<%d>\n", drv_mode[0], dma_size[0]); ++ seq_printf(s, "-> MSDC[1] mode<%d> size<%d>\n", drv_mode[1], dma_size[1]); ++ seq_printf(s, "-> MSDC[2] mode<%d> size<%d>\n", drv_mode[2], dma_size[2]); ++ seq_printf(s, "-> MSDC[3] mode<%d> size<%d>\n", drv_mode[3], dma_size[3]); ++ ++ seq_printf(s, "Index<3> + SDIO_PROFILE + TIME\n"); ++ seq_printf(s, "-> echo 3 1 0x1E >msdc_bebug -> enable sdio_profile, 30s\n"); ++ seq_printf(s, "-> SDIO_PROFILE<%d> TIME<%ds>\n", sdio_pro_enable, sdio_pro_time); ++ seq_printf(s, "=========================================\n\n"); ++ ++ return 0; ++} ++ ++static ssize_t msdc_debug_proc_write(struct file *file, ++ const char __user *buf, size_t count, loff_t *data) ++{ ++ int ret; ++ ++ int cmd, p1, p2; ++ int id, zone; ++ int mode, size; ++ ++ if (count == 0)return -1; ++ if(count > 255)count = 255; ++ ++ ret = copy_from_user(cmd_buf, buf, count); ++ if (ret < 0)return -1; ++ ++ cmd_buf[count] = '\0'; ++ printk("msdc Write %s\n", cmd_buf); ++ ++ sscanf(cmd_buf, "%x %x %x", &cmd, &p1, &p2); ++ ++ if(cmd == SD_TOOL_ZONE) { ++ id = p1; zone = p2; zone &= 0x3ff; ++ printk("msdc host_id<%d> zone<0x%.8x>\n", id, zone); ++ if(id >=0 && id<=3){ ++ sd_debug_zone[id] = zone; ++ } ++ else if(id == 4){ ++ sd_debug_zone[0] = sd_debug_zone[1] = zone; ++ sd_debug_zone[2] = sd_debug_zone[3] = zone; ++ } ++ else{ ++ printk("msdc host_id error when set debug zone\n"); ++ } ++ } else if (cmd == SD_TOOL_DMA_SIZE) { ++ id = p1>>4; mode = (p1&0xf); size = p2; ++ if(id >=0 && id<=3){ ++ drv_mode[id] = mode; ++ dma_size[id] = p2; ++ } ++ else if(id == 4){ ++ drv_mode[0] = drv_mode[1] = mode; ++ drv_mode[2] = drv_mode[3] = mode; ++ dma_size[0] = dma_size[1] = p2; ++ dma_size[2] = dma_size[3] = p2; ++ } ++ else{ ++ printk("msdc host_id error when select mode\n"); ++ } ++ } else if (cmd == SD_TOOL_SDIO_PROFILE) { ++ if (p1 == 1) { /* enable profile */ ++ if (gpt_enable == 0) { ++ // msdc_init_gpt(); /* --- by chhung */ ++ gpt_enable = 1; ++ } ++ sdio_pro_enable = 1; ++ if (p2 == 0) p2 = 1; if (p2 >= 30) p2 = 30; ++ sdio_pro_time = p2 ; ++ } else if (p1 == 0) { ++ /* todo */ ++ sdio_pro_enable = 0; ++ } ++ } ++ ++ return count; ++} ++ ++static int msdc_debug_show(struct inode *inode, struct file *file) ++{ ++ return single_open(file, msdc_debug_proc_read, NULL); ++} ++ ++static const struct file_operations msdc_debug_fops = { ++ .owner = THIS_MODULE, ++ .open = msdc_debug_show, ++ .read = seq_read, ++ .write = msdc_debug_proc_write, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++int msdc_debug_proc_init(void) ++{ ++ struct proc_dir_entry *de = proc_create("msdc_debug", 0667, NULL, &msdc_debug_fops); ++ ++ if (!de || IS_ERR(de)) ++ printk("!! Create MSDC debug PROC fail !!\n"); ++ ++ return 0 ; ++} ++EXPORT_SYMBOL_GPL(msdc_debug_proc_init); ++#endif +--- /dev/null ++++ b/drivers/mmc/host/mtk-mmc/dbg.h +@@ -0,0 +1,156 @@ ++/* Copyright Statement: ++ * ++ * This software/firmware and related documentation ("MediaTek Software") are ++ * protected under relevant copyright laws. The information contained herein ++ * is confidential and proprietary to MediaTek Inc. and/or its licensors. ++ * Without the prior written permission of MediaTek inc. and/or its licensors, ++ * any reproduction, modification, use or disclosure of MediaTek Software, ++ * and information contained herein, in whole or in part, shall be strictly prohibited. ++ * ++ * MediaTek Inc. (C) 2010. All rights reserved. ++ * ++ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES ++ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") ++ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON ++ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. ++ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ++ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR ++ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH ++ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES ++ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES ++ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK ++ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR ++ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND ++ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, ++ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, ++ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO ++ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. ++ * ++ * The following software/firmware and/or related documentation ("MediaTek Software") ++ * have been modified by MediaTek Inc. All revisions are subject to any receiver's ++ * applicable license agreements with MediaTek Inc. ++ */ ++#ifndef __MT_MSDC_DEUBG__ ++#define __MT_MSDC_DEUBG__ ++ ++//========================== ++extern u32 sdio_pro_enable; ++/* for a type command, e.g. CMD53, 2 blocks */ ++struct cmd_profile { ++ u32 max_tc; /* Max tick count */ ++ u32 min_tc; ++ u32 tot_tc; /* total tick count */ ++ u32 tot_bytes; ++ u32 count; /* the counts of the command */ ++}; ++ ++/* dump when total_tc and total_bytes */ ++struct sdio_profile { ++ u32 total_tc; /* total tick count of CMD52 and CMD53 */ ++ u32 total_tx_bytes; /* total bytes of CMD53 Tx */ ++ u32 total_rx_bytes; /* total bytes of CMD53 Rx */ ++ ++ /*CMD52*/ ++ struct cmd_profile cmd52_tx; ++ struct cmd_profile cmd52_rx; ++ ++ /*CMD53 in byte unit */ ++ struct cmd_profile cmd53_tx_byte[512]; ++ struct cmd_profile cmd53_rx_byte[512]; ++ ++ /*CMD53 in block unit */ ++ struct cmd_profile cmd53_tx_blk[100]; ++ struct cmd_profile cmd53_rx_blk[100]; ++}; ++ ++//========================== ++typedef enum { ++ SD_TOOL_ZONE = 0, ++ SD_TOOL_DMA_SIZE = 1, ++ SD_TOOL_PM_ENABLE = 2, ++ SD_TOOL_SDIO_PROFILE = 3, ++} msdc_dbg; ++ ++typedef enum { ++ MODE_PIO = 0, ++ MODE_DMA = 1, ++ MODE_SIZE_DEP = 2, ++} msdc_mode; ++extern msdc_mode drv_mode[4]; ++extern u32 dma_size[4]; ++ ++/* Debug message event */ ++#define DBG_EVT_NONE (0) /* No event */ ++#define DBG_EVT_DMA (1 << 0) /* DMA related event */ ++#define DBG_EVT_CMD (1 << 1) /* MSDC CMD related event */ ++#define DBG_EVT_RSP (1 << 2) /* MSDC CMD RSP related event */ ++#define DBG_EVT_INT (1 << 3) /* MSDC INT event */ ++#define DBG_EVT_CFG (1 << 4) /* MSDC CFG event */ ++#define DBG_EVT_FUC (1 << 5) /* Function event */ ++#define DBG_EVT_OPS (1 << 6) /* Read/Write operation event */ ++#define DBG_EVT_FIO (1 << 7) /* FIFO operation event */ ++#define DBG_EVT_WRN (1 << 8) /* Warning event */ ++#define DBG_EVT_PWR (1 << 9) /* Power event */ ++#define DBG_EVT_ALL (0xffffffff) ++ ++#define DBG_EVT_MASK (DBG_EVT_ALL) ++ ++extern unsigned int sd_debug_zone[4]; ++#define TAG "msdc" ++#if 0 /* +++ chhung */ ++#define BUG_ON(x) \ ++do { \ ++ if (x) { \ ++ printk("[BUG] %s LINE:%d FILE:%s\n", #x, __LINE__, __FILE__); \ ++ while(1); \ ++ } \ ++}while(0) ++#endif /* end of +++ */ ++ ++#define N_MSG(evt, fmt, args...) ++/* ++do { \ ++ if ((DBG_EVT_##evt) & sd_debug_zone[host->id]) { \ ++ printk(KERN_ERR TAG"%d -> "fmt" <- %s() : L<%d> PID<%s><0x%x>\n", \ ++ host->id, ##args , __FUNCTION__, __LINE__, current->comm, current->pid); \ ++ } \ ++} while(0) ++*/ ++ ++#define ERR_MSG(fmt, args...) \ ++do { \ ++ printk(KERN_ERR TAG"%d -> "fmt" <- %s() : L<%d> PID<%s><0x%x>\n", \ ++ host->id, ##args , __FUNCTION__, __LINE__, current->comm, current->pid); \ ++} while(0); ++ ++#if 1 ++//defined CONFIG_MTK_MMC_CD_POLL ++#define INIT_MSG(fmt, args...) ++#define IRQ_MSG(fmt, args...) ++#else ++#define INIT_MSG(fmt, args...) \ ++do { \ ++ printk(KERN_ERR TAG"%d -> "fmt" <- %s() : L<%d> PID<%s><0x%x>\n", \ ++ host->id, ##args , __FUNCTION__, __LINE__, current->comm, current->pid); \ ++} while(0); ++ ++/* PID in ISR in not corrent */ ++#define IRQ_MSG(fmt, args...) \ ++do { \ ++ printk(KERN_ERR TAG"%d -> "fmt" <- %s() : L<%d>\n", \ ++ host->id, ##args , __FUNCTION__, __LINE__); \ ++} while(0); ++#endif ++ ++int msdc_debug_proc_init(void); ++ ++#if 0 /* --- chhung */ ++void msdc_init_gpt(void); ++extern void GPT_GetCounter64(UINT32 *cntL32, UINT32 *cntH32); ++#endif /* end of --- */ ++u32 msdc_time_calc(u32 old_L32, u32 old_H32, u32 new_L32, u32 new_H32); ++void msdc_performance(u32 opcode, u32 sizes, u32 bRx, u32 ticks); ++ ++#endif +--- /dev/null ++++ b/drivers/mmc/host/mtk-mmc/mt6575_sd.h +@@ -0,0 +1,1001 @@ ++/* Copyright Statement: ++ * ++ * This software/firmware and related documentation ("MediaTek Software") are ++ * protected under relevant copyright laws. The information contained herein ++ * is confidential and proprietary to MediaTek Inc. and/or its licensors. ++ * Without the prior written permission of MediaTek inc. and/or its licensors, ++ * any reproduction, modification, use or disclosure of MediaTek Software, ++ * and information contained herein, in whole or in part, shall be strictly prohibited. ++ */ ++/* MediaTek Inc. (C) 2010. All rights reserved. ++ * ++ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES ++ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") ++ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON ++ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. ++ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ++ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR ++ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH ++ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES ++ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES ++ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK ++ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR ++ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND ++ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, ++ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, ++ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO ++ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. ++ * ++ * The following software/firmware and/or related documentation ("MediaTek Software") ++ * have been modified by MediaTek Inc. All revisions are subject to any receiver's ++ * applicable license agreements with MediaTek Inc. ++ */ ++ ++#ifndef MT6575_SD_H ++#define MT6575_SD_H ++ ++#include <linux/bitops.h> ++#include <linux/mmc/host.h> ++ ++// #include <mach/mt6575_reg_base.h> /* --- by chhung */ ++ ++/*--------------------------------------------------------------------------*/ ++/* Common Macro */ ++/*--------------------------------------------------------------------------*/ ++#define REG_ADDR(x) ((volatile u32*)(base + OFFSET_##x)) ++ ++/*--------------------------------------------------------------------------*/ ++/* Common Definition */ ++/*--------------------------------------------------------------------------*/ ++#define MSDC_FIFO_SZ (128) ++#define MSDC_FIFO_THD (64) // (128) ++#define MSDC_NUM (4) ++ ++#define MSDC_MS (0) ++#define MSDC_SDMMC (1) ++ ++#define MSDC_MODE_UNKNOWN (0) ++#define MSDC_MODE_PIO (1) ++#define MSDC_MODE_DMA_BASIC (2) ++#define MSDC_MODE_DMA_DESC (3) ++#define MSDC_MODE_DMA_ENHANCED (4) ++#define MSDC_MODE_MMC_STREAM (5) ++ ++#define MSDC_BUS_1BITS (0) ++#define MSDC_BUS_4BITS (1) ++#define MSDC_BUS_8BITS (2) ++ ++#define MSDC_BRUST_8B (3) ++#define MSDC_BRUST_16B (4) ++#define MSDC_BRUST_32B (5) ++#define MSDC_BRUST_64B (6) ++ ++#define MSDC_PIN_PULL_NONE (0) ++#define MSDC_PIN_PULL_DOWN (1) ++#define MSDC_PIN_PULL_UP (2) ++#define MSDC_PIN_KEEP (3) ++ ++#define MSDC_MAX_SCLK (48000000) /* +/- by chhung */ ++#define MSDC_MIN_SCLK (260000) ++ ++#define MSDC_AUTOCMD12 (0x0001) ++#define MSDC_AUTOCMD23 (0x0002) ++#define MSDC_AUTOCMD19 (0x0003) ++ ++#define MSDC_EMMC_BOOTMODE0 (0) /* Pull low CMD mode */ ++#define MSDC_EMMC_BOOTMODE1 (1) /* Reset CMD mode */ ++ ++enum { ++ RESP_NONE = 0, ++ RESP_R1, ++ RESP_R2, ++ RESP_R3, ++ RESP_R4, ++ RESP_R5, ++ RESP_R6, ++ RESP_R7, ++ RESP_R1B ++}; ++ ++/*--------------------------------------------------------------------------*/ ++/* Register Offset */ ++/*--------------------------------------------------------------------------*/ ++#define OFFSET_MSDC_CFG (0x0) ++#define OFFSET_MSDC_IOCON (0x04) ++#define OFFSET_MSDC_PS (0x08) ++#define OFFSET_MSDC_INT (0x0c) ++#define OFFSET_MSDC_INTEN (0x10) ++#define OFFSET_MSDC_FIFOCS (0x14) ++#define OFFSET_MSDC_TXDATA (0x18) ++#define OFFSET_MSDC_RXDATA (0x1c) ++#define OFFSET_SDC_CFG (0x30) ++#define OFFSET_SDC_CMD (0x34) ++#define OFFSET_SDC_ARG (0x38) ++#define OFFSET_SDC_STS (0x3c) ++#define OFFSET_SDC_RESP0 (0x40) ++#define OFFSET_SDC_RESP1 (0x44) ++#define OFFSET_SDC_RESP2 (0x48) ++#define OFFSET_SDC_RESP3 (0x4c) ++#define OFFSET_SDC_BLK_NUM (0x50) ++#define OFFSET_SDC_CSTS (0x58) ++#define OFFSET_SDC_CSTS_EN (0x5c) ++#define OFFSET_SDC_DCRC_STS (0x60) ++#define OFFSET_EMMC_CFG0 (0x70) ++#define OFFSET_EMMC_CFG1 (0x74) ++#define OFFSET_EMMC_STS (0x78) ++#define OFFSET_EMMC_IOCON (0x7c) ++#define OFFSET_SDC_ACMD_RESP (0x80) ++#define OFFSET_SDC_ACMD19_TRG (0x84) ++#define OFFSET_SDC_ACMD19_STS (0x88) ++#define OFFSET_MSDC_DMA_SA (0x90) ++#define OFFSET_MSDC_DMA_CA (0x94) ++#define OFFSET_MSDC_DMA_CTRL (0x98) ++#define OFFSET_MSDC_DMA_CFG (0x9c) ++#define OFFSET_MSDC_DBG_SEL (0xa0) ++#define OFFSET_MSDC_DBG_OUT (0xa4) ++#define OFFSET_MSDC_PATCH_BIT (0xb0) ++#define OFFSET_MSDC_PATCH_BIT1 (0xb4) ++#define OFFSET_MSDC_PAD_CTL0 (0xe0) ++#define OFFSET_MSDC_PAD_CTL1 (0xe4) ++#define OFFSET_MSDC_PAD_CTL2 (0xe8) ++#define OFFSET_MSDC_PAD_TUNE (0xec) ++#define OFFSET_MSDC_DAT_RDDLY0 (0xf0) ++#define OFFSET_MSDC_DAT_RDDLY1 (0xf4) ++#define OFFSET_MSDC_HW_DBG (0xf8) ++#define OFFSET_MSDC_VERSION (0x100) ++#define OFFSET_MSDC_ECO_VER (0x104) ++ ++/*--------------------------------------------------------------------------*/ ++/* Register Address */ ++/*--------------------------------------------------------------------------*/ ++ ++/* common register */ ++#define MSDC_CFG REG_ADDR(MSDC_CFG) ++#define MSDC_IOCON REG_ADDR(MSDC_IOCON) ++#define MSDC_PS REG_ADDR(MSDC_PS) ++#define MSDC_INT REG_ADDR(MSDC_INT) ++#define MSDC_INTEN REG_ADDR(MSDC_INTEN) ++#define MSDC_FIFOCS REG_ADDR(MSDC_FIFOCS) ++#define MSDC_TXDATA REG_ADDR(MSDC_TXDATA) ++#define MSDC_RXDATA REG_ADDR(MSDC_RXDATA) ++#define MSDC_PATCH_BIT0 REG_ADDR(MSDC_PATCH_BIT) ++ ++/* sdmmc register */ ++#define SDC_CFG REG_ADDR(SDC_CFG) ++#define SDC_CMD REG_ADDR(SDC_CMD) ++#define SDC_ARG REG_ADDR(SDC_ARG) ++#define SDC_STS REG_ADDR(SDC_STS) ++#define SDC_RESP0 REG_ADDR(SDC_RESP0) ++#define SDC_RESP1 REG_ADDR(SDC_RESP1) ++#define SDC_RESP2 REG_ADDR(SDC_RESP2) ++#define SDC_RESP3 REG_ADDR(SDC_RESP3) ++#define SDC_BLK_NUM REG_ADDR(SDC_BLK_NUM) ++#define SDC_CSTS REG_ADDR(SDC_CSTS) ++#define SDC_CSTS_EN REG_ADDR(SDC_CSTS_EN) ++#define SDC_DCRC_STS REG_ADDR(SDC_DCRC_STS) ++ ++/* emmc register*/ ++#define EMMC_CFG0 REG_ADDR(EMMC_CFG0) ++#define EMMC_CFG1 REG_ADDR(EMMC_CFG1) ++#define EMMC_STS REG_ADDR(EMMC_STS) ++#define EMMC_IOCON REG_ADDR(EMMC_IOCON) ++ ++/* auto command register */ ++#define SDC_ACMD_RESP REG_ADDR(SDC_ACMD_RESP) ++#define SDC_ACMD19_TRG REG_ADDR(SDC_ACMD19_TRG) ++#define SDC_ACMD19_STS REG_ADDR(SDC_ACMD19_STS) ++ ++/* dma register */ ++#define MSDC_DMA_SA REG_ADDR(MSDC_DMA_SA) ++#define MSDC_DMA_CA REG_ADDR(MSDC_DMA_CA) ++#define MSDC_DMA_CTRL REG_ADDR(MSDC_DMA_CTRL) ++#define MSDC_DMA_CFG REG_ADDR(MSDC_DMA_CFG) ++ ++/* pad ctrl register */ ++#define MSDC_PAD_CTL0 REG_ADDR(MSDC_PAD_CTL0) ++#define MSDC_PAD_CTL1 REG_ADDR(MSDC_PAD_CTL1) ++#define MSDC_PAD_CTL2 REG_ADDR(MSDC_PAD_CTL2) ++ ++/* data read delay */ ++#define MSDC_DAT_RDDLY0 REG_ADDR(MSDC_DAT_RDDLY0) ++#define MSDC_DAT_RDDLY1 REG_ADDR(MSDC_DAT_RDDLY1) ++ ++/* debug register */ ++#define MSDC_DBG_SEL REG_ADDR(MSDC_DBG_SEL) ++#define MSDC_DBG_OUT REG_ADDR(MSDC_DBG_OUT) ++ ++/* misc register */ ++#define MSDC_PATCH_BIT REG_ADDR(MSDC_PATCH_BIT) ++#define MSDC_PATCH_BIT1 REG_ADDR(MSDC_PATCH_BIT1) ++#define MSDC_PAD_TUNE REG_ADDR(MSDC_PAD_TUNE) ++#define MSDC_HW_DBG REG_ADDR(MSDC_HW_DBG) ++#define MSDC_VERSION REG_ADDR(MSDC_VERSION) ++#define MSDC_ECO_VER REG_ADDR(MSDC_ECO_VER) /* ECO Version */ ++ ++/*--------------------------------------------------------------------------*/ ++/* Register Mask */ ++/*--------------------------------------------------------------------------*/ ++ ++/* MSDC_CFG mask */ ++#define MSDC_CFG_MODE (0x1 << 0) /* RW */ ++#define MSDC_CFG_CKPDN (0x1 << 1) /* RW */ ++#define MSDC_CFG_RST (0x1 << 2) /* RW */ ++#define MSDC_CFG_PIO (0x1 << 3) /* RW */ ++#define MSDC_CFG_CKDRVEN (0x1 << 4) /* RW */ ++#define MSDC_CFG_BV18SDT (0x1 << 5) /* RW */ ++#define MSDC_CFG_BV18PSS (0x1 << 6) /* R */ ++#define MSDC_CFG_CKSTB (0x1 << 7) /* R */ ++#define MSDC_CFG_CKDIV (0xff << 8) /* RW */ ++#define MSDC_CFG_CKMOD (0x3 << 16) /* RW */ ++ ++/* MSDC_IOCON mask */ ++#define MSDC_IOCON_SDR104CKS (0x1 << 0) /* RW */ ++#define MSDC_IOCON_RSPL (0x1 << 1) /* RW */ ++#define MSDC_IOCON_DSPL (0x1 << 2) /* RW */ ++#define MSDC_IOCON_DDLSEL (0x1 << 3) /* RW */ ++#define MSDC_IOCON_DDR50CKD (0x1 << 4) /* RW */ ++#define MSDC_IOCON_DSPLSEL (0x1 << 5) /* RW */ ++#define MSDC_IOCON_D0SPL (0x1 << 16) /* RW */ ++#define MSDC_IOCON_D1SPL (0x1 << 17) /* RW */ ++#define MSDC_IOCON_D2SPL (0x1 << 18) /* RW */ ++#define MSDC_IOCON_D3SPL (0x1 << 19) /* RW */ ++#define MSDC_IOCON_D4SPL (0x1 << 20) /* RW */ ++#define MSDC_IOCON_D5SPL (0x1 << 21) /* RW */ ++#define MSDC_IOCON_D6SPL (0x1 << 22) /* RW */ ++#define MSDC_IOCON_D7SPL (0x1 << 23) /* RW */ ++#define MSDC_IOCON_RISCSZ (0x3 << 24) /* RW */ ++ ++/* MSDC_PS mask */ ++#define MSDC_PS_CDEN (0x1 << 0) /* RW */ ++#define MSDC_PS_CDSTS (0x1 << 1) /* R */ ++#define MSDC_PS_CDDEBOUNCE (0xf << 12) /* RW */ ++#define MSDC_PS_DAT (0xff << 16) /* R */ ++#define MSDC_PS_CMD (0x1 << 24) /* R */ ++#define MSDC_PS_WP (0x1UL<< 31) /* R */ ++ ++/* MSDC_INT mask */ ++#define MSDC_INT_MMCIRQ (0x1 << 0) /* W1C */ ++#define MSDC_INT_CDSC (0x1 << 1) /* W1C */ ++#define MSDC_INT_ACMDRDY (0x1 << 3) /* W1C */ ++#define MSDC_INT_ACMDTMO (0x1 << 4) /* W1C */ ++#define MSDC_INT_ACMDCRCERR (0x1 << 5) /* W1C */ ++#define MSDC_INT_DMAQ_EMPTY (0x1 << 6) /* W1C */ ++#define MSDC_INT_SDIOIRQ (0x1 << 7) /* W1C */ ++#define MSDC_INT_CMDRDY (0x1 << 8) /* W1C */ ++#define MSDC_INT_CMDTMO (0x1 << 9) /* W1C */ ++#define MSDC_INT_RSPCRCERR (0x1 << 10) /* W1C */ ++#define MSDC_INT_CSTA (0x1 << 11) /* R */ ++#define MSDC_INT_XFER_COMPL (0x1 << 12) /* W1C */ ++#define MSDC_INT_DXFER_DONE (0x1 << 13) /* W1C */ ++#define MSDC_INT_DATTMO (0x1 << 14) /* W1C */ ++#define MSDC_INT_DATCRCERR (0x1 << 15) /* W1C */ ++#define MSDC_INT_ACMD19_DONE (0x1 << 16) /* W1C */ ++ ++/* MSDC_INTEN mask */ ++#define MSDC_INTEN_MMCIRQ (0x1 << 0) /* RW */ ++#define MSDC_INTEN_CDSC (0x1 << 1) /* RW */ ++#define MSDC_INTEN_ACMDRDY (0x1 << 3) /* RW */ ++#define MSDC_INTEN_ACMDTMO (0x1 << 4) /* RW */ ++#define MSDC_INTEN_ACMDCRCERR (0x1 << 5) /* RW */ ++#define MSDC_INTEN_DMAQ_EMPTY (0x1 << 6) /* RW */ ++#define MSDC_INTEN_SDIOIRQ (0x1 << 7) /* RW */ ++#define MSDC_INTEN_CMDRDY (0x1 << 8) /* RW */ ++#define MSDC_INTEN_CMDTMO (0x1 << 9) /* RW */ ++#define MSDC_INTEN_RSPCRCERR (0x1 << 10) /* RW */ ++#define MSDC_INTEN_CSTA (0x1 << 11) /* RW */ ++#define MSDC_INTEN_XFER_COMPL (0x1 << 12) /* RW */ ++#define MSDC_INTEN_DXFER_DONE (0x1 << 13) /* RW */ ++#define MSDC_INTEN_DATTMO (0x1 << 14) /* RW */ ++#define MSDC_INTEN_DATCRCERR (0x1 << 15) /* RW */ ++#define MSDC_INTEN_ACMD19_DONE (0x1 << 16) /* RW */ ++ ++/* MSDC_FIFOCS mask */ ++#define MSDC_FIFOCS_RXCNT (0xff << 0) /* R */ ++#define MSDC_FIFOCS_TXCNT (0xff << 16) /* R */ ++#define MSDC_FIFOCS_CLR (0x1UL<< 31) /* RW */ ++ ++/* SDC_CFG mask */ ++#define SDC_CFG_SDIOINTWKUP (0x1 << 0) /* RW */ ++#define SDC_CFG_INSWKUP (0x1 << 1) /* RW */ ++#define SDC_CFG_BUSWIDTH (0x3 << 16) /* RW */ ++#define SDC_CFG_SDIO (0x1 << 19) /* RW */ ++#define SDC_CFG_SDIOIDE (0x1 << 20) /* RW */ ++#define SDC_CFG_INTATGAP (0x1 << 21) /* RW */ ++#define SDC_CFG_DTOC (0xffUL << 24) /* RW */ ++ ++/* SDC_CMD mask */ ++#define SDC_CMD_OPC (0x3f << 0) /* RW */ ++#define SDC_CMD_BRK (0x1 << 6) /* RW */ ++#define SDC_CMD_RSPTYP (0x7 << 7) /* RW */ ++#define SDC_CMD_DTYP (0x3 << 11) /* RW */ ++#define SDC_CMD_DTYP (0x3 << 11) /* RW */ ++#define SDC_CMD_RW (0x1 << 13) /* RW */ ++#define SDC_CMD_STOP (0x1 << 14) /* RW */ ++#define SDC_CMD_GOIRQ (0x1 << 15) /* RW */ ++#define SDC_CMD_BLKLEN (0xfff<< 16) /* RW */ ++#define SDC_CMD_AUTOCMD (0x3 << 28) /* RW */ ++#define SDC_CMD_VOLSWTH (0x1 << 30) /* RW */ ++ ++/* SDC_STS mask */ ++#define SDC_STS_SDCBUSY (0x1 << 0) /* RW */ ++#define SDC_STS_CMDBUSY (0x1 << 1) /* RW */ ++#define SDC_STS_SWR_COMPL (0x1 << 31) /* RW */ ++ ++/* SDC_DCRC_STS mask */ ++#define SDC_DCRC_STS_NEG (0xf << 8) /* RO */ ++#define SDC_DCRC_STS_POS (0xff << 0) /* RO */ ++ ++/* EMMC_CFG0 mask */ ++#define EMMC_CFG0_BOOTSTART (0x1 << 0) /* W */ ++#define EMMC_CFG0_BOOTSTOP (0x1 << 1) /* W */ ++#define EMMC_CFG0_BOOTMODE (0x1 << 2) /* RW */ ++#define EMMC_CFG0_BOOTACKDIS (0x1 << 3) /* RW */ ++#define EMMC_CFG0_BOOTWDLY (0x7 << 12) /* RW */ ++#define EMMC_CFG0_BOOTSUPP (0x1 << 15) /* RW */ ++ ++/* EMMC_CFG1 mask */ ++#define EMMC_CFG1_BOOTDATTMC (0xfffff << 0) /* RW */ ++#define EMMC_CFG1_BOOTACKTMC (0xfffUL << 20) /* RW */ ++ ++/* EMMC_STS mask */ ++#define EMMC_STS_BOOTCRCERR (0x1 << 0) /* W1C */ ++#define EMMC_STS_BOOTACKERR (0x1 << 1) /* W1C */ ++#define EMMC_STS_BOOTDATTMO (0x1 << 2) /* W1C */ ++#define EMMC_STS_BOOTACKTMO (0x1 << 3) /* W1C */ ++#define EMMC_STS_BOOTUPSTATE (0x1 << 4) /* R */ ++#define EMMC_STS_BOOTACKRCV (0x1 << 5) /* W1C */ ++#define EMMC_STS_BOOTDATRCV (0x1 << 6) /* R */ ++ ++/* EMMC_IOCON mask */ ++#define EMMC_IOCON_BOOTRST (0x1 << 0) /* RW */ ++ ++/* SDC_ACMD19_TRG mask */ ++#define SDC_ACMD19_TRG_TUNESEL (0xf << 0) /* RW */ ++ ++/* MSDC_DMA_CTRL mask */ ++#define MSDC_DMA_CTRL_START (0x1 << 0) /* W */ ++#define MSDC_DMA_CTRL_STOP (0x1 << 1) /* W */ ++#define MSDC_DMA_CTRL_RESUME (0x1 << 2) /* W */ ++#define MSDC_DMA_CTRL_MODE (0x1 << 8) /* RW */ ++#define MSDC_DMA_CTRL_LASTBUF (0x1 << 10) /* RW */ ++#define MSDC_DMA_CTRL_BRUSTSZ (0x7 << 12) /* RW */ ++#define MSDC_DMA_CTRL_XFERSZ (0xffffUL << 16)/* RW */ ++ ++/* MSDC_DMA_CFG mask */ ++#define MSDC_DMA_CFG_STS (0x1 << 0) /* R */ ++#define MSDC_DMA_CFG_DECSEN (0x1 << 1) /* RW */ ++#define MSDC_DMA_CFG_BDCSERR (0x1 << 4) /* R */ ++#define MSDC_DMA_CFG_GPDCSERR (0x1 << 5) /* R */ ++ ++/* MSDC_PATCH_BIT mask */ ++#define MSDC_PATCH_BIT_WFLSMODE (0x1 << 0) /* RW */ ++#define MSDC_PATCH_BIT_ODDSUPP (0x1 << 1) /* RW */ ++#define MSDC_PATCH_BIT_CKGEN_CK (0x1 << 6) /* E2: Fixed to 1 */ ++#define MSDC_PATCH_BIT_IODSSEL (0x1 << 16) /* RW */ ++#define MSDC_PATCH_BIT_IOINTSEL (0x1 << 17) /* RW */ ++#define MSDC_PATCH_BIT_BUSYDLY (0xf << 18) /* RW */ ++#define MSDC_PATCH_BIT_WDOD (0xf << 22) /* RW */ ++#define MSDC_PATCH_BIT_IDRTSEL (0x1 << 26) /* RW */ ++#define MSDC_PATCH_BIT_CMDFSEL (0x1 << 27) /* RW */ ++#define MSDC_PATCH_BIT_INTDLSEL (0x1 << 28) /* RW */ ++#define MSDC_PATCH_BIT_SPCPUSH (0x1 << 29) /* RW */ ++#define MSDC_PATCH_BIT_DECRCTMO (0x1 << 30) /* RW */ ++ ++/* MSDC_PATCH_BIT1 mask */ ++#define MSDC_PATCH_BIT1_WRDAT_CRCS (0x7 << 3) ++#define MSDC_PATCH_BIT1_CMD_RSP (0x7 << 0) ++ ++/* MSDC_PAD_CTL0 mask */ ++#define MSDC_PAD_CTL0_CLKDRVN (0x7 << 0) /* RW */ ++#define MSDC_PAD_CTL0_CLKDRVP (0x7 << 4) /* RW */ ++#define MSDC_PAD_CTL0_CLKSR (0x1 << 8) /* RW */ ++#define MSDC_PAD_CTL0_CLKPD (0x1 << 16) /* RW */ ++#define MSDC_PAD_CTL0_CLKPU (0x1 << 17) /* RW */ ++#define MSDC_PAD_CTL0_CLKSMT (0x1 << 18) /* RW */ ++#define MSDC_PAD_CTL0_CLKIES (0x1 << 19) /* RW */ ++#define MSDC_PAD_CTL0_CLKTDSEL (0xf << 20) /* RW */ ++#define MSDC_PAD_CTL0_CLKRDSEL (0xffUL<< 24) /* RW */ ++ ++/* MSDC_PAD_CTL1 mask */ ++#define MSDC_PAD_CTL1_CMDDRVN (0x7 << 0) /* RW */ ++#define MSDC_PAD_CTL1_CMDDRVP (0x7 << 4) /* RW */ ++#define MSDC_PAD_CTL1_CMDSR (0x1 << 8) /* RW */ ++#define MSDC_PAD_CTL1_CMDPD (0x1 << 16) /* RW */ ++#define MSDC_PAD_CTL1_CMDPU (0x1 << 17) /* RW */ ++#define MSDC_PAD_CTL1_CMDSMT (0x1 << 18) /* RW */ ++#define MSDC_PAD_CTL1_CMDIES (0x1 << 19) /* RW */ ++#define MSDC_PAD_CTL1_CMDTDSEL (0xf << 20) /* RW */ ++#define MSDC_PAD_CTL1_CMDRDSEL (0xffUL<< 24) /* RW */ ++ ++/* MSDC_PAD_CTL2 mask */ ++#define MSDC_PAD_CTL2_DATDRVN (0x7 << 0) /* RW */ ++#define MSDC_PAD_CTL2_DATDRVP (0x7 << 4) /* RW */ ++#define MSDC_PAD_CTL2_DATSR (0x1 << 8) /* RW */ ++#define MSDC_PAD_CTL2_DATPD (0x1 << 16) /* RW */ ++#define MSDC_PAD_CTL2_DATPU (0x1 << 17) /* RW */ ++#define MSDC_PAD_CTL2_DATIES (0x1 << 19) /* RW */ ++#define MSDC_PAD_CTL2_DATSMT (0x1 << 18) /* RW */ ++#define MSDC_PAD_CTL2_DATTDSEL (0xf << 20) /* RW */ ++#define MSDC_PAD_CTL2_DATRDSEL (0xffUL<< 24) /* RW */ ++ ++/* MSDC_PAD_TUNE mask */ ++#define MSDC_PAD_TUNE_DATWRDLY (0x1F << 0) /* RW */ ++#define MSDC_PAD_TUNE_DATRRDLY (0x1F << 8) /* RW */ ++#define MSDC_PAD_TUNE_CMDRDLY (0x1F << 16) /* RW */ ++#define MSDC_PAD_TUNE_CMDRRDLY (0x1FUL << 22) /* RW */ ++#define MSDC_PAD_TUNE_CLKTXDLY (0x1FUL << 27) /* RW */ ++ ++/* MSDC_DAT_RDDLY0/1 mask */ ++#define MSDC_DAT_RDDLY0_D0 (0x1F << 0) /* RW */ ++#define MSDC_DAT_RDDLY0_D1 (0x1F << 8) /* RW */ ++#define MSDC_DAT_RDDLY0_D2 (0x1F << 16) /* RW */ ++#define MSDC_DAT_RDDLY0_D3 (0x1F << 24) /* RW */ ++ ++#define MSDC_DAT_RDDLY1_D4 (0x1F << 0) /* RW */ ++#define MSDC_DAT_RDDLY1_D5 (0x1F << 8) /* RW */ ++#define MSDC_DAT_RDDLY1_D6 (0x1F << 16) /* RW */ ++#define MSDC_DAT_RDDLY1_D7 (0x1F << 24) /* RW */ ++ ++#define MSDC_CKGEN_MSDC_DLY_SEL (0x1F<<10) ++#define MSDC_INT_DAT_LATCH_CK_SEL (0x7<<7) ++#define MSDC_CKGEN_MSDC_CK_SEL (0x1<<6) ++#define CARD_READY_FOR_DATA (1<<8) ++#define CARD_CURRENT_STATE(x) ((x&0x00001E00)>>9) ++ ++/*--------------------------------------------------------------------------*/ ++/* Descriptor Structure */ ++/*--------------------------------------------------------------------------*/ ++typedef struct { ++ u32 hwo:1; /* could be changed by hw */ ++ u32 bdp:1; ++ u32 rsv0:6; ++ u32 chksum:8; ++ u32 intr:1; ++ u32 rsv1:15; ++ void *next; ++ void *ptr; ++ u32 buflen:16; ++ u32 extlen:8; ++ u32 rsv2:8; ++ u32 arg; ++ u32 blknum; ++ u32 cmd; ++} gpd_t; ++ ++typedef struct { ++ u32 eol:1; ++ u32 rsv0:7; ++ u32 chksum:8; ++ u32 rsv1:1; ++ u32 blkpad:1; ++ u32 dwpad:1; ++ u32 rsv2:13; ++ void *next; ++ void *ptr; ++ u32 buflen:16; ++ u32 rsv3:16; ++} bd_t; ++ ++/*--------------------------------------------------------------------------*/ ++/* Register Debugging Structure */ ++/*--------------------------------------------------------------------------*/ ++ ++typedef struct { ++ u32 msdc:1; ++ u32 ckpwn:1; ++ u32 rst:1; ++ u32 pio:1; ++ u32 ckdrven:1; ++ u32 start18v:1; ++ u32 pass18v:1; ++ u32 ckstb:1; ++ u32 ckdiv:8; ++ u32 ckmod:2; ++ u32 pad:14; ++} msdc_cfg_reg; ++typedef struct { ++ u32 sdr104cksel:1; ++ u32 rsmpl:1; ++ u32 dsmpl:1; ++ u32 ddlysel:1; ++ u32 ddr50ckd:1; ++ u32 dsplsel:1; ++ u32 pad1:10; ++ u32 d0spl:1; ++ u32 d1spl:1; ++ u32 d2spl:1; ++ u32 d3spl:1; ++ u32 d4spl:1; ++ u32 d5spl:1; ++ u32 d6spl:1; ++ u32 d7spl:1; ++ u32 riscsz:1; ++ u32 pad2:7; ++} msdc_iocon_reg; ++typedef struct { ++ u32 cden:1; ++ u32 cdsts:1; ++ u32 pad1:10; ++ u32 cddebounce:4; ++ u32 dat:8; ++ u32 cmd:1; ++ u32 pad2:6; ++ u32 wp:1; ++} msdc_ps_reg; ++typedef struct { ++ u32 mmcirq:1; ++ u32 cdsc:1; ++ u32 pad1:1; ++ u32 atocmdrdy:1; ++ u32 atocmdtmo:1; ++ u32 atocmdcrc:1; ++ u32 dmaqempty:1; ++ u32 sdioirq:1; ++ u32 cmdrdy:1; ++ u32 cmdtmo:1; ++ u32 rspcrc:1; ++ u32 csta:1; ++ u32 xfercomp:1; ++ u32 dxferdone:1; ++ u32 dattmo:1; ++ u32 datcrc:1; ++ u32 atocmd19done:1; ++ u32 pad2:15; ++} msdc_int_reg; ++typedef struct { ++ u32 mmcirq:1; ++ u32 cdsc:1; ++ u32 pad1:1; ++ u32 atocmdrdy:1; ++ u32 atocmdtmo:1; ++ u32 atocmdcrc:1; ++ u32 dmaqempty:1; ++ u32 sdioirq:1; ++ u32 cmdrdy:1; ++ u32 cmdtmo:1; ++ u32 rspcrc:1; ++ u32 csta:1; ++ u32 xfercomp:1; ++ u32 dxferdone:1; ++ u32 dattmo:1; ++ u32 datcrc:1; ++ u32 atocmd19done:1; ++ u32 pad2:15; ++} msdc_inten_reg; ++typedef struct { ++ u32 rxcnt:8; ++ u32 pad1:8; ++ u32 txcnt:8; ++ u32 pad2:7; ++ u32 clr:1; ++} msdc_fifocs_reg; ++typedef struct { ++ u32 val; ++} msdc_txdat_reg; ++typedef struct { ++ u32 val; ++} msdc_rxdat_reg; ++typedef struct { ++ u32 sdiowkup:1; ++ u32 inswkup:1; ++ u32 pad1:14; ++ u32 buswidth:2; ++ u32 pad2:1; ++ u32 sdio:1; ++ u32 sdioide:1; ++ u32 intblkgap:1; ++ u32 pad4:2; ++ u32 dtoc:8; ++} sdc_cfg_reg; ++typedef struct { ++ u32 cmd:6; ++ u32 brk:1; ++ u32 rsptyp:3; ++ u32 pad1:1; ++ u32 dtype:2; ++ u32 rw:1; ++ u32 stop:1; ++ u32 goirq:1; ++ u32 blklen:12; ++ u32 atocmd:2; ++ u32 volswth:1; ++ u32 pad2:1; ++} sdc_cmd_reg; ++typedef struct { ++ u32 arg; ++} sdc_arg_reg; ++typedef struct { ++ u32 sdcbusy:1; ++ u32 cmdbusy:1; ++ u32 pad:29; ++ u32 swrcmpl:1; ++} sdc_sts_reg; ++typedef struct { ++ u32 val; ++} sdc_resp0_reg; ++typedef struct { ++ u32 val; ++} sdc_resp1_reg; ++typedef struct { ++ u32 val; ++} sdc_resp2_reg; ++typedef struct { ++ u32 val; ++} sdc_resp3_reg; ++typedef struct { ++ u32 num; ++} sdc_blknum_reg; ++typedef struct { ++ u32 sts; ++} sdc_csts_reg; ++typedef struct { ++ u32 sts; ++} sdc_cstsen_reg; ++typedef struct { ++ u32 datcrcsts:8; ++ u32 ddrcrcsts:4; ++ u32 pad:20; ++} sdc_datcrcsts_reg; ++typedef struct { ++ u32 bootstart:1; ++ u32 bootstop:1; ++ u32 bootmode:1; ++ u32 pad1:9; ++ u32 bootwaidly:3; ++ u32 bootsupp:1; ++ u32 pad2:16; ++} emmc_cfg0_reg; ++typedef struct { ++ u32 bootcrctmc:16; ++ u32 pad:4; ++ u32 bootacktmc:12; ++} emmc_cfg1_reg; ++typedef struct { ++ u32 bootcrcerr:1; ++ u32 bootackerr:1; ++ u32 bootdattmo:1; ++ u32 bootacktmo:1; ++ u32 bootupstate:1; ++ u32 bootackrcv:1; ++ u32 bootdatrcv:1; ++ u32 pad:25; ++} emmc_sts_reg; ++typedef struct { ++ u32 bootrst:1; ++ u32 pad:31; ++} emmc_iocon_reg; ++typedef struct { ++ u32 val; ++} msdc_acmd_resp_reg; ++typedef struct { ++ u32 tunesel:4; ++ u32 pad:28; ++} msdc_acmd19_trg_reg; ++typedef struct { ++ u32 val; ++} msdc_acmd19_sts_reg; ++typedef struct { ++ u32 addr; ++} msdc_dma_sa_reg; ++typedef struct { ++ u32 addr; ++} msdc_dma_ca_reg; ++typedef struct { ++ u32 start:1; ++ u32 stop:1; ++ u32 resume:1; ++ u32 pad1:5; ++ u32 mode:1; ++ u32 pad2:1; ++ u32 lastbuf:1; ++ u32 pad3:1; ++ u32 brustsz:3; ++ u32 pad4:1; ++ u32 xfersz:16; ++} msdc_dma_ctrl_reg; ++typedef struct { ++ u32 status:1; ++ u32 decsen:1; ++ u32 pad1:2; ++ u32 bdcsen:1; ++ u32 gpdcsen:1; ++ u32 pad2:26; ++} msdc_dma_cfg_reg; ++typedef struct { ++ u32 sel:16; ++ u32 pad2:16; ++} msdc_dbg_sel_reg; ++typedef struct { ++ u32 val; ++} msdc_dbg_out_reg; ++typedef struct { ++ u32 clkdrvn:3; ++ u32 rsv0:1; ++ u32 clkdrvp:3; ++ u32 rsv1:1; ++ u32 clksr:1; ++ u32 rsv2:7; ++ u32 clkpd:1; ++ u32 clkpu:1; ++ u32 clksmt:1; ++ u32 clkies:1; ++ u32 clktdsel:4; ++ u32 clkrdsel:8; ++} msdc_pad_ctl0_reg; ++typedef struct { ++ u32 cmddrvn:3; ++ u32 rsv0:1; ++ u32 cmddrvp:3; ++ u32 rsv1:1; ++ u32 cmdsr:1; ++ u32 rsv2:7; ++ u32 cmdpd:1; ++ u32 cmdpu:1; ++ u32 cmdsmt:1; ++ u32 cmdies:1; ++ u32 cmdtdsel:4; ++ u32 cmdrdsel:8; ++} msdc_pad_ctl1_reg; ++typedef struct { ++ u32 datdrvn:3; ++ u32 rsv0:1; ++ u32 datdrvp:3; ++ u32 rsv1:1; ++ u32 datsr:1; ++ u32 rsv2:7; ++ u32 datpd:1; ++ u32 datpu:1; ++ u32 datsmt:1; ++ u32 daties:1; ++ u32 dattdsel:4; ++ u32 datrdsel:8; ++} msdc_pad_ctl2_reg; ++typedef struct { ++ u32 wrrxdly:3; ++ u32 pad1:5; ++ u32 rdrxdly:8; ++ u32 pad2:16; ++} msdc_pad_tune_reg; ++typedef struct { ++ u32 dat0:5; ++ u32 rsv0:3; ++ u32 dat1:5; ++ u32 rsv1:3; ++ u32 dat2:5; ++ u32 rsv2:3; ++ u32 dat3:5; ++ u32 rsv3:3; ++} msdc_dat_rddly0; ++typedef struct { ++ u32 dat4:5; ++ u32 rsv4:3; ++ u32 dat5:5; ++ u32 rsv5:3; ++ u32 dat6:5; ++ u32 rsv6:3; ++ u32 dat7:5; ++ u32 rsv7:3; ++} msdc_dat_rddly1; ++typedef struct { ++ u32 dbg0sel:8; ++ u32 dbg1sel:6; ++ u32 pad1:2; ++ u32 dbg2sel:6; ++ u32 pad2:2; ++ u32 dbg3sel:6; ++ u32 pad3:2; ++} msdc_hw_dbg_reg; ++typedef struct { ++ u32 val; ++} msdc_version_reg; ++typedef struct { ++ u32 val; ++} msdc_eco_ver_reg; ++ ++struct msdc_regs { ++ msdc_cfg_reg msdc_cfg; /* base+0x00h */ ++ msdc_iocon_reg msdc_iocon; /* base+0x04h */ ++ msdc_ps_reg msdc_ps; /* base+0x08h */ ++ msdc_int_reg msdc_int; /* base+0x0ch */ ++ msdc_inten_reg msdc_inten; /* base+0x10h */ ++ msdc_fifocs_reg msdc_fifocs; /* base+0x14h */ ++ msdc_txdat_reg msdc_txdat; /* base+0x18h */ ++ msdc_rxdat_reg msdc_rxdat; /* base+0x1ch */ ++ u32 rsv1[4]; ++ sdc_cfg_reg sdc_cfg; /* base+0x30h */ ++ sdc_cmd_reg sdc_cmd; /* base+0x34h */ ++ sdc_arg_reg sdc_arg; /* base+0x38h */ ++ sdc_sts_reg sdc_sts; /* base+0x3ch */ ++ sdc_resp0_reg sdc_resp0; /* base+0x40h */ ++ sdc_resp1_reg sdc_resp1; /* base+0x44h */ ++ sdc_resp2_reg sdc_resp2; /* base+0x48h */ ++ sdc_resp3_reg sdc_resp3; /* base+0x4ch */ ++ sdc_blknum_reg sdc_blknum; /* base+0x50h */ ++ u32 rsv2[1]; ++ sdc_csts_reg sdc_csts; /* base+0x58h */ ++ sdc_cstsen_reg sdc_cstsen; /* base+0x5ch */ ++ sdc_datcrcsts_reg sdc_dcrcsta; /* base+0x60h */ ++ u32 rsv3[3]; ++ emmc_cfg0_reg emmc_cfg0; /* base+0x70h */ ++ emmc_cfg1_reg emmc_cfg1; /* base+0x74h */ ++ emmc_sts_reg emmc_sts; /* base+0x78h */ ++ emmc_iocon_reg emmc_iocon; /* base+0x7ch */ ++ msdc_acmd_resp_reg acmd_resp; /* base+0x80h */ ++ msdc_acmd19_trg_reg acmd19_trg; /* base+0x84h */ ++ msdc_acmd19_sts_reg acmd19_sts; /* base+0x88h */ ++ u32 rsv4[1]; ++ msdc_dma_sa_reg dma_sa; /* base+0x90h */ ++ msdc_dma_ca_reg dma_ca; /* base+0x94h */ ++ msdc_dma_ctrl_reg dma_ctrl; /* base+0x98h */ ++ msdc_dma_cfg_reg dma_cfg; /* base+0x9ch */ ++ msdc_dbg_sel_reg dbg_sel; /* base+0xa0h */ ++ msdc_dbg_out_reg dbg_out; /* base+0xa4h */ ++ u32 rsv5[2]; ++ u32 patch0; /* base+0xb0h */ ++ u32 patch1; /* base+0xb4h */ ++ u32 rsv6[10]; ++ msdc_pad_ctl0_reg pad_ctl0; /* base+0xe0h */ ++ msdc_pad_ctl1_reg pad_ctl1; /* base+0xe4h */ ++ msdc_pad_ctl2_reg pad_ctl2; /* base+0xe8h */ ++ msdc_pad_tune_reg pad_tune; /* base+0xech */ ++ msdc_dat_rddly0 dat_rddly0; /* base+0xf0h */ ++ msdc_dat_rddly1 dat_rddly1; /* base+0xf4h */ ++ msdc_hw_dbg_reg hw_dbg; /* base+0xf8h */ ++ u32 rsv7[1]; ++ msdc_version_reg version; /* base+0x100h */ ++ msdc_eco_ver_reg eco_ver; /* base+0x104h */ ++}; ++ ++struct scatterlist_ex { ++ u32 cmd; ++ u32 arg; ++ u32 sglen; ++ struct scatterlist *sg; ++}; ++ ++#define DMA_FLAG_NONE (0x00000000) ++#define DMA_FLAG_EN_CHKSUM (0x00000001) ++#define DMA_FLAG_PAD_BLOCK (0x00000002) ++#define DMA_FLAG_PAD_DWORD (0x00000004) ++ ++struct msdc_dma { ++ u32 flags; /* flags */ ++ u32 xfersz; /* xfer size in bytes */ ++ u32 sglen; /* size of scatter list */ ++ u32 blklen; /* block size */ ++ struct scatterlist *sg; /* I/O scatter list */ ++ struct scatterlist_ex *esg; /* extended I/O scatter list */ ++ u8 mode; /* dma mode */ ++ u8 burstsz; /* burst size */ ++ u8 intr; /* dma done interrupt */ ++ u8 padding; /* padding */ ++ u32 cmd; /* enhanced mode command */ ++ u32 arg; /* enhanced mode arg */ ++ u32 rsp; /* enhanced mode command response */ ++ u32 autorsp; /* auto command response */ ++ ++ gpd_t *gpd; /* pointer to gpd array */ ++ bd_t *bd; /* pointer to bd array */ ++ dma_addr_t gpd_addr; /* the physical address of gpd array */ ++ dma_addr_t bd_addr; /* the physical address of bd array */ ++ u32 used_gpd; /* the number of used gpd elements */ ++ u32 used_bd; /* the number of used bd elements */ ++}; ++ ++struct msdc_host ++{ ++ struct msdc_hw *hw; ++ ++ struct mmc_host *mmc; /* mmc structure */ ++ struct mmc_command *cmd; ++ struct mmc_data *data; ++ struct mmc_request *mrq; ++ int cmd_rsp; ++ int cmd_rsp_done; ++ int cmd_r1b_done; ++ ++ int error; ++ spinlock_t lock; /* mutex */ ++ struct semaphore sem; ++ ++ u32 blksz; /* host block size */ ++ u32 base; /* host base address */ ++ int id; /* host id */ ++ int pwr_ref; /* core power reference count */ ++ ++ u32 xfer_size; /* total transferred size */ ++ ++ struct msdc_dma dma; /* dma channel */ ++ u32 dma_addr; /* dma transfer address */ ++ u32 dma_left_size; /* dma transfer left size */ ++ u32 dma_xfer_size; /* dma transfer size in bytes */ ++ int dma_xfer; /* dma transfer mode */ ++ ++ u32 timeout_ns; /* data timeout ns */ ++ u32 timeout_clks; /* data timeout clks */ ++ ++ atomic_t abort; /* abort transfer */ ++ ++ int irq; /* host interrupt */ ++ ++ struct tasklet_struct card_tasklet; ++#if 0 ++ struct work_struct card_workqueue; ++#else ++ struct delayed_work card_delaywork; ++#endif ++ ++ struct completion cmd_done; ++ struct completion xfer_done; ++ struct pm_message pm_state; ++ ++ u32 mclk; /* mmc subsystem clock */ ++ u32 hclk; /* host clock speed */ ++ u32 sclk; /* SD/MS clock speed */ ++ u8 core_clkon; /* Host core clock on ? */ ++ u8 card_clkon; /* Card clock on ? */ ++ u8 core_power; /* core power */ ++ u8 power_mode; /* host power mode */ ++ u8 card_inserted; /* card inserted ? */ ++ u8 suspend; /* host suspended ? */ ++ u8 reserved; ++ u8 app_cmd; /* for app command */ ++ u32 app_cmd_arg; ++ u64 starttime; ++}; ++ ++static inline unsigned int uffs(unsigned int x) ++{ ++ unsigned int r = 1; ++ ++ if (!x) ++ return 0; ++ if (!(x & 0xffff)) { ++ x >>= 16; ++ r += 16; ++ } ++ if (!(x & 0xff)) { ++ x >>= 8; ++ r += 8; ++ } ++ if (!(x & 0xf)) { ++ x >>= 4; ++ r += 4; ++ } ++ if (!(x & 3)) { ++ x >>= 2; ++ r += 2; ++ } ++ if (!(x & 1)) { ++ x >>= 1; ++ r += 1; ++ } ++ return r; ++} ++#define sdr_read8(reg) __raw_readb(reg) ++#define sdr_read16(reg) __raw_readw(reg) ++#define sdr_read32(reg) __raw_readl(reg) ++#define sdr_write8(reg,val) __raw_writeb(val,reg) ++#define sdr_write16(reg,val) __raw_writew(val,reg) ++#define sdr_write32(reg,val) __raw_writel(val,reg) ++ ++#define sdr_set_bits(reg,bs) ((*(volatile u32*)(reg)) |= (u32)(bs)) ++#define sdr_clr_bits(reg,bs) ((*(volatile u32*)(reg)) &= ~((u32)(bs))) ++ ++#define sdr_set_field(reg,field,val) \ ++ do { \ ++ volatile unsigned int tv = sdr_read32(reg); \ ++ tv &= ~(field); \ ++ tv |= ((val) << (uffs((unsigned int)field) - 1)); \ ++ sdr_write32(reg,tv); \ ++ } while(0) ++#define sdr_get_field(reg,field,val) \ ++ do { \ ++ volatile unsigned int tv = sdr_read32(reg); \ ++ val = ((tv & (field)) >> (uffs((unsigned int)field) - 1)); \ ++ } while(0) ++ ++#endif ++ +--- /dev/null ++++ b/drivers/mmc/host/mtk-mmc/sd.c +@@ -0,0 +1,3060 @@ ++/* Copyright Statement: ++ * ++ * This software/firmware and related documentation ("MediaTek Software") are ++ * protected under relevant copyright laws. The information contained herein ++ * is confidential and proprietary to MediaTek Inc. and/or its licensors. ++ * Without the prior written permission of MediaTek inc. and/or its licensors, ++ * any reproduction, modification, use or disclosure of MediaTek Software, ++ * and information contained herein, in whole or in part, shall be strictly prohibited. ++ * ++ * MediaTek Inc. (C) 2010. All rights reserved. ++ * ++ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES ++ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") ++ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON ++ * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. ++ * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE ++ * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR ++ * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH ++ * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES ++ * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES ++ * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK ++ * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR ++ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND ++ * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, ++ * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, ++ * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO ++ * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. ++ * ++ * The following software/firmware and/or related documentation ("MediaTek Software") ++ * have been modified by MediaTek Inc. All revisions are subject to any receiver's ++ * applicable license agreements with MediaTek Inc. ++ */ ++ ++#include <linux/module.h> ++#include <linux/moduleparam.h> ++#include <linux/init.h> ++#include <linux/spinlock.h> ++#include <linux/timer.h> ++#include <linux/ioport.h> ++#include <linux/device.h> ++#include <linux/platform_device.h> ++#include <linux/interrupt.h> ++#include <linux/delay.h> ++#include <linux/blkdev.h> ++#include <linux/slab.h> ++#include <linux/mmc/host.h> ++#include <linux/mmc/card.h> ++#include <linux/mmc/core.h> ++#include <linux/mmc/mmc.h> ++#include <linux/mmc/sd.h> ++#include <linux/mmc/sdio.h> ++#include <linux/dma-mapping.h> ++ ++/* +++ by chhung */ ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/version.h> ++#include <linux/pm.h> ++#include <linux/of.h> ++ ++#define MSDC_SMPL_FALLING (1) ++#define MSDC_CD_PIN_EN (1 << 0) /* card detection pin is wired */ ++#define MSDC_WP_PIN_EN (1 << 1) /* write protection pin is wired */ ++#define MSDC_REMOVABLE (1 << 5) /* removable slot */ ++#define MSDC_SYS_SUSPEND (1 << 6) /* suspended by system */ ++#define MSDC_HIGHSPEED (1 << 7) ++ ++//#define IRQ_SDC 14 //MT7620 /*FIXME*/ ++#ifdef CONFIG_SOC_MT7621 ++#define RALINK_SYSCTL_BASE 0xbe000000 ++#define RALINK_MSDC_BASE 0xbe130000 ++#else ++#define RALINK_SYSCTL_BASE 0xb0000000 ++#define RALINK_MSDC_BASE 0xb0130000 ++#endif ++#define IRQ_SDC 22 /*FIXME*/ ++ ++#include <asm/dma.h> ++/* end of +++ */ ++ ++ ++#include <asm/mach-ralink/ralink_regs.h> ++ ++#if 0 /* --- by chhung */ ++#include <mach/board.h> ++#include <mach/mt6575_devs.h> ++#include <mach/mt6575_typedefs.h> ++#include <mach/mt6575_clock_manager.h> ++#include <mach/mt6575_pm_ldo.h> ++//#include <mach/mt6575_pll.h> ++//#include <mach/mt6575_gpio.h> ++//#include <mach/mt6575_gpt_sw.h> ++#include <asm/tcm.h> ++// #include <mach/mt6575_gpt.h> ++#endif /* end of --- */ ++ ++#include "mt6575_sd.h" ++#include "dbg.h" ++ ++/* +++ by chhung */ ++#include "board.h" ++/* end of +++ */ ++ ++#if 0 /* --- by chhung */ ++#define isb() __asm__ __volatile__ ("" : : : "memory") ++#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \ ++ : : "r" (0) : "memory") ++#define dmb() __asm__ __volatile__ ("" : : : "memory") ++#endif /* end of --- */ ++ ++#define DRV_NAME "mtk-sd" ++ ++#define HOST_MAX_NUM (1) /* +/- by chhung */ ++ ++#if defined (CONFIG_SOC_MT7620) ++#define HOST_MAX_MCLK (48000000) /* +/- by chhung */ ++#elif defined (CONFIG_SOC_MT7621) ++#define HOST_MAX_MCLK (50000000) /* +/- by chhung */ ++#endif ++#define HOST_MIN_MCLK (260000) ++ ++#define HOST_MAX_BLKSZ (2048) ++ ++#define MSDC_OCR_AVAIL (MMC_VDD_28_29 | MMC_VDD_29_30 | MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33) ++ ++#define GPIO_PULL_DOWN (0) ++#define GPIO_PULL_UP (1) ++ ++#if 0 /* --- by chhung */ ++#define MSDC_CLKSRC_REG (0xf100000C) ++#define PDN_REG (0xF1000010) ++#endif /* end of --- */ ++ ++#define DEFAULT_DEBOUNCE (8) /* 8 cycles */ ++#define DEFAULT_DTOC (40) /* data timeout counter. 65536x40 sclk. */ ++ ++#define CMD_TIMEOUT (HZ/10) /* 100ms */ ++#define DAT_TIMEOUT (HZ/2 * 5) /* 500ms x5 */ ++ ++#define MAX_DMA_CNT (64 * 1024 - 512) /* a single transaction for WIFI may be 50K*/ ++ ++#define MAX_GPD_NUM (1 + 1) /* one null gpd */ ++#define MAX_BD_NUM (1024) ++#define MAX_BD_PER_GPD (MAX_BD_NUM) ++ ++#define MAX_HW_SGMTS (MAX_BD_NUM) ++#define MAX_PHY_SGMTS (MAX_BD_NUM) ++#define MAX_SGMT_SZ (MAX_DMA_CNT) ++#define MAX_REQ_SZ (MAX_SGMT_SZ * 8) ++ ++#ifdef MT6575_SD_DEBUG ++static struct msdc_regs *msdc_reg[HOST_MAX_NUM]; ++#endif ++ ++static int mtk_sw_poll; ++ ++static int cd_active_low = 1; ++ ++//================================= ++#define PERI_MSDC0_PDN (15) ++//#define PERI_MSDC1_PDN (16) ++//#define PERI_MSDC2_PDN (17) ++//#define PERI_MSDC3_PDN (18) ++ ++struct msdc_host *msdc_6575_host[] = {NULL,NULL,NULL,NULL}; ++#if 0 /* --- by chhung */ ++/* gate means clock power down */ ++static int g_clk_gate = 0; ++#define msdc_gate_clock(id) \ ++ do { \ ++ g_clk_gate &= ~(1 << ((id) + PERI_MSDC0_PDN)); \ ++ } while(0) ++/* not like power down register. 1 means clock on. */ ++#define msdc_ungate_clock(id) \ ++ do { \ ++ g_clk_gate |= 1 << ((id) + PERI_MSDC0_PDN); \ ++ } while(0) ++ ++// do we need sync object or not ++void msdc_clk_status(int * status) ++{ ++ *status = g_clk_gate; ++} ++#endif /* end of --- */ ++ ++/* +++ by chhung */ ++struct msdc_hw msdc0_hw = { ++ .clk_src = 0, ++ .cmd_edge = MSDC_SMPL_FALLING, ++ .data_edge = MSDC_SMPL_FALLING, ++ .clk_drv = 4, ++ .cmd_drv = 4, ++ .dat_drv = 4, ++ .data_pins = 4, ++ .data_offset = 0, ++ .flags = MSDC_SYS_SUSPEND | MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | MSDC_REMOVABLE | MSDC_HIGHSPEED, ++// .flags = MSDC_SYS_SUSPEND | MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | MSDC_REMOVABLE, ++}; ++ ++static struct resource mtk_sd_resources[] = { ++ [0] = { ++ .start = RALINK_MSDC_BASE, ++ .end = RALINK_MSDC_BASE+0x3fff, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = IRQ_SDC, /*FIXME*/ ++ .end = IRQ_SDC, /*FIXME*/ ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device mtk_sd_device = { ++ .name = "mtk-sd", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(mtk_sd_resources), ++ .resource = mtk_sd_resources, ++}; ++/* end of +++ */ ++ ++static int msdc_rsp[] = { ++ 0, /* RESP_NONE */ ++ 1, /* RESP_R1 */ ++ 2, /* RESP_R2 */ ++ 3, /* RESP_R3 */ ++ 4, /* RESP_R4 */ ++ 1, /* RESP_R5 */ ++ 1, /* RESP_R6 */ ++ 1, /* RESP_R7 */ ++ 7, /* RESP_R1b */ ++}; ++ ++/* For Inhanced DMA */ ++#define msdc_init_gpd_ex(gpd,extlen,cmd,arg,blknum) \ ++ do { \ ++ ((gpd_t*)gpd)->extlen = extlen; \ ++ ((gpd_t*)gpd)->cmd = cmd; \ ++ ((gpd_t*)gpd)->arg = arg; \ ++ ((gpd_t*)gpd)->blknum = blknum; \ ++ }while(0) ++ ++#define msdc_init_bd(bd, blkpad, dwpad, dptr, dlen) \ ++ do { \ ++ BUG_ON(dlen > 0xFFFFUL); \ ++ ((bd_t*)bd)->blkpad = blkpad; \ ++ ((bd_t*)bd)->dwpad = dwpad; \ ++ ((bd_t*)bd)->ptr = (void*)dptr; \ ++ ((bd_t*)bd)->buflen = dlen; \ ++ }while(0) ++ ++#define msdc_txfifocnt() ((sdr_read32(MSDC_FIFOCS) & MSDC_FIFOCS_TXCNT) >> 16) ++#define msdc_rxfifocnt() ((sdr_read32(MSDC_FIFOCS) & MSDC_FIFOCS_RXCNT) >> 0) ++#define msdc_fifo_write32(v) sdr_write32(MSDC_TXDATA, (v)) ++#define msdc_fifo_write8(v) sdr_write8(MSDC_TXDATA, (v)) ++#define msdc_fifo_read32() sdr_read32(MSDC_RXDATA) ++#define msdc_fifo_read8() sdr_read8(MSDC_RXDATA) ++ ++ ++#define msdc_dma_on() sdr_clr_bits(MSDC_CFG, MSDC_CFG_PIO) ++#define msdc_dma_off() sdr_set_bits(MSDC_CFG, MSDC_CFG_PIO) ++ ++#define msdc_retry(expr,retry,cnt) \ ++ do { \ ++ int backup = cnt; \ ++ while (retry) { \ ++ if (!(expr)) break; \ ++ if (cnt-- == 0) { \ ++ retry--; mdelay(1); cnt = backup; \ ++ } \ ++ } \ ++ WARN_ON(retry == 0); \ ++ } while(0) ++ ++#if 0 /* --- by chhung */ ++#define msdc_reset() \ ++ do { \ ++ int retry = 3, cnt = 1000; \ ++ sdr_set_bits(MSDC_CFG, MSDC_CFG_RST); \ ++ dsb(); \ ++ msdc_retry(sdr_read32(MSDC_CFG) & MSDC_CFG_RST, retry, cnt); \ ++ } while(0) ++#else ++#define msdc_reset() \ ++ do { \ ++ int retry = 3, cnt = 1000; \ ++ sdr_set_bits(MSDC_CFG, MSDC_CFG_RST); \ ++ msdc_retry(sdr_read32(MSDC_CFG) & MSDC_CFG_RST, retry, cnt); \ ++ } while(0) ++#endif /* end of +/- */ ++ ++#define msdc_clr_int() \ ++ do { \ ++ volatile u32 val = sdr_read32(MSDC_INT); \ ++ sdr_write32(MSDC_INT, val); \ ++ } while(0) ++ ++#define msdc_clr_fifo() \ ++ do { \ ++ int retry = 3, cnt = 1000; \ ++ sdr_set_bits(MSDC_FIFOCS, MSDC_FIFOCS_CLR); \ ++ msdc_retry(sdr_read32(MSDC_FIFOCS) & MSDC_FIFOCS_CLR, retry, cnt); \ ++ } while(0) ++ ++#define msdc_irq_save(val) \ ++ do { \ ++ val = sdr_read32(MSDC_INTEN); \ ++ sdr_clr_bits(MSDC_INTEN, val); \ ++ } while(0) ++ ++#define msdc_irq_restore(val) \ ++ do { \ ++ sdr_set_bits(MSDC_INTEN, val); \ ++ } while(0) ++ ++/* clock source for host: global */ ++#if defined (CONFIG_SOC_MT7620) ++static u32 hclks[] = {48000000}; /* +/- by chhung */ ++#elif defined (CONFIG_SOC_MT7621) ++static u32 hclks[] = {50000000}; /* +/- by chhung */ ++#endif ++ ++//============================================ ++// the power for msdc host controller: global ++// always keep the VMC on. ++//============================================ ++#define msdc_vcore_on(host) \ ++ do { \ ++ INIT_MSG("[+]VMC ref. count<%d>", ++host->pwr_ref); \ ++ (void)hwPowerOn(MT65XX_POWER_LDO_VMC, VOL_3300, "SD"); \ ++ } while (0) ++#define msdc_vcore_off(host) \ ++ do { \ ++ INIT_MSG("[-]VMC ref. count<%d>", --host->pwr_ref); \ ++ (void)hwPowerDown(MT65XX_POWER_LDO_VMC, "SD"); \ ++ } while (0) ++ ++//==================================== ++// the vdd output for card: global ++// always keep the VMCH on. ++//==================================== ++#define msdc_vdd_on(host) \ ++ do { \ ++ (void)hwPowerOn(MT65XX_POWER_LDO_VMCH, VOL_3300, "SD"); \ ++ } while (0) ++#define msdc_vdd_off(host) \ ++ do { \ ++ (void)hwPowerDown(MT65XX_POWER_LDO_VMCH, "SD"); \ ++ } while (0) ++ ++#define sdc_is_busy() (sdr_read32(SDC_STS) & SDC_STS_SDCBUSY) ++#define sdc_is_cmd_busy() (sdr_read32(SDC_STS) & SDC_STS_CMDBUSY) ++ ++#define sdc_send_cmd(cmd,arg) \ ++ do { \ ++ sdr_write32(SDC_ARG, (arg)); \ ++ sdr_write32(SDC_CMD, (cmd)); \ ++ } while(0) ++ ++// can modify to read h/w register. ++//#define is_card_present(h) ((sdr_read32(MSDC_PS) & MSDC_PS_CDSTS) ? 0 : 1); ++#define is_card_present(h) (((struct msdc_host*)(h))->card_inserted) ++ ++/* +++ by chhung */ ++#ifndef __ASSEMBLY__ ++#define PHYSADDR(a) (((unsigned long)(a)) & 0x1fffffff) ++#else ++#define PHYSADDR(a) ((a) & 0x1fffffff) ++#endif ++/* end of +++ */ ++static unsigned int msdc_do_command(struct msdc_host *host, ++ struct mmc_command *cmd, ++ int tune, ++ unsigned long timeout); ++ ++static int msdc_tune_cmdrsp(struct msdc_host*host,struct mmc_command *cmd); ++ ++#ifdef MT6575_SD_DEBUG ++static void msdc_dump_card_status(struct msdc_host *host, u32 status) ++{ ++ static char *state[] = { ++ "Idle", /* 0 */ ++ "Ready", /* 1 */ ++ "Ident", /* 2 */ ++ "Stby", /* 3 */ ++ "Tran", /* 4 */ ++ "Data", /* 5 */ ++ "Rcv", /* 6 */ ++ "Prg", /* 7 */ ++ "Dis", /* 8 */ ++ "Reserved", /* 9 */ ++ "Reserved", /* 10 */ ++ "Reserved", /* 11 */ ++ "Reserved", /* 12 */ ++ "Reserved", /* 13 */ ++ "Reserved", /* 14 */ ++ "I/O mode", /* 15 */ ++ }; ++ if (status & R1_OUT_OF_RANGE) ++ N_MSG(RSP, "[CARD_STATUS] Out of Range"); ++ if (status & R1_ADDRESS_ERROR) ++ N_MSG(RSP, "[CARD_STATUS] Address Error"); ++ if (status & R1_BLOCK_LEN_ERROR) ++ N_MSG(RSP, "[CARD_STATUS] Block Len Error"); ++ if (status & R1_ERASE_SEQ_ERROR) ++ N_MSG(RSP, "[CARD_STATUS] Erase Seq Error"); ++ if (status & R1_ERASE_PARAM) ++ N_MSG(RSP, "[CARD_STATUS] Erase Param"); ++ if (status & R1_WP_VIOLATION) ++ N_MSG(RSP, "[CARD_STATUS] WP Violation"); ++ if (status & R1_CARD_IS_LOCKED) ++ N_MSG(RSP, "[CARD_STATUS] Card is Locked"); ++ if (status & R1_LOCK_UNLOCK_FAILED) ++ N_MSG(RSP, "[CARD_STATUS] Lock/Unlock Failed"); ++ if (status & R1_COM_CRC_ERROR) ++ N_MSG(RSP, "[CARD_STATUS] Command CRC Error"); ++ if (status & R1_ILLEGAL_COMMAND) ++ N_MSG(RSP, "[CARD_STATUS] Illegal Command"); ++ if (status & R1_CARD_ECC_FAILED) ++ N_MSG(RSP, "[CARD_STATUS] Card ECC Failed"); ++ if (status & R1_CC_ERROR) ++ N_MSG(RSP, "[CARD_STATUS] CC Error"); ++ if (status & R1_ERROR) ++ N_MSG(RSP, "[CARD_STATUS] Error"); ++ if (status & R1_UNDERRUN) ++ N_MSG(RSP, "[CARD_STATUS] Underrun"); ++ if (status & R1_OVERRUN) ++ N_MSG(RSP, "[CARD_STATUS] Overrun"); ++ if (status & R1_CID_CSD_OVERWRITE) ++ N_MSG(RSP, "[CARD_STATUS] CID/CSD Overwrite"); ++ if (status & R1_WP_ERASE_SKIP) ++ N_MSG(RSP, "[CARD_STATUS] WP Eraser Skip"); ++ if (status & R1_CARD_ECC_DISABLED) ++ N_MSG(RSP, "[CARD_STATUS] Card ECC Disabled"); ++ if (status & R1_ERASE_RESET) ++ N_MSG(RSP, "[CARD_STATUS] Erase Reset"); ++ if (status & R1_READY_FOR_DATA) ++ N_MSG(RSP, "[CARD_STATUS] Ready for Data"); ++ if (status & R1_SWITCH_ERROR) ++ N_MSG(RSP, "[CARD_STATUS] Switch error"); ++ if (status & R1_APP_CMD) ++ N_MSG(RSP, "[CARD_STATUS] App Command"); ++ ++ N_MSG(RSP, "[CARD_STATUS] '%s' State", state[R1_CURRENT_STATE(status)]); ++} ++ ++static void msdc_dump_ocr_reg(struct msdc_host *host, u32 resp) ++{ ++ if (resp & (1 << 7)) ++ N_MSG(RSP, "[OCR] Low Voltage Range"); ++ if (resp & (1 << 15)) ++ N_MSG(RSP, "[OCR] 2.7-2.8 volt"); ++ if (resp & (1 << 16)) ++ N_MSG(RSP, "[OCR] 2.8-2.9 volt"); ++ if (resp & (1 << 17)) ++ N_MSG(RSP, "[OCR] 2.9-3.0 volt"); ++ if (resp & (1 << 18)) ++ N_MSG(RSP, "[OCR] 3.0-3.1 volt"); ++ if (resp & (1 << 19)) ++ N_MSG(RSP, "[OCR] 3.1-3.2 volt"); ++ if (resp & (1 << 20)) ++ N_MSG(RSP, "[OCR] 3.2-3.3 volt"); ++ if (resp & (1 << 21)) ++ N_MSG(RSP, "[OCR] 3.3-3.4 volt"); ++ if (resp & (1 << 22)) ++ N_MSG(RSP, "[OCR] 3.4-3.5 volt"); ++ if (resp & (1 << 23)) ++ N_MSG(RSP, "[OCR] 3.5-3.6 volt"); ++ if (resp & (1 << 24)) ++ N_MSG(RSP, "[OCR] Switching to 1.8V Accepted (S18A)"); ++ if (resp & (1 << 30)) ++ N_MSG(RSP, "[OCR] Card Capacity Status (CCS)"); ++ if (resp & (1 << 31)) ++ N_MSG(RSP, "[OCR] Card Power Up Status (Idle)"); ++ else ++ N_MSG(RSP, "[OCR] Card Power Up Status (Busy)"); ++} ++ ++static void msdc_dump_rca_resp(struct msdc_host *host, u32 resp) ++{ ++ u32 status = (((resp >> 15) & 0x1) << 23) | ++ (((resp >> 14) & 0x1) << 22) | ++ (((resp >> 13) & 0x1) << 19) | ++ (resp & 0x1fff); ++ ++ N_MSG(RSP, "[RCA] 0x%.4x", resp >> 16); ++ msdc_dump_card_status(host, status); ++} ++ ++static void msdc_dump_io_resp(struct msdc_host *host, u32 resp) ++{ ++ u32 flags = (resp >> 8) & 0xFF; ++ char *state[] = {"DIS", "CMD", "TRN", "RFU"}; ++ ++ if (flags & (1 << 7)) ++ N_MSG(RSP, "[IO] COM_CRC_ERR"); ++ if (flags & (1 << 6)) ++ N_MSG(RSP, "[IO] Illgal command"); ++ if (flags & (1 << 3)) ++ N_MSG(RSP, "[IO] Error"); ++ if (flags & (1 << 2)) ++ N_MSG(RSP, "[IO] RFU"); ++ if (flags & (1 << 1)) ++ N_MSG(RSP, "[IO] Function number error"); ++ if (flags & (1 << 0)) ++ N_MSG(RSP, "[IO] Out of range"); ++ ++ N_MSG(RSP, "[IO] State: %s, Data:0x%x", state[(resp >> 12) & 0x3], resp & 0xFF); ++} ++#endif ++ ++static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks) ++{ ++ u32 base = host->base; ++ u32 timeout, clk_ns; ++ ++ host->timeout_ns = ns; ++ host->timeout_clks = clks; ++ ++ clk_ns = 1000000000UL / host->sclk; ++ timeout = ns / clk_ns + clks; ++ timeout = timeout >> 16; /* in 65536 sclk cycle unit */ ++ timeout = timeout > 1 ? timeout - 1 : 0; ++ timeout = timeout > 255 ? 255 : timeout; ++ ++ sdr_set_field(SDC_CFG, SDC_CFG_DTOC, timeout); ++ ++ N_MSG(OPS, "Set read data timeout: %dns %dclks -> %d x 65536 cycles", ++ ns, clks, timeout + 1); ++} ++ ++/* msdc_eirq_sdio() will be called when EIRQ(for WIFI) */ ++static void msdc_eirq_sdio(void *data) ++{ ++ struct msdc_host *host = (struct msdc_host *)data; ++ ++ N_MSG(INT, "SDIO EINT"); ++ ++ mmc_signal_sdio_irq(host->mmc); ++} ++ ++/* msdc_eirq_cd will not be used! We not using EINT for card detection. */ ++static void msdc_eirq_cd(void *data) ++{ ++ struct msdc_host *host = (struct msdc_host *)data; ++ ++ N_MSG(INT, "CD EINT"); ++ ++#if 0 ++ tasklet_hi_schedule(&host->card_tasklet); ++#else ++ schedule_delayed_work(&host->card_delaywork, HZ); ++#endif ++} ++ ++#if 0 ++static void msdc_tasklet_card(unsigned long arg) ++{ ++ struct msdc_host *host = (struct msdc_host *)arg; ++#else ++static void msdc_tasklet_card(struct work_struct *work) ++{ ++ struct msdc_host *host = (struct msdc_host *)container_of(work, ++ struct msdc_host, card_delaywork.work); ++#endif ++ struct msdc_hw *hw = host->hw; ++ u32 base = host->base; ++ u32 inserted; ++ u32 status = 0; ++ //u32 change = 0; ++ ++ spin_lock(&host->lock); ++ ++ if (hw->get_cd_status) { // NULL ++ inserted = hw->get_cd_status(); ++ } else { ++ status = sdr_read32(MSDC_PS); ++ if (cd_active_low) ++ inserted = (status & MSDC_PS_CDSTS) ? 0 : 1; ++ else ++ inserted = (status & MSDC_PS_CDSTS) ? 1 : 0; ++ } ++ ++#if 0 ++ change = host->card_inserted ^ inserted; ++ host->card_inserted = inserted; ++ ++ if (change && !host->suspend) { ++ if (inserted) { ++ host->mmc->f_max = HOST_MAX_MCLK; // work around ++ } ++ mmc_detect_change(host->mmc, msecs_to_jiffies(20)); ++ } ++#else /* Make sure: handle the last interrupt */ ++ host->card_inserted = inserted; ++ ++ if (!host->suspend) { ++ host->mmc->f_max = HOST_MAX_MCLK; ++ mmc_detect_change(host->mmc, msecs_to_jiffies(20)); ++ } ++ ++ IRQ_MSG("card found<%s>", inserted ? "inserted" : "removed"); ++#endif ++ ++ spin_unlock(&host->lock); ++} ++ ++#if 0 /* --- by chhung */ ++/* For E2 only */ ++static u8 clk_src_bit[4] = { ++ 0, 3, 5, 7 ++}; ++ ++static void msdc_select_clksrc(struct msdc_host* host, unsigned char clksrc) ++{ ++ u32 val; ++ u32 base = host->base; ++ ++ BUG_ON(clksrc > 3); ++ INIT_MSG("set clock source to <%d>", clksrc); ++ ++ val = sdr_read32(MSDC_CLKSRC_REG); ++ if (sdr_read32(MSDC_ECO_VER) >= 4) { ++ val &= ~(0x3 << clk_src_bit[host->id]); ++ val |= clksrc << clk_src_bit[host->id]; ++ } else { ++ val &= ~0x3; val |= clksrc; ++ } ++ sdr_write32(MSDC_CLKSRC_REG, val); ++ ++ host->hclk = hclks[clksrc]; ++ host->hw->clk_src = clksrc; ++} ++#endif /* end of --- */ ++ ++static void msdc_set_mclk(struct msdc_host *host, int ddr, unsigned int hz) ++{ ++ //struct msdc_hw *hw = host->hw; ++ u32 base = host->base; ++ u32 mode; ++ u32 flags; ++ u32 div; ++ u32 sclk; ++ u32 hclk = host->hclk; ++ //u8 clksrc = hw->clk_src; ++ ++ if (!hz) { // set mmc system clock to 0 ? ++ //ERR_MSG("set mclk to 0!!!"); ++ msdc_reset(); ++ return; ++ } ++ ++ msdc_irq_save(flags); ++ ++#if defined (CONFIG_MT7621_FPGA) || defined (CONFIG_MT7628_FPGA) ++ mode = 0x0; /* use divisor */ ++ if (hz >= (hclk >> 1)) { ++ div = 0; /* mean div = 1/2 */ ++ sclk = hclk >> 1; /* sclk = clk / 2 */ ++ } else { ++ div = (hclk + ((hz << 2) - 1)) / (hz << 2); ++ sclk = (hclk >> 2) / div; ++ } ++#else ++ if (ddr) { ++ mode = 0x2; /* ddr mode and use divisor */ ++ if (hz >= (hclk >> 2)) { ++ div = 1; /* mean div = 1/4 */ ++ sclk = hclk >> 2; /* sclk = clk / 4 */ ++ } else { ++ div = (hclk + ((hz << 2) - 1)) / (hz << 2); ++ sclk = (hclk >> 2) / div; ++ } ++ } else if (hz >= hclk) { /* bug fix */ ++ mode = 0x1; /* no divisor and divisor is ignored */ ++ div = 0; ++ sclk = hclk; ++ } else { ++ mode = 0x0; /* use divisor */ ++ if (hz >= (hclk >> 1)) { ++ div = 0; /* mean div = 1/2 */ ++ sclk = hclk >> 1; /* sclk = clk / 2 */ ++ } else { ++ div = (hclk + ((hz << 2) - 1)) / (hz << 2); ++ sclk = (hclk >> 2) / div; ++ } ++ } ++#endif ++ /* set clock mode and divisor */ ++ sdr_set_field(MSDC_CFG, MSDC_CFG_CKMOD, mode); ++ sdr_set_field(MSDC_CFG, MSDC_CFG_CKDIV, div); ++ ++ /* wait clock stable */ ++ while (!(sdr_read32(MSDC_CFG) & MSDC_CFG_CKSTB)); ++ ++ host->sclk = sclk; ++ host->mclk = hz; ++ msdc_set_timeout(host, host->timeout_ns, host->timeout_clks); // need? ++ ++ INIT_MSG("================"); ++ INIT_MSG("!!! Set<%dKHz> Source<%dKHz> -> sclk<%dKHz>", hz/1000, hclk/1000, sclk/1000); ++ INIT_MSG("================"); ++ ++ msdc_irq_restore(flags); ++} ++ ++/* Fix me. when need to abort */ ++static void msdc_abort_data(struct msdc_host *host) ++{ ++ u32 base = host->base; ++ struct mmc_command *stop = host->mrq->stop; ++ ++ ERR_MSG("Need to Abort. dma<%d>", host->dma_xfer); ++ ++ msdc_reset(); ++ msdc_clr_fifo(); ++ msdc_clr_int(); ++ ++ // need to check FIFO count 0 ? ++ ++ if (stop) { /* try to stop, but may not success */ ++ ERR_MSG("stop when abort CMD<%d>", stop->opcode); ++ (void)msdc_do_command(host, stop, 0, CMD_TIMEOUT); ++ } ++ ++ //if (host->mclk >= 25000000) { ++ // msdc_set_mclk(host, 0, host->mclk >> 1); ++ //} ++} ++ ++#if 0 /* --- by chhung */ ++static void msdc_pin_config(struct msdc_host *host, int mode) ++{ ++ struct msdc_hw *hw = host->hw; ++ u32 base = host->base; ++ int pull = (mode == MSDC_PIN_PULL_UP) ? GPIO_PULL_UP : GPIO_PULL_DOWN; ++ ++ /* Config WP pin */ ++ if (hw->flags & MSDC_WP_PIN_EN) { ++ if (hw->config_gpio_pin) /* NULL */ ++ hw->config_gpio_pin(MSDC_WP_PIN, pull); ++ } ++ ++ switch (mode) { ++ case MSDC_PIN_PULL_UP: ++ //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPU, 1); /* Check & FIXME */ ++ //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPD, 0); /* Check & FIXME */ ++ sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPU, 1); ++ sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPD, 0); ++ sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPU, 1); ++ sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPD, 0); ++ break; ++ case MSDC_PIN_PULL_DOWN: ++ //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPU, 0); /* Check & FIXME */ ++ //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPD, 1); /* Check & FIXME */ ++ sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPU, 0); ++ sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPD, 1); ++ sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPU, 0); ++ sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPD, 1); ++ break; ++ case MSDC_PIN_PULL_NONE: ++ default: ++ //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPU, 0); /* Check & FIXME */ ++ //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPD, 0); /* Check & FIXME */ ++ sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPU, 0); ++ sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPD, 0); ++ sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPU, 0); ++ sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPD, 0); ++ break; ++ } ++ ++ N_MSG(CFG, "Pins mode(%d), down(%d), up(%d)", ++ mode, MSDC_PIN_PULL_DOWN, MSDC_PIN_PULL_UP); ++} ++ ++void msdc_pin_reset(struct msdc_host *host, int mode) ++{ ++ struct msdc_hw *hw = (struct msdc_hw *)host->hw; ++ u32 base = host->base; ++ int pull = (mode == MSDC_PIN_PULL_UP) ? GPIO_PULL_UP : GPIO_PULL_DOWN; ++ ++ /* Config reset pin */ ++ if (hw->flags & MSDC_RST_PIN_EN) { ++ if (hw->config_gpio_pin) /* NULL */ ++ hw->config_gpio_pin(MSDC_RST_PIN, pull); ++ ++ if (mode == MSDC_PIN_PULL_UP) { ++ sdr_clr_bits(EMMC_IOCON, EMMC_IOCON_BOOTRST); ++ } else { ++ sdr_set_bits(EMMC_IOCON, EMMC_IOCON_BOOTRST); ++ } ++ } ++} ++ ++static void msdc_core_power(struct msdc_host *host, int on) ++{ ++ N_MSG(CFG, "Turn %s %s power (copower: %d -> %d)", ++ on ? "on" : "off", "core", host->core_power, on); ++ ++ if (on && host->core_power == 0) { ++ msdc_vcore_on(host); ++ host->core_power = 1; ++ msleep(1); ++ } else if (!on && host->core_power == 1) { ++ msdc_vcore_off(host); ++ host->core_power = 0; ++ msleep(1); ++ } ++} ++ ++static void msdc_host_power(struct msdc_host *host, int on) ++{ ++ N_MSG(CFG, "Turn %s %s power ", on ? "on" : "off", "host"); ++ ++ if (on) { ++ //msdc_core_power(host, 1); // need do card detection. ++ msdc_pin_reset(host, MSDC_PIN_PULL_UP); ++ } else { ++ msdc_pin_reset(host, MSDC_PIN_PULL_DOWN); ++ //msdc_core_power(host, 0); ++ } ++} ++ ++static void msdc_card_power(struct msdc_host *host, int on) ++{ ++ N_MSG(CFG, "Turn %s %s power ", on ? "on" : "off", "card"); ++ ++ if (on) { ++ msdc_pin_config(host, MSDC_PIN_PULL_UP); ++ if (host->hw->ext_power_on) { ++ host->hw->ext_power_on(); ++ } else { ++ //msdc_vdd_on(host); // need todo card detection. ++ } ++ msleep(1); ++ } else { ++ if (host->hw->ext_power_off) { ++ host->hw->ext_power_off(); ++ } else { ++ //msdc_vdd_off(host); ++ } ++ msdc_pin_config(host, MSDC_PIN_PULL_DOWN); ++ msleep(1); ++ } ++} ++ ++static void msdc_set_power_mode(struct msdc_host *host, u8 mode) ++{ ++ N_MSG(CFG, "Set power mode(%d)", mode); ++ ++ if (host->power_mode == MMC_POWER_OFF && mode != MMC_POWER_OFF) { ++ msdc_host_power(host, 1); ++ msdc_card_power(host, 1); ++ } else if (host->power_mode != MMC_POWER_OFF && mode == MMC_POWER_OFF) { ++ msdc_card_power(host, 0); ++ msdc_host_power(host, 0); ++ } ++ host->power_mode = mode; ++} ++#endif /* end of --- */ ++ ++#ifdef CONFIG_PM ++/* ++ register as callback function of WIFI(combo_sdio_register_pm) . ++ can called by msdc_drv_suspend/resume too. ++*/ ++static void msdc_pm(pm_message_t state, void *data) ++{ ++ struct msdc_host *host = (struct msdc_host *)data; ++ int evt = state.event; ++ ++ if (evt == PM_EVENT_USER_RESUME || evt == PM_EVENT_USER_SUSPEND) { ++ INIT_MSG("USR_%s: suspend<%d> power<%d>", ++ evt == PM_EVENT_USER_RESUME ? "EVENT_USER_RESUME" : "EVENT_USER_SUSPEND", ++ host->suspend, host->power_mode); ++ } ++ ++ if (evt == PM_EVENT_SUSPEND || evt == PM_EVENT_USER_SUSPEND) { ++ if (host->suspend) /* already suspend */ /* default 0*/ ++ return; ++ ++ /* for memory card. already power off by mmc */ ++ if (evt == PM_EVENT_SUSPEND && host->power_mode == MMC_POWER_OFF) ++ return; ++ ++ host->suspend = 1; ++ host->pm_state = state; /* default PMSG_RESUME */ ++ ++ INIT_MSG("%s Suspend", evt == PM_EVENT_SUSPEND ? "PM" : "USR"); ++ if(host->hw->flags & MSDC_SYS_SUSPEND) /* set for card */ ++ (void)mmc_suspend_host(host->mmc); ++ else { ++ // host->mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY; /* just for double confirm */ /* --- by chhung */ ++ mmc_remove_host(host->mmc); ++ } ++ } else if (evt == PM_EVENT_RESUME || evt == PM_EVENT_USER_RESUME) { ++ if (!host->suspend){ ++ //ERR_MSG("warning: already resume"); ++ return; ++ } ++ ++ /* No PM resume when USR suspend */ ++ if (evt == PM_EVENT_RESUME && host->pm_state.event == PM_EVENT_USER_SUSPEND) { ++ ERR_MSG("PM Resume when in USR Suspend"); /* won't happen. */ ++ return; ++ } ++ ++ host->suspend = 0; ++ host->pm_state = state; ++ ++ INIT_MSG("%s Resume", evt == PM_EVENT_RESUME ? "PM" : "USR"); ++ if(host->hw->flags & MSDC_SYS_SUSPEND) { /* will not set for WIFI */ ++ (void)mmc_resume_host(host->mmc); ++ } ++ else { ++ // host->mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY; /* --- by chhung */ ++ mmc_add_host(host->mmc); ++ } ++ } ++} ++#endif ++ ++/*--------------------------------------------------------------------------*/ ++/* mmc_host_ops members */ ++/*--------------------------------------------------------------------------*/ ++static unsigned int msdc_command_start(struct msdc_host *host, ++ struct mmc_command *cmd, ++ int tune, /* not used */ ++ unsigned long timeout) ++{ ++ u32 base = host->base; ++ u32 opcode = cmd->opcode; ++ u32 rawcmd; ++ u32 wints = MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | ++ MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO | ++ MSDC_INT_ACMD19_DONE; ++ ++ u32 resp; ++ unsigned long tmo; ++ ++ /* Protocol layer does not provide response type, but our hardware needs ++ * to know exact type, not just size! ++ */ ++ if (opcode == MMC_SEND_OP_COND || opcode == SD_APP_OP_COND) ++ resp = RESP_R3; ++ else if (opcode == MMC_SET_RELATIVE_ADDR || opcode == SD_SEND_RELATIVE_ADDR) ++ resp = (mmc_cmd_type(cmd) == MMC_CMD_BCR) ? RESP_R6 : RESP_R1; ++ else if (opcode == MMC_FAST_IO) ++ resp = RESP_R4; ++ else if (opcode == MMC_GO_IRQ_STATE) ++ resp = RESP_R5; ++ else if (opcode == MMC_SELECT_CARD) ++ resp = (cmd->arg != 0) ? RESP_R1B : RESP_NONE; ++ else if (opcode == SD_IO_RW_DIRECT || opcode == SD_IO_RW_EXTENDED) ++ resp = RESP_R1; /* SDIO workaround. */ ++ else if (opcode == SD_SEND_IF_COND && (mmc_cmd_type(cmd) == MMC_CMD_BCR)) ++ resp = RESP_R1; ++ else { ++ switch (mmc_resp_type(cmd)) { ++ case MMC_RSP_R1: ++ resp = RESP_R1; ++ break; ++ case MMC_RSP_R1B: ++ resp = RESP_R1B; ++ break; ++ case MMC_RSP_R2: ++ resp = RESP_R2; ++ break; ++ case MMC_RSP_R3: ++ resp = RESP_R3; ++ break; ++ case MMC_RSP_NONE: ++ default: ++ resp = RESP_NONE; ++ break; ++ } ++ } ++ ++ cmd->error = 0; ++ /* rawcmd : ++ * vol_swt << 30 | auto_cmd << 28 | blklen << 16 | go_irq << 15 | ++ * stop << 14 | rw << 13 | dtype << 11 | rsptyp << 7 | brk << 6 | opcode ++ */ ++ rawcmd = opcode | msdc_rsp[resp] << 7 | host->blksz << 16; ++ ++ if (opcode == MMC_READ_MULTIPLE_BLOCK) { ++ rawcmd |= (2 << 11); ++ } else if (opcode == MMC_READ_SINGLE_BLOCK) { ++ rawcmd |= (1 << 11); ++ } else if (opcode == MMC_WRITE_MULTIPLE_BLOCK) { ++ rawcmd |= ((2 << 11) | (1 << 13)); ++ } else if (opcode == MMC_WRITE_BLOCK) { ++ rawcmd |= ((1 << 11) | (1 << 13)); ++ } else if (opcode == SD_IO_RW_EXTENDED) { ++ if (cmd->data->flags & MMC_DATA_WRITE) ++ rawcmd |= (1 << 13); ++ if (cmd->data->blocks > 1) ++ rawcmd |= (2 << 11); ++ else ++ rawcmd |= (1 << 11); ++ } else if (opcode == SD_IO_RW_DIRECT && cmd->flags == (unsigned int)-1) { ++ rawcmd |= (1 << 14); ++ } else if ((opcode == SD_APP_SEND_SCR) || ++ (opcode == SD_APP_SEND_NUM_WR_BLKS) || ++ (opcode == SD_SWITCH && (mmc_cmd_type(cmd) == MMC_CMD_ADTC)) || ++ (opcode == SD_APP_SD_STATUS && (mmc_cmd_type(cmd) == MMC_CMD_ADTC)) || ++ (opcode == MMC_SEND_EXT_CSD && (mmc_cmd_type(cmd) == MMC_CMD_ADTC))) { ++ rawcmd |= (1 << 11); ++ } else if (opcode == MMC_STOP_TRANSMISSION) { ++ rawcmd |= (1 << 14); ++ rawcmd &= ~(0x0FFF << 16); ++ } ++ ++ N_MSG(CMD, "CMD<%d><0x%.8x> Arg<0x%.8x>", opcode , rawcmd, cmd->arg); ++ ++ tmo = jiffies + timeout; ++ ++ if (opcode == MMC_SEND_STATUS) { ++ for (;;) { ++ if (!sdc_is_cmd_busy()) ++ break; ++ ++ if (time_after(jiffies, tmo)) { ++ ERR_MSG("XXX cmd_busy timeout: before CMD<%d>", opcode); ++ cmd->error = (unsigned int)-ETIMEDOUT; ++ msdc_reset(); ++ goto end; ++ } ++ } ++ }else { ++ for (;;) { ++ if (!sdc_is_busy()) ++ break; ++ if (time_after(jiffies, tmo)) { ++ ERR_MSG("XXX sdc_busy timeout: before CMD<%d>", opcode); ++ cmd->error = (unsigned int)-ETIMEDOUT; ++ msdc_reset(); ++ goto end; ++ } ++ } ++ } ++ ++ //BUG_ON(in_interrupt()); ++ host->cmd = cmd; ++ host->cmd_rsp = resp; ++ ++ init_completion(&host->cmd_done); ++ ++ sdr_set_bits(MSDC_INTEN, wints); ++ sdc_send_cmd(rawcmd, cmd->arg); ++ ++end: ++ return cmd->error; ++} ++ ++static unsigned int msdc_command_resp(struct msdc_host *host, ++ struct mmc_command *cmd, ++ int tune, ++ unsigned long timeout) ++{ ++ u32 base = host->base; ++ u32 opcode = cmd->opcode; ++ //u32 rawcmd; ++ u32 resp; ++ u32 wints = MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | ++ MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO | ++ MSDC_INT_ACMD19_DONE; ++ ++ resp = host->cmd_rsp; ++ ++ BUG_ON(in_interrupt()); ++ //init_completion(&host->cmd_done); ++ //sdr_set_bits(MSDC_INTEN, wints); ++ ++ spin_unlock(&host->lock); ++ if(!wait_for_completion_timeout(&host->cmd_done, 10*timeout)){ ++ ERR_MSG("XXX CMD<%d> wait_for_completion timeout ARG<0x%.8x>", opcode, cmd->arg); ++ cmd->error = (unsigned int)-ETIMEDOUT; ++ msdc_reset(); ++ } ++ spin_lock(&host->lock); ++ ++ sdr_clr_bits(MSDC_INTEN, wints); ++ host->cmd = NULL; ++ ++//end: ++#ifdef MT6575_SD_DEBUG ++ switch (resp) { ++ case RESP_NONE: ++ N_MSG(RSP, "CMD_RSP(%d): %d RSP(%d)", opcode, cmd->error, resp); ++ break; ++ case RESP_R2: ++ N_MSG(RSP, "CMD_RSP(%d): %d RSP(%d)= %.8x %.8x %.8x %.8x", ++ opcode, cmd->error, resp, cmd->resp[0], cmd->resp[1], ++ cmd->resp[2], cmd->resp[3]); ++ break; ++ default: /* Response types 1, 3, 4, 5, 6, 7(1b) */ ++ N_MSG(RSP, "CMD_RSP(%d): %d RSP(%d)= 0x%.8x", ++ opcode, cmd->error, resp, cmd->resp[0]); ++ if (cmd->error == 0) { ++ switch (resp) { ++ case RESP_R1: ++ case RESP_R1B: ++ msdc_dump_card_status(host, cmd->resp[0]); ++ break; ++ case RESP_R3: ++ msdc_dump_ocr_reg(host, cmd->resp[0]); ++ break; ++ case RESP_R5: ++ msdc_dump_io_resp(host, cmd->resp[0]); ++ break; ++ case RESP_R6: ++ msdc_dump_rca_resp(host, cmd->resp[0]); ++ break; ++ } ++ } ++ break; ++ } ++#endif ++ ++ /* do we need to save card's RCA when SD_SEND_RELATIVE_ADDR */ ++ ++ if (!tune) { ++ return cmd->error; ++ } ++ ++ /* memory card CRC */ ++ if(host->hw->flags & MSDC_REMOVABLE && cmd->error == (unsigned int)(-EIO) ) { ++ if (sdr_read32(SDC_CMD) & 0x1800) { /* check if has data phase */ ++ msdc_abort_data(host); ++ } else { ++ /* do basic: reset*/ ++ msdc_reset(); ++ msdc_clr_fifo(); ++ msdc_clr_int(); ++ } ++ cmd->error = msdc_tune_cmdrsp(host,cmd); ++ } ++ ++ // check DAT0 ++ /* if (resp == RESP_R1B) { ++ while ((sdr_read32(MSDC_PS) & 0x10000) != 0x10000); ++ } */ ++ /* CMD12 Error Handle */ ++ ++ return cmd->error; ++} ++ ++static unsigned int msdc_do_command(struct msdc_host *host, ++ struct mmc_command *cmd, ++ int tune, ++ unsigned long timeout) ++{ ++ if (msdc_command_start(host, cmd, tune, timeout)) ++ goto end; ++ ++ if (msdc_command_resp(host, cmd, tune, timeout)) ++ goto end; ++ ++end: ++ ++ N_MSG(CMD, " return<%d> resp<0x%.8x>", cmd->error, cmd->resp[0]); ++ return cmd->error; ++} ++ ++/* The abort condition when PIO read/write ++ tmo: ++*/ ++static int msdc_pio_abort(struct msdc_host *host, struct mmc_data *data, unsigned long tmo) ++{ ++ int ret = 0; ++ u32 base = host->base; ++ ++ if (atomic_read(&host->abort)) { ++ ret = 1; ++ } ++ ++ if (time_after(jiffies, tmo)) { ++ data->error = (unsigned int)-ETIMEDOUT; ++ ERR_MSG("XXX PIO Data Timeout: CMD<%d>", host->mrq->cmd->opcode); ++ ret = 1; ++ } ++ ++ if(ret) { ++ msdc_reset(); ++ msdc_clr_fifo(); ++ msdc_clr_int(); ++ ERR_MSG("msdc pio find abort"); ++ } ++ return ret; ++} ++ ++/* ++ Need to add a timeout, or WDT timeout, system reboot. ++*/ ++// pio mode data read/write ++static int msdc_pio_read(struct msdc_host *host, struct mmc_data *data) ++{ ++ struct scatterlist *sg = data->sg; ++ u32 base = host->base; ++ u32 num = data->sg_len; ++ u32 *ptr; ++ u8 *u8ptr; ++ u32 left = 0; ++ u32 count, size = 0; ++ u32 wints = MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR ; ++ unsigned long tmo = jiffies + DAT_TIMEOUT; ++ ++ sdr_set_bits(MSDC_INTEN, wints); ++ while (num) { ++ left = sg_dma_len(sg); ++ ptr = sg_virt(sg); ++ while (left) { ++ if ((left >= MSDC_FIFO_THD) && (msdc_rxfifocnt() >= MSDC_FIFO_THD)) { ++ count = MSDC_FIFO_THD >> 2; ++ do { ++ *ptr++ = msdc_fifo_read32(); ++ } while (--count); ++ left -= MSDC_FIFO_THD; ++ } else if ((left < MSDC_FIFO_THD) && msdc_rxfifocnt() >= left) { ++ while (left > 3) { ++ *ptr++ = msdc_fifo_read32(); ++ left -= 4; ++ } ++ ++ u8ptr = (u8 *)ptr; ++ while(left) { ++ * u8ptr++ = msdc_fifo_read8(); ++ left--; ++ } ++ } ++ ++ if (msdc_pio_abort(host, data, tmo)) { ++ goto end; ++ } ++ } ++ size += sg_dma_len(sg); ++ sg = sg_next(sg); num--; ++ } ++end: ++ data->bytes_xfered += size; ++ N_MSG(FIO, " PIO Read<%d>bytes", size); ++ ++ sdr_clr_bits(MSDC_INTEN, wints); ++ if(data->error) ERR_MSG("read pio data->error<%d> left<%d> size<%d>", data->error, left, size); ++ return data->error; ++} ++ ++/* please make sure won't using PIO when size >= 512 ++ which means, memory card block read/write won't using pio ++ then don't need to handle the CMD12 when data error. ++*/ ++static int msdc_pio_write(struct msdc_host* host, struct mmc_data *data) ++{ ++ u32 base = host->base; ++ struct scatterlist *sg = data->sg; ++ u32 num = data->sg_len; ++ u32 *ptr; ++ u8 *u8ptr; ++ u32 left; ++ u32 count, size = 0; ++ u32 wints = MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR ; ++ unsigned long tmo = jiffies + DAT_TIMEOUT; ++ ++ sdr_set_bits(MSDC_INTEN, wints); ++ while (num) { ++ left = sg_dma_len(sg); ++ ptr = sg_virt(sg); ++ ++ while (left) { ++ if (left >= MSDC_FIFO_SZ && msdc_txfifocnt() == 0) { ++ count = MSDC_FIFO_SZ >> 2; ++ do { ++ msdc_fifo_write32(*ptr); ptr++; ++ } while (--count); ++ left -= MSDC_FIFO_SZ; ++ } else if (left < MSDC_FIFO_SZ && msdc_txfifocnt() == 0) { ++ while (left > 3) { ++ msdc_fifo_write32(*ptr); ptr++; ++ left -= 4; ++ } ++ ++ u8ptr = (u8*)ptr; ++ while(left){ ++ msdc_fifo_write8(*u8ptr); u8ptr++; ++ left--; ++ } ++ } ++ ++ if (msdc_pio_abort(host, data, tmo)) { ++ goto end; ++ } ++ } ++ size += sg_dma_len(sg); ++ sg = sg_next(sg); num--; ++ } ++end: ++ data->bytes_xfered += size; ++ N_MSG(FIO, " PIO Write<%d>bytes", size); ++ if(data->error) ERR_MSG("write pio data->error<%d>", data->error); ++ ++ sdr_clr_bits(MSDC_INTEN, wints); ++ return data->error; ++} ++ ++#if 0 /* --- by chhung */ ++// DMA resume / start / stop ++static void msdc_dma_resume(struct msdc_host *host) ++{ ++ u32 base = host->base; ++ ++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_RESUME, 1); ++ ++ N_MSG(DMA, "DMA resume"); ++} ++#endif /* end of --- */ ++ ++static void msdc_dma_start(struct msdc_host *host) ++{ ++ u32 base = host->base; ++ u32 wints = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR ; ++ ++ sdr_set_bits(MSDC_INTEN, wints); ++ //dsb(); /* --- by chhung */ ++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_START, 1); ++ ++ N_MSG(DMA, "DMA start"); ++} ++ ++static void msdc_dma_stop(struct msdc_host *host) ++{ ++ u32 base = host->base; ++ //u32 retries=500; ++ u32 wints = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR ; ++ ++ N_MSG(DMA, "DMA status: 0x%.8x",sdr_read32(MSDC_DMA_CFG)); ++ //while (sdr_read32(MSDC_DMA_CFG) & MSDC_DMA_CFG_STS); ++ ++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP, 1); ++ while (sdr_read32(MSDC_DMA_CFG) & MSDC_DMA_CFG_STS); ++ ++ //dsb(); /* --- by chhung */ ++ sdr_clr_bits(MSDC_INTEN, wints); /* Not just xfer_comp */ ++ ++ N_MSG(DMA, "DMA stop"); ++} ++ ++#if 0 /* --- by chhung */ ++/* dump a gpd list */ ++static void msdc_dma_dump(struct msdc_host *host, struct msdc_dma *dma) ++{ ++ gpd_t *gpd = dma->gpd; ++ bd_t *bd = dma->bd; ++ bd_t *ptr; ++ int i = 0; ++ int p_to_v; ++ ++ if (dma->mode != MSDC_MODE_DMA_DESC) { ++ return; ++ } ++ ++ ERR_MSG("try to dump gpd and bd"); ++ ++ /* dump gpd */ ++ ERR_MSG(".gpd<0x%.8x> gpd_phy<0x%.8x>", (int)gpd, (int)dma->gpd_addr); ++ ERR_MSG("...hwo <%d>", gpd->hwo ); ++ ERR_MSG("...bdp <%d>", gpd->bdp ); ++ ERR_MSG("...chksum<0x%.8x>", gpd->chksum ); ++ //ERR_MSG("...intr <0x%.8x>", gpd->intr ); ++ ERR_MSG("...next <0x%.8x>", (int)gpd->next ); ++ ERR_MSG("...ptr <0x%.8x>", (int)gpd->ptr ); ++ ERR_MSG("...buflen<0x%.8x>", gpd->buflen ); ++ //ERR_MSG("...extlen<0x%.8x>", gpd->extlen ); ++ //ERR_MSG("...arg <0x%.8x>", gpd->arg ); ++ //ERR_MSG("...blknum<0x%.8x>", gpd->blknum ); ++ //ERR_MSG("...cmd <0x%.8x>", gpd->cmd ); ++ ++ /* dump bd */ ++ ERR_MSG(".bd<0x%.8x> bd_phy<0x%.8x> gpd_ptr<0x%.8x>", (int)bd, (int)dma->bd_addr, (int)gpd->ptr); ++ ptr = bd; ++ p_to_v = ((u32)bd - (u32)dma->bd_addr); ++ while (1) { ++ ERR_MSG(".bd[%d]", i); i++; ++ ERR_MSG("...eol <%d>", ptr->eol ); ++ ERR_MSG("...chksum<0x%.8x>", ptr->chksum ); ++ //ERR_MSG("...blkpad<0x%.8x>", ptr->blkpad ); ++ //ERR_MSG("...dwpad <0x%.8x>", ptr->dwpad ); ++ ERR_MSG("...next <0x%.8x>", (int)ptr->next ); ++ ERR_MSG("...ptr <0x%.8x>", (int)ptr->ptr ); ++ ERR_MSG("...buflen<0x%.8x>", (int)ptr->buflen ); ++ ++ if (ptr->eol == 1) { ++ break; ++ } ++ ++ /* find the next bd, virtual address of ptr->next */ ++ /* don't need to enable when use malloc */ ++ //BUG_ON( (ptr->next + p_to_v)!=(ptr+1) ); ++ //ERR_MSG(".next bd<0x%.8x><0x%.8x>", (ptr->next + p_to_v), (ptr+1)); ++ ptr++; ++ } ++ ++ ERR_MSG("dump gpd and bd finished"); ++} ++#endif /* end of --- */ ++ ++/* calc checksum */ ++static u8 msdc_dma_calcs(u8 *buf, u32 len) ++{ ++ u32 i, sum = 0; ++ for (i = 0; i < len; i++) { ++ sum += buf[i]; ++ } ++ return 0xFF - (u8)sum; ++} ++ ++/* gpd bd setup + dma registers */ ++static int msdc_dma_config(struct msdc_host *host, struct msdc_dma *dma) ++{ ++ u32 base = host->base; ++ u32 sglen = dma->sglen; ++ //u32 i, j, num, bdlen, arg, xfersz; ++ u32 j, num, bdlen; ++ u8 blkpad, dwpad, chksum; ++ struct scatterlist *sg = dma->sg; ++ gpd_t *gpd; ++ bd_t *bd; ++ ++ switch (dma->mode) { ++ case MSDC_MODE_DMA_BASIC: ++ BUG_ON(dma->xfersz > 65535); ++ BUG_ON(dma->sglen != 1); ++ sdr_write32(MSDC_DMA_SA, PHYSADDR(sg_dma_address(sg))); ++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_LASTBUF, 1); ++//#if defined (CONFIG_RALINK_MT7620) ++ if (ralink_soc == MT762X_SOC_MT7620A) ++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_XFERSZ, sg_dma_len(sg)); ++//#elif defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) ++ else ++ sdr_write32((volatile u32*)(RALINK_MSDC_BASE+0xa8), sg_dma_len(sg)); ++//#endif ++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_BRUSTSZ, dma->burstsz); ++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_MODE, 0); ++ break; ++ case MSDC_MODE_DMA_DESC: ++ blkpad = (dma->flags & DMA_FLAG_PAD_BLOCK) ? 1 : 0; ++ dwpad = (dma->flags & DMA_FLAG_PAD_DWORD) ? 1 : 0; ++ chksum = (dma->flags & DMA_FLAG_EN_CHKSUM) ? 1 : 0; ++ ++ /* calculate the required number of gpd */ ++ num = (sglen + MAX_BD_PER_GPD - 1) / MAX_BD_PER_GPD; ++ BUG_ON(num !=1 ); ++ ++ gpd = dma->gpd; ++ bd = dma->bd; ++ bdlen = sglen; ++ ++ /* modify gpd*/ ++ //gpd->intr = 0; ++ gpd->hwo = 1; /* hw will clear it */ ++ gpd->bdp = 1; ++ gpd->chksum = 0; /* need to clear first. */ ++ gpd->chksum = (chksum ? msdc_dma_calcs((u8 *)gpd, 16) : 0); ++ ++ /* modify bd*/ ++ for (j = 0; j < bdlen; j++) { ++ msdc_init_bd(&bd[j], blkpad, dwpad, sg_dma_address(sg), sg_dma_len(sg)); ++ if(j == bdlen - 1) { ++ bd[j].eol = 1; /* the last bd */ ++ } else { ++ bd[j].eol = 0; ++ } ++ bd[j].chksum = 0; /* checksume need to clear first */ ++ bd[j].chksum = (chksum ? msdc_dma_calcs((u8 *)(&bd[j]), 16) : 0); ++ sg++; ++ } ++ ++ dma->used_gpd += 2; ++ dma->used_bd += bdlen; ++ ++ sdr_set_field(MSDC_DMA_CFG, MSDC_DMA_CFG_DECSEN, chksum); ++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_BRUSTSZ, dma->burstsz); ++ sdr_set_field(MSDC_DMA_CTRL, MSDC_DMA_CTRL_MODE, 1); ++ ++ sdr_write32(MSDC_DMA_SA, PHYSADDR((u32)dma->gpd_addr)); ++ break; ++ ++ default: ++ break; ++ } ++ ++ N_MSG(DMA, "DMA_CTRL = 0x%x", sdr_read32(MSDC_DMA_CTRL)); ++ N_MSG(DMA, "DMA_CFG = 0x%x", sdr_read32(MSDC_DMA_CFG)); ++ N_MSG(DMA, "DMA_SA = 0x%x", sdr_read32(MSDC_DMA_SA)); ++ ++ return 0; ++} ++ ++static void msdc_dma_setup(struct msdc_host *host, struct msdc_dma *dma, ++ struct scatterlist *sg, unsigned int sglen) ++{ ++ BUG_ON(sglen > MAX_BD_NUM); /* not support currently */ ++ ++ dma->sg = sg; ++ dma->flags = DMA_FLAG_EN_CHKSUM; ++ //dma->flags = DMA_FLAG_NONE; /* CHECKME */ ++ dma->sglen = sglen; ++ dma->xfersz = host->xfer_size; ++ dma->burstsz = MSDC_BRUST_64B; ++ ++ if (sglen == 1 && sg_dma_len(sg) <= MAX_DMA_CNT) ++ dma->mode = MSDC_MODE_DMA_BASIC; ++ else ++ dma->mode = MSDC_MODE_DMA_DESC; ++ ++ N_MSG(DMA, "DMA mode<%d> sglen<%d> xfersz<%d>", dma->mode, dma->sglen, dma->xfersz); ++ ++ msdc_dma_config(host, dma); ++ ++ /*if (dma->mode == MSDC_MODE_DMA_DESC) { ++ //msdc_dma_dump(host, dma); ++ } */ ++} ++ ++/* set block number before send command */ ++static void msdc_set_blknum(struct msdc_host *host, u32 blknum) ++{ ++ u32 base = host->base; ++ ++ sdr_write32(SDC_BLK_NUM, blknum); ++} ++ ++static int msdc_do_request(struct mmc_host*mmc, struct mmc_request*mrq) ++{ ++ struct msdc_host *host = mmc_priv(mmc); ++ struct mmc_command *cmd; ++ struct mmc_data *data; ++ u32 base = host->base; ++ //u32 intsts = 0; ++ unsigned int left=0; ++ int dma = 0, read = 1, dir = DMA_FROM_DEVICE, send_type=0; ++ ++ #define SND_DAT 0 ++ #define SND_CMD 1 ++ ++ BUG_ON(mmc == NULL); ++ BUG_ON(mrq == NULL); ++ ++ host->error = 0; ++ atomic_set(&host->abort, 0); ++ ++ cmd = mrq->cmd; ++ data = mrq->cmd->data; ++ ++#if 0 /* --- by chhung */ ++ //if(host->id ==1){ ++ N_MSG(OPS, "enable clock!"); ++ msdc_ungate_clock(host->id); ++ //} ++#endif /* end of --- */ ++ ++ if (!data) { ++ send_type=SND_CMD; ++ if (msdc_do_command(host, cmd, 1, CMD_TIMEOUT) != 0) { ++ goto done; ++ } ++ } else { ++ BUG_ON(data->blksz > HOST_MAX_BLKSZ); ++ send_type=SND_DAT; ++ ++ data->error = 0; ++ read = data->flags & MMC_DATA_READ ? 1 : 0; ++ host->data = data; ++ host->xfer_size = data->blocks * data->blksz; ++ host->blksz = data->blksz; ++ ++ /* deside the transfer mode */ ++ if (drv_mode[host->id] == MODE_PIO) { ++ host->dma_xfer = dma = 0; ++ } else if (drv_mode[host->id] == MODE_DMA) { ++ host->dma_xfer = dma = 1; ++ } else if (drv_mode[host->id] == MODE_SIZE_DEP) { ++ host->dma_xfer = dma = ((host->xfer_size >= dma_size[host->id]) ? 1 : 0); ++ } ++ ++ if (read) { ++ if ((host->timeout_ns != data->timeout_ns) || ++ (host->timeout_clks != data->timeout_clks)) { ++ msdc_set_timeout(host, data->timeout_ns, data->timeout_clks); ++ } ++ } ++ ++ msdc_set_blknum(host, data->blocks); ++ //msdc_clr_fifo(); /* no need */ ++ ++ if (dma) { ++ msdc_dma_on(); /* enable DMA mode first!! */ ++ init_completion(&host->xfer_done); ++ ++ /* start the command first*/ ++ if (msdc_command_start(host, cmd, 1, CMD_TIMEOUT) != 0) ++ goto done; ++ ++ dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; ++ (void)dma_map_sg(mmc_dev(mmc), data->sg, data->sg_len, dir); ++ msdc_dma_setup(host, &host->dma, data->sg, data->sg_len); ++ ++ /* then wait command done */ ++ if (msdc_command_resp(host, cmd, 1, CMD_TIMEOUT) != 0) ++ goto done; ++ ++ /* for read, the data coming too fast, then CRC error ++ start DMA no business with CRC. */ ++ //init_completion(&host->xfer_done); ++ msdc_dma_start(host); ++ ++ spin_unlock(&host->lock); ++ if(!wait_for_completion_timeout(&host->xfer_done, DAT_TIMEOUT)){ ++ ERR_MSG("XXX CMD<%d> wait xfer_done<%d> timeout!!", cmd->opcode, data->blocks * data->blksz); ++ ERR_MSG(" DMA_SA = 0x%x", sdr_read32(MSDC_DMA_SA)); ++ ERR_MSG(" DMA_CA = 0x%x", sdr_read32(MSDC_DMA_CA)); ++ ERR_MSG(" DMA_CTRL = 0x%x", sdr_read32(MSDC_DMA_CTRL)); ++ ERR_MSG(" DMA_CFG = 0x%x", sdr_read32(MSDC_DMA_CFG)); ++ data->error = (unsigned int)-ETIMEDOUT; ++ ++ msdc_reset(); ++ msdc_clr_fifo(); ++ msdc_clr_int(); ++ } ++ spin_lock(&host->lock); ++ msdc_dma_stop(host); ++ } else { ++ /* Firstly: send command */ ++ if (msdc_do_command(host, cmd, 1, CMD_TIMEOUT) != 0) { ++ goto done; ++ } ++ ++ /* Secondly: pio data phase */ ++ if (read) { ++ if (msdc_pio_read(host, data)){ ++ goto done; ++ } ++ } else { ++ if (msdc_pio_write(host, data)) { ++ goto done; ++ } ++ } ++ ++ /* For write case: make sure contents in fifo flushed to device */ ++ if (!read) { ++ while (1) { ++ left=msdc_txfifocnt(); ++ if (left == 0) { ++ break; ++ } ++ if (msdc_pio_abort(host, data, jiffies + DAT_TIMEOUT)) { ++ break; ++ /* Fix me: what about if data error, when stop ? how to? */ ++ } ++ } ++ } else { ++ /* Fix me: read case: need to check CRC error */ ++ } ++ ++ /* For write case: SDCBUSY and Xfer_Comp will assert when DAT0 not busy. ++ For read case : SDCBUSY and Xfer_Comp will assert when last byte read out from FIFO. ++ */ ++ ++ /* try not to wait xfer_comp interrupt. ++ the next command will check SDC_BUSY. ++ SDC_BUSY means xfer_comp assert ++ */ ++ ++ } // PIO mode ++ ++ /* Last: stop transfer */ ++ if (data->stop){ ++ if (msdc_do_command(host, data->stop, 0, CMD_TIMEOUT) != 0) { ++ goto done; ++ } ++ } ++ } ++ ++done: ++ if (data != NULL) { ++ host->data = NULL; ++ host->dma_xfer = 0; ++ if (dma != 0) { ++ msdc_dma_off(); ++ host->dma.used_bd = 0; ++ host->dma.used_gpd = 0; ++ dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len, dir); ++ } ++ host->blksz = 0; ++ ++#if 0 // don't stop twice! ++ if(host->hw->flags & MSDC_REMOVABLE && data->error) { ++ msdc_abort_data(host); ++ /* reset in IRQ, stop command has issued. -> No need */ ++ } ++#endif ++ ++ N_MSG(OPS, "CMD<%d> data<%s %s> blksz<%d> block<%d> error<%d>",cmd->opcode, (dma? "dma":"pio"), ++ (read ? "read ":"write") ,data->blksz, data->blocks, data->error); ++ } ++ ++#if 0 /* --- by chhung */ ++#if 1 ++ //if(host->id==1) { ++ if(send_type==SND_CMD) { ++ if(cmd->opcode == MMC_SEND_STATUS) { ++ if((cmd->resp[0] & CARD_READY_FOR_DATA) ||(CARD_CURRENT_STATE(cmd->resp[0]) != 7)){ ++ N_MSG(OPS,"disable clock, CMD13 IDLE"); ++ msdc_gate_clock(host->id); ++ } ++ } else { ++ N_MSG(OPS,"disable clock, CMD<%d>", cmd->opcode); ++ msdc_gate_clock(host->id); ++ } ++ } else { ++ if(read) { ++ N_MSG(OPS,"disable clock!!! Read CMD<%d>",cmd->opcode); ++ msdc_gate_clock(host->id); ++ } ++ } ++ //} ++#else ++ msdc_gate_clock(host->id); ++#endif ++#endif /* end of --- */ ++ ++ if (mrq->cmd->error) host->error = 0x001; ++ if (mrq->data && mrq->data->error) host->error |= 0x010; ++ if (mrq->stop && mrq->stop->error) host->error |= 0x100; ++ ++ //if (host->error) ERR_MSG("host->error<%d>", host->error); ++ ++ return host->error; ++} ++ ++static int msdc_app_cmd(struct mmc_host *mmc, struct msdc_host *host) ++{ ++ struct mmc_command cmd; ++ struct mmc_request mrq; ++ u32 err; ++ ++ memset(&cmd, 0, sizeof(struct mmc_command)); ++ cmd.opcode = MMC_APP_CMD; ++#if 0 /* bug: we meet mmc->card is null when ACMD6 */ ++ cmd.arg = mmc->card->rca << 16; ++#else ++ cmd.arg = host->app_cmd_arg; ++#endif ++ cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; ++ ++ memset(&mrq, 0, sizeof(struct mmc_request)); ++ mrq.cmd = &cmd; cmd.mrq = &mrq; ++ cmd.data = NULL; ++ ++ err = msdc_do_command(host, &cmd, 0, CMD_TIMEOUT); ++ return err; ++} ++ ++static int msdc_tune_cmdrsp(struct msdc_host*host, struct mmc_command *cmd) ++{ ++ int result = -1; ++ u32 base = host->base; ++ u32 rsmpl, cur_rsmpl, orig_rsmpl; ++ u32 rrdly, cur_rrdly = 0xffffffff, orig_rrdly; ++ u32 skip = 1; ++ ++ /* ==== don't support 3.0 now ==== ++ 1: R_SMPL[1] ++ 2: PAD_CMD_RESP_RXDLY[26:22] ++ ==========================*/ ++ ++ // save the previous tune result ++ sdr_get_field(MSDC_IOCON, MSDC_IOCON_RSPL, orig_rsmpl); ++ sdr_get_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRRDLY, orig_rrdly); ++ ++ rrdly = 0; ++ do { ++ for (rsmpl = 0; rsmpl < 2; rsmpl++) { ++ /* Lv1: R_SMPL[1] */ ++ cur_rsmpl = (orig_rsmpl + rsmpl) % 2; ++ if (skip == 1) { ++ skip = 0; ++ continue; ++ } ++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_RSPL, cur_rsmpl); ++ ++ if (host->app_cmd) { ++ result = msdc_app_cmd(host->mmc, host); ++ if (result) { ++ ERR_MSG("TUNE_CMD app_cmd<%d> failed: RESP_RXDLY<%d>,R_SMPL<%d>", ++ host->mrq->cmd->opcode, cur_rrdly, cur_rsmpl); ++ continue; ++ } ++ } ++ result = msdc_do_command(host, cmd, 0, CMD_TIMEOUT); // not tune. ++ ERR_MSG("TUNE_CMD<%d> %s PAD_CMD_RESP_RXDLY[26:22]<%d> R_SMPL[1]<%d>", cmd->opcode, ++ (result == 0) ? "PASS" : "FAIL", cur_rrdly, cur_rsmpl); ++ ++ if (result == 0) { ++ return 0; ++ } ++ if (result != (unsigned int)(-EIO)) { ++ ERR_MSG("TUNE_CMD<%d> Error<%d> not -EIO", cmd->opcode, result); ++ return result; ++ } ++ ++ /* should be EIO */ ++ if (sdr_read32(SDC_CMD) & 0x1800) { /* check if has data phase */ ++ msdc_abort_data(host); ++ } ++ } ++ ++ /* Lv2: PAD_CMD_RESP_RXDLY[26:22] */ ++ cur_rrdly = (orig_rrdly + rrdly + 1) % 32; ++ sdr_set_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRRDLY, cur_rrdly); ++ }while (++rrdly < 32); ++ ++ return result; ++} ++ ++/* Support SD2.0 Only */ ++static int msdc_tune_bread(struct mmc_host *mmc, struct mmc_request *mrq) ++{ ++ struct msdc_host *host = mmc_priv(mmc); ++ u32 base = host->base; ++ u32 ddr=0; ++ u32 dcrc=0; ++ u32 rxdly, cur_rxdly0, cur_rxdly1; ++ u32 dsmpl, cur_dsmpl, orig_dsmpl; ++ u32 cur_dat0, cur_dat1, cur_dat2, cur_dat3; ++ u32 cur_dat4, cur_dat5, cur_dat6, cur_dat7; ++ u32 orig_dat0, orig_dat1, orig_dat2, orig_dat3; ++ u32 orig_dat4, orig_dat5, orig_dat6, orig_dat7; ++ int result = -1; ++ u32 skip = 1; ++ ++ sdr_get_field(MSDC_IOCON, MSDC_IOCON_DSPL, orig_dsmpl); ++ ++ /* Tune Method 2. */ ++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_DDLSEL, 1); ++ ++ rxdly = 0; ++ do { ++ for (dsmpl = 0; dsmpl < 2; dsmpl++) { ++ cur_dsmpl = (orig_dsmpl + dsmpl) % 2; ++ if (skip == 1) { ++ skip = 0; ++ continue; ++ } ++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_DSPL, cur_dsmpl); ++ ++ if (host->app_cmd) { ++ result = msdc_app_cmd(host->mmc, host); ++ if (result) { ++ ERR_MSG("TUNE_BREAD app_cmd<%d> failed", host->mrq->cmd->opcode); ++ continue; ++ } ++ } ++ result = msdc_do_request(mmc,mrq); ++ ++ sdr_get_field(SDC_DCRC_STS, SDC_DCRC_STS_POS|SDC_DCRC_STS_NEG, dcrc); /* RO */ ++ if (!ddr) dcrc &= ~SDC_DCRC_STS_NEG; ++ ERR_MSG("TUNE_BREAD<%s> dcrc<0x%x> DATRDDLY0/1<0x%x><0x%x> dsmpl<0x%x>", ++ (result == 0 && dcrc == 0) ? "PASS" : "FAIL", dcrc, ++ sdr_read32(MSDC_DAT_RDDLY0), sdr_read32(MSDC_DAT_RDDLY1), cur_dsmpl); ++ ++ /* Fix me: result is 0, but dcrc is still exist */ ++ if (result == 0 && dcrc == 0) { ++ goto done; ++ } else { ++ /* there is a case: command timeout, and data phase not processed */ ++ if (mrq->data->error != 0 && mrq->data->error != (unsigned int)(-EIO)) { ++ ERR_MSG("TUNE_READ: result<0x%x> cmd_error<%d> data_error<%d>", ++ result, mrq->cmd->error, mrq->data->error); ++ goto done; ++ } ++ } ++ } ++ ++ cur_rxdly0 = sdr_read32(MSDC_DAT_RDDLY0); ++ cur_rxdly1 = sdr_read32(MSDC_DAT_RDDLY1); ++ ++ /* E1 ECO. YD: Reverse */ ++ if (sdr_read32(MSDC_ECO_VER) >= 4) { ++ orig_dat0 = (cur_rxdly0 >> 24) & 0x1F; ++ orig_dat1 = (cur_rxdly0 >> 16) & 0x1F; ++ orig_dat2 = (cur_rxdly0 >> 8) & 0x1F; ++ orig_dat3 = (cur_rxdly0 >> 0) & 0x1F; ++ orig_dat4 = (cur_rxdly1 >> 24) & 0x1F; ++ orig_dat5 = (cur_rxdly1 >> 16) & 0x1F; ++ orig_dat6 = (cur_rxdly1 >> 8) & 0x1F; ++ orig_dat7 = (cur_rxdly1 >> 0) & 0x1F; ++ } else { ++ orig_dat0 = (cur_rxdly0 >> 0) & 0x1F; ++ orig_dat1 = (cur_rxdly0 >> 8) & 0x1F; ++ orig_dat2 = (cur_rxdly0 >> 16) & 0x1F; ++ orig_dat3 = (cur_rxdly0 >> 24) & 0x1F; ++ orig_dat4 = (cur_rxdly1 >> 0) & 0x1F; ++ orig_dat5 = (cur_rxdly1 >> 8) & 0x1F; ++ orig_dat6 = (cur_rxdly1 >> 16) & 0x1F; ++ orig_dat7 = (cur_rxdly1 >> 24) & 0x1F; ++ } ++ ++ if (ddr) { ++ cur_dat0 = (dcrc & (1 << 0) || dcrc & (1 << 8)) ? ((orig_dat0 + 1) % 32) : orig_dat0; ++ cur_dat1 = (dcrc & (1 << 1) || dcrc & (1 << 9)) ? ((orig_dat1 + 1) % 32) : orig_dat1; ++ cur_dat2 = (dcrc & (1 << 2) || dcrc & (1 << 10)) ? ((orig_dat2 + 1) % 32) : orig_dat2; ++ cur_dat3 = (dcrc & (1 << 3) || dcrc & (1 << 11)) ? ((orig_dat3 + 1) % 32) : orig_dat3; ++ } else { ++ cur_dat0 = (dcrc & (1 << 0)) ? ((orig_dat0 + 1) % 32) : orig_dat0; ++ cur_dat1 = (dcrc & (1 << 1)) ? ((orig_dat1 + 1) % 32) : orig_dat1; ++ cur_dat2 = (dcrc & (1 << 2)) ? ((orig_dat2 + 1) % 32) : orig_dat2; ++ cur_dat3 = (dcrc & (1 << 3)) ? ((orig_dat3 + 1) % 32) : orig_dat3; ++ } ++ cur_dat4 = (dcrc & (1 << 4)) ? ((orig_dat4 + 1) % 32) : orig_dat4; ++ cur_dat5 = (dcrc & (1 << 5)) ? ((orig_dat5 + 1) % 32) : orig_dat5; ++ cur_dat6 = (dcrc & (1 << 6)) ? ((orig_dat6 + 1) % 32) : orig_dat6; ++ cur_dat7 = (dcrc & (1 << 7)) ? ((orig_dat7 + 1) % 32) : orig_dat7; ++ ++ cur_rxdly0 = (cur_dat0 << 24) | (cur_dat1 << 16) | (cur_dat2 << 8) | (cur_dat3 << 0); ++ cur_rxdly1 = (cur_dat4 << 24) | (cur_dat5 << 16) | (cur_dat6 << 8) | (cur_dat7 << 0); ++ ++ sdr_write32(MSDC_DAT_RDDLY0, cur_rxdly0); ++ sdr_write32(MSDC_DAT_RDDLY1, cur_rxdly1); ++ ++ } while (++rxdly < 32); ++ ++done: ++ return result; ++} ++ ++static int msdc_tune_bwrite(struct mmc_host *mmc,struct mmc_request *mrq) ++{ ++ struct msdc_host *host = mmc_priv(mmc); ++ u32 base = host->base; ++ ++ u32 wrrdly, cur_wrrdly = 0xffffffff, orig_wrrdly; ++ u32 dsmpl, cur_dsmpl, orig_dsmpl; ++ u32 rxdly, cur_rxdly0; ++ u32 orig_dat0, orig_dat1, orig_dat2, orig_dat3; ++ u32 cur_dat0, cur_dat1, cur_dat2, cur_dat3; ++ int result = -1; ++ u32 skip = 1; ++ ++ // MSDC_IOCON_DDR50CKD need to check. [Fix me] ++ ++ sdr_get_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, orig_wrrdly); ++ sdr_get_field(MSDC_IOCON, MSDC_IOCON_DSPL, orig_dsmpl ); ++ ++ /* Tune Method 2. just DAT0 */ ++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_DDLSEL, 1); ++ cur_rxdly0 = sdr_read32(MSDC_DAT_RDDLY0); ++ ++ /* E1 ECO. YD: Reverse */ ++ if (sdr_read32(MSDC_ECO_VER) >= 4) { ++ orig_dat0 = (cur_rxdly0 >> 24) & 0x1F; ++ orig_dat1 = (cur_rxdly0 >> 16) & 0x1F; ++ orig_dat2 = (cur_rxdly0 >> 8) & 0x1F; ++ orig_dat3 = (cur_rxdly0 >> 0) & 0x1F; ++ } else { ++ orig_dat0 = (cur_rxdly0 >> 0) & 0x1F; ++ orig_dat1 = (cur_rxdly0 >> 8) & 0x1F; ++ orig_dat2 = (cur_rxdly0 >> 16) & 0x1F; ++ orig_dat3 = (cur_rxdly0 >> 24) & 0x1F; ++ } ++ ++ rxdly = 0; ++ do { ++ wrrdly = 0; ++ do { ++ for (dsmpl = 0; dsmpl < 2; dsmpl++) { ++ cur_dsmpl = (orig_dsmpl + dsmpl) % 2; ++ if (skip == 1) { ++ skip = 0; ++ continue; ++ } ++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_DSPL, cur_dsmpl); ++ ++ if (host->app_cmd) { ++ result = msdc_app_cmd(host->mmc, host); ++ if (result) { ++ ERR_MSG("TUNE_BWRITE app_cmd<%d> failed", host->mrq->cmd->opcode); ++ continue; ++ } ++ } ++ result = msdc_do_request(mmc,mrq); ++ ++ ERR_MSG("TUNE_BWRITE<%s> DSPL<%d> DATWRDLY<%d> MSDC_DAT_RDDLY0<0x%x>", ++ result == 0 ? "PASS" : "FAIL", ++ cur_dsmpl, cur_wrrdly, cur_rxdly0); ++ ++ if (result == 0) { ++ goto done; ++ } ++ else { ++ /* there is a case: command timeout, and data phase not processed */ ++ if (mrq->data->error != (unsigned int)(-EIO)) { ++ ERR_MSG("TUNE_READ: result<0x%x> cmd_error<%d> data_error<%d>", ++ result, mrq->cmd->error, mrq->data->error); ++ goto done; ++ } ++ } ++ } ++ cur_wrrdly = (orig_wrrdly + wrrdly + 1) % 32; ++ sdr_set_field(MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, cur_wrrdly); ++ } while (++wrrdly < 32); ++ ++ cur_dat0 = (orig_dat0 + rxdly) % 32; /* only adjust bit-1 for crc */ ++ cur_dat1 = orig_dat1; ++ cur_dat2 = orig_dat2; ++ cur_dat3 = orig_dat3; ++ ++ cur_rxdly0 = (cur_dat0 << 24) | (cur_dat1 << 16) | (cur_dat2 << 8) | (cur_dat3 << 0); ++ sdr_write32(MSDC_DAT_RDDLY0, cur_rxdly0); ++ } while (++rxdly < 32); ++ ++done: ++ return result; ++} ++ ++static int msdc_get_card_status(struct mmc_host *mmc, struct msdc_host *host, u32 *status) ++{ ++ struct mmc_command cmd; ++ struct mmc_request mrq; ++ u32 err; ++ ++ memset(&cmd, 0, sizeof(struct mmc_command)); ++ cmd.opcode = MMC_SEND_STATUS; ++ if (mmc->card) { ++ cmd.arg = mmc->card->rca << 16; ++ } else { ++ ERR_MSG("cmd13 mmc card is null"); ++ cmd.arg = host->app_cmd_arg; ++ } ++ cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; ++ ++ memset(&mrq, 0, sizeof(struct mmc_request)); ++ mrq.cmd = &cmd; cmd.mrq = &mrq; ++ cmd.data = NULL; ++ ++ err = msdc_do_command(host, &cmd, 1, CMD_TIMEOUT); ++ ++ if (status) { ++ *status = cmd.resp[0]; ++ } ++ ++ return err; ++} ++ ++static int msdc_check_busy(struct mmc_host *mmc, struct msdc_host *host) ++{ ++ u32 err = 0; ++ u32 status = 0; ++ ++ do { ++ err = msdc_get_card_status(mmc, host, &status); ++ if (err) return err; ++ /* need cmd12? */ ++ ERR_MSG("cmd<13> resp<0x%x>", status); ++ } while (R1_CURRENT_STATE(status) == 7); ++ ++ return err; ++} ++ ++/* failed when msdc_do_request */ ++static int msdc_tune_request(struct mmc_host *mmc, struct mmc_request *mrq) ++{ ++ struct msdc_host *host = mmc_priv(mmc); ++ struct mmc_command *cmd; ++ struct mmc_data *data; ++ //u32 base = host->base; ++ int ret=0, read; ++ ++ cmd = mrq->cmd; ++ data = mrq->cmd->data; ++ ++ read = data->flags & MMC_DATA_READ ? 1 : 0; ++ ++ if (read) { ++ if (data->error == (unsigned int)(-EIO)) { ++ ret = msdc_tune_bread(mmc,mrq); ++ } ++ } else { ++ ret = msdc_check_busy(mmc, host); ++ if (ret){ ++ ERR_MSG("XXX cmd13 wait program done failed"); ++ return ret; ++ } ++ /* CRC and TO */ ++ /* Fix me: don't care card status? */ ++ ret = msdc_tune_bwrite(mmc,mrq); ++ } ++ ++ return ret; ++} ++ ++/* ops.request */ ++static void msdc_ops_request(struct mmc_host *mmc,struct mmc_request *mrq) ++{ ++ struct msdc_host *host = mmc_priv(mmc); ++ ++ //=== for sdio profile === ++#if 0 /* --- by chhung */ ++ u32 old_H32, old_L32, new_H32, new_L32; ++ u32 ticks = 0, opcode = 0, sizes = 0, bRx = 0; ++#endif /* end of --- */ ++ ++ if(host->mrq){ ++ ERR_MSG("XXX host->mrq<0x%.8x>", (int)host->mrq); ++ BUG(); ++ } ++ ++ if (!is_card_present(host) || host->power_mode == MMC_POWER_OFF) { ++ ERR_MSG("cmd<%d> card<%d> power<%d>", mrq->cmd->opcode, is_card_present(host), host->power_mode); ++ mrq->cmd->error = (unsigned int)-ENOMEDIUM; ++ ++#if 1 ++ mrq->done(mrq); // call done directly. ++#else ++ mrq->cmd->retries = 0; // please don't retry. ++ mmc_request_done(mmc, mrq); ++#endif ++ ++ return; ++ } ++ ++ /* start to process */ ++ spin_lock(&host->lock); ++#if 0 /* --- by chhung */ ++ if (sdio_pro_enable) { //=== for sdio profile === ++ if (mrq->cmd->opcode == 52 || mrq->cmd->opcode == 53) { ++ GPT_GetCounter64(&old_L32, &old_H32); ++ } ++ } ++#endif /* end of --- */ ++ ++ host->mrq = mrq; ++ ++ if (msdc_do_request(mmc,mrq)) { ++ if(host->hw->flags & MSDC_REMOVABLE && mrq->data && mrq->data->error) { ++ //msdc_tune_request(mmc,mrq); ++ } ++ } ++ ++ /* ==== when request done, check if app_cmd ==== */ ++ if (mrq->cmd->opcode == MMC_APP_CMD) { ++ host->app_cmd = 1; ++ host->app_cmd_arg = mrq->cmd->arg; /* save the RCA */ ++ } else { ++ host->app_cmd = 0; ++ //host->app_cmd_arg = 0; ++ } ++ ++ host->mrq = NULL; ++ ++#if 0 /* --- by chhung */ ++ //=== for sdio profile === ++ if (sdio_pro_enable) { ++ if (mrq->cmd->opcode == 52 || mrq->cmd->opcode == 53) { ++ GPT_GetCounter64(&new_L32, &new_H32); ++ ticks = msdc_time_calc(old_L32, old_H32, new_L32, new_H32); ++ ++ opcode = mrq->cmd->opcode; ++ if (mrq->cmd->data) { ++ sizes = mrq->cmd->data->blocks * mrq->cmd->data->blksz; ++ bRx = mrq->cmd->data->flags & MMC_DATA_READ ? 1 : 0 ; ++ } else { ++ bRx = mrq->cmd->arg & 0x80000000 ? 1 : 0; ++ } ++ ++ if (!mrq->cmd->error) { ++ msdc_performance(opcode, sizes, bRx, ticks); ++ } ++ } ++ } ++#endif /* end of --- */ ++ spin_unlock(&host->lock); ++ ++ mmc_request_done(mmc, mrq); ++ ++ return; ++} ++ ++/* called by ops.set_ios */ ++static void msdc_set_buswidth(struct msdc_host *host, u32 width) ++{ ++ u32 base = host->base; ++ u32 val = sdr_read32(SDC_CFG); ++ ++ val &= ~SDC_CFG_BUSWIDTH; ++ ++ switch (width) { ++ default: ++ case MMC_BUS_WIDTH_1: ++ width = 1; ++ val |= (MSDC_BUS_1BITS << 16); ++ break; ++ case MMC_BUS_WIDTH_4: ++ val |= (MSDC_BUS_4BITS << 16); ++ break; ++ case MMC_BUS_WIDTH_8: ++ val |= (MSDC_BUS_8BITS << 16); ++ break; ++ } ++ ++ sdr_write32(SDC_CFG, val); ++ ++ N_MSG(CFG, "Bus Width = %d", width); ++} ++ ++/* ops.set_ios */ ++static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ++{ ++ struct msdc_host *host = mmc_priv(mmc); ++ struct msdc_hw *hw=host->hw; ++ u32 base = host->base; ++ u32 ddr = 0; ++ ++#ifdef MT6575_SD_DEBUG ++ static char *vdd[] = { ++ "1.50v", "1.55v", "1.60v", "1.65v", "1.70v", "1.80v", "1.90v", ++ "2.00v", "2.10v", "2.20v", "2.30v", "2.40v", "2.50v", "2.60v", ++ "2.70v", "2.80v", "2.90v", "3.00v", "3.10v", "3.20v", "3.30v", ++ "3.40v", "3.50v", "3.60v" ++ }; ++ static char *power_mode[] = { ++ "OFF", "UP", "ON" ++ }; ++ static char *bus_mode[] = { ++ "UNKNOWN", "OPENDRAIN", "PUSHPULL" ++ }; ++ static char *timing[] = { ++ "LEGACY", "MMC_HS", "SD_HS" ++ }; ++ ++ printk("SET_IOS: CLK(%dkHz), BUS(%s), BW(%u), PWR(%s), VDD(%s), TIMING(%s)", ++ ios->clock / 1000, bus_mode[ios->bus_mode], ++ (ios->bus_width == MMC_BUS_WIDTH_4) ? 4 : 1, ++ power_mode[ios->power_mode], vdd[ios->vdd], timing[ios->timing]); ++#endif ++ ++ msdc_set_buswidth(host, ios->bus_width); ++ ++ /* Power control ??? */ ++ switch (ios->power_mode) { ++ case MMC_POWER_OFF: ++ case MMC_POWER_UP: ++ // msdc_set_power_mode(host, ios->power_mode); /* --- by chhung */ ++ break; ++ case MMC_POWER_ON: ++ host->power_mode = MMC_POWER_ON; ++ break; ++ default: ++ break; ++ } ++ ++ /* Clock control */ ++ if (host->mclk != ios->clock) { ++ if(ios->clock > 25000000) { ++ //if (!(host->hw->flags & MSDC_REMOVABLE)) { ++ INIT_MSG("SD data latch edge<%d>", hw->data_edge); ++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_RSPL, hw->cmd_edge); ++ sdr_set_field(MSDC_IOCON, MSDC_IOCON_DSPL, hw->data_edge); ++ //} /* for tuning debug */ ++ } else { /* default value */ ++ sdr_write32(MSDC_IOCON, 0x00000000); ++ // sdr_write32(MSDC_DAT_RDDLY0, 0x00000000); ++ sdr_write32(MSDC_DAT_RDDLY0, 0x10101010); // for MT7620 E2 and afterward ++ sdr_write32(MSDC_DAT_RDDLY1, 0x00000000); ++ // sdr_write32(MSDC_PAD_TUNE, 0x00000000); ++ sdr_write32(MSDC_PAD_TUNE, 0x84101010); // for MT7620 E2 and afterward ++ } ++ msdc_set_mclk(host, ddr, ios->clock); ++ } ++} ++ ++/* ops.get_ro */ ++static int msdc_ops_get_ro(struct mmc_host *mmc) ++{ ++ struct msdc_host *host = mmc_priv(mmc); ++ u32 base = host->base; ++ unsigned long flags; ++ int ro = 0; ++ ++ if (host->hw->flags & MSDC_WP_PIN_EN) { /* set for card */ ++ spin_lock_irqsave(&host->lock, flags); ++ ro = (sdr_read32(MSDC_PS) >> 31); ++ spin_unlock_irqrestore(&host->lock, flags); ++ } ++ return ro; ++} ++ ++/* ops.get_cd */ ++static int msdc_ops_get_cd(struct mmc_host *mmc) ++{ ++ struct msdc_host *host = mmc_priv(mmc); ++ u32 base = host->base; ++ unsigned long flags; ++ int present = 1; ++ ++ /* for sdio, MSDC_REMOVABLE not set, always return 1 */ ++ if (!(host->hw->flags & MSDC_REMOVABLE)) { ++ /* For sdio, read H/W always get<1>, but may timeout some times */ ++#if 1 ++ host->card_inserted = 1; ++ return 1; ++#else ++ host->card_inserted = (host->pm_state.event == PM_EVENT_USER_RESUME) ? 1 : 0; ++ INIT_MSG("sdio ops_get_cd<%d>", host->card_inserted); ++ return host->card_inserted; ++#endif ++ } ++ ++ /* MSDC_CD_PIN_EN set for card */ ++ if (host->hw->flags & MSDC_CD_PIN_EN) { ++ spin_lock_irqsave(&host->lock, flags); ++#if 0 ++ present = host->card_inserted; /* why not read from H/W: Fix me*/ ++#else ++ // CD ++ if (cd_active_low) ++ present = (sdr_read32(MSDC_PS) & MSDC_PS_CDSTS) ? 0 : 1; ++ else ++ present = (sdr_read32(MSDC_PS) & MSDC_PS_CDSTS) ? 1 : 0; ++ host->card_inserted = present; ++#endif ++ spin_unlock_irqrestore(&host->lock, flags); ++ } else { ++ present = 0; /* TODO? Check DAT3 pins for card detection */ ++ } ++ ++ INIT_MSG("ops_get_cd return<%d>", present); ++ return present; ++} ++ ++/* ops.enable_sdio_irq */ ++static void msdc_ops_enable_sdio_irq(struct mmc_host *mmc, int enable) ++{ ++ struct msdc_host *host = mmc_priv(mmc); ++ struct msdc_hw *hw = host->hw; ++ u32 base = host->base; ++ u32 tmp; ++ ++ if (hw->flags & MSDC_EXT_SDIO_IRQ) { /* yes for sdio */ ++ if (enable) { ++ hw->enable_sdio_eirq(); /* combo_sdio_enable_eirq */ ++ } else { ++ hw->disable_sdio_eirq(); /* combo_sdio_disable_eirq */ ++ } ++ } else { ++ ERR_MSG("XXX "); /* so never enter here */ ++ tmp = sdr_read32(SDC_CFG); ++ /* FIXME. Need to interrupt gap detection */ ++ if (enable) { ++ tmp |= (SDC_CFG_SDIOIDE | SDC_CFG_SDIOINTWKUP); ++ } else { ++ tmp &= ~(SDC_CFG_SDIOIDE | SDC_CFG_SDIOINTWKUP); ++ } ++ sdr_write32(SDC_CFG, tmp); ++ } ++} ++ ++static struct mmc_host_ops mt_msdc_ops = { ++ .request = msdc_ops_request, ++ .set_ios = msdc_ops_set_ios, ++ .get_ro = msdc_ops_get_ro, ++ .get_cd = msdc_ops_get_cd, ++ .enable_sdio_irq = msdc_ops_enable_sdio_irq, ++}; ++ ++/*--------------------------------------------------------------------------*/ ++/* interrupt handler */ ++/*--------------------------------------------------------------------------*/ ++static irqreturn_t msdc_irq(int irq, void *dev_id) ++{ ++ struct msdc_host *host = (struct msdc_host *)dev_id; ++ struct mmc_data *data = host->data; ++ struct mmc_command *cmd = host->cmd; ++ u32 base = host->base; ++ ++ u32 cmdsts = MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | MSDC_INT_CMDRDY | ++ MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO | MSDC_INT_ACMDRDY | ++ MSDC_INT_ACMD19_DONE; ++ u32 datsts = MSDC_INT_DATCRCERR |MSDC_INT_DATTMO; ++ ++ u32 intsts = sdr_read32(MSDC_INT); ++ u32 inten = sdr_read32(MSDC_INTEN); inten &= intsts; ++ ++ sdr_write32(MSDC_INT, intsts); /* clear interrupts */ ++ /* MSG will cause fatal error */ ++ ++ /* card change interrupt */ ++ if (intsts & MSDC_INT_CDSC){ ++ if (mtk_sw_poll) ++ return IRQ_HANDLED; ++ IRQ_MSG("MSDC_INT_CDSC irq<0x%.8x>", intsts); ++#if 0 /* ---/+++ by chhung: fix slot mechanical bounce issue */ ++ tasklet_hi_schedule(&host->card_tasklet); ++#else ++ schedule_delayed_work(&host->card_delaywork, HZ); ++#endif ++ /* tuning when plug card ? */ ++ } ++ ++ /* sdio interrupt */ ++ if (intsts & MSDC_INT_SDIOIRQ){ ++ IRQ_MSG("XXX MSDC_INT_SDIOIRQ"); /* seems not sdio irq */ ++ //mmc_signal_sdio_irq(host->mmc); ++ } ++ ++ /* transfer complete interrupt */ ++ if (data != NULL) { ++ if (inten & MSDC_INT_XFER_COMPL) { ++ data->bytes_xfered = host->dma.xfersz; ++ complete(&host->xfer_done); ++ } ++ ++ if (intsts & datsts) { ++ /* do basic reset, or stop command will sdc_busy */ ++ msdc_reset(); ++ msdc_clr_fifo(); ++ msdc_clr_int(); ++ atomic_set(&host->abort, 1); /* For PIO mode exit */ ++ ++ if (intsts & MSDC_INT_DATTMO){ ++ IRQ_MSG("XXX CMD<%d> MSDC_INT_DATTMO", host->mrq->cmd->opcode); ++ data->error = (unsigned int)-ETIMEDOUT; ++ } ++ else if (intsts & MSDC_INT_DATCRCERR){ ++ IRQ_MSG("XXX CMD<%d> MSDC_INT_DATCRCERR, SDC_DCRC_STS<0x%x>", host->mrq->cmd->opcode, sdr_read32(SDC_DCRC_STS)); ++ data->error = (unsigned int)-EIO; ++ } ++ ++ //if(sdr_read32(MSDC_INTEN) & MSDC_INT_XFER_COMPL) { ++ if (host->dma_xfer) { ++ complete(&host->xfer_done); /* Read CRC come fast, XFER_COMPL not enabled */ ++ } /* PIO mode can't do complete, because not init */ ++ } ++ } ++ ++ /* command interrupts */ ++ if ((cmd != NULL) && (intsts & cmdsts)) { ++ if ((intsts & MSDC_INT_CMDRDY) || (intsts & MSDC_INT_ACMDRDY) || ++ (intsts & MSDC_INT_ACMD19_DONE)) { ++ u32 *rsp = &cmd->resp[0]; ++ ++ switch (host->cmd_rsp) { ++ case RESP_NONE: ++ break; ++ case RESP_R2: ++ *rsp++ = sdr_read32(SDC_RESP3); *rsp++ = sdr_read32(SDC_RESP2); ++ *rsp++ = sdr_read32(SDC_RESP1); *rsp++ = sdr_read32(SDC_RESP0); ++ break; ++ default: /* Response types 1, 3, 4, 5, 6, 7(1b) */ ++ if ((intsts & MSDC_INT_ACMDRDY) || (intsts & MSDC_INT_ACMD19_DONE)) { ++ *rsp = sdr_read32(SDC_ACMD_RESP); ++ } else { ++ *rsp = sdr_read32(SDC_RESP0); ++ } ++ break; ++ } ++ } else if ((intsts & MSDC_INT_RSPCRCERR) || (intsts & MSDC_INT_ACMDCRCERR)) { ++ if(intsts & MSDC_INT_ACMDCRCERR){ ++ IRQ_MSG("XXX CMD<%d> MSDC_INT_ACMDCRCERR",cmd->opcode); ++ } ++ else { ++ IRQ_MSG("XXX CMD<%d> MSDC_INT_RSPCRCERR",cmd->opcode); ++ } ++ cmd->error = (unsigned int)-EIO; ++ } else if ((intsts & MSDC_INT_CMDTMO) || (intsts & MSDC_INT_ACMDTMO)) { ++ if(intsts & MSDC_INT_ACMDTMO){ ++ IRQ_MSG("XXX CMD<%d> MSDC_INT_ACMDTMO",cmd->opcode); ++ } ++ else { ++ IRQ_MSG("XXX CMD<%d> MSDC_INT_CMDTMO",cmd->opcode); ++ } ++ cmd->error = (unsigned int)-ETIMEDOUT; ++ msdc_reset(); ++ msdc_clr_fifo(); ++ msdc_clr_int(); ++ } ++ complete(&host->cmd_done); ++ } ++ ++ /* mmc irq interrupts */ ++ if (intsts & MSDC_INT_MMCIRQ) { ++ printk(KERN_INFO "msdc[%d] MMCIRQ: SDC_CSTS=0x%.8x\r\n", host->id, sdr_read32(SDC_CSTS)); ++ } ++ ++#ifdef MT6575_SD_DEBUG ++ { ++ msdc_int_reg *int_reg = (msdc_int_reg*)&intsts; ++ N_MSG(INT, "IRQ_EVT(0x%x): MMCIRQ(%d) CDSC(%d), ACRDY(%d), ACTMO(%d), ACCRE(%d) AC19DN(%d)", ++ intsts, ++ int_reg->mmcirq, ++ int_reg->cdsc, ++ int_reg->atocmdrdy, ++ int_reg->atocmdtmo, ++ int_reg->atocmdcrc, ++ int_reg->atocmd19done); ++ N_MSG(INT, "IRQ_EVT(0x%x): SDIO(%d) CMDRDY(%d), CMDTMO(%d), RSPCRC(%d), CSTA(%d)", ++ intsts, ++ int_reg->sdioirq, ++ int_reg->cmdrdy, ++ int_reg->cmdtmo, ++ int_reg->rspcrc, ++ int_reg->csta); ++ N_MSG(INT, "IRQ_EVT(0x%x): XFCMP(%d) DXDONE(%d), DATTMO(%d), DATCRC(%d), DMAEMP(%d)", ++ intsts, ++ int_reg->xfercomp, ++ int_reg->dxferdone, ++ int_reg->dattmo, ++ int_reg->datcrc, ++ int_reg->dmaqempty); ++ ++ } ++#endif ++ ++ return IRQ_HANDLED; ++} ++ ++/*--------------------------------------------------------------------------*/ ++/* platform_driver members */ ++/*--------------------------------------------------------------------------*/ ++/* called by msdc_drv_probe/remove */ ++static void msdc_enable_cd_irq(struct msdc_host *host, int enable) ++{ ++ struct msdc_hw *hw = host->hw; ++ u32 base = host->base; ++ ++ /* for sdio, not set */ ++ if ((hw->flags & MSDC_CD_PIN_EN) == 0) { ++ /* Pull down card detection pin since it is not avaiable */ ++ /* ++ if (hw->config_gpio_pin) ++ hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_DOWN); ++ */ ++ sdr_clr_bits(MSDC_PS, MSDC_PS_CDEN); ++ sdr_clr_bits(MSDC_INTEN, MSDC_INTEN_CDSC); ++ sdr_clr_bits(SDC_CFG, SDC_CFG_INSWKUP); ++ return; ++ } ++ ++ N_MSG(CFG, "CD IRQ Eanable(%d)", enable); ++ ++ if (enable) { ++ if (hw->enable_cd_eirq) { /* not set, never enter */ ++ hw->enable_cd_eirq(); ++ } else { ++ /* card detection circuit relies on the core power so that the core power ++ * shouldn't be turned off. Here adds a reference count to keep ++ * the core power alive. ++ */ ++ //msdc_vcore_on(host); //did in msdc_init_hw() ++ ++ if (hw->config_gpio_pin) /* NULL */ ++ hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_UP); ++ ++ sdr_set_field(MSDC_PS, MSDC_PS_CDDEBOUNCE, DEFAULT_DEBOUNCE); ++ sdr_set_bits(MSDC_PS, MSDC_PS_CDEN); ++ sdr_set_bits(MSDC_INTEN, MSDC_INTEN_CDSC); ++ sdr_set_bits(SDC_CFG, SDC_CFG_INSWKUP); /* not in document! Fix me */ ++ } ++ } else { ++ if (hw->disable_cd_eirq) { ++ hw->disable_cd_eirq(); ++ } else { ++ if (hw->config_gpio_pin) /* NULL */ ++ hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_DOWN); ++ ++ sdr_clr_bits(SDC_CFG, SDC_CFG_INSWKUP); ++ sdr_clr_bits(MSDC_PS, MSDC_PS_CDEN); ++ sdr_clr_bits(MSDC_INTEN, MSDC_INTEN_CDSC); ++ ++ /* Here decreases a reference count to core power since card ++ * detection circuit is shutdown. ++ */ ++ //msdc_vcore_off(host); ++ } ++ } ++} ++ ++/* called by msdc_drv_probe */ ++static void msdc_init_hw(struct msdc_host *host) ++{ ++ u32 base = host->base; ++ struct msdc_hw *hw = host->hw; ++ ++#ifdef MT6575_SD_DEBUG ++ msdc_reg[host->id] = (struct msdc_regs *)host->base; ++#endif ++ ++ /* Power on */ ++#if 0 /* --- by chhung */ ++ msdc_vcore_on(host); ++ msdc_pin_reset(host, MSDC_PIN_PULL_UP); ++ msdc_select_clksrc(host, hw->clk_src); ++ enable_clock(PERI_MSDC0_PDN + host->id, "SD"); ++ msdc_vdd_on(host); ++#endif /* end of --- */ ++ /* Configure to MMC/SD mode */ ++ sdr_set_field(MSDC_CFG, MSDC_CFG_MODE, MSDC_SDMMC); ++ ++ /* Reset */ ++ msdc_reset(); ++ msdc_clr_fifo(); ++ ++ /* Disable card detection */ ++ sdr_clr_bits(MSDC_PS, MSDC_PS_CDEN); ++ ++ /* Disable and clear all interrupts */ ++ sdr_clr_bits(MSDC_INTEN, sdr_read32(MSDC_INTEN)); ++ sdr_write32(MSDC_INT, sdr_read32(MSDC_INT)); ++ ++#if 1 ++ /* reset tuning parameter */ ++ sdr_write32(MSDC_PAD_CTL0, 0x00090000); ++ sdr_write32(MSDC_PAD_CTL1, 0x000A0000); ++ sdr_write32(MSDC_PAD_CTL2, 0x000A0000); ++ // sdr_write32(MSDC_PAD_TUNE, 0x00000000); ++ sdr_write32(MSDC_PAD_TUNE, 0x84101010); // for MT7620 E2 and afterward ++ // sdr_write32(MSDC_DAT_RDDLY0, 0x00000000); ++ sdr_write32(MSDC_DAT_RDDLY0, 0x10101010); // for MT7620 E2 and afterward ++ sdr_write32(MSDC_DAT_RDDLY1, 0x00000000); ++ sdr_write32(MSDC_IOCON, 0x00000000); ++#if 0 // use MT7620 default value: 0x403c004f ++ sdr_write32(MSDC_PATCH_BIT0, 0x003C000F); /* bit0 modified: Rx Data Clock Source: 1 -> 2.0*/ ++#endif ++ ++ if (sdr_read32(MSDC_ECO_VER) >= 4) { ++ if (host->id == 1) { ++ sdr_set_field(MSDC_PATCH_BIT1, MSDC_PATCH_BIT1_WRDAT_CRCS, 1); ++ sdr_set_field(MSDC_PATCH_BIT1, MSDC_PATCH_BIT1_CMD_RSP, 1); ++ ++ /* internal clock: latch read data */ ++ sdr_set_bits(MSDC_PATCH_BIT0, MSDC_PATCH_BIT_CKGEN_CK); ++ } ++ } ++#endif ++ ++ /* for safety, should clear SDC_CFG.SDIO_INT_DET_EN & set SDC_CFG.SDIO in ++ pre-loader,uboot,kernel drivers. and SDC_CFG.SDIO_INT_DET_EN will be only ++ set when kernel driver wants to use SDIO bus interrupt */ ++ /* Configure to enable SDIO mode. it's must otherwise sdio cmd5 failed */ ++ sdr_set_bits(SDC_CFG, SDC_CFG_SDIO); ++ ++ /* disable detect SDIO device interupt function */ ++ sdr_clr_bits(SDC_CFG, SDC_CFG_SDIOIDE); ++ ++ /* eneable SMT for glitch filter */ ++ sdr_set_bits(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKSMT); ++ sdr_set_bits(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDSMT); ++ sdr_set_bits(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATSMT); ++ ++#if 1 ++ /* set clk, cmd, dat pad driving */ ++ sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVN, hw->clk_drv); ++ sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVP, hw->clk_drv); ++ sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVN, hw->cmd_drv); ++ sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVP, hw->cmd_drv); ++ sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVN, hw->dat_drv); ++ sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVP, hw->dat_drv); ++#else ++ sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVN, 0); ++ sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVP, 0); ++ sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVN, 0); ++ sdr_set_field(MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVP, 0); ++ sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVN, 0); ++ sdr_set_field(MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVP, 0); ++#endif ++ ++ /* set sampling edge */ ++ ++ /* write crc timeout detection */ ++ sdr_set_field(MSDC_PATCH_BIT0, 1 << 30, 1); ++ ++ /* Configure to default data timeout */ ++ sdr_set_field(SDC_CFG, SDC_CFG_DTOC, DEFAULT_DTOC); ++ ++ msdc_set_buswidth(host, MMC_BUS_WIDTH_1); ++ ++ N_MSG(FUC, "init hardware done!"); ++} ++ ++/* called by msdc_drv_remove */ ++static void msdc_deinit_hw(struct msdc_host *host) ++{ ++ u32 base = host->base; ++ ++ /* Disable and clear all interrupts */ ++ sdr_clr_bits(MSDC_INTEN, sdr_read32(MSDC_INTEN)); ++ sdr_write32(MSDC_INT, sdr_read32(MSDC_INT)); ++ ++ /* Disable card detection */ ++ msdc_enable_cd_irq(host, 0); ++ // msdc_set_power_mode(host, MMC_POWER_OFF); /* make sure power down */ /* --- by chhung */ ++} ++ ++/* init gpd and bd list in msdc_drv_probe */ ++static void msdc_init_gpd_bd(struct msdc_host *host, struct msdc_dma *dma) ++{ ++ gpd_t *gpd = dma->gpd; ++ bd_t *bd = dma->bd; ++ bd_t *ptr, *prev; ++ ++ /* we just support one gpd */ ++ int bdlen = MAX_BD_PER_GPD; ++ ++ /* init the 2 gpd */ ++ memset(gpd, 0, sizeof(gpd_t) * 2); ++ //gpd->next = (void *)virt_to_phys(gpd + 1); /* pointer to a null gpd, bug! kmalloc <-> virt_to_phys */ ++ //gpd->next = (dma->gpd_addr + 1); /* bug */ ++ gpd->next = (void *)((u32)dma->gpd_addr + sizeof(gpd_t)); ++ ++ //gpd->intr = 0; ++ gpd->bdp = 1; /* hwo, cs, bd pointer */ ++ //gpd->ptr = (void*)virt_to_phys(bd); ++ gpd->ptr = (void *)dma->bd_addr; /* physical address */ ++ ++ memset(bd, 0, sizeof(bd_t) * bdlen); ++ ptr = bd + bdlen - 1; ++ //ptr->eol = 1; /* 0 or 1 [Fix me]*/ ++ //ptr->next = 0; ++ ++ while (ptr != bd) { ++ prev = ptr - 1; ++ prev->next = (void *)(dma->bd_addr + sizeof(bd_t) *(ptr - bd)); ++ ptr = prev; ++ } ++} ++ ++static int msdc_drv_probe(struct platform_device *pdev) ++{ ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ __iomem void *base; ++ struct mmc_host *mmc; ++ struct resource *mem; ++ struct msdc_host *host; ++ struct msdc_hw *hw; ++ int ret, irq; ++ ++ pdev->dev.platform_data = &msdc0_hw; ++ ++ /* Allocate MMC host for this device */ ++ mmc = mmc_alloc_host(sizeof(struct msdc_host), &pdev->dev); ++ if (!mmc) return -ENOMEM; ++ ++ hw = (struct msdc_hw*)pdev->dev.platform_data; ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ irq = platform_get_irq(pdev, 0); ++ ++ //BUG_ON((!hw) || (!mem) || (irq < 0)); /* --- by chhung */ ++ ++ base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ /* Set host parameters to mmc */ ++ mmc->ops = &mt_msdc_ops; ++ mmc->f_min = HOST_MIN_MCLK; ++ mmc->f_max = HOST_MAX_MCLK; ++ mmc->ocr_avail = MSDC_OCR_AVAIL; ++ ++ /* For sd card: MSDC_SYS_SUSPEND | MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | MSDC_REMOVABLE | MSDC_HIGHSPEED, ++ For sdio : MSDC_EXT_SDIO_IRQ | MSDC_HIGHSPEED */ ++ if (hw->flags & MSDC_HIGHSPEED) { ++ mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; ++ } ++ if (hw->data_pins == 4) { /* current data_pins are all 4*/ ++ mmc->caps |= MMC_CAP_4_BIT_DATA; ++ } else if (hw->data_pins == 8) { ++ mmc->caps |= MMC_CAP_8_BIT_DATA; ++ } ++ if ((hw->flags & MSDC_SDIO_IRQ) || (hw->flags & MSDC_EXT_SDIO_IRQ)) ++ mmc->caps |= MMC_CAP_SDIO_IRQ; /* yes for sdio */ ++ ++ cd_active_low = !of_property_read_bool(pdev->dev.of_node, "mediatek,cd-high"); ++ mtk_sw_poll = of_property_read_bool(pdev->dev.of_node, "mediatek,cd-poll"); ++ ++ if (mtk_sw_poll) ++ mmc->caps |= MMC_CAP_NEEDS_POLL; ++ ++ /* MMC core transfer sizes tunable parameters */ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0) ++ mmc->max_segs = MAX_HW_SGMTS; ++#else ++ mmc->max_hw_segs = MAX_HW_SGMTS; ++ mmc->max_phys_segs = MAX_PHY_SGMTS; ++#endif ++ mmc->max_seg_size = MAX_SGMT_SZ; ++ mmc->max_blk_size = HOST_MAX_BLKSZ; ++ mmc->max_req_size = MAX_REQ_SZ; ++ mmc->max_blk_count = mmc->max_req_size; ++ ++ host = mmc_priv(mmc); ++ host->hw = hw; ++ host->mmc = mmc; ++ host->id = pdev->id; ++ host->error = 0; ++ host->irq = irq; ++ host->base = (unsigned long) base; ++ host->mclk = 0; /* mclk: the request clock of mmc sub-system */ ++ host->hclk = hclks[hw->clk_src]; /* hclk: clock of clock source to msdc controller */ ++ host->sclk = 0; /* sclk: the really clock after divition */ ++ host->pm_state = PMSG_RESUME; ++ host->suspend = 0; ++ host->core_clkon = 0; ++ host->card_clkon = 0; ++ host->core_power = 0; ++ host->power_mode = MMC_POWER_OFF; ++// host->card_inserted = hw->flags & MSDC_REMOVABLE ? 0 : 1; ++ host->timeout_ns = 0; ++ host->timeout_clks = DEFAULT_DTOC * 65536; ++ ++ host->mrq = NULL; ++ //init_MUTEX(&host->sem); /* we don't need to support multiple threads access */ ++ ++ host->dma.used_gpd = 0; ++ host->dma.used_bd = 0; ++ ++ /* using dma_alloc_coherent*/ /* todo: using 1, for all 4 slots */ ++ host->dma.gpd = dma_alloc_coherent(NULL, MAX_GPD_NUM * sizeof(gpd_t), &host->dma.gpd_addr, GFP_KERNEL); ++ host->dma.bd = dma_alloc_coherent(NULL, MAX_BD_NUM * sizeof(bd_t), &host->dma.bd_addr, GFP_KERNEL); ++ BUG_ON((!host->dma.gpd) || (!host->dma.bd)); ++ msdc_init_gpd_bd(host, &host->dma); ++ /*for emmc*/ ++ msdc_6575_host[pdev->id] = host; ++ ++#if 0 ++ tasklet_init(&host->card_tasklet, msdc_tasklet_card, (ulong)host); ++#else ++ INIT_DELAYED_WORK(&host->card_delaywork, msdc_tasklet_card); ++#endif ++ spin_lock_init(&host->lock); ++ msdc_init_hw(host); ++ ++ ret = request_irq((unsigned int)irq, msdc_irq, IRQF_TRIGGER_LOW, dev_name(&pdev->dev), host); ++ if (ret) goto release; ++ // mt65xx_irq_unmask(irq); /* --- by chhung */ ++ ++ if (hw->flags & MSDC_CD_PIN_EN) { /* not set for sdio */ ++ if (hw->request_cd_eirq) { /* not set for MT6575 */ ++ hw->request_cd_eirq(msdc_eirq_cd, (void*)host); /* msdc_eirq_cd will not be used! */ ++ } ++ } ++ ++ if (hw->request_sdio_eirq) /* set to combo_sdio_request_eirq() for WIFI */ ++ hw->request_sdio_eirq(msdc_eirq_sdio, (void*)host); /* msdc_eirq_sdio() will be called when EIRQ */ ++ ++ if (hw->register_pm) {/* yes for sdio */ ++#ifdef CONFIG_PM ++ hw->register_pm(msdc_pm, (void*)host); /* combo_sdio_register_pm() */ ++#endif ++ if(hw->flags & MSDC_SYS_SUSPEND) { /* will not set for WIFI */ ++ ERR_MSG("MSDC_SYS_SUSPEND and register_pm both set"); ++ } ++ //mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY; /* pm not controlled by system but by client. */ /* --- by chhung */ ++ } ++ ++ platform_set_drvdata(pdev, mmc); ++ ++ ret = mmc_add_host(mmc); ++ if (ret) goto free_irq; ++ ++ /* Config card detection pin and enable interrupts */ ++ if (hw->flags & MSDC_CD_PIN_EN) { /* set for card */ ++ msdc_enable_cd_irq(host, 1); ++ } else { ++ msdc_enable_cd_irq(host, 0); ++ } ++ ++ return 0; ++ ++free_irq: ++ free_irq(irq, host); ++release: ++ platform_set_drvdata(pdev, NULL); ++ msdc_deinit_hw(host); ++ ++#if 0 ++ tasklet_kill(&host->card_tasklet); ++#else ++ cancel_delayed_work_sync(&host->card_delaywork); ++#endif ++ ++ if (mem) ++ release_mem_region(mem->start, mem->end - mem->start + 1); ++ ++ mmc_free_host(mmc); ++ ++ return ret; ++} ++ ++/* 4 device share one driver, using "drvdata" to show difference */ ++static int msdc_drv_remove(struct platform_device *pdev) ++{ ++ struct mmc_host *mmc; ++ struct msdc_host *host; ++ struct resource *mem; ++ ++ mmc = platform_get_drvdata(pdev); ++ BUG_ON(!mmc); ++ ++ host = mmc_priv(mmc); ++ BUG_ON(!host); ++ ++ ERR_MSG("removed !!!"); ++ ++ platform_set_drvdata(pdev, NULL); ++ mmc_remove_host(host->mmc); ++ msdc_deinit_hw(host); ++ ++#if 0 ++ tasklet_kill(&host->card_tasklet); ++#else ++ cancel_delayed_work_sync(&host->card_delaywork); ++#endif ++ free_irq(host->irq, host); ++ ++ dma_free_coherent(NULL, MAX_GPD_NUM * sizeof(gpd_t), host->dma.gpd, host->dma.gpd_addr); ++ dma_free_coherent(NULL, MAX_BD_NUM * sizeof(bd_t), host->dma.bd, host->dma.bd_addr); ++ ++ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ ++ if (mem) ++ release_mem_region(mem->start, mem->end - mem->start + 1); ++ ++ mmc_free_host(host->mmc); ++ ++ return 0; ++} ++ ++/* Fix me: Power Flow */ ++#ifdef CONFIG_PM ++static int msdc_drv_suspend(struct platform_device *pdev, pm_message_t state) ++{ ++ int ret = 0; ++ struct mmc_host *mmc = platform_get_drvdata(pdev); ++ struct msdc_host *host = mmc_priv(mmc); ++ ++ if (mmc && state.event == PM_EVENT_SUSPEND && (host->hw->flags & MSDC_SYS_SUSPEND)) { /* will set for card */ ++ msdc_pm(state, (void*)host); ++ } ++ ++ return ret; ++} ++ ++static int msdc_drv_resume(struct platform_device *pdev) ++{ ++ int ret = 0; ++ struct mmc_host *mmc = platform_get_drvdata(pdev); ++ struct msdc_host *host = mmc_priv(mmc); ++ struct pm_message state; ++ ++ state.event = PM_EVENT_RESUME; ++ if (mmc && (host->hw->flags & MSDC_SYS_SUSPEND)) {/* will set for card */ ++ msdc_pm(state, (void*)host); ++ } ++ ++ /* This mean WIFI not controller by PM */ ++ ++ return ret; ++} ++#endif ++ ++static const struct of_device_id mt7620_sdhci_match[] = { ++ { .compatible = "ralink,mt7620-sdhci" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, rt288x_wdt_match); ++ ++static struct platform_driver mt_msdc_driver = { ++ .probe = msdc_drv_probe, ++ .remove = msdc_drv_remove, ++#ifdef CONFIG_PM ++ .suspend = msdc_drv_suspend, ++ .resume = msdc_drv_resume, ++#endif ++ .driver = { ++ .name = DRV_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = mt7620_sdhci_match, ++ }, ++}; ++ ++/*--------------------------------------------------------------------------*/ ++/* module init/exit */ ++/*--------------------------------------------------------------------------*/ ++static int __init mt_msdc_init(void) ++{ ++ int ret; ++/* +++ by chhung */ ++ u32 reg; ++ ++#if defined (CONFIG_MTD_ANY_RALINK) ++ extern int ra_check_flash_type(void); ++ if(ra_check_flash_type() == 2) { /* NAND */ ++ printk("%s: !!!!! SDXC Module Initialize Fail !!!!!", __func__); ++ return 0; ++ } ++#endif ++ printk("MTK MSDC device init.\n"); ++ mtk_sd_device.dev.platform_data = &msdc0_hw; ++if (ralink_soc == MT762X_SOC_MT7620A || ralink_soc == MT762X_SOC_MT7621AT) { ++//#if defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) ++ reg = sdr_read32((volatile u32*)(RALINK_SYSCTL_BASE + 0x60)) & ~(0x3<<18); ++//#if defined (CONFIG_RALINK_MT7620) ++ if (ralink_soc == MT762X_SOC_MT7620A) ++ reg |= 0x1<<18; ++//#endif ++} else { ++//#elif defined (CONFIG_RALINK_MT7628) ++ /* TODO: maybe omitted when RAether already toggle AGPIO_CFG */ ++ reg = sdr_read32((volatile u32*)(RALINK_SYSCTL_BASE + 0x3c)); ++ reg |= 0x1e << 16; ++ sdr_write32((volatile u32*)(RALINK_SYSCTL_BASE + 0x3c), reg); ++ ++ reg = sdr_read32((volatile u32*)(RALINK_SYSCTL_BASE + 0x60)) & ~(0x3<<10); ++#if defined (CONFIG_MTK_MMC_EMMC_8BIT) ++ reg |= 0x3<<26 | 0x3<<28 | 0x3<<30; ++ msdc0_hw.data_pins = 8, ++#endif ++//#endif ++} ++ sdr_write32((volatile u32*)(RALINK_SYSCTL_BASE + 0x60), reg); ++ //platform_device_register(&mtk_sd_device); ++/* end of +++ */ ++ ++ ret = platform_driver_register(&mt_msdc_driver); ++ if (ret) { ++ printk(KERN_ERR DRV_NAME ": Can't register driver"); ++ return ret; ++ } ++ printk(KERN_INFO DRV_NAME ": MediaTek MT6575 MSDC Driver\n"); ++ ++#if defined (MT6575_SD_DEBUG) ++ msdc_debug_proc_init(); ++#endif ++ return 0; ++} ++ ++static void __exit mt_msdc_exit(void) ++{ ++// platform_device_unregister(&mtk_sd_device); ++ platform_driver_unregister(&mt_msdc_driver); ++} ++ ++module_init(mt_msdc_init); ++module_exit(mt_msdc_exit); ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("MediaTek MT6575 SD/MMC Card Driver"); ++MODULE_AUTHOR("Infinity Chen <infinity.chen@mediatek.com>"); ++ ++EXPORT_SYMBOL(msdc_6575_host); diff --git a/target/linux/ramips/patches-3.18/0054-DMA-ralink-add-rt2880-dma-engine.patch b/target/linux/ramips/patches-3.18/0054-DMA-ralink-add-rt2880-dma-engine.patch new file mode 100644 index 0000000..fa0f42f --- /dev/null +++ b/target/linux/ramips/patches-3.18/0054-DMA-ralink-add-rt2880-dma-engine.patch @@ -0,0 +1,627 @@ +From cf93418a4bd5e69f069a65da92537bd4d6191223 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 27 Jul 2014 09:29:51 +0100 +Subject: [PATCH 54/57] DMA: ralink: add rt2880 dma engine + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + drivers/dma/Kconfig | 6 + + drivers/dma/Makefile | 1 + + drivers/dma/dmaengine.c | 26 ++ + drivers/dma/ralink-gdma.c | 577 +++++++++++++++++++++++++++++++++++++++++++++ + include/linux/dmaengine.h | 1 + + 5 files changed, 611 insertions(+) + create mode 100644 drivers/dma/ralink-gdma.c + +--- a/drivers/dma/Kconfig ++++ b/drivers/dma/Kconfig +@@ -409,6 +409,12 @@ config NBPFAXI_DMA + help + Support for "Type-AXI" NBPF DMA IPs from Renesas + ++config DMA_RALINK ++ tristate "RALINK DMA support" ++ depends on RALINK && SOC_MT7620 ++ select DMA_ENGINE ++ select DMA_VIRTUAL_CHANNELS ++ + config DMA_ENGINE + bool + +--- a/drivers/dma/Makefile ++++ b/drivers/dma/Makefile +@@ -49,3 +49,4 @@ obj-y += xilinx/ + obj-$(CONFIG_INTEL_MIC_X100_DMA) += mic_x100_dma.o + obj-$(CONFIG_NBPFAXI_DMA) += nbpfaxi.o + obj-$(CONFIG_DMA_SUN6I) += sun6i-dma.o ++obj-$(CONFIG_DMA_RALINK) += ralink-gdma.o +--- /dev/null ++++ b/drivers/dma/ralink-gdma.c +@@ -0,0 +1,577 @@ ++/* ++ * Copyright (C) 2013, Lars-Peter Clausen <lars@metafoo.de> ++ * GDMA4740 DMAC support ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ */ ++ ++#include <linux/dmaengine.h> ++#include <linux/dma-mapping.h> ++#include <linux/err.h> ++#include <linux/init.h> ++#include <linux/list.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++#include <linux/spinlock.h> ++#include <linux/irq.h> ++#include <linux/of_dma.h> ++ ++#include "virt-dma.h" ++ ++#define GDMA_NR_CHANS 16 ++ ++#define GDMA_REG_SRC_ADDR(x) (0x00 + (x) * 0x10) ++#define GDMA_REG_DST_ADDR(x) (0x04 + (x) * 0x10) ++ ++#define GDMA_REG_CTRL0(x) (0x08 + (x) * 0x10) ++#define GDMA_REG_CTRL0_TX_MASK 0xffff ++#define GDMA_REG_CTRL0_TX_SHIFT 16 ++#define GDMA_REG_CTRL0_CURR_MASK 0xff ++#define GDMA_REG_CTRL0_CURR_SHIFT 8 ++#define GDMA_REG_CTRL0_SRC_ADDR_FIXED BIT(7) ++#define GDMA_REG_CTRL0_DST_ADDR_FIXED BIT(6) ++#define GDMA_REG_CTRL0_BURST_MASK 0x7 ++#define GDMA_REG_CTRL0_BURST_SHIFT 3 ++#define GDMA_REG_CTRL0_DONE_INT BIT(2) ++#define GDMA_REG_CTRL0_ENABLE BIT(1) ++#define GDMA_REG_CTRL0_HW_MODE 0 ++ ++#define GDMA_REG_CTRL1(x) (0x0c + (x) * 0x10) ++#define GDMA_REG_CTRL1_SEG_MASK 0xf ++#define GDMA_REG_CTRL1_SEG_SHIFT 22 ++#define GDMA_REG_CTRL1_REQ_MASK 0x3f ++#define GDMA_REG_CTRL1_SRC_REQ_SHIFT 16 ++#define GDMA_REG_CTRL1_DST_REQ_SHIFT 8 ++#define GDMA_REG_CTRL1_CONTINOUS BIT(14) ++#define GDMA_REG_CTRL1_NEXT_MASK 0x1f ++#define GDMA_REG_CTRL1_NEXT_SHIFT 3 ++#define GDMA_REG_CTRL1_COHERENT BIT(2) ++#define GDMA_REG_CTRL1_FAIL BIT(1) ++#define GDMA_REG_CTRL1_MASK BIT(0) ++ ++#define GDMA_REG_UNMASK_INT 0x200 ++#define GDMA_REG_DONE_INT 0x204 ++ ++#define GDMA_REG_GCT 0x220 ++#define GDMA_REG_GCT_CHAN_MASK 0x3 ++#define GDMA_REG_GCT_CHAN_SHIFT 3 ++#define GDMA_REG_GCT_VER_MASK 0x3 ++#define GDMA_REG_GCT_VER_SHIFT 1 ++#define GDMA_REG_GCT_ARBIT_RR BIT(0) ++ ++enum gdma_dma_transfer_size { ++ GDMA_TRANSFER_SIZE_4BYTE = 0, ++ GDMA_TRANSFER_SIZE_8BYTE = 1, ++ GDMA_TRANSFER_SIZE_16BYTE = 2, ++ GDMA_TRANSFER_SIZE_32BYTE = 3, ++}; ++ ++struct gdma_dma_sg { ++ dma_addr_t addr; ++ unsigned int len; ++}; ++ ++struct gdma_dma_desc { ++ struct virt_dma_desc vdesc; ++ ++ enum dma_transfer_direction direction; ++ bool cyclic; ++ ++ unsigned int num_sgs; ++ struct gdma_dma_sg sg[]; ++}; ++ ++struct gdma_dmaengine_chan { ++ struct virt_dma_chan vchan; ++ unsigned int id; ++ ++ dma_addr_t fifo_addr; ++ unsigned int transfer_shift; ++ ++ struct gdma_dma_desc *desc; ++ unsigned int next_sg; ++}; ++ ++struct gdma_dma_dev { ++ struct dma_device ddev; ++ void __iomem *base; ++ struct clk *clk; ++ ++ struct gdma_dmaengine_chan chan[GDMA_NR_CHANS]; ++}; ++ ++static struct gdma_dma_dev *gdma_dma_chan_get_dev( ++ struct gdma_dmaengine_chan *chan) ++{ ++ return container_of(chan->vchan.chan.device, struct gdma_dma_dev, ++ ddev); ++} ++ ++static struct gdma_dmaengine_chan *to_gdma_dma_chan(struct dma_chan *c) ++{ ++ return container_of(c, struct gdma_dmaengine_chan, vchan.chan); ++} ++ ++static struct gdma_dma_desc *to_gdma_dma_desc(struct virt_dma_desc *vdesc) ++{ ++ return container_of(vdesc, struct gdma_dma_desc, vdesc); ++} ++ ++static inline uint32_t gdma_dma_read(struct gdma_dma_dev *dma_dev, ++ unsigned int reg) ++{ ++ return readl(dma_dev->base + reg); ++} ++ ++static inline void gdma_dma_write(struct gdma_dma_dev *dma_dev, ++ unsigned reg, uint32_t val) ++{ ++ //printk("gdma --> %p = 0x%08X\n", dma_dev->base + reg, val); ++ writel(val, dma_dev->base + reg); ++} ++ ++static inline void gdma_dma_write_mask(struct gdma_dma_dev *dma_dev, ++ unsigned int reg, uint32_t val, uint32_t mask) ++{ ++ uint32_t tmp; ++ ++ tmp = gdma_dma_read(dma_dev, reg); ++ tmp &= ~mask; ++ tmp |= val; ++ gdma_dma_write(dma_dev, reg, tmp); ++} ++ ++static struct gdma_dma_desc *gdma_dma_alloc_desc(unsigned int num_sgs) ++{ ++ return kzalloc(sizeof(struct gdma_dma_desc) + ++ sizeof(struct gdma_dma_sg) * num_sgs, GFP_ATOMIC); ++} ++ ++static enum gdma_dma_transfer_size gdma_dma_maxburst(u32 maxburst) ++{ ++ if (maxburst <= 7) ++ return GDMA_TRANSFER_SIZE_4BYTE; ++ else if (maxburst <= 15) ++ return GDMA_TRANSFER_SIZE_8BYTE; ++ else if (maxburst <= 31) ++ return GDMA_TRANSFER_SIZE_16BYTE; ++ ++ return GDMA_TRANSFER_SIZE_32BYTE; ++} ++ ++static int gdma_dma_slave_config(struct dma_chan *c, ++ const struct dma_slave_config *config) ++{ ++ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); ++ struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); ++ enum gdma_dma_transfer_size transfer_size; ++ uint32_t flags; ++ uint32_t ctrl0, ctrl1; ++ ++ switch (config->direction) { ++ case DMA_MEM_TO_DEV: ++ ctrl1 = 32 << GDMA_REG_CTRL1_SRC_REQ_SHIFT; ++ ctrl1 |= config->slave_id << GDMA_REG_CTRL1_DST_REQ_SHIFT; ++ flags = GDMA_REG_CTRL0_DST_ADDR_FIXED; ++ transfer_size = gdma_dma_maxburst(config->dst_maxburst); ++ chan->fifo_addr = config->dst_addr; ++ break; ++ ++ case DMA_DEV_TO_MEM: ++ ctrl1 = config->slave_id << GDMA_REG_CTRL1_SRC_REQ_SHIFT; ++ ctrl1 |= 32 << GDMA_REG_CTRL1_DST_REQ_SHIFT; ++ flags = GDMA_REG_CTRL0_SRC_ADDR_FIXED; ++ transfer_size = gdma_dma_maxburst(config->src_maxburst); ++ chan->fifo_addr = config->src_addr; ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ chan->transfer_shift = 1 + transfer_size; ++ ++ ctrl0 = flags | GDMA_REG_CTRL0_HW_MODE; ++ ctrl0 |= GDMA_REG_CTRL0_DONE_INT; ++ ++ ctrl1 &= ~(GDMA_REG_CTRL1_NEXT_MASK << GDMA_REG_CTRL1_NEXT_SHIFT); ++ ctrl1 |= chan->id << GDMA_REG_CTRL1_NEXT_SHIFT; ++ ctrl1 |= GDMA_REG_CTRL1_FAIL; ++ ctrl1 &= ~GDMA_REG_CTRL1_CONTINOUS; ++ gdma_dma_write(dma_dev, GDMA_REG_CTRL0(chan->id), ctrl0); ++ gdma_dma_write(dma_dev, GDMA_REG_CTRL1(chan->id), ctrl1); ++ ++ return 0; ++} ++ ++static int gdma_dma_terminate_all(struct dma_chan *c) ++{ ++ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); ++ struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); ++ unsigned long flags; ++ LIST_HEAD(head); ++ ++ spin_lock_irqsave(&chan->vchan.lock, flags); ++ gdma_dma_write_mask(dma_dev, GDMA_REG_CTRL0(chan->id), 0, ++ GDMA_REG_CTRL0_ENABLE); ++ chan->desc = NULL; ++ vchan_get_all_descriptors(&chan->vchan, &head); ++ spin_unlock_irqrestore(&chan->vchan.lock, flags); ++ ++ vchan_dma_desc_free_list(&chan->vchan, &head); ++ ++ return 0; ++} ++ ++static int gdma_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, ++ unsigned long arg) ++{ ++ struct dma_slave_config *config = (struct dma_slave_config *)arg; ++ ++ switch (cmd) { ++ case DMA_SLAVE_CONFIG: ++ return gdma_dma_slave_config(chan, config); ++ case DMA_TERMINATE_ALL: ++ return gdma_dma_terminate_all(chan); ++ default: ++ return -ENOSYS; ++ } ++} ++ ++static int gdma_dma_start_transfer(struct gdma_dmaengine_chan *chan) ++{ ++ struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); ++ dma_addr_t src_addr, dst_addr; ++ struct virt_dma_desc *vdesc; ++ struct gdma_dma_sg *sg; ++ ++ gdma_dma_write_mask(dma_dev, GDMA_REG_CTRL0(chan->id), 0, ++ GDMA_REG_CTRL0_ENABLE); ++ ++ if (!chan->desc) { ++ vdesc = vchan_next_desc(&chan->vchan); ++ if (!vdesc) ++ return 0; ++ chan->desc = to_gdma_dma_desc(vdesc); ++ chan->next_sg = 0; ++ } ++ ++ if (chan->next_sg == chan->desc->num_sgs) ++ chan->next_sg = 0; ++ ++ sg = &chan->desc->sg[chan->next_sg]; ++ ++ if (chan->desc->direction == DMA_MEM_TO_DEV) { ++ src_addr = sg->addr; ++ dst_addr = chan->fifo_addr; ++ } else { ++ src_addr = chan->fifo_addr; ++ dst_addr = sg->addr; ++ } ++ gdma_dma_write(dma_dev, GDMA_REG_SRC_ADDR(chan->id), src_addr); ++ gdma_dma_write(dma_dev, GDMA_REG_DST_ADDR(chan->id), dst_addr); ++ gdma_dma_write_mask(dma_dev, GDMA_REG_CTRL0(chan->id), ++ (sg->len << GDMA_REG_CTRL0_TX_SHIFT) | GDMA_REG_CTRL0_ENABLE, ++ GDMA_REG_CTRL0_TX_MASK << GDMA_REG_CTRL0_TX_SHIFT); ++ chan->next_sg++; ++ gdma_dma_write_mask(dma_dev, GDMA_REG_CTRL1(chan->id), 0, GDMA_REG_CTRL1_MASK); ++ ++ return 0; ++} ++ ++static void gdma_dma_chan_irq(struct gdma_dmaengine_chan *chan) ++{ ++ spin_lock(&chan->vchan.lock); ++ if (chan->desc) { ++ if (chan->desc && chan->desc->cyclic) { ++ vchan_cyclic_callback(&chan->desc->vdesc); ++ } else { ++ if (chan->next_sg == chan->desc->num_sgs) { ++ chan->desc = NULL; ++ vchan_cookie_complete(&chan->desc->vdesc); ++ } ++ } ++ } ++ gdma_dma_start_transfer(chan); ++ spin_unlock(&chan->vchan.lock); ++} ++ ++static irqreturn_t gdma_dma_irq(int irq, void *devid) ++{ ++ struct gdma_dma_dev *dma_dev = devid; ++ uint32_t unmask, done; ++ unsigned int i; ++ ++ unmask = gdma_dma_read(dma_dev, GDMA_REG_UNMASK_INT); ++ gdma_dma_write(dma_dev, GDMA_REG_UNMASK_INT, unmask); ++ done = gdma_dma_read(dma_dev, GDMA_REG_DONE_INT); ++ ++ for (i = 0; i < GDMA_NR_CHANS; ++i) ++ if (done & BIT(i)) ++ gdma_dma_chan_irq(&dma_dev->chan[i]); ++ gdma_dma_write(dma_dev, GDMA_REG_DONE_INT, done); ++ ++ return IRQ_HANDLED; ++} ++ ++static void gdma_dma_issue_pending(struct dma_chan *c) ++{ ++ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&chan->vchan.lock, flags); ++ if (vchan_issue_pending(&chan->vchan) && !chan->desc) ++ gdma_dma_start_transfer(chan); ++ spin_unlock_irqrestore(&chan->vchan.lock, flags); ++} ++ ++static struct dma_async_tx_descriptor *gdma_dma_prep_slave_sg( ++ struct dma_chan *c, struct scatterlist *sgl, ++ unsigned int sg_len, enum dma_transfer_direction direction, ++ unsigned long flags, void *context) ++{ ++ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); ++ struct gdma_dma_desc *desc; ++ struct scatterlist *sg; ++ unsigned int i; ++ ++ desc = gdma_dma_alloc_desc(sg_len); ++ if (!desc) ++ return NULL; ++ ++ for_each_sg(sgl, sg, sg_len, i) { ++ desc->sg[i].addr = sg_dma_address(sg); ++ desc->sg[i].len = sg_dma_len(sg); ++ } ++ ++ desc->num_sgs = sg_len; ++ desc->direction = direction; ++ desc->cyclic = false; ++ ++ return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); ++} ++ ++static struct dma_async_tx_descriptor *gdma_dma_prep_dma_cyclic( ++ struct dma_chan *c, dma_addr_t buf_addr, size_t buf_len, ++ size_t period_len, enum dma_transfer_direction direction, ++ unsigned long flags, void *context) ++{ ++ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); ++ struct gdma_dma_desc *desc; ++ unsigned int num_periods, i; ++ ++ if (buf_len % period_len) ++ return NULL; ++ ++ num_periods = buf_len / period_len; ++ ++ desc = gdma_dma_alloc_desc(num_periods); ++ if (!desc) ++ return NULL; ++ ++ for (i = 0; i < num_periods; i++) { ++ desc->sg[i].addr = buf_addr; ++ desc->sg[i].len = period_len; ++ buf_addr += period_len; ++ } ++ ++ desc->num_sgs = num_periods; ++ desc->direction = direction; ++ desc->cyclic = true; ++ ++ return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); ++} ++ ++static size_t gdma_dma_desc_residue(struct gdma_dmaengine_chan *chan, ++ struct gdma_dma_desc *desc, unsigned int next_sg) ++{ ++ struct gdma_dma_dev *dma_dev = gdma_dma_chan_get_dev(chan); ++ unsigned int residue, count; ++ unsigned int i; ++ ++ residue = 0; ++ ++ for (i = next_sg; i < desc->num_sgs; i++) ++ residue += desc->sg[i].len; ++ ++ if (next_sg != 0) { ++ count = gdma_dma_read(dma_dev, GDMA_REG_CTRL0(chan->id)); ++ count >>= GDMA_REG_CTRL0_CURR_SHIFT; ++ count &= GDMA_REG_CTRL0_CURR_MASK; ++ residue += count << chan->transfer_shift; ++ } ++ ++ return residue; ++} ++ ++static enum dma_status gdma_dma_tx_status(struct dma_chan *c, ++ dma_cookie_t cookie, struct dma_tx_state *state) ++{ ++ struct gdma_dmaengine_chan *chan = to_gdma_dma_chan(c); ++ struct virt_dma_desc *vdesc; ++ enum dma_status status; ++ unsigned long flags; ++ ++ status = dma_cookie_status(c, cookie, state); ++ if (status == DMA_SUCCESS || !state) ++ return status; ++ ++ spin_lock_irqsave(&chan->vchan.lock, flags); ++ vdesc = vchan_find_desc(&chan->vchan, cookie); ++ if (cookie == chan->desc->vdesc.tx.cookie) { ++ state->residue = gdma_dma_desc_residue(chan, chan->desc, ++ chan->next_sg); ++ } else if (vdesc) { ++ state->residue = gdma_dma_desc_residue(chan, ++ to_gdma_dma_desc(vdesc), 0); ++ } else { ++ state->residue = 0; ++ } ++ spin_unlock_irqrestore(&chan->vchan.lock, flags); ++ ++ return status; ++} ++ ++static int gdma_dma_alloc_chan_resources(struct dma_chan *c) ++{ ++ return 0; ++} ++ ++static void gdma_dma_free_chan_resources(struct dma_chan *c) ++{ ++ vchan_free_chan_resources(to_virt_chan(c)); ++} ++ ++static void gdma_dma_desc_free(struct virt_dma_desc *vdesc) ++{ ++ kfree(container_of(vdesc, struct gdma_dma_desc, vdesc)); ++} ++ ++static struct dma_chan * ++of_dma_xlate_by_chan_id(struct of_phandle_args *dma_spec, ++ struct of_dma *ofdma) ++{ ++ struct gdma_dma_dev *dma_dev = ofdma->of_dma_data; ++ unsigned int request = dma_spec->args[0]; ++ ++ if (request >= GDMA_NR_CHANS) ++ return NULL; ++ ++ return dma_get_slave_channel(&(dma_dev->chan[request].vchan.chan)); ++} ++ ++static int gdma_dma_probe(struct platform_device *pdev) ++{ ++ struct gdma_dmaengine_chan *chan; ++ struct gdma_dma_dev *dma_dev; ++ struct dma_device *dd; ++ unsigned int i; ++ struct resource *res; ++ uint32_t gct; ++ int ret; ++ int irq; ++ ++ ++ dma_dev = devm_kzalloc(&pdev->dev, sizeof(*dma_dev), GFP_KERNEL); ++ if (!dma_dev) ++ return -EINVAL; ++ ++ dd = &dma_dev->ddev; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ dma_dev->base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(dma_dev->base)) ++ return PTR_ERR(dma_dev->base); ++ ++ dma_cap_set(DMA_SLAVE, dd->cap_mask); ++ dma_cap_set(DMA_CYCLIC, dd->cap_mask); ++ dd->device_alloc_chan_resources = gdma_dma_alloc_chan_resources; ++ dd->device_free_chan_resources = gdma_dma_free_chan_resources; ++ dd->device_tx_status = gdma_dma_tx_status; ++ dd->device_issue_pending = gdma_dma_issue_pending; ++ dd->device_prep_slave_sg = gdma_dma_prep_slave_sg; ++ dd->device_prep_dma_cyclic = gdma_dma_prep_dma_cyclic; ++ dd->device_control = gdma_dma_control; ++ dd->dev = &pdev->dev; ++ dd->chancnt = GDMA_NR_CHANS; ++ INIT_LIST_HEAD(&dd->channels); ++ ++ for (i = 0; i < dd->chancnt; i++) { ++ chan = &dma_dev->chan[i]; ++ chan->id = i; ++ chan->vchan.desc_free = gdma_dma_desc_free; ++ vchan_init(&chan->vchan, dd); ++ } ++ ++ ret = dma_async_device_register(dd); ++ if (ret) ++ return ret; ++ ++ ret = of_dma_controller_register(pdev->dev.of_node, ++ of_dma_xlate_by_chan_id, dma_dev); ++ if (ret) ++ goto err_unregister; ++ ++ irq = platform_get_irq(pdev, 0); ++ ret = request_irq(irq, gdma_dma_irq, 0, dev_name(&pdev->dev), dma_dev); ++ if (ret) ++ goto err_unregister; ++ ++ gdma_dma_write(dma_dev, GDMA_REG_UNMASK_INT, 0); ++ gdma_dma_write(dma_dev, GDMA_REG_DONE_INT, BIT(dd->chancnt) - 1); ++ ++ gct = gdma_dma_read(dma_dev, GDMA_REG_GCT); ++ dev_info(&pdev->dev, "revision: %d, channels: %d\n", ++ (gct >> GDMA_REG_GCT_VER_SHIFT) & GDMA_REG_GCT_VER_MASK, ++ 8 << ((gct >> GDMA_REG_GCT_CHAN_SHIFT) & GDMA_REG_GCT_CHAN_MASK)); ++ platform_set_drvdata(pdev, dma_dev); ++ ++ gdma_dma_write(dma_dev, GDMA_REG_GCT, GDMA_REG_GCT_ARBIT_RR); ++ ++ return 0; ++ ++err_unregister: ++ dma_async_device_unregister(dd); ++ return ret; ++} ++ ++static int gdma_dma_remove(struct platform_device *pdev) ++{ ++ struct gdma_dma_dev *dma_dev = platform_get_drvdata(pdev); ++ int irq = platform_get_irq(pdev, 0); ++ ++ free_irq(irq, dma_dev); ++ of_dma_controller_free(pdev->dev.of_node); ++ dma_async_device_unregister(&dma_dev->ddev); ++ ++ return 0; ++} ++ ++static const struct of_device_id gdma_of_match_table[] = { ++ { .compatible = "ralink,rt2880-gdma" }, ++ { }, ++}; ++ ++static struct platform_driver gdma_dma_driver = { ++ .probe = gdma_dma_probe, ++ .remove = gdma_dma_remove, ++ .driver = { ++ .name = "gdma-rt2880", ++ .owner = THIS_MODULE, ++ .of_match_table = gdma_of_match_table, ++ }, ++}; ++module_platform_driver(gdma_dma_driver); ++ ++MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); ++MODULE_DESCRIPTION("GDMA4740 DMA driver"); ++MODULE_LICENSE("GPLv2"); +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -1058,6 +1058,7 @@ struct dma_chan *dma_request_slave_chann + const char *name); + struct dma_chan *dma_request_slave_channel(struct device *dev, const char *name); + void dma_release_channel(struct dma_chan *chan); ++struct dma_chan *dma_get_slave_channel(struct dma_chan *chan); + #else + static inline struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type) + { diff --git a/target/linux/ramips/patches-3.18/0055-asoc-add-mt7620-support.patch b/target/linux/ramips/patches-3.18/0055-asoc-add-mt7620-support.patch new file mode 100644 index 0000000..b439b9d --- /dev/null +++ b/target/linux/ramips/patches-3.18/0055-asoc-add-mt7620-support.patch @@ -0,0 +1,766 @@ +From 241188942603dc73f62cf2553c53cae2235c9957 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 27 Jul 2014 09:31:47 +0100 +Subject: [PATCH 55/57] asoc: add mt7620 support + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/ralink/of.c | 2 + + sound/soc/Kconfig | 1 + + sound/soc/Makefile | 1 + + sound/soc/ralink/Kconfig | 15 ++ + sound/soc/ralink/Makefile | 11 + + sound/soc/ralink/mt7620-i2s.c | 466 ++++++++++++++++++++++++++++++++++++++ + sound/soc/ralink/mt7620-wm8960.c | 125 ++++++++++ + sound/soc/soc-io.c | 10 - + 8 files changed, 621 insertions(+), 10 deletions(-) + create mode 100644 sound/soc/ralink/Kconfig + create mode 100644 sound/soc/ralink/Makefile + create mode 100644 sound/soc/ralink/mt7620-i2s.c + create mode 100644 sound/soc/ralink/mt7620-wm8960.c + +--- a/arch/mips/ralink/of.c ++++ b/arch/mips/ralink/of.c +@@ -15,6 +15,7 @@ + #include <linux/of_fdt.h> + #include <linux/kernel.h> + #include <linux/bootmem.h> ++#include <linux/module.h> + #include <linux/of_platform.h> + #include <linux/of_address.h> + +@@ -26,6 +27,7 @@ + #include "common.h" + + __iomem void *rt_sysc_membase; ++EXPORT_SYMBOL(rt_sysc_membase); + __iomem void *rt_memc_membase; + + __iomem void *plat_of_remap_node(const char *node) +--- a/sound/soc/Kconfig ++++ b/sound/soc/Kconfig +@@ -48,6 +48,7 @@ source "sound/soc/intel/Kconfig" + source "sound/soc/mxs/Kconfig" + source "sound/soc/pxa/Kconfig" + source "sound/soc/rockchip/Kconfig" ++source "sound/soc/ralink/Kconfig" + source "sound/soc/samsung/Kconfig" + source "sound/soc/sh/Kconfig" + source "sound/soc/sirf/Kconfig" +--- a/sound/soc/Makefile ++++ b/sound/soc/Makefile +@@ -25,6 +25,7 @@ obj-$(CONFIG_SND_SOC) += omap/ + obj-$(CONFIG_SND_SOC) += kirkwood/ + obj-$(CONFIG_SND_SOC) += pxa/ + obj-$(CONFIG_SND_SOC) += rockchip/ ++obj-$(CONFIG_SND_SOC) += ralink/ + obj-$(CONFIG_SND_SOC) += samsung/ + obj-$(CONFIG_SND_SOC) += sh/ + obj-$(CONFIG_SND_SOC) += sirf/ +--- /dev/null ++++ b/sound/soc/ralink/Kconfig +@@ -0,0 +1,15 @@ ++config SND_MT7620_SOC_I2S ++ depends on SOC_MT7620 && SND_SOC ++ select SND_SOC_GENERIC_DMAENGINE_PCM ++ tristate "SoC Audio (I2S protocol) for Ralink MT7620 SoC" ++ help ++ Say Y if you want to use I2S protocol and I2S codec on Ingenic MT7620 ++ based boards. ++ ++config SND_MT7620_SOC_WM8960 ++ tristate "SoC Audio support for Ralink WM8960" ++ select SND_MT7620_SOC_I2S ++ select SND_SOC_WM8960 ++ help ++ Say Y if you want to add support for ASoC audio on the Qi LB60 board ++ a.k.a Qi Ben NanoNote. +--- /dev/null ++++ b/sound/soc/ralink/Makefile +@@ -0,0 +1,11 @@ ++# ++# Jz4740 Platform Support ++# ++snd-soc-mt7620-i2s-objs := mt7620-i2s.o ++ ++obj-$(CONFIG_SND_MT7620_SOC_I2S) += snd-soc-mt7620-i2s.o ++ ++# Jz4740 Machine Support ++snd-soc-mt7620-wm8960-objs := mt7620-wm8960.o ++ ++obj-$(CONFIG_SND_MT7620_SOC_WM8960) += snd-soc-mt7620-wm8960.o +--- /dev/null ++++ b/sound/soc/ralink/mt7620-i2s.c +@@ -0,0 +1,436 @@ ++/* ++ * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ */ ++ ++#include <linux/init.h> ++#include <linux/io.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++ ++#include <linux/delay.h> ++ ++#include <linux/dma-mapping.h> ++ ++#include <sound/core.h> ++#include <sound/pcm.h> ++#include <sound/pcm_params.h> ++#include <sound/soc.h> ++#include <sound/initval.h> ++#include <sound/dmaengine_pcm.h> ++ ++#include <ralink_regs.h> ++ ++#define I2S_REG_CFG0 0x00 ++#define I2S_REG_CFG0_EN BIT(31) ++#define I2S_REG_CFG0_DMA_EN BIT(30) ++#define I2S_REG_CFG0_BYTE_SWAP BIT(28) ++#define I2S_REG_CFG0_TX_EN BIT(24) ++#define I2S_REG_CFG0_RX_EN BIT(20) ++#define I2S_REG_CFG0_SLAVE BIT(16) ++#define I2S_REG_CFG0_RX_THRES 12 ++#define I2S_REG_CFG0_TX_THRES 4 ++#define I2S_REG_CFG0_DFT_THRES (4 << I2S_REG_CFG0_RX_THRES) | \ ++ (4 << I2S_REG_CFG0_TX_THRES) ++ ++#define I2S_REG_INT_STATUS 0x04 ++#define I2S_REG_INT_EN 0x08 ++#define I2S_REG_FF_STATUS 0x0c ++#define I2S_REG_WREG 0x10 ++#define I2S_REG_RREG 0x14 ++#define I2S_REG_CFG1 0x18 ++ ++#define I2S_REG_DIVCMP 0x20 ++#define I2S_REG_DIVINT 0x24 ++#define I2S_REG_CLK_EN BIT(31) ++ ++struct mt7620_i2s { ++ struct resource *mem; ++ void __iomem *base; ++ dma_addr_t phys_base; ++ ++ struct snd_dmaengine_dai_dma_data playback_dma_data; ++ struct snd_dmaengine_dai_dma_data capture_dma_data; ++}; ++ ++static inline uint32_t mt7620_i2s_read(const struct mt7620_i2s *i2s, ++ unsigned int reg) ++{ ++ return readl(i2s->base + reg); ++} ++ ++static inline void mt7620_i2s_write(const struct mt7620_i2s *i2s, ++ unsigned int reg, uint32_t value) ++{ ++ //printk("i2s --> %p = 0x%08X\n", i2s->base + reg, value); ++ writel(value, i2s->base + reg); ++} ++ ++static int mt7620_i2s_startup(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct mt7620_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ uint32_t cfg; ++ ++ if (dai->active) ++ return 0; ++ ++ cfg = mt7620_i2s_read(i2s, I2S_REG_CFG0); ++ cfg |= I2S_REG_CFG0_EN; ++ mt7620_i2s_write(i2s, I2S_REG_CFG0, cfg); ++ ++ return 0; ++} ++ ++static void mt7620_i2s_shutdown(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct mt7620_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ uint32_t cfg; ++ ++ if (dai->active) ++ return; ++ ++ cfg = mt7620_i2s_read(i2s, I2S_REG_CFG0); ++ cfg &= ~I2S_REG_CFG0_EN; ++ mt7620_i2s_write(i2s, I2S_REG_CFG0, cfg); ++} ++ ++static int mt7620_i2s_trigger(struct snd_pcm_substream *substream, int cmd, ++ struct snd_soc_dai *dai) ++{ ++ struct mt7620_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ ++ uint32_t cfg; ++ uint32_t mask; ++ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++ mask = I2S_REG_CFG0_TX_EN; ++ else ++ mask = I2S_REG_CFG0_RX_EN; ++ ++ cfg = mt7620_i2s_read(i2s, I2S_REG_CFG0); ++ ++ switch (cmd) { ++ case SNDRV_PCM_TRIGGER_START: ++ case SNDRV_PCM_TRIGGER_RESUME: ++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ cfg |= mask; ++ break; ++ case SNDRV_PCM_TRIGGER_STOP: ++ case SNDRV_PCM_TRIGGER_SUSPEND: ++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: ++ cfg &= ~mask; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (cfg & (I2S_REG_CFG0_TX_EN | I2S_REG_CFG0_RX_EN)) ++ cfg |= I2S_REG_CFG0_DMA_EN; ++ else ++ cfg &= ~I2S_REG_CFG0_DMA_EN; ++ ++ mt7620_i2s_write(i2s, I2S_REG_CFG0, cfg); ++ ++ return 0; ++} ++ ++static int mt7620_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) ++{ ++ struct mt7620_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ uint32_t cfg; ++ ++ cfg = mt7620_i2s_read(i2s, I2S_REG_CFG0); ++ ++ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { ++ case SND_SOC_DAIFMT_CBS_CFS: ++ cfg |= I2S_REG_CFG0_SLAVE; ++ break; ++ case SND_SOC_DAIFMT_CBM_CFM: ++ cfg &= ~I2S_REG_CFG0_SLAVE; ++ break; ++ case SND_SOC_DAIFMT_CBM_CFS: ++ default: ++ return -EINVAL; ++ } ++ ++ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { ++ case SND_SOC_DAIFMT_I2S: ++ case SND_SOC_DAIFMT_MSB: ++ cfg &= ~I2S_REG_CFG0_BYTE_SWAP; ++ break; ++ case SND_SOC_DAIFMT_LSB: ++ cfg |= I2S_REG_CFG0_BYTE_SWAP; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { ++ case SND_SOC_DAIFMT_NB_NF: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ mt7620_i2s_write(i2s, I2S_REG_CFG0, cfg); ++ ++ return 0; ++} ++ ++static int mt7620_i2s_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) ++{ ++ ++ return 0; ++} ++ ++unsigned long i2sMaster_inclk_int[11] = { ++ 78, 56, 52, 39, 28, 26, 19, 14, 13, 9, 6}; ++unsigned long i2sMaster_inclk_comp[11] = { ++ 64, 352, 42, 32, 176, 21, 272, 88, 10, 455, 261}; ++ ++ ++static int mt7620_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, ++ unsigned int freq, int dir) ++{ ++ struct mt7620_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ ++ printk("Internal REFCLK with fractional division\n"); ++ ++ mt7620_i2s_write(i2s, I2S_REG_DIVINT, i2sMaster_inclk_int[7]); ++ mt7620_i2s_write(i2s, I2S_REG_DIVCMP, ++ i2sMaster_inclk_comp[7] | I2S_REG_CLK_EN); ++ ++/* struct mt7620_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ struct clk *parent; ++ int ret = 0; ++ ++ switch (clk_id) { ++ case JZ4740_I2S_CLKSRC_EXT: ++ parent = clk_get(NULL, "ext"); ++ clk_set_parent(i2s->clk_i2s, parent); ++ break; ++ case JZ4740_I2S_CLKSRC_PLL: ++ parent = clk_get(NULL, "pll half"); ++ clk_set_parent(i2s->clk_i2s, parent); ++ ret = clk_set_rate(i2s->clk_i2s, freq); ++ break; ++ default: ++ return -EINVAL; ++ } ++ clk_put(parent); ++ ++ return ret;*/ ++ return 0; ++} ++ ++static void mt7620_i2c_init_pcm_config(struct mt7620_i2s *i2s) ++{ ++ struct snd_dmaengine_dai_dma_data *dma_data; ++ ++ /* Playback */ ++ dma_data = &i2s->playback_dma_data; ++ dma_data->maxburst = 16; ++ dma_data->slave_id = 2; //JZ4740_DMA_TYPE_AIC_TRANSMIT; ++ dma_data->addr = i2s->phys_base + I2S_REG_WREG; ++ ++ /* Capture */ ++ dma_data = &i2s->capture_dma_data; ++ dma_data->maxburst = 16; ++ dma_data->slave_id = 3; //JZ4740_DMA_TYPE_AIC_RECEIVE; ++ dma_data->addr = i2s->phys_base + I2S_REG_RREG; ++} ++ ++static int mt7620_i2s_dai_probe(struct snd_soc_dai *dai) ++{ ++ struct mt7620_i2s *i2s = snd_soc_dai_get_drvdata(dai); ++ uint32_t data; ++ ++ mt7620_i2c_init_pcm_config(i2s); ++ dai->playback_dma_data = &i2s->playback_dma_data; ++ dai->capture_dma_data = &i2s->capture_dma_data; ++ ++ /* set share pins to i2s/gpio mode and i2c mode */ ++ data = rt_sysc_r32(0x60); ++ data &= 0xFFFFFFE2; ++ data |= 0x00000018; ++ rt_sysc_w32(data, 0x60); ++ ++ printk("Internal REFCLK with fractional division\n"); ++ ++ mt7620_i2s_write(i2s, I2S_REG_CFG0, I2S_REG_CFG0_DFT_THRES); ++ mt7620_i2s_write(i2s, I2S_REG_CFG1, 0); ++ mt7620_i2s_write(i2s, I2S_REG_INT_EN, 0); ++ ++ mt7620_i2s_write(i2s, I2S_REG_DIVINT, i2sMaster_inclk_int[7]); ++ mt7620_i2s_write(i2s, I2S_REG_DIVCMP, ++ i2sMaster_inclk_comp[7] | I2S_REG_CLK_EN); ++ ++ return 0; ++} ++ ++static int mt7620_i2s_dai_remove(struct snd_soc_dai *dai) ++{ ++ return 0; ++} ++ ++static const struct snd_soc_dai_ops mt7620_i2s_dai_ops = { ++ .startup = mt7620_i2s_startup, ++ .shutdown = mt7620_i2s_shutdown, ++ .trigger = mt7620_i2s_trigger, ++ .hw_params = mt7620_i2s_hw_params, ++ .set_fmt = mt7620_i2s_set_fmt, ++ .set_sysclk = mt7620_i2s_set_sysclk, ++}; ++ ++#define JZ4740_I2S_FMTS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ ++ SNDRV_PCM_FMTBIT_S24_LE) ++ ++static struct snd_soc_dai_driver mt7620_i2s_dai = { ++ .probe = mt7620_i2s_dai_probe, ++ .remove = mt7620_i2s_dai_remove, ++ .playback = { ++ .channels_min = 1, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000_48000, ++ .formats = JZ4740_I2S_FMTS, ++ }, ++ .capture = { ++ .channels_min = 2, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000_48000, ++ .formats = JZ4740_I2S_FMTS, ++ }, ++ .symmetric_rates = 1, ++ .ops = &mt7620_i2s_dai_ops, ++}; ++ ++static const struct snd_pcm_hardware mt7620_pcm_hardware = { ++ .info = SNDRV_PCM_INFO_MMAP | ++ SNDRV_PCM_INFO_MMAP_VALID | ++ SNDRV_PCM_INFO_INTERLEAVED | ++ SNDRV_PCM_INFO_BLOCK_TRANSFER, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8, ++ .period_bytes_min = PAGE_SIZE, ++ .period_bytes_max = 64 * 1024, ++ .periods_min = 2, ++ .periods_max = 128, ++ .buffer_bytes_max = 128 * 1024, ++ .fifo_size = 32, ++}; ++ ++static const struct snd_dmaengine_pcm_config mt7620_dmaengine_pcm_config = { ++ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config, ++ .pcm_hardware = &mt7620_pcm_hardware, ++ .prealloc_buffer_size = 256 * PAGE_SIZE, ++}; ++ ++static const struct snd_soc_component_driver mt7620_i2s_component = { ++ .name = "mt7620-i2s", ++}; ++ ++static int mt7620_i2s_dev_probe(struct platform_device *pdev) ++{ ++ struct mt7620_i2s *i2s; ++ int ret; ++ ++ snd_dmaengine_pcm_register(&pdev->dev, ++ &mt7620_dmaengine_pcm_config, ++ SND_DMAENGINE_PCM_FLAG_COMPAT); ++ ++ i2s = kzalloc(sizeof(*i2s), GFP_KERNEL); ++ if (!i2s) ++ return -ENOMEM; ++ ++ i2s->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!i2s->mem) { ++ ret = -ENOENT; ++ goto err_free; ++ } ++ ++ i2s->mem = request_mem_region(i2s->mem->start, resource_size(i2s->mem), ++ pdev->name); ++ if (!i2s->mem) { ++ ret = -EBUSY; ++ goto err_free; ++ } ++ ++ i2s->base = ioremap_nocache(i2s->mem->start, resource_size(i2s->mem)); ++ if (!i2s->base) { ++ ret = -EBUSY; ++ goto err_release_mem_region; ++ } ++ ++ i2s->phys_base = i2s->mem->start; ++ ++ platform_set_drvdata(pdev, i2s); ++ ret = snd_soc_register_component(&pdev->dev, &mt7620_i2s_component, ++ &mt7620_i2s_dai, 1); ++ ++ if (!ret) { ++ dev_err(&pdev->dev, "loaded\n"); ++ return ret; ++ } ++ ++ dev_err(&pdev->dev, "Failed to register DAI\n"); ++ iounmap(i2s->base); ++ ++err_release_mem_region: ++ release_mem_region(i2s->mem->start, resource_size(i2s->mem)); ++err_free: ++ kfree(i2s); ++ ++ return ret; ++} ++ ++static int mt7620_i2s_dev_remove(struct platform_device *pdev) ++{ ++ struct mt7620_i2s *i2s = platform_get_drvdata(pdev); ++ ++ snd_soc_unregister_component(&pdev->dev); ++ ++ iounmap(i2s->base); ++ release_mem_region(i2s->mem->start, resource_size(i2s->mem)); ++ ++ kfree(i2s); ++ ++ snd_dmaengine_pcm_unregister(&pdev->dev); ++ ++ return 0; ++} ++ ++static const struct of_device_id mt7620_i2s_match[] = { ++ { .compatible = "ralink,mt7620a-i2s" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mt7620_i2s_match); ++ ++static struct platform_driver mt7620_i2s_driver = { ++ .probe = mt7620_i2s_dev_probe, ++ .remove = mt7620_i2s_dev_remove, ++ .driver = { ++ .name = "mt7620-i2s", ++ .owner = THIS_MODULE, ++ .of_match_table = mt7620_i2s_match, ++ }, ++}; ++ ++module_platform_driver(mt7620_i2s_driver); ++ ++MODULE_AUTHOR("Lars-Peter Clausen, <lars@metafoo.de>"); ++MODULE_DESCRIPTION("Ingenic JZ4740 SoC I2S driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:mt7620-i2s"); +--- /dev/null ++++ b/sound/soc/ralink/mt7620-wm8960.c +@@ -0,0 +1,233 @@ ++/* ++ * Copyright 2013 Freescale Semiconductor, Inc. ++ * ++ * Based on mt7620-sgtl5000.c ++ * Copyright 2012 Freescale Semiconductor, Inc. ++ * Copyright 2012 Linaro Ltd. ++ * ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#include <linux/module.h> ++#include <linux/of_platform.h> ++#include <linux/i2c.h> ++#include <linux/slab.h> ++#include <sound/soc.h> ++#include <sound/pcm_params.h> ++#include <sound/soc-dapm.h> ++#include <linux/pinctrl/consumer.h> ++ ++#include "../codecs/wm8960.h" ++ ++#define DAI_NAME_SIZE 32 ++ ++struct mt7620_wm8960_data { ++ struct snd_soc_dai_link dai; ++ struct snd_soc_card card; ++ char codec_dai_name[DAI_NAME_SIZE]; ++ char platform_name[DAI_NAME_SIZE]; ++ unsigned int clk_frequency; ++}; ++ ++struct mt7620_priv { ++ struct platform_device *pdev; ++}; ++static struct mt7620_priv card_priv; ++ ++static const struct snd_soc_dapm_widget mt7620_wm8960_dapm_widgets[] = { ++ SND_SOC_DAPM_HP("Headphone Jack", NULL), ++ SND_SOC_DAPM_SPK("Ext Spk", NULL), ++ SND_SOC_DAPM_MIC("AMIC", NULL), ++ SND_SOC_DAPM_MIC("DMIC", NULL), ++}; ++ ++static int sample_rate = 44100; ++static snd_pcm_format_t sample_format = SNDRV_PCM_FORMAT_S16_LE; ++ ++static int mt7620_hifi_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ sample_rate = params_rate(params); ++ sample_format = params_format(params); ++ ++ return 0; ++} ++ ++static struct snd_soc_ops mt7620_hifi_ops = { ++ .hw_params = mt7620_hifi_hw_params, ++}; ++ ++static int mt7620_wm8960_set_bias_level(struct snd_soc_card *card, ++ struct snd_soc_dapm_context *dapm, ++ enum snd_soc_bias_level level) ++{ ++ struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; ++ struct mt7620_priv *priv = &card_priv; ++ struct mt7620_wm8960_data *data = snd_soc_card_get_drvdata(card); ++ struct device *dev = &priv->pdev->dev; ++ int ret; ++ ++ if (dapm->dev != codec_dai->dev) ++ return 0; ++ ++ switch (level) { ++ case SND_SOC_BIAS_PREPARE: ++ if (dapm->bias_level == SND_SOC_BIAS_STANDBY) { ++ } ++ break; ++ ++ case SND_SOC_BIAS_STANDBY: ++ if (dapm->bias_level == SND_SOC_BIAS_PREPARE) { ++ ret = snd_soc_dai_set_sysclk(codec_dai, ++ WM8960_SYSCLK_MCLK, data->clk_frequency, ++ SND_SOC_CLOCK_IN); ++ if (ret < 0) { ++ dev_err(dev, ++ "failed to switch away from FLL: %d\n", ++ ret); ++ return ret; ++ } ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static int mt7620_wm8960_late_probe(struct snd_soc_card *card) ++{ ++ struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; ++ struct mt7620_priv *priv = &card_priv; ++ struct mt7620_wm8960_data *data = snd_soc_card_get_drvdata(card); ++ struct device *dev = &priv->pdev->dev; ++ int ret; ++ ++ ret = snd_soc_dai_set_sysclk(codec_dai, WM8960_SYSCLK_MCLK, ++ data->clk_frequency, SND_SOC_CLOCK_IN); ++ if (ret < 0) ++ dev_err(dev, "failed to set sysclk in %s\n", __func__); ++ ++ return ret; ++} ++ ++static int mt7620_wm8960_probe(struct platform_device *pdev) ++{ ++ struct device_node *i2s_np, *codec_np; ++ struct platform_device *i2s_pdev; ++ struct mt7620_priv *priv = &card_priv; ++ struct i2c_client *codec_dev; ++ struct mt7620_wm8960_data *data; ++ int ret; ++ ++ priv->pdev = pdev; ++ ++ i2s_np = of_parse_phandle(pdev->dev.of_node, "i2s-controller", 0); ++ codec_np = of_parse_phandle(pdev->dev.of_node, "audio-codec", 0); ++ if (!i2s_np || !codec_np) { ++ dev_err(&pdev->dev, "phandle missing or invalid\n"); ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ i2s_pdev = of_find_device_by_node(i2s_np); ++ if (!i2s_pdev) { ++ dev_err(&pdev->dev, "failed to find SSI platform device\n"); ++ ret = -EINVAL; ++ goto fail; ++ } ++ codec_dev = of_find_i2c_device_by_node(codec_np); ++ if (!codec_dev || !codec_dev->dev.driver) { ++ dev_err(&pdev->dev, "failed to find codec platform device\n"); ++ ret = -EINVAL; ++ goto fail; ++ } ++ ++ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); ++ if (!data) { ++ ret = -ENOMEM; ++ goto fail; ++ } ++ ++ data->clk_frequency = 12000000; ++ data->dai.name = "HiFi"; ++ data->dai.stream_name = "HiFi"; ++ data->dai.codec_dai_name = "wm8960-hifi"; ++ data->dai.codec_of_node = codec_np; ++ data->dai.cpu_dai_name = dev_name(&i2s_pdev->dev); ++ data->dai.platform_of_node = i2s_np; ++ data->dai.ops = &mt7620_hifi_ops; ++ data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ++ SND_SOC_DAIFMT_CBM_CFM; ++ ++ data->card.dev = &pdev->dev; ++ ret = snd_soc_of_parse_card_name(&data->card, "model"); ++ if (ret) ++ goto fail; ++ ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing"); ++ if (ret) ++ goto fail; ++ data->card.num_links = 1; ++ data->card.dai_link = &data->dai; ++ data->card.dapm_widgets = mt7620_wm8960_dapm_widgets; ++ data->card.num_dapm_widgets = ARRAY_SIZE(mt7620_wm8960_dapm_widgets); ++ ++ data->card.late_probe = mt7620_wm8960_late_probe; ++ data->card.set_bias_level = mt7620_wm8960_set_bias_level; ++ ++ platform_set_drvdata(pdev, &data->card); ++ snd_soc_card_set_drvdata(&data->card, data); ++ ++ ret = devm_snd_soc_register_card(&pdev->dev, &data->card); ++ if (ret) { ++ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); ++ goto fail; ++ } ++ ++ of_node_put(i2s_np); ++ of_node_put(codec_np); ++ ++ return 0; ++fail: ++ if (i2s_np) ++ of_node_put(i2s_np); ++ if (codec_np) ++ of_node_put(codec_np); ++ ++ return ret; ++} ++ ++static int mt7620_wm8960_remove(struct platform_device *pdev) ++{ ++ return 0; ++} ++ ++static const struct of_device_id mt7620_wm8960_dt_ids[] = { ++ { .compatible = "mediatek,mt7620-audio-wm8960", }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, mt7620_wm8960_dt_ids); ++ ++static struct platform_driver mt7620_wm8960_driver = { ++ .driver = { ++ .name = "mt7620-wm8960", ++ .owner = THIS_MODULE, ++ .pm = &snd_soc_pm_ops, ++ .of_match_table = mt7620_wm8960_dt_ids, ++ }, ++ .probe = mt7620_wm8960_probe, ++ .remove = mt7620_wm8960_remove, ++}; ++module_platform_driver(mt7620_wm8960_driver); ++ ++MODULE_AUTHOR("Freescale Semiconductor, Inc."); ++MODULE_DESCRIPTION("Freescale i.MX WM8962 ASoC machine driver"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:mt7620-wm8962"); diff --git a/target/linux/ramips/patches-3.18/0056-watchdog-add-MT7621-support.patch b/target/linux/ramips/patches-3.18/0056-watchdog-add-MT7621-support.patch new file mode 100644 index 0000000..9a079d8 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0056-watchdog-add-MT7621-support.patch @@ -0,0 +1,227 @@ +From 6a42dd698ddf91b6e9902b17e21dc13c6ae412ff Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Sun, 16 Mar 2014 05:24:42 +0000 +Subject: [PATCH 56/57] watchdog: add MT7621 support + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + drivers/watchdog/Kconfig | 7 ++ + drivers/watchdog/Makefile | 1 + + drivers/watchdog/mt7621_wdt.c | 185 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 193 insertions(+) + create mode 100644 drivers/watchdog/mt7621_wdt.c + +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -1257,6 +1257,13 @@ config RALINK_WDT + help + Hardware driver for the Ralink SoC Watchdog Timer. + ++config MT7621_WDT ++ tristate "Mediatek SoC watchdog" ++ select WATCHDOG_CORE ++ depends on SOC_MT7620 || SOC_MT7621 ++ help ++ Hardware driver for the Ralink SoC Watchdog Timer. ++ + # PARISC Architecture + + # POWERPC Architecture +--- a/drivers/watchdog/Makefile ++++ b/drivers/watchdog/Makefile +@@ -143,6 +143,7 @@ obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o + octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o + obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o + obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o ++obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o + + # PARISC Architecture + +--- /dev/null ++++ b/drivers/watchdog/mt7621_wdt.c +@@ -0,0 +1,185 @@ ++/* ++ * Ralink RT288x/RT3xxx/MT76xx built-in hardware watchdog timer ++ * ++ * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2013 John Crispin <blogic@openwrt.org> ++ * ++ * This driver was based on: drivers/watchdog/softdog.c ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/clk.h> ++#include <linux/reset.h> ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/watchdog.h> ++#include <linux/miscdevice.h> ++#include <linux/moduleparam.h> ++#include <linux/platform_device.h> ++ ++#include <asm/mach-ralink/ralink_regs.h> ++ ++#define SYSC_RSTSTAT 0x38 ++#define WDT_RST_CAUSE BIT(1) ++ ++#define RALINK_WDT_TIMEOUT 30 ++ ++#define TIMER_REG_TMRSTAT 0x00 ++#define TIMER_REG_TMR1LOAD 0x24 ++#define TIMER_REG_TMR1CTL 0x20 ++ ++#define TMR1CTL_ENABLE BIT(7) ++#define TMR1CTL_RESTART BIT(9) ++ ++static void __iomem *mt762x_wdt_base; ++ ++static bool nowayout = WATCHDOG_NOWAYOUT; ++module_param(nowayout, bool, 0); ++MODULE_PARM_DESC(nowayout, ++ "Watchdog cannot be stopped once started (default=" ++ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); ++ ++static inline void rt_wdt_w32(unsigned reg, u32 val) ++{ ++ iowrite32(val, mt762x_wdt_base + reg); ++} ++ ++static inline u32 rt_wdt_r32(unsigned reg) ++{ ++ return ioread32(mt762x_wdt_base + reg); ++} ++ ++static int mt762x_wdt_ping(struct watchdog_device *w) ++{ ++ rt_wdt_w32(TIMER_REG_TMRSTAT, TMR1CTL_RESTART); ++ ++ return 0; ++} ++ ++static int mt762x_wdt_set_timeout(struct watchdog_device *w, unsigned int t) ++{ ++ w->timeout = t; ++ rt_wdt_w32(TIMER_REG_TMR1LOAD, t * 1000); ++ mt762x_wdt_ping(w); ++ ++ return 0; ++} ++ ++static int mt762x_wdt_start(struct watchdog_device *w) ++{ ++ u32 t; ++ ++ rt_wdt_w32(TIMER_REG_TMR1CTL, 1000 << 16); ++ mt762x_wdt_set_timeout(w, w->timeout); ++ ++ t = rt_wdt_r32(TIMER_REG_TMR1CTL); ++ t |= TMR1CTL_ENABLE; ++ rt_wdt_w32(TIMER_REG_TMR1CTL, t); ++ ++ return 0; ++} ++ ++static int mt762x_wdt_stop(struct watchdog_device *w) ++{ ++ u32 t; ++ ++ mt762x_wdt_ping(w); ++ ++ t = rt_wdt_r32(TIMER_REG_TMR1CTL); ++ t &= ~TMR1CTL_ENABLE; ++ rt_wdt_w32(TIMER_REG_TMR1CTL, t); ++ ++ return 0; ++} ++ ++static int mt762x_wdt_bootcause(void) ++{ ++ if (rt_sysc_r32(SYSC_RSTSTAT) & WDT_RST_CAUSE) ++ return WDIOF_CARDRESET; ++ ++ return 0; ++} ++ ++static struct watchdog_info mt762x_wdt_info = { ++ .identity = "Mediatek Watchdog", ++ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, ++}; ++ ++static struct watchdog_ops mt762x_wdt_ops = { ++ .owner = THIS_MODULE, ++ .start = mt762x_wdt_start, ++ .stop = mt762x_wdt_stop, ++ .ping = mt762x_wdt_ping, ++ .set_timeout = mt762x_wdt_set_timeout, ++}; ++ ++static struct watchdog_device mt762x_wdt_dev = { ++ .info = &mt762x_wdt_info, ++ .ops = &mt762x_wdt_ops, ++ .min_timeout = 1, ++}; ++ ++static int mt762x_wdt_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ int ret; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ mt762x_wdt_base = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(mt762x_wdt_base)) ++ return PTR_ERR(mt762x_wdt_base); ++ ++ device_reset(&pdev->dev); ++ ++ mt762x_wdt_dev.dev = &pdev->dev; ++ mt762x_wdt_dev.bootstatus = mt762x_wdt_bootcause(); ++ mt762x_wdt_dev.max_timeout = (0xfffful / 1000); ++ mt762x_wdt_dev.timeout = mt762x_wdt_dev.max_timeout; ++ ++ watchdog_set_nowayout(&mt762x_wdt_dev, nowayout); ++ ++ ret = watchdog_register_device(&mt762x_wdt_dev); ++ if (!ret) ++ dev_info(&pdev->dev, "Initialized\n"); ++ ++ return 0; ++} ++ ++static int mt762x_wdt_remove(struct platform_device *pdev) ++{ ++ watchdog_unregister_device(&mt762x_wdt_dev); ++ ++ return 0; ++} ++ ++static void mt762x_wdt_shutdown(struct platform_device *pdev) ++{ ++ mt762x_wdt_stop(&mt762x_wdt_dev); ++} ++ ++static const struct of_device_id mt762x_wdt_match[] = { ++ { .compatible = "mtk,mt7621-wdt" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mt762x_wdt_match); ++ ++static struct platform_driver mt762x_wdt_driver = { ++ .probe = mt762x_wdt_probe, ++ .remove = mt762x_wdt_remove, ++ .shutdown = mt762x_wdt_shutdown, ++ .driver = { ++ .name = KBUILD_MODNAME, ++ .owner = THIS_MODULE, ++ .of_match_table = mt762x_wdt_match, ++ }, ++}; ++ ++module_platform_driver(mt762x_wdt_driver); ++ ++MODULE_DESCRIPTION("MediaTek MT762x hardware watchdog driver"); ++MODULE_AUTHOR("John Crispin <blogic@openwrt.org"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/target/linux/ramips/patches-3.18/0057-uvc-add-iPassion-iP2970-support.patch b/target/linux/ramips/patches-3.18/0057-uvc-add-iPassion-iP2970-support.patch new file mode 100644 index 0000000..0828cc5 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0057-uvc-add-iPassion-iP2970-support.patch @@ -0,0 +1,246 @@ +From 0d3e92b4d3e2160873b610aabd46bbc4853ff82e Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Thu, 19 Sep 2013 01:50:59 +0200 +Subject: [PATCH 57/57] uvc: add iPassion iP2970 support + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + drivers/media/usb/uvc/uvc_driver.c | 14 ++++ + drivers/media/usb/uvc/uvc_status.c | 2 + + drivers/media/usb/uvc/uvc_video.c | 147 ++++++++++++++++++++++++++++++++++++ + drivers/media/usb/uvc/uvcvideo.h | 3 + + 4 files changed, 166 insertions(+) + +--- a/drivers/media/usb/uvc/uvc_driver.c ++++ b/drivers/media/usb/uvc/uvc_driver.c +@@ -2504,6 +2504,20 @@ static struct usb_device_id uvc_ids[] = + .bInterfaceProtocol = 0, + .driver_info = UVC_QUIRK_PROBE_MINMAX + | UVC_QUIRK_IGNORE_SELECTOR_UNIT }, ++ ++/* iPassion iP2970 */ ++ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE ++ | USB_DEVICE_ID_MATCH_INT_INFO, ++ .idVendor = 0x1B3B, ++ .idProduct = 0x2970, ++ .bInterfaceClass = USB_CLASS_VIDEO, ++ .bInterfaceSubClass = 1, ++ .bInterfaceProtocol = 0, ++ .driver_info = UVC_QUIRK_PROBE_MINMAX ++ | UVC_QUIRK_STREAM_NO_FID ++ | UVC_QUIRK_MOTION ++ | UVC_QUIRK_SINGLE_ISO }, ++ + /* Generic USB Video Class */ + { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, + {} +--- a/drivers/media/usb/uvc/uvc_status.c ++++ b/drivers/media/usb/uvc/uvc_status.c +@@ -139,6 +139,7 @@ static void uvc_status_complete(struct u + switch (dev->status[0] & 0x0f) { + case UVC_STATUS_TYPE_CONTROL: + uvc_event_control(dev, dev->status, len); ++ dev->motion = 1; + break; + + case UVC_STATUS_TYPE_STREAMING: +@@ -182,6 +183,7 @@ int uvc_status_init(struct uvc_device *d + } + + pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress); ++ dev->motion = 0; + + /* For high-speed interrupt endpoints, the bInterval value is used as + * an exponent of two. Some developers forgot about it. +--- a/drivers/media/usb/uvc/uvc_video.c ++++ b/drivers/media/usb/uvc/uvc_video.c +@@ -21,6 +21,11 @@ + #include <linux/wait.h> + #include <linux/atomic.h> + #include <asm/unaligned.h> ++#include <linux/skbuff.h> ++#include <linux/kobject.h> ++#include <linux/netlink.h> ++#include <linux/kobject.h> ++#include <linux/workqueue.h> + + #include <media/v4l2-common.h> + +@@ -1080,9 +1085,149 @@ static void uvc_video_decode_data(struct + } + } + ++struct bh_priv { ++ unsigned long seen; ++}; ++ ++struct bh_event { ++ const char *name; ++ struct sk_buff *skb; ++ struct work_struct work; ++}; ++ ++#define BH_ERR(fmt, args...) printk(KERN_ERR "%s: " fmt, "webcam", ##args ) ++#define BH_DBG(fmt, args...) do {} while (0) ++#define BH_SKB_SIZE 2048 ++ ++extern u64 uevent_next_seqnum(void); ++static int seen = 0; ++ ++static int bh_event_add_var(struct bh_event *event, int argv, ++ const char *format, ...) ++{ ++ static char buf[128]; ++ char *s; ++ va_list args; ++ int len; ++ ++ if (argv) ++ return 0; ++ ++ va_start(args, format); ++ len = vsnprintf(buf, sizeof(buf), format, args); ++ va_end(args); ++ ++ if (len >= sizeof(buf)) { ++ BH_ERR("buffer size too small\n"); ++ WARN_ON(1); ++ return -ENOMEM; ++ } ++ ++ s = skb_put(event->skb, len + 1); ++ strcpy(s, buf); ++ ++ BH_DBG("added variable '%s'\n", s); ++ ++ return 0; ++} ++ ++static int motion_hotplug_fill_event(struct bh_event *event) ++{ ++ int s = jiffies; ++ int ret; ++ ++ if (!seen) ++ seen = jiffies; ++ ++ ret = bh_event_add_var(event, 0, "HOME=%s", "/"); ++ if (ret) ++ return ret; ++ ++ ret = bh_event_add_var(event, 0, "PATH=%s", ++ "/sbin:/bin:/usr/sbin:/usr/bin"); ++ if (ret) ++ return ret; ++ ++ ret = bh_event_add_var(event, 0, "SUBSYSTEM=usb"); ++ if (ret) ++ return ret; ++ ++ ret = bh_event_add_var(event, 0, "ACTION=motion"); ++ if (ret) ++ return ret; ++ ++ ret = bh_event_add_var(event, 0, "SEEN=%d", s - seen); ++ if (ret) ++ return ret; ++ seen = s; ++ ++ ret = bh_event_add_var(event, 0, "SEQNUM=%llu", uevent_next_seqnum()); ++ ++ return ret; ++} ++ ++static void motion_hotplug_work(struct work_struct *work) ++{ ++ struct bh_event *event = container_of(work, struct bh_event, work); ++ int ret = 0; ++ ++ event->skb = alloc_skb(BH_SKB_SIZE, GFP_KERNEL); ++ if (!event->skb) ++ goto out_free_event; ++ ++ ret = bh_event_add_var(event, 0, "%s@", "add"); ++ if (ret) ++ goto out_free_skb; ++ ++ ret = motion_hotplug_fill_event(event); ++ if (ret) ++ goto out_free_skb; ++ ++ NETLINK_CB(event->skb).dst_group = 1; ++ broadcast_uevent(event->skb, 0, 1, GFP_KERNEL); ++ ++out_free_skb: ++ if (ret) { ++ BH_ERR("work error %d\n", ret); ++ kfree_skb(event->skb); ++ } ++out_free_event: ++ kfree(event); ++} ++ ++static int motion_hotplug_create_event(void) ++{ ++ struct bh_event *event; ++ ++ event = kzalloc(sizeof(*event), GFP_KERNEL); ++ if (!event) ++ return -ENOMEM; ++ ++ event->name = "motion"; ++ ++ INIT_WORK(&event->work, (void *)(void *)motion_hotplug_work); ++ schedule_work(&event->work); ++ ++ return 0; ++} ++ ++#define MOTION_FLAG_OFFSET 4 + static void uvc_video_decode_end(struct uvc_streaming *stream, + struct uvc_buffer *buf, const __u8 *data, int len) + { ++ if ((stream->dev->quirks & UVC_QUIRK_MOTION) && ++ (data[len - 2] == 0xff) && (data[len - 1] == 0xd9)) { ++ u8 *mem; ++ buf->state = UVC_BUF_STATE_READY; ++ mem = (u8 *) (buf->mem + MOTION_FLAG_OFFSET); ++ if ( stream->dev->motion ) { ++ stream->dev->motion = 0; ++ motion_hotplug_create_event(); ++ } else { ++ *mem &= 0x7f; ++ } ++ } ++ + /* Mark the buffer as done if the EOF marker is set. */ + if (data[1] & UVC_STREAM_EOF && buf->bytesused != 0) { + uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n"); +@@ -1495,6 +1640,8 @@ static int uvc_init_video_isoc(struct uv + if (npackets == 0) + return -ENOMEM; + ++ if (stream->dev->quirks & UVC_QUIRK_SINGLE_ISO) ++ npackets = 1; + size = npackets * psize; + + for (i = 0; i < UVC_URBS; ++i) { +--- a/drivers/media/usb/uvc/uvcvideo.h ++++ b/drivers/media/usb/uvc/uvcvideo.h +@@ -148,6 +148,8 @@ + #define UVC_QUIRK_PROBE_DEF 0x00000100 + #define UVC_QUIRK_RESTRICT_FRAME_RATE 0x00000200 + #define UVC_QUIRK_RESTORE_CTRLS_ON_INIT 0x00000400 ++#define UVC_QUIRK_MOTION 0x00000800 ++#define UVC_QUIRK_SINGLE_ISO 0x00001000 + + /* Format flags */ + #define UVC_FMT_FLAG_COMPRESSED 0x00000001 +@@ -551,6 +553,7 @@ struct uvc_device { + __u8 *status; + struct input_dev *input; + char input_phys[64]; ++ int motion; + }; + + enum uvc_handle_state { diff --git a/target/linux/ramips/patches-3.18/0059-USB-fix-dwc2.patch b/target/linux/ramips/patches-3.18/0059-USB-fix-dwc2.patch new file mode 100644 index 0000000..92e4dc0 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0059-USB-fix-dwc2.patch @@ -0,0 +1,19 @@ +--- a/drivers/usb/dwc2/hcd.c ++++ b/drivers/usb/dwc2/hcd.c +@@ -47,6 +47,7 @@ + #include <linux/io.h> + #include <linux/slab.h> + #include <linux/usb.h> ++#include <linux/reset.h> + + #include <linux/usb/hcd.h> + #include <linux/usb/ch11.h> +@@ -2780,6 +2781,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hso + + dev_dbg(hsotg->dev, "DWC OTG HCD INIT\n"); + ++ device_reset(hsotg->dev); ++ + /* Detect config values from hardware */ + retval = dwc2_get_hwparams(hsotg); + diff --git a/target/linux/ramips/patches-3.18/0060-soc_type.patch b/target/linux/ramips/patches-3.18/0060-soc_type.patch new file mode 100644 index 0000000..41cc120 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0060-soc_type.patch @@ -0,0 +1,229 @@ +--- a/arch/mips/include/asm/mach-ralink/mt7620.h ++++ b/arch/mips/include/asm/mach-ralink/mt7620.h +@@ -13,14 +13,6 @@ + #ifndef _MT7620_REGS_H_ + #define _MT7620_REGS_H_ + +-enum mt762x_soc_type { +- MT762X_SOC_UNKNOWN = 0, +- MT762X_SOC_MT7620A, +- MT762X_SOC_MT7620N, +- MT762X_SOC_MT7628AN, +-}; +-extern enum mt762x_soc_type mt762x_soc; +- + #define MT7620_SYSC_BASE 0x10000000 + + #define SYSC_REG_CHIP_NAME0 0x00 +--- a/arch/mips/include/asm/mach-ralink/ralink_regs.h ++++ b/arch/mips/include/asm/mach-ralink/ralink_regs.h +@@ -13,6 +13,20 @@ + #ifndef _RALINK_REGS_H_ + #define _RALINK_REGS_H_ + ++enum ralink_soc_type { ++ RALINK_UNKNOWN = 0, ++ RT305X_SOC_RT3050, ++ RT305X_SOC_RT3052, ++ RT305X_SOC_RT3350, ++ RT305X_SOC_RT3352, ++ RT305X_SOC_RT5350, ++ MT762X_SOC_MT7620A, ++ MT762X_SOC_MT7620N, ++ MT762X_SOC_MT7621AT, ++ MT762X_SOC_MT7628AN, ++}; ++extern enum ralink_soc_type ralink_soc; ++ + extern __iomem void *rt_sysc_membase; + extern __iomem void *rt_memc_membase; + +--- a/arch/mips/include/asm/mach-ralink/rt305x.h ++++ b/arch/mips/include/asm/mach-ralink/rt305x.h +@@ -13,25 +13,16 @@ + #ifndef _RT305X_REGS_H_ + #define _RT305X_REGS_H_ + +-enum rt305x_soc_type { +- RT305X_SOC_UNKNOWN = 0, +- RT305X_SOC_RT3050, +- RT305X_SOC_RT3052, +- RT305X_SOC_RT3350, +- RT305X_SOC_RT3352, +- RT305X_SOC_RT5350, +-}; +- +-extern enum rt305x_soc_type rt305x_soc; ++extern enum ralink_soc_type ralink_soc; + + static inline int soc_is_rt3050(void) + { +- return rt305x_soc == RT305X_SOC_RT3050; ++ return ralink_soc == RT305X_SOC_RT3050; + } + + static inline int soc_is_rt3052(void) + { +- return rt305x_soc == RT305X_SOC_RT3052; ++ return ralink_soc == RT305X_SOC_RT3052; + } + + static inline int soc_is_rt305x(void) +@@ -41,17 +32,17 @@ static inline int soc_is_rt305x(void) + + static inline int soc_is_rt3350(void) + { +- return rt305x_soc == RT305X_SOC_RT3350; ++ return ralink_soc == RT305X_SOC_RT3350; + } + + static inline int soc_is_rt3352(void) + { +- return rt305x_soc == RT305X_SOC_RT3352; ++ return ralink_soc == RT305X_SOC_RT3352; + } + + static inline int soc_is_rt5350(void) + { +- return rt305x_soc == RT305X_SOC_RT5350; ++ return ralink_soc == RT305X_SOC_RT5350; + } + + #define RT305X_SYSC_BASE 0x10000000 +--- a/arch/mips/ralink/mt7620.c ++++ b/arch/mips/ralink/mt7620.c +@@ -43,8 +43,6 @@ + #define CLKCFG_FFRAC_MASK 0x001f + #define CLKCFG_FFRAC_USB_VAL 0x0003 + +-enum mt762x_soc_type mt762x_soc; +- + /* does the board have sdram or ddram */ + static int dram_type; + +@@ -375,7 +373,7 @@ void __init ralink_clk_init(void) + #define RINT(x) ((x) / 1000000) + #define RFRAC(x) (((x) / 1000) % 1000) + +- if (mt762x_soc == MT762X_SOC_MT7628AN) { ++ if (ralink_soc == MT762X_SOC_MT7628AN) { + if (xtal_rate == MHZ(40)) + cpu_rate = MHZ(580); + else +@@ -420,7 +418,7 @@ void __init ralink_clk_init(void) + ralink_clk_add("10000e00.uart2", periph_rate); + ralink_clk_add("10180000.wmac", xtal_rate); + +- if (IS_ENABLED(CONFIG_USB) && mt762x_soc != MT762X_SOC_MT7628AN) { ++ if (IS_ENABLED(CONFIG_USB) && ralink_soc != MT762X_SOC_MT7628AN) { + /* + * When the CPU goes into sleep mode, the BUS clock will be too low for + * USB to function properly +@@ -508,11 +506,11 @@ void prom_soc_init(struct ralink_soc_inf + + if (n0 == MT7620_CHIP_NAME0 && n1 == MT7620_CHIP_NAME1) { + if (bga) { +- mt762x_soc = MT762X_SOC_MT7620A; ++ ralink_soc = MT762X_SOC_MT7620A; + name = "MT7620A"; + soc_info->compatible = "ralink,mt7620a-soc"; + } else { +- mt762x_soc = MT762X_SOC_MT7620N; ++ ralink_soc = MT762X_SOC_MT7620N; + name = "MT7620N"; + soc_info->compatible = "ralink,mt7620n-soc"; + #ifdef CONFIG_PCI +@@ -520,7 +518,7 @@ void prom_soc_init(struct ralink_soc_inf + #endif + } + } else if (n0 == MT7620_CHIP_NAME0 && n1 == MT7628_CHIP_NAME1) { +- mt762x_soc = MT762X_SOC_MT7628AN; ++ ralink_soc = MT762X_SOC_MT7628AN; + name = "MT7628AN"; + soc_info->compatible = "ralink,mt7628an-soc"; + } else { +@@ -537,7 +535,7 @@ void prom_soc_init(struct ralink_soc_inf + dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK; + + soc_info->mem_base = MT7620_DRAM_BASE; +- if (mt762x_soc == MT762X_SOC_MT7628AN) ++ if (ralink_soc == MT762X_SOC_MT7628AN) + mt7628_dram_init(soc_info); + else + mt7620_dram_init(soc_info); +@@ -550,7 +548,7 @@ void prom_soc_init(struct ralink_soc_inf + pr_info("Digital PMU set to %s control\n", + (pmu1 & DIG_SW_SEL) ? ("sw") : ("hw")); + +- if (mt762x_soc == MT762X_SOC_MT7628AN) ++ if (ralink_soc == MT762X_SOC_MT7628AN) + rt2880_pinmux_data = mt7628an_pinmux_data; + else + rt2880_pinmux_data = mt7620a_pinmux_data; +--- a/arch/mips/ralink/rt305x.c ++++ b/arch/mips/ralink/rt305x.c +@@ -21,8 +21,6 @@ + + #include "common.h" + +-enum rt305x_soc_type rt305x_soc; +- + static struct rt2880_pmx_func i2c_func[] = { FUNC("i2c", 0, 1, 2) }; + static struct rt2880_pmx_func spi_func[] = { FUNC("spi", 0, 3, 4) }; + static struct rt2880_pmx_func uartf_func[] = { +@@ -234,24 +232,24 @@ void prom_soc_init(struct ralink_soc_inf + + icache_sets = (read_c0_config1() >> 22) & 7; + if (icache_sets == 1) { +- rt305x_soc = RT305X_SOC_RT3050; ++ ralink_soc = RT305X_SOC_RT3050; + name = "RT3050"; + soc_info->compatible = "ralink,rt3050-soc"; + } else { +- rt305x_soc = RT305X_SOC_RT3052; ++ ralink_soc = RT305X_SOC_RT3052; + name = "RT3052"; + soc_info->compatible = "ralink,rt3052-soc"; + } + } else if (n0 == RT3350_CHIP_NAME0 && n1 == RT3350_CHIP_NAME1) { +- rt305x_soc = RT305X_SOC_RT3350; ++ ralink_soc = RT305X_SOC_RT3350; + name = "RT3350"; + soc_info->compatible = "ralink,rt3350-soc"; + } else if (n0 == RT3352_CHIP_NAME0 && n1 == RT3352_CHIP_NAME1) { +- rt305x_soc = RT305X_SOC_RT3352; ++ ralink_soc = RT305X_SOC_RT3352; + name = "RT3352"; + soc_info->compatible = "ralink,rt3352-soc"; + } else if (n0 == RT5350_CHIP_NAME0 && n1 == RT5350_CHIP_NAME1) { +- rt305x_soc = RT305X_SOC_RT5350; ++ ralink_soc = RT305X_SOC_RT5350; + name = "RT5350"; + soc_info->compatible = "ralink,rt5350-soc"; + } else { +--- a/arch/mips/ralink/prom.c ++++ b/arch/mips/ralink/prom.c +@@ -15,9 +15,13 @@ + #include <asm/bootinfo.h> + #include <asm/addrspace.h> + ++#include <asm/mach-ralink/ralink_regs.h> ++ + #include "common.h" + + struct ralink_soc_info soc_info; ++enum ralink_soc_type ralink_soc; ++EXPORT_SYMBOL_GPL(ralink_soc); + + const char *get_system_type(void) + { +--- a/arch/mips/ralink/mt7621.c ++++ b/arch/mips/ralink/mt7621.c +@@ -193,6 +193,7 @@ void prom_soc_init(struct ralink_soc_inf + soc_info->mem_size_min = MT7621_DDR2_SIZE_MIN; + soc_info->mem_size_max = MT7621_DDR2_SIZE_MAX; + soc_info->mem_base = MT7621_DRAM_BASE; ++ ralink_soc = MT762X_SOC_MT7621AT; + + rt2880_pinmux_data = mt7621_pinmux_data; + diff --git a/target/linux/ramips/patches-3.18/0061-SPI-ralink-add-mt7621-SoC-spi-driver.patch b/target/linux/ramips/patches-3.18/0061-SPI-ralink-add-mt7621-SoC-spi-driver.patch new file mode 100644 index 0000000..5aa119e --- /dev/null +++ b/target/linux/ramips/patches-3.18/0061-SPI-ralink-add-mt7621-SoC-spi-driver.patch @@ -0,0 +1,508 @@ +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -439,6 +439,12 @@ config SPI_RT2880 + help + This selects a driver for the Ralink RT288x/RT305x SPI Controller. + ++config SPI_MT7621 ++ tristate "MediaTek MT7621 SPI Controller" ++ depends on RALINK ++ help ++ This selects a driver for the MediaTek MT7621 SPI Controller. ++ + config SPI_S3C24XX + tristate "Samsung S3C24XX series SPI" + depends on ARCH_S3C24XX +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -46,6 +46,7 @@ obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70l + obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o + obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o + obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o ++obj-$(CONFIG_SPI_MT7621) += spi-mt7621.o + obj-$(CONFIG_SPI_MXS) += spi-mxs.o + obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o + obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o +--- /dev/null ++++ b/drivers/spi/spi-mt7621.c +@@ -0,0 +1,480 @@ ++/* ++ * spi-mt7621.c -- MediaTek MT7621 SPI controller driver ++ * ++ * Copyright (C) 2011 Sergiy <piratfm@gmail.com> ++ * Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2014-2015 Felix Fietkau <nbd@openwrt.org> ++ * ++ * Some parts are based on spi-orion.c: ++ * Author: Shadi Ammouri <shadi@marvell.com> ++ * Copyright (C) 2007-2008 Marvell Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/clk.h> ++#include <linux/err.h> ++#include <linux/delay.h> ++#include <linux/io.h> ++#include <linux/reset.h> ++#include <linux/spi/spi.h> ++#include <linux/of_device.h> ++#include <linux/platform_device.h> ++#include <linux/swab.h> ++ ++#include <ralink_regs.h> ++ ++#define SPI_BPW_MASK(bits) BIT((bits) - 1) ++ ++#define DRIVER_NAME "spi-mt7621" ++/* in usec */ ++#define RALINK_SPI_WAIT_MAX_LOOP 2000 ++ ++/* SPISTAT register bit field */ ++#define SPISTAT_BUSY BIT(0) ++ ++#define MT7621_SPI_TRANS 0x00 ++#define SPITRANS_BUSY BIT(16) ++ ++#define MT7621_SPI_OPCODE 0x04 ++#define MT7621_SPI_DATA0 0x08 ++#define MT7621_SPI_DATA4 0x18 ++#define SPI_CTL_TX_RX_CNT_MASK 0xff ++#define SPI_CTL_START BIT(8) ++ ++#define MT7621_SPI_POLAR 0x38 ++#define MT7621_SPI_MASTER 0x28 ++#define MT7621_SPI_MOREBUF 0x2c ++#define MT7621_SPI_SPACE 0x3c ++ ++#define MT7621_CPHA BIT(5) ++#define MT7621_CPOL BIT(4) ++#define MT7621_LSB_FIRST BIT(3) ++ ++#define RT2880_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH) ++ ++struct mt7621_spi; ++ ++struct mt7621_spi { ++ struct spi_master *master; ++ void __iomem *base; ++ unsigned int sys_freq; ++ unsigned int speed; ++ struct clk *clk; ++ spinlock_t lock; ++ ++ struct mt7621_spi_ops *ops; ++}; ++ ++static inline struct mt7621_spi *spidev_to_mt7621_spi(struct spi_device *spi) ++{ ++ return spi_master_get_devdata(spi->master); ++} ++ ++static inline u32 mt7621_spi_read(struct mt7621_spi *rs, u32 reg) ++{ ++ return ioread32(rs->base + reg); ++} ++ ++static inline void mt7621_spi_write(struct mt7621_spi *rs, u32 reg, u32 val) ++{ ++ iowrite32(val, rs->base + reg); ++} ++ ++static void mt7621_spi_reset(struct mt7621_spi *rs, int duplex) ++{ ++ u32 master = mt7621_spi_read(rs, MT7621_SPI_MASTER); ++ ++ master |= 7 << 29; ++ master |= 1 << 2; ++ if (duplex) ++ master |= 1 << 10; ++ else ++ master &= ~(1 << 10); ++ ++ mt7621_spi_write(rs, MT7621_SPI_MASTER, master); ++} ++ ++static void mt7621_spi_set_cs(struct spi_device *spi, int enable) ++{ ++ struct mt7621_spi *rs = spidev_to_mt7621_spi(spi); ++ int cs = spi->chip_select; ++ u32 polar = 0; ++ ++ mt7621_spi_reset(rs, cs); ++ if (enable) ++ polar = BIT(cs); ++ mt7621_spi_write(rs, MT7621_SPI_POLAR, polar); ++} ++ ++static int mt7621_spi_prepare(struct spi_device *spi, unsigned int speed) ++{ ++ struct mt7621_spi *rs = spidev_to_mt7621_spi(spi); ++ u32 rate; ++ u32 reg; ++ ++ dev_dbg(&spi->dev, "speed:%u\n", speed); ++ ++ rate = DIV_ROUND_UP(rs->sys_freq, speed); ++ dev_dbg(&spi->dev, "rate-1:%u\n", rate); ++ ++ if (rate > 4097) ++ return -EINVAL; ++ ++ if (rate < 2) ++ rate = 2; ++ ++ reg = mt7621_spi_read(rs, MT7621_SPI_MASTER); ++ reg &= ~(0xfff << 16); ++ reg |= (rate - 2) << 16; ++ rs->speed = speed; ++ ++ reg &= ~MT7621_LSB_FIRST; ++ if (spi->mode & SPI_LSB_FIRST) ++ reg |= MT7621_LSB_FIRST; ++ ++ reg &= ~(MT7621_CPHA | MT7621_CPOL); ++ switch(spi->mode & (SPI_CPOL | SPI_CPHA)) { ++ case SPI_MODE_0: ++ break; ++ case SPI_MODE_1: ++ reg |= MT7621_CPHA; ++ break; ++ case SPI_MODE_2: ++ reg |= MT7621_CPOL; ++ break; ++ case SPI_MODE_3: ++ reg |= MT7621_CPOL | MT7621_CPHA; ++ break; ++ } ++ mt7621_spi_write(rs, MT7621_SPI_MASTER, reg); ++ ++ return 0; ++} ++ ++static inline int mt7621_spi_wait_till_ready(struct spi_device *spi) ++{ ++ struct mt7621_spi *rs = spidev_to_mt7621_spi(spi); ++ int i; ++ ++ for (i = 0; i < RALINK_SPI_WAIT_MAX_LOOP; i++) { ++ u32 status; ++ ++ status = mt7621_spi_read(rs, MT7621_SPI_TRANS); ++ if ((status & SPITRANS_BUSY) == 0) { ++ return 0; ++ } ++ cpu_relax(); ++ udelay(1); ++ } ++ ++ return -ETIMEDOUT; ++} ++ ++static int mt7621_spi_transfer_half_duplex(struct spi_master *master, ++ struct spi_message *m) ++{ ++ struct mt7621_spi *rs = spi_master_get_devdata(master); ++ struct spi_device *spi = m->spi; ++ unsigned int speed = spi->max_speed_hz; ++ struct spi_transfer *t = NULL; ++ int status = 0; ++ int i, len = 0; ++ int rx_len = 0; ++ u32 data[9] = { 0 }; ++ u32 val; ++ ++ mt7621_spi_wait_till_ready(spi); ++ ++ list_for_each_entry(t, &m->transfers, transfer_list) { ++ const u8 *buf = t->tx_buf; ++ ++ if (t->rx_buf) ++ rx_len += t->len; ++ ++ if (!buf) ++ continue; ++ ++ if (WARN_ON(len + t->len > 36)) { ++ status = -EIO; ++ goto msg_done; ++ } ++ ++ for (i = 0; i < t->len; i++, len++) ++ data[len / 4] |= buf[i] << (8 * (len & 3)); ++ } ++ ++ if (WARN_ON(rx_len > 32)) { ++ status = -EIO; ++ goto msg_done; ++ } ++ ++ if (mt7621_spi_prepare(spi, speed)) { ++ status = -EIO; ++ goto msg_done; ++ } ++ data[0] = swab32(data[0]); ++ if (len < 4) ++ data[0] >>= (4 - len) * 8; ++ ++ for (i = 0; i < len; i += 4) ++ mt7621_spi_write(rs, MT7621_SPI_OPCODE + i, data[i / 4]); ++ ++ val = (min_t(int, len, 4) * 8) << 24; ++ if (len > 4) ++ val |= (len - 4) * 8; ++ val |= (rx_len * 8) << 12; ++ mt7621_spi_write(rs, MT7621_SPI_MOREBUF, val); ++ ++ mt7621_spi_set_cs(spi, 1); ++ ++ val = mt7621_spi_read(rs, MT7621_SPI_TRANS); ++ val |= SPI_CTL_START; ++ mt7621_spi_write(rs, MT7621_SPI_TRANS, val); ++ ++ mt7621_spi_wait_till_ready(spi); ++ ++ mt7621_spi_set_cs(spi, 0); ++ ++ for (i = 0; i < rx_len; i += 4) ++ data[i / 4] = mt7621_spi_read(rs, MT7621_SPI_DATA0 + i); ++ ++ m->actual_length = len + rx_len; ++ ++ len = 0; ++ list_for_each_entry(t, &m->transfers, transfer_list) { ++ u8 *buf = t->rx_buf; ++ ++ if (!buf) ++ continue; ++ ++ for (i = 0; i < t->len; i++, len++) ++ buf[i] = data[len / 4] >> (8 * (len & 3)); ++ } ++ ++msg_done: ++ m->status = status; ++ spi_finalize_current_message(master); ++ ++ return 0; ++} ++ ++static int mt7621_spi_transfer_full_duplex(struct spi_master *master, ++ struct spi_message *m) ++{ ++ struct mt7621_spi *rs = spi_master_get_devdata(master); ++ struct spi_device *spi = m->spi; ++ unsigned int speed = spi->max_speed_hz; ++ struct spi_transfer *t = NULL; ++ int status = 0; ++ int i, len = 0; ++ int rx_len = 0; ++ u32 data[9] = { 0 }; ++ u32 val = 0; ++ ++ mt7621_spi_wait_till_ready(spi); ++ ++ list_for_each_entry(t, &m->transfers, transfer_list) { ++ const u8 *buf = t->tx_buf; ++ ++ if (t->rx_buf) ++ rx_len += t->len; ++ ++ if (!buf) ++ continue; ++ ++ if (WARN_ON(len + t->len > 16)) { ++ status = -EIO; ++ goto msg_done; ++ } ++ ++ for (i = 0; i < t->len; i++, len++) ++ data[len / 4] |= buf[i] << (8 * (len & 3)); ++ if (speed > t->speed_hz) ++ speed = t->speed_hz; ++ } ++ ++ if (WARN_ON(rx_len > 16)) { ++ status = -EIO; ++ goto msg_done; ++ } ++ ++ if (mt7621_spi_prepare(spi, speed)) { ++ status = -EIO; ++ goto msg_done; ++ } ++ ++ for (i = 0; i < len; i += 4) ++ mt7621_spi_write(rs, MT7621_SPI_DATA0 + i, data[i / 4]); ++ ++ val |= len * 8; ++ val |= (rx_len * 8) << 12; ++ mt7621_spi_write(rs, MT7621_SPI_MOREBUF, val); ++ ++ mt7621_spi_set_cs(spi, 1); ++ ++ val = mt7621_spi_read(rs, MT7621_SPI_TRANS); ++ val |= SPI_CTL_START; ++ mt7621_spi_write(rs, MT7621_SPI_TRANS, val); ++ ++ mt7621_spi_wait_till_ready(spi); ++ ++ mt7621_spi_set_cs(spi, 0); ++ ++ for (i = 0; i < rx_len; i += 4) ++ data[i / 4] = mt7621_spi_read(rs, MT7621_SPI_DATA4 + i); ++ ++ m->actual_length = rx_len; ++ ++ len = 0; ++ list_for_each_entry(t, &m->transfers, transfer_list) { ++ u8 *buf = t->rx_buf; ++ ++ if (!buf) ++ continue; ++ ++ for (i = 0; i < t->len; i++, len++) ++ buf[i] = data[len / 4] >> (8 * (len & 3)); ++ } ++ ++msg_done: ++ m->status = status; ++ spi_finalize_current_message(master); ++ ++ return 0; ++} ++ ++static int mt7621_spi_transfer_one_message(struct spi_master *master, ++ struct spi_message *m) ++{ ++ struct spi_device *spi = m->spi; ++ int cs = spi->chip_select; ++ ++ if (cs) ++ return mt7621_spi_transfer_full_duplex(master, m); ++ return mt7621_spi_transfer_half_duplex(master, m); ++} ++ ++static int mt7621_spi_setup(struct spi_device *spi) ++{ ++ struct mt7621_spi *rs = spidev_to_mt7621_spi(spi); ++ ++ if ((spi->max_speed_hz == 0) || ++ (spi->max_speed_hz > (rs->sys_freq / 2))) ++ spi->max_speed_hz = (rs->sys_freq / 2); ++ ++ if (spi->max_speed_hz < (rs->sys_freq / 4097)) { ++ dev_err(&spi->dev, "setup: requested speed is too low %d Hz\n", ++ spi->max_speed_hz); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id mt7621_spi_match[] = { ++ { .compatible = "ralink,mt7621-spi" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, mt7621_spi_match); ++ ++static int mt7621_spi_probe(struct platform_device *pdev) ++{ ++ const struct of_device_id *match; ++ struct spi_master *master; ++ struct mt7621_spi *rs; ++ unsigned long flags; ++ void __iomem *base; ++ struct resource *r; ++ int status = 0; ++ struct clk *clk; ++ struct mt7621_spi_ops *ops; ++ ++ match = of_match_device(mt7621_spi_match, &pdev->dev); ++ if (!match) ++ return -EINVAL; ++ ops = (struct mt7621_spi_ops *)match->data; ++ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ base = devm_ioremap_resource(&pdev->dev, r); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ clk = devm_clk_get(&pdev->dev, NULL); ++ if (IS_ERR(clk)) { ++ dev_err(&pdev->dev, "unable to get SYS clock, err=%d\n", ++ status); ++ return PTR_ERR(clk); ++ } ++ ++ status = clk_prepare_enable(clk); ++ if (status) ++ return status; ++ ++ master = spi_alloc_master(&pdev->dev, sizeof(*rs)); ++ if (master == NULL) { ++ dev_info(&pdev->dev, "master allocation failed\n"); ++ return -ENOMEM; ++ } ++ ++ master->mode_bits = RT2880_SPI_MODE_BITS; ++ ++ master->setup = mt7621_spi_setup; ++ master->transfer_one_message = mt7621_spi_transfer_one_message; ++ master->bits_per_word_mask = SPI_BPW_MASK(8); ++ master->dev.of_node = pdev->dev.of_node; ++ master->num_chipselect = 2; ++ ++ dev_set_drvdata(&pdev->dev, master); ++ ++ rs = spi_master_get_devdata(master); ++ rs->base = base; ++ rs->clk = clk; ++ rs->master = master; ++ rs->sys_freq = clk_get_rate(rs->clk); ++ rs->ops = ops; ++ dev_info(&pdev->dev, "sys_freq: %u\n", rs->sys_freq); ++ spin_lock_irqsave(&rs->lock, flags); ++ ++ device_reset(&pdev->dev); ++ ++ mt7621_spi_reset(rs, 0); ++ ++ return spi_register_master(master); ++} ++ ++static int mt7621_spi_remove(struct platform_device *pdev) ++{ ++ struct spi_master *master; ++ struct mt7621_spi *rs; ++ ++ master = dev_get_drvdata(&pdev->dev); ++ rs = spi_master_get_devdata(master); ++ ++ clk_disable(rs->clk); ++ spi_unregister_master(master); ++ ++ return 0; ++} ++ ++MODULE_ALIAS("platform:" DRIVER_NAME); ++ ++static struct platform_driver mt7621_spi_driver = { ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ .of_match_table = mt7621_spi_match, ++ }, ++ .probe = mt7621_spi_probe, ++ .remove = mt7621_spi_remove, ++}; ++ ++module_platform_driver(mt7621_spi_driver); ++ ++MODULE_DESCRIPTION("MT7621 SPI driver"); ++MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>"); ++MODULE_LICENSE("GPL"); diff --git a/target/linux/ramips/patches-3.18/0062-mt7621-add-ECHI-OCHI-XCHI-support.patch b/target/linux/ramips/patches-3.18/0062-mt7621-add-ECHI-OCHI-XCHI-support.patch new file mode 100644 index 0000000..f407578 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0062-mt7621-add-ECHI-OCHI-XCHI-support.patch @@ -0,0 +1,5706 @@ +--- a/drivers/usb/core/hcd-pci.c ++++ b/drivers/usb/core/hcd-pci.c +@@ -214,8 +214,13 @@ int usb_hcd_pci_probe(struct pci_dev *de + goto disable_pci; + } + ++ ++#ifdef CONFIG_USB_MT7621_XHCI_PLATFORM ++ hcd->amd_resume_bug = 0; ++#else + hcd->amd_resume_bug = (usb_hcd_amd_remote_wakeup_quirk(dev) && + driver->flags & (HCD_USB11 | HCD_USB3)) ? 1 : 0; ++#endif + + if (driver->flags & HCD_MEMORY) { + /* EHCI, OHCI */ +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -1286,7 +1286,7 @@ static void hub_quiesce(struct usb_hub * + if (type != HUB_SUSPEND) { + /* Disconnect all the children */ + for (i = 0; i < hdev->maxchild; ++i) { +- if (hub->ports[i]->child) ++ if (hub->ports[i] && hub->ports[i]->child) + usb_disconnect(&hub->ports[i]->child); + } + } +--- a/drivers/usb/core/port.c ++++ b/drivers/usb/core/port.c +@@ -480,8 +480,10 @@ void usb_hub_remove_port_device(struct u + struct usb_port *port_dev = hub->ports[port1 - 1]; + struct usb_port *peer; + +- peer = port_dev->peer; +- if (peer) +- unlink_peers(port_dev, peer); +- device_unregister(&port_dev->dev); ++ if(port_dev) { ++ peer = port_dev->peer; ++ if (peer) ++ unlink_peers(port_dev, peer); ++ device_unregister(&port_dev->dev); ++ } + } +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -41,6 +41,13 @@ config USB_XHCI_PLATFORM + + If unsure, say N. + ++config USB_MT7621_XHCI_PLATFORM ++ bool ++ depends on USB_XHCI_PLATFORM ++ depends on SOC_MT7621 ++ select USB_PHY ++ default y ++ + config USB_XHCI_MVEBU + tristate "xHCI support for Marvell Armada 375/38x" + select USB_XHCI_PLATFORM +@@ -596,7 +603,7 @@ endif # USB_OHCI_HCD + + config USB_UHCI_HCD + tristate "UHCI HCD (most Intel and VIA) support" +- depends on PCI || USB_UHCI_SUPPORT_NON_PCI_HC ++ depends on BROKEN && (PCI || USB_UHCI_SUPPORT_NON_PCI_HC) + ---help--- + The Universal Host Controller Interface is a standard by Intel for + accessing the USB hardware in the PC (which is also called the USB +--- a/drivers/usb/host/Makefile ++++ b/drivers/usb/host/Makefile +@@ -16,7 +16,12 @@ xhci-hcd-y := xhci.o xhci-mem.o + xhci-hcd-y += xhci-ring.o xhci-hub.o xhci-dbg.o + xhci-hcd-y += xhci-trace.o + ++ifdef CONFIG_USB_MT7621_XHCI_PLATFORM ++xhci-hcd-y += mtk-phy.o xhci-mtk-scheduler.o xhci-mtk-power.o xhci-mtk.o mtk-phy-7621.o mtk-phy-ahb.o ++endif ++ + xhci-plat-hcd-y := xhci-plat.o ++ + ifneq ($(CONFIG_USB_XHCI_MVEBU), ) + xhci-plat-hcd-y += xhci-mvebu.o + endif +@@ -26,9 +31,14 @@ endif + + obj-$(CONFIG_USB_WHCI_HCD) += whci/ + ++ifndef CONFIG_USB_MT7621_XHCI_PLATFORM + obj-$(CONFIG_PCI) += pci-quirks.o ++endif + ++ifndef CONFIG_USB_MT7621_XHCI_PLATFORM + obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o ++endif ++ + obj-$(CONFIG_USB_XHCI_PLATFORM) += xhci-plat-hcd.o + + obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o +--- /dev/null ++++ b/drivers/usb/host/mtk-phy-7621.c +@@ -0,0 +1,445 @@ ++#include "mtk-phy.h" ++ ++#ifdef CONFIG_PROJECT_7621 ++#include "mtk-phy-7621.h" ++ ++//not used on SoC ++PHY_INT32 phy_init(struct u3phy_info *info){ ++ return PHY_TRUE; ++} ++ ++//not used on SoC ++PHY_INT32 phy_change_pipe_phase(struct u3phy_info *info, PHY_INT32 phy_drv, PHY_INT32 pipe_phase){ ++ return PHY_TRUE; ++} ++ ++//-------------------------------------------------------- ++// Function : fgEyeScanHelper_CheckPtInRegion() ++// Description : Check if the test point is in a rectangle region. ++// If it is in the rectangle, also check if this point ++// is on the multiple of deltaX and deltaY. ++// Parameter : strucScanRegion * prEye - the region ++// BYTE bX ++// BYTE bY ++// Return : BYTE - TRUE : This point needs to be tested ++// FALSE: This point will be omitted ++// Note : First check within the rectangle. ++// Secondly, use modulous to check if the point will be tested. ++//-------------------------------------------------------- ++static PHY_INT8 fgEyeScanHelper_CheckPtInRegion(struct strucScanRegion * prEye, PHY_INT8 bX, PHY_INT8 bY) ++{ ++ PHY_INT8 fgValid = true; ++ ++ ++ /// Be careful, the axis origin is on the TOP-LEFT corner. ++ /// Therefore the top-left point has the minimum X and Y ++ /// Botton-right point is the maximum X and Y ++ if ( (prEye->bX_tl <= bX) && (bX <= prEye->bX_br) ++ && (prEye->bY_tl <= bY) && (bY <= prEye->bX_br)) ++ { ++ // With the region, now check whether or not the input test point is ++ // on the multiples of X and Y ++ // Do not have to worry about negative value, because we have already ++ // check the input bX, and bY is within the region. ++ if ( ((bX - prEye->bX_tl) % (prEye->bDeltaX)) ++ || ((bY - prEye->bY_tl) % (prEye->bDeltaY)) ) ++ { ++ // if the division will have remainder, that means ++ // the input test point is on the multiples of X and Y ++ fgValid = false; ++ } ++ else ++ { ++ } ++ } ++ else ++ { ++ ++ fgValid = false; ++ } ++ return fgValid; ++} ++ ++//-------------------------------------------------------- ++// Function : EyeScanHelper_RunTest() ++// Description : Enable the test, and wait til it is completed ++// Parameter : None ++// Return : None ++// Note : None ++//-------------------------------------------------------- ++static void EyeScanHelper_RunTest(struct u3phy_info *info) ++{ ++ DRV_UDELAY(100); ++ // Disable the test ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0) ++ , RG_SSUSB_EQ_EYE_CNT_EN_OFST, RG_SSUSB_EQ_EYE_CNT_EN, 0); //RG_SSUSB_RX_EYE_CNT_EN = 0 ++ DRV_UDELAY(100); ++ // Run the test ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0) ++ , RG_SSUSB_EQ_EYE_CNT_EN_OFST, RG_SSUSB_EQ_EYE_CNT_EN, 1); //RG_SSUSB_RX_EYE_CNT_EN = 1 ++ DRV_UDELAY(100); ++ // Wait til it's done ++ //RGS_SSUSB_RX_EYE_CNT_RDY ++ while(!U3PhyReadField32(((PHY_UINT32)&info->u3phyd_regs->phya_rx_mon5) ++ , RGS_SSUSB_EQ_EYE_CNT_RDY_OFST, RGS_SSUSB_EQ_EYE_CNT_RDY)); ++} ++ ++//-------------------------------------------------------- ++// Function : fgEyeScanHelper_CalNextPoint() ++// Description : Calcualte the test point for the measurement ++// Parameter : None ++// Return : BOOL - TRUE : the next point is within the ++// boundaryof HW limit ++// FALSE: the next point is out of the HW limit ++// Note : The next point is obtained by calculating ++// from the bottom left of the region rectangle ++// and then scanning up until it reaches the upper ++// limit. At this time, the x will increment, and ++// start scanning downwards until the y hits the ++// zero. ++//-------------------------------------------------------- ++static PHY_INT8 fgEyeScanHelper_CalNextPoint(void) ++{ ++ if ( ((_bYcurr == MAX_Y) && (_eScanDir == SCAN_DN)) ++ || ((_bYcurr == MIN_Y) && (_eScanDir == SCAN_UP)) ++ ) ++ { ++ /// Reaches the limit of Y axis ++ /// Increment X ++ _bXcurr++; ++ _fgXChged = true; ++ _eScanDir = (_eScanDir == SCAN_UP) ? SCAN_DN : SCAN_UP; ++ ++ if (_bXcurr > MAX_X) ++ { ++ return false; ++ } ++ } ++ else ++ { ++ _bYcurr = (_eScanDir == SCAN_DN) ? _bYcurr + 1 : _bYcurr - 1; ++ _fgXChged = false; ++ } ++ return PHY_TRUE; ++} ++ ++PHY_INT32 eyescan_init(struct u3phy_info *info){ ++ //initial PHY setting ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phya_regs->rega) ++ , RG_SSUSB_CDR_EPEN_OFST, RG_SSUSB_CDR_EPEN, 1); ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->phyd_mix3) ++ , RG_SSUSB_FORCE_CDR_PI_PWD_OFST, RG_SSUSB_FORCE_CDR_PI_PWD, 1); ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_bank2_regs->b2_phyd_misc0) ++ , RG_SSUSB_RX_PI_CAL_EN_SEL_OFST, RG_SSUSB_RX_PI_CAL_EN_SEL, 1); //RG_SSUSB_RX_PI_CAL_MANUAL_SEL = 1 ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_bank2_regs->b2_phyd_misc0) ++ , RG_SSUSB_RX_PI_CAL_EN_OFST, RG_SSUSB_RX_PI_CAL_EN, 1); //RG_SSUSB_RX_PI_CAL_MANUAL_EN = 1 ++ return PHY_TRUE; ++} ++ ++PHY_INT32 phy_eyescan(struct u3phy_info *info, PHY_INT32 x_t1, PHY_INT32 y_t1, PHY_INT32 x_br, PHY_INT32 y_br, PHY_INT32 delta_x, PHY_INT32 delta_y ++ , PHY_INT32 eye_cnt, PHY_INT32 num_cnt, PHY_INT32 PI_cal_en, PHY_INT32 num_ignore_cnt){ ++ PHY_INT32 cOfst = 0; ++ PHY_UINT8 bIdxX = 0; ++ PHY_UINT8 bIdxY = 0; ++ //PHY_INT8 bCnt = 0; ++ PHY_UINT8 bIdxCycCnt = 0; ++ PHY_INT8 fgValid; ++ PHY_INT8 cX; ++ PHY_INT8 cY; ++ PHY_UINT8 bExtendCnt; ++ PHY_INT8 isContinue; ++ //PHY_INT8 isBreak; ++ PHY_UINT32 wErr0 = 0, wErr1 = 0; ++ //PHY_UINT32 temp; ++ ++ PHY_UINT32 pwErrCnt0[CYCLE_COUNT_MAX][ERRCNT_MAX][ERRCNT_MAX]; ++ PHY_UINT32 pwErrCnt1[CYCLE_COUNT_MAX][ERRCNT_MAX][ERRCNT_MAX]; ++ ++ _rEye1.bX_tl = x_t1; ++ _rEye1.bY_tl = y_t1; ++ _rEye1.bX_br = x_br; ++ _rEye1.bY_br = y_br; ++ _rEye1.bDeltaX = delta_x; ++ _rEye1.bDeltaY = delta_y; ++ ++ _rEye2.bX_tl = x_t1; ++ _rEye2.bY_tl = y_t1; ++ _rEye2.bX_br = x_br; ++ _rEye2.bY_br = y_br; ++ _rEye2.bDeltaX = delta_x; ++ _rEye2.bDeltaY = delta_y; ++ ++ _rTestCycle.wEyeCnt = eye_cnt; ++ _rTestCycle.bNumOfEyeCnt = num_cnt; ++ _rTestCycle.bNumOfIgnoreCnt = num_ignore_cnt; ++ _rTestCycle.bPICalEn = PI_cal_en; ++ ++ _bXcurr = 0; ++ _bYcurr = 0; ++ _eScanDir = SCAN_DN; ++ _fgXChged = false; ++ ++ printk("x_t1: %x, y_t1: %x, x_br: %x, y_br: %x, delta_x: %x, delta_y: %x, \ ++ eye_cnt: %x, num_cnt: %x, PI_cal_en: %x, num_ignore_cnt: %x\n", \ ++ x_t1, y_t1, x_br, y_br, delta_x, delta_y, eye_cnt, num_cnt, PI_cal_en, num_ignore_cnt); ++ ++ //force SIGDET to OFF ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_bank2_regs->b2_phyd_misc0) ++ , RG_SSUSB_RX_SIGDET_EN_SEL_OFST, RG_SSUSB_RX_SIGDET_EN_SEL, 1); //RG_SSUSB_RX_SIGDET_SEL = 1 ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_bank2_regs->b2_phyd_misc0) ++ , RG_SSUSB_RX_SIGDET_EN_OFST, RG_SSUSB_RX_SIGDET_EN, 0); //RG_SSUSB_RX_SIGDET_EN = 0 ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye1) ++ , RG_SSUSB_EQ_SIGDET_OFST, RG_SSUSB_EQ_SIGDET, 0); //RG_SSUSB_RX_SIGDET = 0 ++ ++ // RX_TRI_DET_EN to Disable ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq3) ++ , RG_SSUSB_EQ_TRI_DET_EN_OFST, RG_SSUSB_EQ_TRI_DET_EN, 0); //RG_SSUSB_RX_TRI_DET_EN = 0 ++ ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0) ++ , RG_SSUSB_EQ_EYE_MON_EN_OFST, RG_SSUSB_EQ_EYE_MON_EN, 1); //RG_SSUSB_EYE_MON_EN = 1 ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0) ++ , RG_SSUSB_EQ_EYE_XOFFSET_OFST, RG_SSUSB_EQ_EYE_XOFFSET, 0); //RG_SSUSB_RX_EYE_XOFFSET = 0 ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0) ++ , RG_SSUSB_EQ_EYE0_Y_OFST, RG_SSUSB_EQ_EYE0_Y, 0); //RG_SSUSB_RX_EYE0_Y = 0 ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0) ++ , RG_SSUSB_EQ_EYE1_Y_OFST, RG_SSUSB_EQ_EYE1_Y, 0); //RG_SSUSB_RX_EYE1_Y = 0 ++ ++ ++ if (PI_cal_en){ ++ // PI Calibration ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_bank2_regs->b2_phyd_misc0) ++ , RG_SSUSB_RX_PI_CAL_EN_SEL_OFST, RG_SSUSB_RX_PI_CAL_EN_SEL, 1); //RG_SSUSB_RX_PI_CAL_MANUAL_SEL = 1 ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_bank2_regs->b2_phyd_misc0) ++ , RG_SSUSB_RX_PI_CAL_EN_OFST, RG_SSUSB_RX_PI_CAL_EN, 0); //RG_SSUSB_RX_PI_CAL_MANUAL_EN = 0 ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_bank2_regs->b2_phyd_misc0) ++ , RG_SSUSB_RX_PI_CAL_EN_OFST, RG_SSUSB_RX_PI_CAL_EN, 1); //RG_SSUSB_RX_PI_CAL_MANUAL_EN = 1 ++ ++ DRV_UDELAY(20); ++ ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_bank2_regs->b2_phyd_misc0) ++ , RG_SSUSB_RX_PI_CAL_EN_OFST, RG_SSUSB_RX_PI_CAL_EN, 0); //RG_SSUSB_RX_PI_CAL_MANUAL_EN = 0 ++ _bPIResult = U3PhyReadField32(((PHY_UINT32)&info->u3phyd_regs->phya_rx_mon5) ++ , RGS_SSUSB_EQ_PILPO_OFST, RGS_SSUSB_EQ_PILPO); //read RGS_SSUSB_RX_PILPO ++ ++ printk(KERN_ERR "PI result: %d\n", _bPIResult); ++ } ++ // Read Initial DAC ++ // Set CYCLE ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye3) ++ ,RG_SSUSB_EQ_EYE_CNT_OFST, RG_SSUSB_EQ_EYE_CNT, eye_cnt); //RG_SSUSB_RX_EYE_CNT ++ ++ // Eye Monitor Feature ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye1) ++ , RG_SSUSB_EQ_EYE_MASK_OFST, RG_SSUSB_EQ_EYE_MASK, 0x3ff); //RG_SSUSB_RX_EYE_MASK = 0x3ff ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0) ++ , RG_SSUSB_EQ_EYE_MON_EN_OFST, RG_SSUSB_EQ_EYE_MON_EN, 1); //RG_SSUSB_EYE_MON_EN = 1 ++ ++ // Move X,Y to the top-left corner ++ for (cOfst = 0; cOfst >= -64; cOfst--) ++ { ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0) ++ ,RG_SSUSB_EQ_EYE_XOFFSET_OFST, RG_SSUSB_EQ_EYE_XOFFSET, cOfst); //RG_SSUSB_RX_EYE_XOFFSET ++ } ++ for (cOfst = 0; cOfst < 64; cOfst++) ++ { ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0) ++ , RG_SSUSB_EQ_EYE0_Y_OFST, RG_SSUSB_EQ_EYE0_Y, cOfst); //RG_SSUSB_RX_EYE0_Y ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0) ++ , RG_SSUSB_EQ_EYE1_Y_OFST, RG_SSUSB_EQ_EYE1_Y, cOfst); //RG_SSUSB_RX_EYE1_Y ++ } ++ //ClearErrorResult ++ for(bIdxCycCnt = 0; bIdxCycCnt < CYCLE_COUNT_MAX; bIdxCycCnt++){ ++ for(bIdxX = 0; bIdxX < ERRCNT_MAX; bIdxX++) ++ { ++ for(bIdxY = 0; bIdxY < ERRCNT_MAX; bIdxY++){ ++ pwErrCnt0[bIdxCycCnt][bIdxX][bIdxY] = 0; ++ pwErrCnt1[bIdxCycCnt][bIdxX][bIdxY] = 0; ++ } ++ } ++ } ++ isContinue = true; ++ while(isContinue){ ++ //printk(KERN_ERR "_bXcurr: %d, _bYcurr: %d\n", _bXcurr, _bYcurr); ++ // The point is within the boundary, then let's check if it is within ++ // the testing region. ++ // The point is only test-able if one of the eye region ++ // includes this point. ++ fgValid = fgEyeScanHelper_CheckPtInRegion(&_rEye1, _bXcurr, _bYcurr) ++ || fgEyeScanHelper_CheckPtInRegion(&_rEye2, _bXcurr, _bYcurr); ++ // Translate bX and bY to 2's complement from where the origin was on the ++ // top left corner. ++ // 0x40 and 0x3F needs a bit of thinking!!!! >"< ++ cX = (_bXcurr ^ 0x40); ++ cY = (_bYcurr ^ 0x3F); ++ ++ // Set X if necessary ++ if (_fgXChged == true) ++ { ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0) ++ , RG_SSUSB_EQ_EYE_XOFFSET_OFST, RG_SSUSB_EQ_EYE_XOFFSET, cX); //RG_SSUSB_RX_EYE_XOFFSET ++ } ++ // Set Y ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0) ++ , RG_SSUSB_EQ_EYE0_Y_OFST, RG_SSUSB_EQ_EYE0_Y, cY); //RG_SSUSB_RX_EYE0_Y ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0) ++ , RG_SSUSB_EQ_EYE1_Y_OFST, RG_SSUSB_EQ_EYE1_Y, cY); //RG_SSUSB_RX_EYE1_Y ++ ++ /// Test this point! ++ if (fgValid){ ++ for (bExtendCnt = 0; bExtendCnt < num_ignore_cnt; bExtendCnt++) ++ { ++ //run test ++ EyeScanHelper_RunTest(info); ++ } ++ for (bExtendCnt = 0; bExtendCnt < num_cnt; bExtendCnt++) ++ { ++ EyeScanHelper_RunTest(info); ++ wErr0 = U3PhyReadField32(((PHY_UINT32)&info->u3phyd_regs->phya_rx_mon3) ++ , RGS_SSUSB_EQ_EYE_MONITOR_ERRCNT_0_OFST, RGS_SSUSB_EQ_EYE_MONITOR_ERRCNT_0); ++ wErr1 = U3PhyReadField32(((PHY_UINT32)&info->u3phyd_regs->phya_rx_mon4) ++ , RGS_SSUSB_EQ_EYE_MONITOR_ERRCNT_1_OFST, RGS_SSUSB_EQ_EYE_MONITOR_ERRCNT_1); ++ ++ pwErrCnt0[bExtendCnt][_bXcurr][_bYcurr] = wErr0; ++ pwErrCnt1[bExtendCnt][_bXcurr][_bYcurr] = wErr1; ++ ++ //EyeScanHelper_GetResult(&_rRes.pwErrCnt0[bCnt], &_rRes.pwErrCnt1[bCnt]); ++// printk(KERN_ERR "cnt[%d] cur_x,y [0x%x][0x%x], cX,cY [0x%x][0x%x], ErrCnt[%d][%d]\n" ++// , bExtendCnt, _bXcurr, _bYcurr, cX, cY, pwErrCnt0[bExtendCnt][_bXcurr][_bYcurr], pwErrCnt1[bExtendCnt][_bXcurr][_bYcurr]); ++ } ++ //printk(KERN_ERR "cur_x,y [0x%x][0x%x], cX,cY [0x%x][0x%x], ErrCnt[%d][%d]\n", _bXcurr, _bYcurr, cX, cY, pwErrCnt0[0][_bXcurr][_bYcurr], pwErrCnt1[0][_bXcurr][_bYcurr]); ++ } ++ else{ ++ ++ } ++ if (fgEyeScanHelper_CalNextPoint() == false){ ++#if 0 ++ printk(KERN_ERR "Xcurr [0x%x] Ycurr [0x%x]\n", _bXcurr, _bYcurr); ++ printk(KERN_ERR "XcurrREG [0x%x] YcurrREG [0x%x]\n", cX, cY); ++#endif ++ printk(KERN_ERR "end of eye scan\n"); ++ isContinue = false; ++ } ++ } ++ printk(KERN_ERR "CurX [0x%x] CurY [0x%x]\n" ++ , U3PhyReadField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0), RG_SSUSB_EQ_EYE_XOFFSET_OFST, RG_SSUSB_EQ_EYE_XOFFSET) ++ , U3PhyReadField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0), RG_SSUSB_EQ_EYE0_Y_OFST, RG_SSUSB_EQ_EYE0_Y)); ++ ++ // Move X,Y to the top-left corner ++ for (cOfst = 63; cOfst >= 0; cOfst--) ++ { ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0) ++ , RG_SSUSB_EQ_EYE_XOFFSET_OFST, RG_SSUSB_EQ_EYE_XOFFSET, cOfst); //RG_SSUSB_RX_EYE_XOFFSET ++ } ++ for (cOfst = 63; cOfst >= 0; cOfst--) ++ { ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0) ++ , RG_SSUSB_EQ_EYE0_Y_OFST, RG_SSUSB_EQ_EYE0_Y, cOfst); ++ U3PhyWriteField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0) ++ , RG_SSUSB_EQ_EYE1_Y_OFST, RG_SSUSB_EQ_EYE1_Y, cOfst); ++ ++ } ++ printk(KERN_ERR "CurX [0x%x] CurY [0x%x]\n" ++ , U3PhyReadField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0), RG_SSUSB_EQ_EYE_XOFFSET_OFST, RG_SSUSB_EQ_EYE_XOFFSET) ++ , U3PhyReadField32(((PHY_UINT32)&info->u3phyd_regs->eq_eye0), RG_SSUSB_EQ_EYE0_Y_OFST, RG_SSUSB_EQ_EYE0_Y)); ++ ++ printk(KERN_ERR "PI result: %d\n", _bPIResult); ++ printk(KERN_ERR "pwErrCnt0 addr: 0x%x\n", (PHY_UINT32)pwErrCnt0); ++ printk(KERN_ERR "pwErrCnt1 addr: 0x%x\n", (PHY_UINT32)pwErrCnt1); ++ ++ return PHY_TRUE; ++} ++ ++//not used on SoC ++PHY_INT32 u2_save_cur_en(struct u3phy_info *info){ ++ return PHY_TRUE; ++} ++ ++//not used on SoC ++PHY_INT32 u2_save_cur_re(struct u3phy_info *info){ ++ return PHY_TRUE; ++} ++ ++PHY_INT32 u2_slew_rate_calibration(struct u3phy_info *info){ ++ PHY_INT32 i=0; ++ //PHY_INT32 j=0; ++ //PHY_INT8 u1SrCalVal = 0; ++ //PHY_INT8 u1Reg_addr_HSTX_SRCAL_EN; ++ PHY_INT32 fgRet = 0; ++ PHY_INT32 u4FmOut = 0; ++ PHY_INT32 u4Tmp = 0; ++ //PHY_INT32 temp; ++ ++ // => RG_USB20_HSTX_SRCAL_EN = 1 ++ // enable HS TX SR calibration ++ U3PhyWriteField32(((PHY_UINT32)&info->u2phy_regs->u2phyacr0) ++ , RG_USB20_HSTX_SRCAL_EN_OFST, RG_USB20_HSTX_SRCAL_EN, 0x1); ++ DRV_MSLEEP(1); ++ ++ // => RG_FRCK_EN = 1 ++ // Enable free run clock ++ U3PhyWriteField32(((PHY_UINT32)&info->sifslv_fm_regs->fmmonr1) ++ , RG_FRCK_EN_OFST, RG_FRCK_EN, 1); ++ ++ // MT6290 HS signal quality patch ++ // => RG_CYCLECNT = 400 ++ // Setting cyclecnt =400 ++ U3PhyWriteField32(((PHY_UINT32)&info->sifslv_fm_regs->fmcr0) ++ , RG_CYCLECNT_OFST, RG_CYCLECNT, 0x400); ++ ++ // => RG_FREQDET_EN = 1 ++ // Enable frequency meter ++ U3PhyWriteField32(((PHY_UINT32)&info->sifslv_fm_regs->fmcr0) ++ , RG_FREQDET_EN_OFST, RG_FREQDET_EN, 0x1); ++ ++ // wait for FM detection done, set 10ms timeout ++ for(i=0; i<10; i++){ ++ // => u4FmOut = USB_FM_OUT ++ // read FM_OUT ++ u4FmOut = U3PhyReadReg32(((PHY_UINT32)&info->sifslv_fm_regs->fmmonr0)); ++ printk("FM_OUT value: u4FmOut = %d(0x%08X)\n", u4FmOut, u4FmOut); ++ ++ // check if FM detection done ++ if (u4FmOut != 0) ++ { ++ fgRet = 0; ++ printk("FM detection done! loop = %d\n", i); ++ ++ break; ++ } ++ ++ fgRet = 1; ++ DRV_MSLEEP(1); ++ } ++ // => RG_FREQDET_EN = 0 ++ // disable frequency meter ++ U3PhyWriteField32(((PHY_UINT32)&info->sifslv_fm_regs->fmcr0) ++ , RG_FREQDET_EN_OFST, RG_FREQDET_EN, 0); ++ ++ // => RG_FRCK_EN = 0 ++ // disable free run clock ++ U3PhyWriteField32(((PHY_UINT32)&info->sifslv_fm_regs->fmmonr1) ++ , RG_FRCK_EN_OFST, RG_FRCK_EN, 0); ++ ++ // => RG_USB20_HSTX_SRCAL_EN = 0 ++ // disable HS TX SR calibration ++ U3PhyWriteField32(((PHY_UINT32)&info->u2phy_regs->u2phyacr0) ++ , RG_USB20_HSTX_SRCAL_EN_OFST, RG_USB20_HSTX_SRCAL_EN, 0); ++ DRV_MSLEEP(1); ++ ++ if(u4FmOut == 0){ ++ U3PhyWriteField32(((PHY_UINT32)&info->u2phy_regs->u2phyacr0) ++ , RG_USB20_HSTX_SRCTRL_OFST, RG_USB20_HSTX_SRCTRL, 0x4); ++ ++ fgRet = 1; ++ } ++ else{ ++ // set reg = (1024/FM_OUT) * 25 * 0.028 (round to the nearest digits) ++ u4Tmp = (((1024 * 25 * U2_SR_COEF_7621) / u4FmOut) + 500) / 1000; ++ printk("SR calibration value u1SrCalVal = %d\n", (PHY_UINT8)u4Tmp); ++ U3PhyWriteField32(((PHY_UINT32)&info->u2phy_regs->u2phyacr0) ++ , RG_USB20_HSTX_SRCTRL_OFST, RG_USB20_HSTX_SRCTRL, u4Tmp); ++ } ++ return fgRet; ++} ++ ++#endif +--- /dev/null ++++ b/drivers/usb/host/mtk-phy-7621.h +@@ -0,0 +1,2871 @@ ++#ifdef CONFIG_PROJECT_7621 ++#ifndef __MTK_PHY_7621_H ++#define __MTK_PHY_7621_H ++ ++#define U2_SR_COEF_7621 28 ++ ++/////////////////////////////////////////////////////////////////////////////// ++ ++struct u2phy_reg { ++ //0x0 ++ PHY_LE32 u2phyac0; ++ PHY_LE32 u2phyac1; ++ PHY_LE32 u2phyac2; ++ PHY_LE32 reserve0; ++ //0x10 ++ PHY_LE32 u2phyacr0; ++ PHY_LE32 u2phyacr1; ++ PHY_LE32 u2phyacr2; ++ PHY_LE32 u2phyacr3; ++ //0x20 ++ PHY_LE32 u2phyacr4; ++ PHY_LE32 u2phyamon0; ++ PHY_LE32 reserve1[2]; ++ //0x30~0x50 ++ PHY_LE32 reserve2[12]; ++ //0x60 ++ PHY_LE32 u2phydcr0; ++ PHY_LE32 u2phydcr1; ++ PHY_LE32 u2phydtm0; ++ PHY_LE32 u2phydtm1; ++ //0x70 ++ PHY_LE32 u2phydmon0; ++ PHY_LE32 u2phydmon1; ++ PHY_LE32 u2phydmon2; ++ PHY_LE32 u2phydmon3; ++ //0x80 ++ PHY_LE32 u2phybc12c; ++ PHY_LE32 u2phybc12c1; ++ PHY_LE32 reserve3[2]; ++ //0x90~0xe0 ++ PHY_LE32 reserve4[24]; ++ //0xf0 ++ PHY_LE32 reserve6[3]; ++ PHY_LE32 regfcom; ++}; ++ ++//U3D_U2PHYAC0 ++#define RG_USB20_USBPLL_DIVEN (0x7<<28) //30:28 ++#define RG_USB20_USBPLL_CKCTRL (0x3<<26) //27:26 ++#define RG_USB20_USBPLL_PREDIV (0x3<<24) //25:24 ++#define RG_USB20_USBPLL_FORCE_ON (0x1<<23) //23:23 ++#define RG_USB20_USBPLL_FBDIV (0x7f<<16) //22:16 ++#define RG_USB20_REF_EN (0x1<<15) //15:15 ++#define RG_USB20_INTR_EN (0x1<<14) //14:14 ++#define RG_USB20_BG_TRIM (0xf<<8) //11:8 ++#define RG_USB20_BG_RBSEL (0x3<<6) //7:6 ++#define RG_USB20_BG_RASEL (0x3<<4) //5:4 ++#define RG_USB20_BGR_DIV (0x3<<2) //3:2 ++#define RG_SIFSLV_CHP_EN (0x1<<1) //1:1 ++#define RG_SIFSLV_BGR_EN (0x1<<0) //0:0 ++ ++//U3D_U2PHYAC1 ++#define RG_USB20_VRT_VREF_SEL (0x7<<28) //30:28 ++#define RG_USB20_TERM_VREF_SEL (0x7<<24) //26:24 ++#define RG_USB20_MPX_SEL (0xff<<16) //23:16 ++#define RG_USB20_MPX_OUT_SEL (0x3<<12) //13:12 ++#define RG_USB20_TX_PH_ROT_SEL (0x7<<8) //10:8 ++#define RG_USB20_USBPLL_ACCEN (0x1<<3) //3:3 ++#define RG_USB20_USBPLL_LF (0x1<<2) //2:2 ++#define RG_USB20_USBPLL_BR (0x1<<1) //1:1 ++#define RG_USB20_USBPLL_BP (0x1<<0) //0:0 ++ ++//U3D_U2PHYAC2 ++#define RG_SIFSLV_MAC_BANDGAP_EN (0x1<<17) //17:17 ++#define RG_SIFSLV_MAC_CHOPPER_EN (0x1<<16) //16:16 ++#define RG_USB20_CLKREF_REV (0xff<<0) //7:0 ++ ++//U3D_U2PHYACR0 ++#define RG_USB20_ICUSB_EN (0x1<<24) //24:24 ++#define RG_USB20_HSTX_SRCAL_EN (0x1<<23) //23:23 ++#define RG_USB20_HSTX_SRCTRL (0x7<<16) //18:16 ++#define RG_USB20_LS_CR (0x7<<12) //14:12 ++#define RG_USB20_FS_CR (0x7<<8) //10:8 ++#define RG_USB20_LS_SR (0x7<<4) //6:4 ++#define RG_USB20_FS_SR (0x7<<0) //2:0 ++ ++//U3D_U2PHYACR1 ++#define RG_USB20_INIT_SQ_EN_DG (0x3<<28) //29:28 ++#define RG_USB20_SQD (0x3<<24) //25:24 ++#define RG_USB20_HSTX_TMODE_SEL (0x3<<20) //21:20 ++#define RG_USB20_HSTX_TMODE_EN (0x1<<19) //19:19 ++#define RG_USB20_PHYD_MONEN (0x1<<18) //18:18 ++#define RG_USB20_INLPBK_EN (0x1<<17) //17:17 ++#define RG_USB20_CHIRP_EN (0x1<<16) //16:16 ++#define RG_USB20_DM_ABIST_SOURCE_EN (0x1<<15) //15:15 ++#define RG_USB20_DM_ABIST_SELE (0xf<<8) //11:8 ++#define RG_USB20_DP_ABIST_SOURCE_EN (0x1<<7) //7:7 ++#define RG_USB20_DP_ABIST_SELE (0xf<<0) //3:0 ++ ++//U3D_U2PHYACR2 ++#define RG_USB20_OTG_ABIST_SELE (0x7<<29) //31:29 ++#define RG_USB20_OTG_ABIST_EN (0x1<<28) //28:28 ++#define RG_USB20_OTG_VBUSCMP_EN (0x1<<27) //27:27 ++#define RG_USB20_OTG_VBUSTH (0x7<<24) //26:24 ++#define RG_USB20_DISC_FIT_EN (0x1<<22) //22:22 ++#define RG_USB20_DISCD (0x3<<20) //21:20 ++#define RG_USB20_DISCTH (0xf<<16) //19:16 ++#define RG_USB20_SQCAL_EN (0x1<<15) //15:15 ++#define RG_USB20_SQCAL (0xf<<8) //11:8 ++#define RG_USB20_SQTH (0xf<<0) //3:0 ++ ++//U3D_U2PHYACR3 ++#define RG_USB20_HSTX_DBIST (0xf<<28) //31:28 ++#define RG_USB20_HSTX_BIST_EN (0x1<<26) //26:26 ++#define RG_USB20_HSTX_I_EN_MODE (0x3<<24) //25:24 ++#define RG_USB20_HSRX_TMODE_EN (0x1<<23) //23:23 ++#define RG_USB20_HSRX_BIAS_EN_SEL (0x3<<20) //21:20 ++#define RG_USB20_USB11_TMODE_EN (0x1<<19) //19:19 ++#define RG_USB20_TMODE_FS_LS_TX_EN (0x1<<18) //18:18 ++#define RG_USB20_TMODE_FS_LS_RCV_EN (0x1<<17) //17:17 ++#define RG_USB20_TMODE_FS_LS_MODE (0x1<<16) //16:16 ++#define RG_USB20_HS_TERM_EN_MODE (0x3<<13) //14:13 ++#define RG_USB20_PUPD_BIST_EN (0x1<<12) //12:12 ++#define RG_USB20_EN_PU_DM (0x1<<11) //11:11 ++#define RG_USB20_EN_PD_DM (0x1<<10) //10:10 ++#define RG_USB20_EN_PU_DP (0x1<<9) //9:9 ++#define RG_USB20_EN_PD_DP (0x1<<8) //8:8 ++#define RG_USB20_PHY_REV (0xff<<0) //7:0 ++ ++//U3D_U2PHYACR4 ++#define RG_USB20_DP_100K_MODE (0x1<<18) //18:18 ++#define RG_USB20_DM_100K_EN (0x1<<17) //17:17 ++#define USB20_DP_100K_EN (0x1<<16) //16:16 ++#define USB20_GPIO_DM_I (0x1<<15) //15:15 ++#define USB20_GPIO_DP_I (0x1<<14) //14:14 ++#define USB20_GPIO_DM_OE (0x1<<13) //13:13 ++#define USB20_GPIO_DP_OE (0x1<<12) //12:12 ++#define RG_USB20_GPIO_CTL (0x1<<9) //9:9 ++#define USB20_GPIO_MODE (0x1<<8) //8:8 ++#define RG_USB20_TX_BIAS_EN (0x1<<5) //5:5 ++#define RG_USB20_TX_VCMPDN_EN (0x1<<4) //4:4 ++#define RG_USB20_HS_SQ_EN_MODE (0x3<<2) //3:2 ++#define RG_USB20_HS_RCV_EN_MODE (0x3<<0) //1:0 ++ ++//U3D_U2PHYAMON0 ++#define RGO_USB20_GPIO_DM_O (0x1<<1) //1:1 ++#define RGO_USB20_GPIO_DP_O (0x1<<0) //0:0 ++ ++//U3D_U2PHYDCR0 ++#define RG_USB20_CDR_TST (0x3<<30) //31:30 ++#define RG_USB20_GATED_ENB (0x1<<29) //29:29 ++#define RG_USB20_TESTMODE (0x3<<26) //27:26 ++#define RG_USB20_PLL_STABLE (0x1<<25) //25:25 ++#define RG_USB20_PLL_FORCE_ON (0x1<<24) //24:24 ++#define RG_USB20_PHYD_RESERVE (0xffff<<8) //23:8 ++#define RG_USB20_EBTHRLD (0x1<<7) //7:7 ++#define RG_USB20_EARLY_HSTX_I (0x1<<6) //6:6 ++#define RG_USB20_TX_TST (0x1<<5) //5:5 ++#define RG_USB20_NEGEDGE_ENB (0x1<<4) //4:4 ++#define RG_USB20_CDR_FILT (0xf<<0) //3:0 ++ ++//U3D_U2PHYDCR1 ++#define RG_USB20_PROBE_SEL (0xff<<24) //31:24 ++#define RG_USB20_DRVVBUS (0x1<<23) //23:23 ++#define RG_DEBUG_EN (0x1<<22) //22:22 ++#define RG_USB20_OTG_PROBE (0x3<<20) //21:20 ++#define RG_USB20_SW_PLLMODE (0x3<<18) //19:18 ++#define RG_USB20_BERTH (0x3<<16) //17:16 ++#define RG_USB20_LBMODE (0x3<<13) //14:13 ++#define RG_USB20_FORCE_TAP (0x1<<12) //12:12 ++#define RG_USB20_TAPSEL (0xfff<<0) //11:0 ++ ++//U3D_U2PHYDTM0 ++#define RG_UART_MODE (0x3<<30) //31:30 ++#define FORCE_UART_I (0x1<<29) //29:29 ++#define FORCE_UART_BIAS_EN (0x1<<28) //28:28 ++#define FORCE_UART_TX_OE (0x1<<27) //27:27 ++#define FORCE_UART_EN (0x1<<26) //26:26 ++#define FORCE_USB_CLKEN (0x1<<25) //25:25 ++#define FORCE_DRVVBUS (0x1<<24) //24:24 ++#define FORCE_DATAIN (0x1<<23) //23:23 ++#define FORCE_TXVALID (0x1<<22) //22:22 ++#define FORCE_DM_PULLDOWN (0x1<<21) //21:21 ++#define FORCE_DP_PULLDOWN (0x1<<20) //20:20 ++#define FORCE_XCVRSEL (0x1<<19) //19:19 ++#define FORCE_SUSPENDM (0x1<<18) //18:18 ++#define FORCE_TERMSEL (0x1<<17) //17:17 ++#define FORCE_OPMODE (0x1<<16) //16:16 ++#define UTMI_MUXSEL (0x1<<15) //15:15 ++#define RG_RESET (0x1<<14) //14:14 ++#define RG_DATAIN (0xf<<10) //13:10 ++#define RG_TXVALIDH (0x1<<9) //9:9 ++#define RG_TXVALID (0x1<<8) //8:8 ++#define RG_DMPULLDOWN (0x1<<7) //7:7 ++#define RG_DPPULLDOWN (0x1<<6) //6:6 ++#define RG_XCVRSEL (0x3<<4) //5:4 ++#define RG_SUSPENDM (0x1<<3) //3:3 ++#define RG_TERMSEL (0x1<<2) //2:2 ++#define RG_OPMODE (0x3<<0) //1:0 ++ ++//U3D_U2PHYDTM1 ++#define RG_USB20_PRBS7_EN (0x1<<31) //31:31 ++#define RG_USB20_PRBS7_BITCNT (0x3f<<24) //29:24 ++#define RG_USB20_CLK48M_EN (0x1<<23) //23:23 ++#define RG_USB20_CLK60M_EN (0x1<<22) //22:22 ++#define RG_UART_I (0x1<<19) //19:19 ++#define RG_UART_BIAS_EN (0x1<<18) //18:18 ++#define RG_UART_TX_OE (0x1<<17) //17:17 ++#define RG_UART_EN (0x1<<16) //16:16 ++#define FORCE_VBUSVALID (0x1<<13) //13:13 ++#define FORCE_SESSEND (0x1<<12) //12:12 ++#define FORCE_BVALID (0x1<<11) //11:11 ++#define FORCE_AVALID (0x1<<10) //10:10 ++#define FORCE_IDDIG (0x1<<9) //9:9 ++#define FORCE_IDPULLUP (0x1<<8) //8:8 ++#define RG_VBUSVALID (0x1<<5) //5:5 ++#define RG_SESSEND (0x1<<4) //4:4 ++#define RG_BVALID (0x1<<3) //3:3 ++#define RG_AVALID (0x1<<2) //2:2 ++#define RG_IDDIG (0x1<<1) //1:1 ++#define RG_IDPULLUP (0x1<<0) //0:0 ++ ++//U3D_U2PHYDMON0 ++#define RG_USB20_PRBS7_BERTH (0xff<<0) //7:0 ++ ++//U3D_U2PHYDMON1 ++#define USB20_UART_O (0x1<<31) //31:31 ++#define RGO_USB20_LB_PASS (0x1<<30) //30:30 ++#define RGO_USB20_LB_DONE (0x1<<29) //29:29 ++#define AD_USB20_BVALID (0x1<<28) //28:28 ++#define USB20_IDDIG (0x1<<27) //27:27 ++#define AD_USB20_VBUSVALID (0x1<<26) //26:26 ++#define AD_USB20_SESSEND (0x1<<25) //25:25 ++#define AD_USB20_AVALID (0x1<<24) //24:24 ++#define USB20_LINE_STATE (0x3<<22) //23:22 ++#define USB20_HST_DISCON (0x1<<21) //21:21 ++#define USB20_TX_READY (0x1<<20) //20:20 ++#define USB20_RX_ERROR (0x1<<19) //19:19 ++#define USB20_RX_ACTIVE (0x1<<18) //18:18 ++#define USB20_RX_VALIDH (0x1<<17) //17:17 ++#define USB20_RX_VALID (0x1<<16) //16:16 ++#define USB20_DATA_OUT (0xffff<<0) //15:0 ++ ++//U3D_U2PHYDMON2 ++#define RGO_TXVALID_CNT (0xff<<24) //31:24 ++#define RGO_RXACTIVE_CNT (0xff<<16) //23:16 ++#define RGO_USB20_LB_BERCNT (0xff<<8) //15:8 ++#define USB20_PROBE_OUT (0xff<<0) //7:0 ++ ++//U3D_U2PHYDMON3 ++#define RGO_USB20_PRBS7_ERRCNT (0xffff<<16) //31:16 ++#define RGO_USB20_PRBS7_DONE (0x1<<3) //3:3 ++#define RGO_USB20_PRBS7_LOCK (0x1<<2) //2:2 ++#define RGO_USB20_PRBS7_PASS (0x1<<1) //1:1 ++#define RGO_USB20_PRBS7_PASSTH (0x1<<0) //0:0 ++ ++//U3D_U2PHYBC12C ++#define RG_SIFSLV_CHGDT_DEGLCH_CNT (0xf<<28) //31:28 ++#define RG_SIFSLV_CHGDT_CTRL_CNT (0xf<<24) //27:24 ++#define RG_SIFSLV_CHGDT_FORCE_MODE (0x1<<16) //16:16 ++#define RG_CHGDT_ISRC_LEV (0x3<<14) //15:14 ++#define RG_CHGDT_VDATSRC (0x1<<13) //13:13 ++#define RG_CHGDT_BGVREF_SEL (0x7<<10) //12:10 ++#define RG_CHGDT_RDVREF_SEL (0x3<<8) //9:8 ++#define RG_CHGDT_ISRC_DP (0x1<<7) //7:7 ++#define RG_SIFSLV_CHGDT_OPOUT_DM (0x1<<6) //6:6 ++#define RG_CHGDT_VDAT_DM (0x1<<5) //5:5 ++#define RG_CHGDT_OPOUT_DP (0x1<<4) //4:4 ++#define RG_SIFSLV_CHGDT_VDAT_DP (0x1<<3) //3:3 ++#define RG_SIFSLV_CHGDT_COMP_EN (0x1<<2) //2:2 ++#define RG_SIFSLV_CHGDT_OPDRV_EN (0x1<<1) //1:1 ++#define RG_CHGDT_EN (0x1<<0) //0:0 ++ ++//U3D_U2PHYBC12C1 ++#define RG_CHGDT_REV (0xff<<0) //7:0 ++ ++//U3D_REGFCOM ++#define RG_PAGE (0xff<<24) //31:24 ++#define I2C_MODE (0x1<<16) //16:16 ++ ++ ++/* OFFSET */ ++ ++//U3D_U2PHYAC0 ++#define RG_USB20_USBPLL_DIVEN_OFST (28) ++#define RG_USB20_USBPLL_CKCTRL_OFST (26) ++#define RG_USB20_USBPLL_PREDIV_OFST (24) ++#define RG_USB20_USBPLL_FORCE_ON_OFST (23) ++#define RG_USB20_USBPLL_FBDIV_OFST (16) ++#define RG_USB20_REF_EN_OFST (15) ++#define RG_USB20_INTR_EN_OFST (14) ++#define RG_USB20_BG_TRIM_OFST (8) ++#define RG_USB20_BG_RBSEL_OFST (6) ++#define RG_USB20_BG_RASEL_OFST (4) ++#define RG_USB20_BGR_DIV_OFST (2) ++#define RG_SIFSLV_CHP_EN_OFST (1) ++#define RG_SIFSLV_BGR_EN_OFST (0) ++ ++//U3D_U2PHYAC1 ++#define RG_USB20_VRT_VREF_SEL_OFST (28) ++#define RG_USB20_TERM_VREF_SEL_OFST (24) ++#define RG_USB20_MPX_SEL_OFST (16) ++#define RG_USB20_MPX_OUT_SEL_OFST (12) ++#define RG_USB20_TX_PH_ROT_SEL_OFST (8) ++#define RG_USB20_USBPLL_ACCEN_OFST (3) ++#define RG_USB20_USBPLL_LF_OFST (2) ++#define RG_USB20_USBPLL_BR_OFST (1) ++#define RG_USB20_USBPLL_BP_OFST (0) ++ ++//U3D_U2PHYAC2 ++#define RG_SIFSLV_MAC_BANDGAP_EN_OFST (17) ++#define RG_SIFSLV_MAC_CHOPPER_EN_OFST (16) ++#define RG_USB20_CLKREF_REV_OFST (0) ++ ++//U3D_U2PHYACR0 ++#define RG_USB20_ICUSB_EN_OFST (24) ++#define RG_USB20_HSTX_SRCAL_EN_OFST (23) ++#define RG_USB20_HSTX_SRCTRL_OFST (16) ++#define RG_USB20_LS_CR_OFST (12) ++#define RG_USB20_FS_CR_OFST (8) ++#define RG_USB20_LS_SR_OFST (4) ++#define RG_USB20_FS_SR_OFST (0) ++ ++//U3D_U2PHYACR1 ++#define RG_USB20_INIT_SQ_EN_DG_OFST (28) ++#define RG_USB20_SQD_OFST (24) ++#define RG_USB20_HSTX_TMODE_SEL_OFST (20) ++#define RG_USB20_HSTX_TMODE_EN_OFST (19) ++#define RG_USB20_PHYD_MONEN_OFST (18) ++#define RG_USB20_INLPBK_EN_OFST (17) ++#define RG_USB20_CHIRP_EN_OFST (16) ++#define RG_USB20_DM_ABIST_SOURCE_EN_OFST (15) ++#define RG_USB20_DM_ABIST_SELE_OFST (8) ++#define RG_USB20_DP_ABIST_SOURCE_EN_OFST (7) ++#define RG_USB20_DP_ABIST_SELE_OFST (0) ++ ++//U3D_U2PHYACR2 ++#define RG_USB20_OTG_ABIST_SELE_OFST (29) ++#define RG_USB20_OTG_ABIST_EN_OFST (28) ++#define RG_USB20_OTG_VBUSCMP_EN_OFST (27) ++#define RG_USB20_OTG_VBUSTH_OFST (24) ++#define RG_USB20_DISC_FIT_EN_OFST (22) ++#define RG_USB20_DISCD_OFST (20) ++#define RG_USB20_DISCTH_OFST (16) ++#define RG_USB20_SQCAL_EN_OFST (15) ++#define RG_USB20_SQCAL_OFST (8) ++#define RG_USB20_SQTH_OFST (0) ++ ++//U3D_U2PHYACR3 ++#define RG_USB20_HSTX_DBIST_OFST (28) ++#define RG_USB20_HSTX_BIST_EN_OFST (26) ++#define RG_USB20_HSTX_I_EN_MODE_OFST (24) ++#define RG_USB20_HSRX_TMODE_EN_OFST (23) ++#define RG_USB20_HSRX_BIAS_EN_SEL_OFST (20) ++#define RG_USB20_USB11_TMODE_EN_OFST (19) ++#define RG_USB20_TMODE_FS_LS_TX_EN_OFST (18) ++#define RG_USB20_TMODE_FS_LS_RCV_EN_OFST (17) ++#define RG_USB20_TMODE_FS_LS_MODE_OFST (16) ++#define RG_USB20_HS_TERM_EN_MODE_OFST (13) ++#define RG_USB20_PUPD_BIST_EN_OFST (12) ++#define RG_USB20_EN_PU_DM_OFST (11) ++#define RG_USB20_EN_PD_DM_OFST (10) ++#define RG_USB20_EN_PU_DP_OFST (9) ++#define RG_USB20_EN_PD_DP_OFST (8) ++#define RG_USB20_PHY_REV_OFST (0) ++ ++//U3D_U2PHYACR4 ++#define RG_USB20_DP_100K_MODE_OFST (18) ++#define RG_USB20_DM_100K_EN_OFST (17) ++#define USB20_DP_100K_EN_OFST (16) ++#define USB20_GPIO_DM_I_OFST (15) ++#define USB20_GPIO_DP_I_OFST (14) ++#define USB20_GPIO_DM_OE_OFST (13) ++#define USB20_GPIO_DP_OE_OFST (12) ++#define RG_USB20_GPIO_CTL_OFST (9) ++#define USB20_GPIO_MODE_OFST (8) ++#define RG_USB20_TX_BIAS_EN_OFST (5) ++#define RG_USB20_TX_VCMPDN_EN_OFST (4) ++#define RG_USB20_HS_SQ_EN_MODE_OFST (2) ++#define RG_USB20_HS_RCV_EN_MODE_OFST (0) ++ ++//U3D_U2PHYAMON0 ++#define RGO_USB20_GPIO_DM_O_OFST (1) ++#define RGO_USB20_GPIO_DP_O_OFST (0) ++ ++//U3D_U2PHYDCR0 ++#define RG_USB20_CDR_TST_OFST (30) ++#define RG_USB20_GATED_ENB_OFST (29) ++#define RG_USB20_TESTMODE_OFST (26) ++#define RG_USB20_PLL_STABLE_OFST (25) ++#define RG_USB20_PLL_FORCE_ON_OFST (24) ++#define RG_USB20_PHYD_RESERVE_OFST (8) ++#define RG_USB20_EBTHRLD_OFST (7) ++#define RG_USB20_EARLY_HSTX_I_OFST (6) ++#define RG_USB20_TX_TST_OFST (5) ++#define RG_USB20_NEGEDGE_ENB_OFST (4) ++#define RG_USB20_CDR_FILT_OFST (0) ++ ++//U3D_U2PHYDCR1 ++#define RG_USB20_PROBE_SEL_OFST (24) ++#define RG_USB20_DRVVBUS_OFST (23) ++#define RG_DEBUG_EN_OFST (22) ++#define RG_USB20_OTG_PROBE_OFST (20) ++#define RG_USB20_SW_PLLMODE_OFST (18) ++#define RG_USB20_BERTH_OFST (16) ++#define RG_USB20_LBMODE_OFST (13) ++#define RG_USB20_FORCE_TAP_OFST (12) ++#define RG_USB20_TAPSEL_OFST (0) ++ ++//U3D_U2PHYDTM0 ++#define RG_UART_MODE_OFST (30) ++#define FORCE_UART_I_OFST (29) ++#define FORCE_UART_BIAS_EN_OFST (28) ++#define FORCE_UART_TX_OE_OFST (27) ++#define FORCE_UART_EN_OFST (26) ++#define FORCE_USB_CLKEN_OFST (25) ++#define FORCE_DRVVBUS_OFST (24) ++#define FORCE_DATAIN_OFST (23) ++#define FORCE_TXVALID_OFST (22) ++#define FORCE_DM_PULLDOWN_OFST (21) ++#define FORCE_DP_PULLDOWN_OFST (20) ++#define FORCE_XCVRSEL_OFST (19) ++#define FORCE_SUSPENDM_OFST (18) ++#define FORCE_TERMSEL_OFST (17) ++#define FORCE_OPMODE_OFST (16) ++#define UTMI_MUXSEL_OFST (15) ++#define RG_RESET_OFST (14) ++#define RG_DATAIN_OFST (10) ++#define RG_TXVALIDH_OFST (9) ++#define RG_TXVALID_OFST (8) ++#define RG_DMPULLDOWN_OFST (7) ++#define RG_DPPULLDOWN_OFST (6) ++#define RG_XCVRSEL_OFST (4) ++#define RG_SUSPENDM_OFST (3) ++#define RG_TERMSEL_OFST (2) ++#define RG_OPMODE_OFST (0) ++ ++//U3D_U2PHYDTM1 ++#define RG_USB20_PRBS7_EN_OFST (31) ++#define RG_USB20_PRBS7_BITCNT_OFST (24) ++#define RG_USB20_CLK48M_EN_OFST (23) ++#define RG_USB20_CLK60M_EN_OFST (22) ++#define RG_UART_I_OFST (19) ++#define RG_UART_BIAS_EN_OFST (18) ++#define RG_UART_TX_OE_OFST (17) ++#define RG_UART_EN_OFST (16) ++#define FORCE_VBUSVALID_OFST (13) ++#define FORCE_SESSEND_OFST (12) ++#define FORCE_BVALID_OFST (11) ++#define FORCE_AVALID_OFST (10) ++#define FORCE_IDDIG_OFST (9) ++#define FORCE_IDPULLUP_OFST (8) ++#define RG_VBUSVALID_OFST (5) ++#define RG_SESSEND_OFST (4) ++#define RG_BVALID_OFST (3) ++#define RG_AVALID_OFST (2) ++#define RG_IDDIG_OFST (1) ++#define RG_IDPULLUP_OFST (0) ++ ++//U3D_U2PHYDMON0 ++#define RG_USB20_PRBS7_BERTH_OFST (0) ++ ++//U3D_U2PHYDMON1 ++#define USB20_UART_O_OFST (31) ++#define RGO_USB20_LB_PASS_OFST (30) ++#define RGO_USB20_LB_DONE_OFST (29) ++#define AD_USB20_BVALID_OFST (28) ++#define USB20_IDDIG_OFST (27) ++#define AD_USB20_VBUSVALID_OFST (26) ++#define AD_USB20_SESSEND_OFST (25) ++#define AD_USB20_AVALID_OFST (24) ++#define USB20_LINE_STATE_OFST (22) ++#define USB20_HST_DISCON_OFST (21) ++#define USB20_TX_READY_OFST (20) ++#define USB20_RX_ERROR_OFST (19) ++#define USB20_RX_ACTIVE_OFST (18) ++#define USB20_RX_VALIDH_OFST (17) ++#define USB20_RX_VALID_OFST (16) ++#define USB20_DATA_OUT_OFST (0) ++ ++//U3D_U2PHYDMON2 ++#define RGO_TXVALID_CNT_OFST (24) ++#define RGO_RXACTIVE_CNT_OFST (16) ++#define RGO_USB20_LB_BERCNT_OFST (8) ++#define USB20_PROBE_OUT_OFST (0) ++ ++//U3D_U2PHYDMON3 ++#define RGO_USB20_PRBS7_ERRCNT_OFST (16) ++#define RGO_USB20_PRBS7_DONE_OFST (3) ++#define RGO_USB20_PRBS7_LOCK_OFST (2) ++#define RGO_USB20_PRBS7_PASS_OFST (1) ++#define RGO_USB20_PRBS7_PASSTH_OFST (0) ++ ++//U3D_U2PHYBC12C ++#define RG_SIFSLV_CHGDT_DEGLCH_CNT_OFST (28) ++#define RG_SIFSLV_CHGDT_CTRL_CNT_OFST (24) ++#define RG_SIFSLV_CHGDT_FORCE_MODE_OFST (16) ++#define RG_CHGDT_ISRC_LEV_OFST (14) ++#define RG_CHGDT_VDATSRC_OFST (13) ++#define RG_CHGDT_BGVREF_SEL_OFST (10) ++#define RG_CHGDT_RDVREF_SEL_OFST (8) ++#define RG_CHGDT_ISRC_DP_OFST (7) ++#define RG_SIFSLV_CHGDT_OPOUT_DM_OFST (6) ++#define RG_CHGDT_VDAT_DM_OFST (5) ++#define RG_CHGDT_OPOUT_DP_OFST (4) ++#define RG_SIFSLV_CHGDT_VDAT_DP_OFST (3) ++#define RG_SIFSLV_CHGDT_COMP_EN_OFST (2) ++#define RG_SIFSLV_CHGDT_OPDRV_EN_OFST (1) ++#define RG_CHGDT_EN_OFST (0) ++ ++//U3D_U2PHYBC12C1 ++#define RG_CHGDT_REV_OFST (0) ++ ++//U3D_REGFCOM ++#define RG_PAGE_OFST (24) ++#define I2C_MODE_OFST (16) ++ ++ ++/////////////////////////////////////////////////////////////////////////////// ++ ++struct u3phya_reg { ++ //0x0 ++ PHY_LE32 reg0; ++ PHY_LE32 reg1; ++ PHY_LE32 reg2; ++ PHY_LE32 reg3; ++ //0x10 ++ PHY_LE32 reg4; ++ PHY_LE32 reg5; ++ PHY_LE32 reg6; ++ PHY_LE32 reg7; ++ //0x20 ++ PHY_LE32 reg8; ++ PHY_LE32 reg9; ++ PHY_LE32 rega; ++ PHY_LE32 regb; ++ //0x30 ++ PHY_LE32 regc; ++ PHY_LE32 regd; ++ PHY_LE32 rege; ++}; ++ ++//U3D_reg0 ++#define RG_SSUSB_BGR_EN (0x1<<31) //31:31 ++#define RG_SSUSB_CHPEN (0x1<<30) //30:30 ++#define RG_SSUSB_BG_DIV (0x3<<28) //29:28 ++#define RG_SSUSB_INTR_EN (0x1<<26) //26:26 ++#define RG_SSUSB_MPX_OUT_SEL (0x3<<24) //25:24 ++#define RG_SSUSB_MPX_SEL (0xff<<16) //23:16 ++#define RG_SSUSB_REF_EN (0x1<<15) //15:15 ++#define RG_SSUSB_VRT_VREF_SEL (0xf<<11) //14:11 ++#define RG_SSUSB_BG_RASEL (0x3<<9) //10:9 ++#define RG_SSUSB_BG_RBSEL (0x3<<7) //8:7 ++#define RG_SSUSB_BG_MONEN (0x1<<6) //6:6 ++#define RG_PCIE_CLKDRV_OFFSET (0x3<<0) //1:0 ++ ++//U3D_reg1 ++#define RG_PCIE_CLKDRV_SLEW (0x3<<30) //31:30 ++#define RG_PCIE_CLKDRV_AMP (0x7<<27) //29:27 ++#define RG_SSUSB_XTAL_TST_A2DCK_EN (0x1<<26) //26:26 ++#define RG_SSUSB_XTAL_MON_EN (0x1<<25) //25:25 ++#define RG_SSUSB_XTAL_HYS (0x1<<24) //24:24 ++#define RG_SSUSB_XTAL_TOP_RESERVE (0xffff<<8) //23:8 ++#define RG_SSUSB_SYSPLL_RESERVE (0xf<<4) //7:4 ++#define RG_SSUSB_SYSPLL_FBSEL (0x3<<2) //3:2 ++#define RG_SSUSB_SYSPLL_PREDIV (0x3<<0) //1:0 ++ ++//U3D_reg2 ++#define RG_SSUSB_SYSPLL_LF (0x1<<31) //31:31 ++#define RG_SSUSB_SYSPLL_FBDIV (0x7f<<24) //30:24 ++#define RG_SSUSB_SYSPLL_POSDIV (0x3<<22) //23:22 ++#define RG_SSUSB_SYSPLL_VCO_DIV_SEL (0x1<<21) //21:21 ++#define RG_SSUSB_SYSPLL_BLP (0x1<<20) //20:20 ++#define RG_SSUSB_SYSPLL_BP (0x1<<19) //19:19 ++#define RG_SSUSB_SYSPLL_BR (0x1<<18) //18:18 ++#define RG_SSUSB_SYSPLL_BC (0x1<<17) //17:17 ++#define RG_SSUSB_SYSPLL_DIVEN (0x7<<14) //16:14 ++#define RG_SSUSB_SYSPLL_FPEN (0x1<<13) //13:13 ++#define RG_SSUSB_SYSPLL_MONCK_EN (0x1<<12) //12:12 ++#define RG_SSUSB_SYSPLL_MONVC_EN (0x1<<11) //11:11 ++#define RG_SSUSB_SYSPLL_MONREF_EN (0x1<<10) //10:10 ++#define RG_SSUSB_SYSPLL_VOD_EN (0x1<<9) //9:9 ++#define RG_SSUSB_SYSPLL_CK_SEL (0x1<<8) //8:8 ++ ++//U3D_reg3 ++#define RG_SSUSB_SYSPLL_TOP_RESERVE (0xffff<<16) //31:16 ++ ++//U3D_reg4 ++#define RG_SSUSB_SYSPLL_PCW_NCPO (0x7fffffff<<1) //31:1 ++ ++//U3D_reg5 ++#define RG_SSUSB_SYSPLL_DDS_PI_C (0x7<<29) //31:29 ++#define RG_SSUSB_SYSPLL_DDS_HF_EN (0x1<<28) //28:28 ++#define RG_SSUSB_SYSPLL_DDS_PREDIV2 (0x1<<27) //27:27 ++#define RG_SSUSB_SYSPLL_DDS_POSTDIV2 (0x1<<26) //26:26 ++#define RG_SSUSB_SYSPLL_DDS_PI_PL_EN (0x1<<25) //25:25 ++#define RG_SSUSB_SYSPLL_DDS_PI_RST_SEL (0x1<<24) //24:24 ++#define RG_SSUSB_SYSPLL_DDS_MONEN (0x1<<23) //23:23 ++#define RG_SSUSB_SYSPLL_DDS_LPF_EN (0x1<<22) //22:22 ++#define RG_SSUSB_SYSPLL_CLK_PH_INV (0x1<<21) //21:21 ++#define RG_SSUSB_SYSPLL_DDS_SEL_EXT (0x1<<20) //20:20 ++#define RG_SSUSB_SYSPLL_DDS_DMY (0xffff<<0) //15:0 ++ ++//U3D_reg6 ++#define RG_SSUSB_TX250MCK_INVB (0x1<<31) //31:31 ++#define RG_SSUSB_IDRV_ITAILOP_EN (0x1<<30) //30:30 ++#define RG_SSUSB_IDRV_CALIB (0x3f<<24) //29:24 ++#define RG_SSUSB_TX_R50_FON (0x1<<23) //23:23 ++#define RG_SSUSB_TX_SR (0x7<<20) //22:20 ++#define RG_SSUSB_TX_EIDLE_CM (0xf<<16) //19:16 ++#define RG_SSUSB_RXDET_RSEL (0x3<<14) //15:14 ++#define RG_SSUSB_RXDET_VTHSEL (0x3<<12) //13:12 ++#define RG_SSUSB_CKMON_EN (0x1<<11) //11:11 ++#define RG_SSUSB_CKMON_SEL (0x7<<8) //10:8 ++#define RG_SSUSB_TX_VLMON_EN (0x1<<7) //7:7 ++#define RG_SSUSB_TX_VLMON_SEL (0x1<<6) //6:6 ++#define RG_SSUSB_RXLBTX_EN (0x1<<5) //5:5 ++#define RG_SSUSB_TXLBRX_EN (0x1<<4) //4:4 ++ ++//U3D_reg7 ++#define RG_SSUSB_RESERVE (0xfffff<<12) //31:12 ++#define RG_SSUSB_PLL_CKCTRL (0x3<<10) //11:10 ++#define RG_SSUSB_PLL_POSDIV (0x3<<8) //9:8 ++#define RG_SSUSB_PLL_AUTOK_LOAD (0x1<<7) //7:7 ++#define RG_SSUSB_PLL_LOAD_RSTB (0x1<<6) //6:6 ++#define RG_SSUSB_PLL_EP_EN (0x1<<5) //5:5 ++#define RG_SSUSB_PLL_VOD_EN (0x1<<4) //4:4 ++#define RG_SSUSB_PLL_V11_EN (0x1<<3) //3:3 ++#define RG_SSUSB_PLL_MONREF_EN (0x1<<2) //2:2 ++#define RG_SSUSB_PLL_MONCK_EN (0x1<<1) //1:1 ++#define RG_SSUSB_PLL_MONVC_EN (0x1<<0) //0:0 ++ ++//U3D_reg8 ++#define RG_SSUSB_PLL_RESERVE (0xffff<<0) //15:0 ++ ++//U3D_reg9 ++#define RG_SSUSB_PLL_DDS_DMY (0xffff<<16) //31:16 ++#define RG_SSUSB_PLL_SSC_PRD (0xffff<<0) //15:0 ++ ++//U3D_regA ++#define RG_SSUSB_PLL_SSC_PHASE_INI (0x1<<31) //31:31 ++#define RG_SSUSB_PLL_SSC_TRI_EN (0x1<<30) //30:30 ++#define RG_SSUSB_PLL_CLK_PH_INV (0x1<<29) //29:29 ++#define RG_SSUSB_PLL_DDS_LPF_EN (0x1<<28) //28:28 ++#define RG_SSUSB_PLL_DDS_VADJ (0x7<<21) //23:21 ++#define RG_SSUSB_PLL_DDS_MONEN (0x1<<20) //20:20 ++#define RG_SSUSB_PLL_DDS_PS_VADJ (0x7<<17) //19:17 ++#define RG_SSUSB_PLL_DDS_SEL_EXT (0x1<<16) //16:16 ++#define RG_SSUSB_CDR_PD_DIV_BYPASS (0x1<<15) //15:15 ++#define RG_SSUSB_CDR_PD_DIV_SEL (0x1<<14) //14:14 ++#define RG_SSUSB_CDR_CPBIAS_SEL (0x1<<13) //13:13 ++#define RG_SSUSB_CDR_OSCDET_EN (0x1<<12) //12:12 ++#define RG_SSUSB_CDR_MONMUX (0x1<<11) //11:11 ++#define RG_SSUSB_CDR_CKCTRL (0x3<<9) //10:9 ++#define RG_SSUSB_CDR_ACCEN (0x1<<8) //8:8 ++#define RG_SSUSB_CDR_BYPASS (0x3<<6) //7:6 ++#define RG_SSUSB_CDR_PI_SLEW (0x3<<4) //5:4 ++#define RG_SSUSB_CDR_EPEN (0x1<<3) //3:3 ++#define RG_SSUSB_CDR_AUTOK_LOAD (0x1<<2) //2:2 ++#define RG_SSUSB_CDR_LOAD_RSTB (0x1<<1) //1:1 ++#define RG_SSUSB_CDR_MONEN (0x1<<0) //0:0 ++ ++//U3D_regB ++#define RG_SSUSB_CDR_MONEN_DIG (0x1<<31) //31:31 ++#define RG_SSUSB_CDR_REGOD (0x3<<29) //30:29 ++#define RG_SSUSB_RX_DAC_EN (0x1<<26) //26:26 ++#define RG_SSUSB_RX_DAC_PWD (0x1<<25) //25:25 ++#define RG_SSUSB_EQ_CURSEL (0x1<<24) //24:24 ++#define RG_SSUSB_RX_DAC_MUX (0x1f<<19) //23:19 ++#define RG_SSUSB_RX_R2T_EN (0x1<<18) //18:18 ++#define RG_SSUSB_RX_T2R_EN (0x1<<17) //17:17 ++#define RG_SSUSB_RX_50_LOWER (0x7<<14) //16:14 ++#define RG_SSUSB_RX_50_TAR (0x3<<12) //13:12 ++#define RG_SSUSB_RX_SW_CTRL (0xf<<7) //10:7 ++#define RG_PCIE_SIGDET_VTH (0x3<<5) //6:5 ++#define RG_PCIE_SIGDET_LPF (0x3<<3) //4:3 ++#define RG_SSUSB_LFPS_MON_EN (0x1<<2) //2:2 ++ ++//U3D_regC ++#define RG_SSUSB_RXAFE_DCMON_SEL (0xf<<28) //31:28 ++#define RG_SSUSB_CDR_RESERVE (0xff<<16) //23:16 ++#define RG_SSUSB_RXAFE_RESERVE (0xff<<8) //15:8 ++#define RG_PCIE_RX_RESERVE (0xff<<0) //7:0 ++ ++//U3D_redD ++#define RGS_SSUSB_CDR_NO_OSC (0x1<<8) //8:8 ++#define RGS_SSUSB_RX_DEBUG_RESERVE (0xff<<0) //7:0 ++ ++//U3D_regE ++#define RG_SSUSB_INT_BIAS_SEL (0x1<<4) //4:4 ++#define RG_SSUSB_EXT_BIAS_SEL (0x1<<3) //3:3 ++#define RG_SSUSB_RX_P1_ENTRY_PASS (0x1<<2) //2:2 ++#define RG_SSUSB_RX_PD_RST (0x1<<1) //1:1 ++#define RG_SSUSB_RX_PD_RST_PASS (0x1<<0) //0:0 ++ ++ ++/* OFFSET */ ++ ++//U3D_reg0 ++#define RG_SSUSB_BGR_EN_OFST (31) ++#define RG_SSUSB_CHPEN_OFST (30) ++#define RG_SSUSB_BG_DIV_OFST (28) ++#define RG_SSUSB_INTR_EN_OFST (26) ++#define RG_SSUSB_MPX_OUT_SEL_OFST (24) ++#define RG_SSUSB_MPX_SEL_OFST (16) ++#define RG_SSUSB_REF_EN_OFST (15) ++#define RG_SSUSB_VRT_VREF_SEL_OFST (11) ++#define RG_SSUSB_BG_RASEL_OFST (9) ++#define RG_SSUSB_BG_RBSEL_OFST (7) ++#define RG_SSUSB_BG_MONEN_OFST (6) ++#define RG_PCIE_CLKDRV_OFFSET_OFST (0) ++ ++//U3D_reg1 ++#define RG_PCIE_CLKDRV_SLEW_OFST (30) ++#define RG_PCIE_CLKDRV_AMP_OFST (27) ++#define RG_SSUSB_XTAL_TST_A2DCK_EN_OFST (26) ++#define RG_SSUSB_XTAL_MON_EN_OFST (25) ++#define RG_SSUSB_XTAL_HYS_OFST (24) ++#define RG_SSUSB_XTAL_TOP_RESERVE_OFST (8) ++#define RG_SSUSB_SYSPLL_RESERVE_OFST (4) ++#define RG_SSUSB_SYSPLL_FBSEL_OFST (2) ++#define RG_SSUSB_SYSPLL_PREDIV_OFST (0) ++ ++//U3D_reg2 ++#define RG_SSUSB_SYSPLL_LF_OFST (31) ++#define RG_SSUSB_SYSPLL_FBDIV_OFST (24) ++#define RG_SSUSB_SYSPLL_POSDIV_OFST (22) ++#define RG_SSUSB_SYSPLL_VCO_DIV_SEL_OFST (21) ++#define RG_SSUSB_SYSPLL_BLP_OFST (20) ++#define RG_SSUSB_SYSPLL_BP_OFST (19) ++#define RG_SSUSB_SYSPLL_BR_OFST (18) ++#define RG_SSUSB_SYSPLL_BC_OFST (17) ++#define RG_SSUSB_SYSPLL_DIVEN_OFST (14) ++#define RG_SSUSB_SYSPLL_FPEN_OFST (13) ++#define RG_SSUSB_SYSPLL_MONCK_EN_OFST (12) ++#define RG_SSUSB_SYSPLL_MONVC_EN_OFST (11) ++#define RG_SSUSB_SYSPLL_MONREF_EN_OFST (10) ++#define RG_SSUSB_SYSPLL_VOD_EN_OFST (9) ++#define RG_SSUSB_SYSPLL_CK_SEL_OFST (8) ++ ++//U3D_reg3 ++#define RG_SSUSB_SYSPLL_TOP_RESERVE_OFST (16) ++ ++//U3D_reg4 ++#define RG_SSUSB_SYSPLL_PCW_NCPO_OFST (1) ++ ++//U3D_reg5 ++#define RG_SSUSB_SYSPLL_DDS_PI_C_OFST (29) ++#define RG_SSUSB_SYSPLL_DDS_HF_EN_OFST (28) ++#define RG_SSUSB_SYSPLL_DDS_PREDIV2_OFST (27) ++#define RG_SSUSB_SYSPLL_DDS_POSTDIV2_OFST (26) ++#define RG_SSUSB_SYSPLL_DDS_PI_PL_EN_OFST (25) ++#define RG_SSUSB_SYSPLL_DDS_PI_RST_SEL_OFST (24) ++#define RG_SSUSB_SYSPLL_DDS_MONEN_OFST (23) ++#define RG_SSUSB_SYSPLL_DDS_LPF_EN_OFST (22) ++#define RG_SSUSB_SYSPLL_CLK_PH_INV_OFST (21) ++#define RG_SSUSB_SYSPLL_DDS_SEL_EXT_OFST (20) ++#define RG_SSUSB_SYSPLL_DDS_DMY_OFST (0) ++ ++//U3D_reg6 ++#define RG_SSUSB_TX250MCK_INVB_OFST (31) ++#define RG_SSUSB_IDRV_ITAILOP_EN_OFST (30) ++#define RG_SSUSB_IDRV_CALIB_OFST (24) ++#define RG_SSUSB_TX_R50_FON_OFST (23) ++#define RG_SSUSB_TX_SR_OFST (20) ++#define RG_SSUSB_TX_EIDLE_CM_OFST (16) ++#define RG_SSUSB_RXDET_RSEL_OFST (14) ++#define RG_SSUSB_RXDET_VTHSEL_OFST (12) ++#define RG_SSUSB_CKMON_EN_OFST (11) ++#define RG_SSUSB_CKMON_SEL_OFST (8) ++#define RG_SSUSB_TX_VLMON_EN_OFST (7) ++#define RG_SSUSB_TX_VLMON_SEL_OFST (6) ++#define RG_SSUSB_RXLBTX_EN_OFST (5) ++#define RG_SSUSB_TXLBRX_EN_OFST (4) ++ ++//U3D_reg7 ++#define RG_SSUSB_RESERVE_OFST (12) ++#define RG_SSUSB_PLL_CKCTRL_OFST (10) ++#define RG_SSUSB_PLL_POSDIV_OFST (8) ++#define RG_SSUSB_PLL_AUTOK_LOAD_OFST (7) ++#define RG_SSUSB_PLL_LOAD_RSTB_OFST (6) ++#define RG_SSUSB_PLL_EP_EN_OFST (5) ++#define RG_SSUSB_PLL_VOD_EN_OFST (4) ++#define RG_SSUSB_PLL_V11_EN_OFST (3) ++#define RG_SSUSB_PLL_MONREF_EN_OFST (2) ++#define RG_SSUSB_PLL_MONCK_EN_OFST (1) ++#define RG_SSUSB_PLL_MONVC_EN_OFST (0) ++ ++//U3D_reg8 ++#define RG_SSUSB_PLL_RESERVE_OFST (0) ++ ++//U3D_reg9 ++#define RG_SSUSB_PLL_DDS_DMY_OFST (16) ++#define RG_SSUSB_PLL_SSC_PRD_OFST (0) ++ ++//U3D_regA ++#define RG_SSUSB_PLL_SSC_PHASE_INI_OFST (31) ++#define RG_SSUSB_PLL_SSC_TRI_EN_OFST (30) ++#define RG_SSUSB_PLL_CLK_PH_INV_OFST (29) ++#define RG_SSUSB_PLL_DDS_LPF_EN_OFST (28) ++#define RG_SSUSB_PLL_DDS_VADJ_OFST (21) ++#define RG_SSUSB_PLL_DDS_MONEN_OFST (20) ++#define RG_SSUSB_PLL_DDS_PS_VADJ_OFST (17) ++#define RG_SSUSB_PLL_DDS_SEL_EXT_OFST (16) ++#define RG_SSUSB_CDR_PD_DIV_BYPASS_OFST (15) ++#define RG_SSUSB_CDR_PD_DIV_SEL_OFST (14) ++#define RG_SSUSB_CDR_CPBIAS_SEL_OFST (13) ++#define RG_SSUSB_CDR_OSCDET_EN_OFST (12) ++#define RG_SSUSB_CDR_MONMUX_OFST (11) ++#define RG_SSUSB_CDR_CKCTRL_OFST (9) ++#define RG_SSUSB_CDR_ACCEN_OFST (8) ++#define RG_SSUSB_CDR_BYPASS_OFST (6) ++#define RG_SSUSB_CDR_PI_SLEW_OFST (4) ++#define RG_SSUSB_CDR_EPEN_OFST (3) ++#define RG_SSUSB_CDR_AUTOK_LOAD_OFST (2) ++#define RG_SSUSB_CDR_LOAD_RSTB_OFST (1) ++#define RG_SSUSB_CDR_MONEN_OFST (0) ++ ++//U3D_regB ++#define RG_SSUSB_CDR_MONEN_DIG_OFST (31) ++#define RG_SSUSB_CDR_REGOD_OFST (29) ++#define RG_SSUSB_RX_DAC_EN_OFST (26) ++#define RG_SSUSB_RX_DAC_PWD_OFST (25) ++#define RG_SSUSB_EQ_CURSEL_OFST (24) ++#define RG_SSUSB_RX_DAC_MUX_OFST (19) ++#define RG_SSUSB_RX_R2T_EN_OFST (18) ++#define RG_SSUSB_RX_T2R_EN_OFST (17) ++#define RG_SSUSB_RX_50_LOWER_OFST (14) ++#define RG_SSUSB_RX_50_TAR_OFST (12) ++#define RG_SSUSB_RX_SW_CTRL_OFST (7) ++#define RG_PCIE_SIGDET_VTH_OFST (5) ++#define RG_PCIE_SIGDET_LPF_OFST (3) ++#define RG_SSUSB_LFPS_MON_EN_OFST (2) ++ ++//U3D_regC ++#define RG_SSUSB_RXAFE_DCMON_SEL_OFST (28) ++#define RG_SSUSB_CDR_RESERVE_OFST (16) ++#define RG_SSUSB_RXAFE_RESERVE_OFST (8) ++#define RG_PCIE_RX_RESERVE_OFST (0) ++ ++//U3D_redD ++#define RGS_SSUSB_CDR_NO_OSC_OFST (8) ++#define RGS_SSUSB_RX_DEBUG_RESERVE_OFST (0) ++ ++//U3D_regE ++#define RG_SSUSB_INT_BIAS_SEL_OFST (4) ++#define RG_SSUSB_EXT_BIAS_SEL_OFST (3) ++#define RG_SSUSB_RX_P1_ENTRY_PASS_OFST (2) ++#define RG_SSUSB_RX_PD_RST_OFST (1) ++#define RG_SSUSB_RX_PD_RST_PASS_OFST (0) ++ ++/////////////////////////////////////////////////////////////////////////////// ++ ++struct u3phya_da_reg { ++ //0x0 ++ PHY_LE32 reg0; ++ PHY_LE32 reg1; ++ PHY_LE32 reg4; ++ PHY_LE32 reg5; ++ //0x10 ++ PHY_LE32 reg6; ++ PHY_LE32 reg7; ++ PHY_LE32 reg8; ++ PHY_LE32 reg9; ++ //0x20 ++ PHY_LE32 reg10; ++ PHY_LE32 reg12; ++ PHY_LE32 reg13; ++ PHY_LE32 reg14; ++ //0x30 ++ PHY_LE32 reg15; ++ PHY_LE32 reg16; ++ PHY_LE32 reg19; ++ PHY_LE32 reg20; ++ //0x40 ++ PHY_LE32 reg21; ++ PHY_LE32 reg23; ++ PHY_LE32 reg25; ++ PHY_LE32 reg26; ++ //0x50 ++ PHY_LE32 reg28; ++ PHY_LE32 reg29; ++ PHY_LE32 reg30; ++ PHY_LE32 reg31; ++ //0x60 ++ PHY_LE32 reg32; ++ PHY_LE32 reg33; ++}; ++ ++//U3D_reg0 ++#define RG_PCIE_SPEED_PE2D (0x1<<24) //24:24 ++#define RG_PCIE_SPEED_PE2H (0x1<<23) //23:23 ++#define RG_PCIE_SPEED_PE1D (0x1<<22) //22:22 ++#define RG_PCIE_SPEED_PE1H (0x1<<21) //21:21 ++#define RG_PCIE_SPEED_U3 (0x1<<20) //20:20 ++#define RG_SSUSB_XTAL_EXT_EN_PE2D (0x3<<18) //19:18 ++#define RG_SSUSB_XTAL_EXT_EN_PE2H (0x3<<16) //17:16 ++#define RG_SSUSB_XTAL_EXT_EN_PE1D (0x3<<14) //15:14 ++#define RG_SSUSB_XTAL_EXT_EN_PE1H (0x3<<12) //13:12 ++#define RG_SSUSB_XTAL_EXT_EN_U3 (0x3<<10) //11:10 ++#define RG_SSUSB_CDR_REFCK_SEL_PE2D (0x3<<8) //9:8 ++#define RG_SSUSB_CDR_REFCK_SEL_PE2H (0x3<<6) //7:6 ++#define RG_SSUSB_CDR_REFCK_SEL_PE1D (0x3<<4) //5:4 ++#define RG_SSUSB_CDR_REFCK_SEL_PE1H (0x3<<2) //3:2 ++#define RG_SSUSB_CDR_REFCK_SEL_U3 (0x3<<0) //1:0 ++ ++//U3D_reg1 ++#define RG_USB20_REFCK_SEL_PE2D (0x1<<30) //30:30 ++#define RG_USB20_REFCK_SEL_PE2H (0x1<<29) //29:29 ++#define RG_USB20_REFCK_SEL_PE1D (0x1<<28) //28:28 ++#define RG_USB20_REFCK_SEL_PE1H (0x1<<27) //27:27 ++#define RG_USB20_REFCK_SEL_U3 (0x1<<26) //26:26 ++#define RG_PCIE_REFCK_DIV4_PE2D (0x1<<25) //25:25 ++#define RG_PCIE_REFCK_DIV4_PE2H (0x1<<24) //24:24 ++#define RG_PCIE_REFCK_DIV4_PE1D (0x1<<18) //18:18 ++#define RG_PCIE_REFCK_DIV4_PE1H (0x1<<17) //17:17 ++#define RG_PCIE_REFCK_DIV4_U3 (0x1<<16) //16:16 ++#define RG_PCIE_MODE_PE2D (0x1<<8) //8:8 ++#define RG_PCIE_MODE_PE2H (0x1<<3) //3:3 ++#define RG_PCIE_MODE_PE1D (0x1<<2) //2:2 ++#define RG_PCIE_MODE_PE1H (0x1<<1) //1:1 ++#define RG_PCIE_MODE_U3 (0x1<<0) //0:0 ++ ++//U3D_reg4 ++#define RG_SSUSB_PLL_DIVEN_PE2D (0x7<<22) //24:22 ++#define RG_SSUSB_PLL_DIVEN_PE2H (0x7<<19) //21:19 ++#define RG_SSUSB_PLL_DIVEN_PE1D (0x7<<16) //18:16 ++#define RG_SSUSB_PLL_DIVEN_PE1H (0x7<<13) //15:13 ++#define RG_SSUSB_PLL_DIVEN_U3 (0x7<<10) //12:10 ++#define RG_SSUSB_PLL_BC_PE2D (0x3<<8) //9:8 ++#define RG_SSUSB_PLL_BC_PE2H (0x3<<6) //7:6 ++#define RG_SSUSB_PLL_BC_PE1D (0x3<<4) //5:4 ++#define RG_SSUSB_PLL_BC_PE1H (0x3<<2) //3:2 ++#define RG_SSUSB_PLL_BC_U3 (0x3<<0) //1:0 ++ ++//U3D_reg5 ++#define RG_SSUSB_PLL_BR_PE2D (0x7<<27) //29:27 ++#define RG_SSUSB_PLL_BR_PE2H (0x7<<24) //26:24 ++#define RG_SSUSB_PLL_BR_PE1D (0x7<<21) //23:21 ++#define RG_SSUSB_PLL_BR_PE1H (0x7<<18) //20:18 ++#define RG_SSUSB_PLL_BR_U3 (0x7<<15) //17:15 ++#define RG_SSUSB_PLL_IC_PE2D (0x7<<12) //14:12 ++#define RG_SSUSB_PLL_IC_PE2H (0x7<<9) //11:9 ++#define RG_SSUSB_PLL_IC_PE1D (0x7<<6) //8:6 ++#define RG_SSUSB_PLL_IC_PE1H (0x7<<3) //5:3 ++#define RG_SSUSB_PLL_IC_U3 (0x7<<0) //2:0 ++ ++//U3D_reg6 ++#define RG_SSUSB_PLL_IR_PE2D (0xf<<24) //27:24 ++#define RG_SSUSB_PLL_IR_PE2H (0xf<<16) //19:16 ++#define RG_SSUSB_PLL_IR_PE1D (0xf<<8) //11:8 ++#define RG_SSUSB_PLL_IR_PE1H (0xf<<4) //7:4 ++#define RG_SSUSB_PLL_IR_U3 (0xf<<0) //3:0 ++ ++//U3D_reg7 ++#define RG_SSUSB_PLL_BP_PE2D (0xf<<24) //27:24 ++#define RG_SSUSB_PLL_BP_PE2H (0xf<<16) //19:16 ++#define RG_SSUSB_PLL_BP_PE1D (0xf<<8) //11:8 ++#define RG_SSUSB_PLL_BP_PE1H (0xf<<4) //7:4 ++#define RG_SSUSB_PLL_BP_U3 (0xf<<0) //3:0 ++ ++//U3D_reg8 ++#define RG_SSUSB_PLL_FBKSEL_PE2D (0x3<<24) //25:24 ++#define RG_SSUSB_PLL_FBKSEL_PE2H (0x3<<16) //17:16 ++#define RG_SSUSB_PLL_FBKSEL_PE1D (0x3<<8) //9:8 ++#define RG_SSUSB_PLL_FBKSEL_PE1H (0x3<<2) //3:2 ++#define RG_SSUSB_PLL_FBKSEL_U3 (0x3<<0) //1:0 ++ ++//U3D_reg9 ++#define RG_SSUSB_PLL_FBKDIV_PE2H (0x7f<<24) //30:24 ++#define RG_SSUSB_PLL_FBKDIV_PE1D (0x7f<<16) //22:16 ++#define RG_SSUSB_PLL_FBKDIV_PE1H (0x7f<<8) //14:8 ++#define RG_SSUSB_PLL_FBKDIV_U3 (0x7f<<0) //6:0 ++ ++//U3D_reg10 ++#define RG_SSUSB_PLL_PREDIV_PE2D (0x3<<26) //27:26 ++#define RG_SSUSB_PLL_PREDIV_PE2H (0x3<<24) //25:24 ++#define RG_SSUSB_PLL_PREDIV_PE1D (0x3<<18) //19:18 ++#define RG_SSUSB_PLL_PREDIV_PE1H (0x3<<16) //17:16 ++#define RG_SSUSB_PLL_PREDIV_U3 (0x3<<8) //9:8 ++#define RG_SSUSB_PLL_FBKDIV_PE2D (0x7f<<0) //6:0 ++ ++//U3D_reg12 ++#define RG_SSUSB_PLL_PCW_NCPO_U3 (0x7fffffff<<0) //30:0 ++ ++//U3D_reg13 ++#define RG_SSUSB_PLL_PCW_NCPO_PE1H (0x7fffffff<<0) //30:0 ++ ++//U3D_reg14 ++#define RG_SSUSB_PLL_PCW_NCPO_PE1D (0x7fffffff<<0) //30:0 ++ ++//U3D_reg15 ++#define RG_SSUSB_PLL_PCW_NCPO_PE2H (0x7fffffff<<0) //30:0 ++ ++//U3D_reg16 ++#define RG_SSUSB_PLL_PCW_NCPO_PE2D (0x7fffffff<<0) //30:0 ++ ++//U3D_reg19 ++#define RG_SSUSB_PLL_SSC_DELTA1_PE1H (0xffff<<16) //31:16 ++#define RG_SSUSB_PLL_SSC_DELTA1_U3 (0xffff<<0) //15:0 ++ ++//U3D_reg20 ++#define RG_SSUSB_PLL_SSC_DELTA1_PE2H (0xffff<<16) //31:16 ++#define RG_SSUSB_PLL_SSC_DELTA1_PE1D (0xffff<<0) //15:0 ++ ++//U3D_reg21 ++#define RG_SSUSB_PLL_SSC_DELTA_U3 (0xffff<<16) //31:16 ++#define RG_SSUSB_PLL_SSC_DELTA1_PE2D (0xffff<<0) //15:0 ++ ++//U3D_reg23 ++#define RG_SSUSB_PLL_SSC_DELTA_PE1D (0xffff<<16) //31:16 ++#define RG_SSUSB_PLL_SSC_DELTA_PE1H (0xffff<<0) //15:0 ++ ++//U3D_reg25 ++#define RG_SSUSB_PLL_SSC_DELTA_PE2D (0xffff<<16) //31:16 ++#define RG_SSUSB_PLL_SSC_DELTA_PE2H (0xffff<<0) //15:0 ++ ++//U3D_reg26 ++#define RG_SSUSB_PLL_REFCKDIV_PE2D (0x1<<25) //25:25 ++#define RG_SSUSB_PLL_REFCKDIV_PE2H (0x1<<24) //24:24 ++#define RG_SSUSB_PLL_REFCKDIV_PE1D (0x1<<16) //16:16 ++#define RG_SSUSB_PLL_REFCKDIV_PE1H (0x1<<8) //8:8 ++#define RG_SSUSB_PLL_REFCKDIV_U3 (0x1<<0) //0:0 ++ ++//U3D_reg28 ++#define RG_SSUSB_CDR_BPA_PE2D (0x3<<24) //25:24 ++#define RG_SSUSB_CDR_BPA_PE2H (0x3<<16) //17:16 ++#define RG_SSUSB_CDR_BPA_PE1D (0x3<<10) //11:10 ++#define RG_SSUSB_CDR_BPA_PE1H (0x3<<8) //9:8 ++#define RG_SSUSB_CDR_BPA_U3 (0x3<<0) //1:0 ++ ++//U3D_reg29 ++#define RG_SSUSB_CDR_BPB_PE2D (0x7<<24) //26:24 ++#define RG_SSUSB_CDR_BPB_PE2H (0x7<<16) //18:16 ++#define RG_SSUSB_CDR_BPB_PE1D (0x7<<6) //8:6 ++#define RG_SSUSB_CDR_BPB_PE1H (0x7<<3) //5:3 ++#define RG_SSUSB_CDR_BPB_U3 (0x7<<0) //2:0 ++ ++//U3D_reg30 ++#define RG_SSUSB_CDR_BR_PE2D (0x7<<24) //26:24 ++#define RG_SSUSB_CDR_BR_PE2H (0x7<<16) //18:16 ++#define RG_SSUSB_CDR_BR_PE1D (0x7<<6) //8:6 ++#define RG_SSUSB_CDR_BR_PE1H (0x7<<3) //5:3 ++#define RG_SSUSB_CDR_BR_U3 (0x7<<0) //2:0 ++ ++//U3D_reg31 ++#define RG_SSUSB_CDR_FBDIV_PE2H (0x7f<<24) //30:24 ++#define RG_SSUSB_CDR_FBDIV_PE1D (0x7f<<16) //22:16 ++#define RG_SSUSB_CDR_FBDIV_PE1H (0x7f<<8) //14:8 ++#define RG_SSUSB_CDR_FBDIV_U3 (0x7f<<0) //6:0 ++ ++//U3D_reg32 ++#define RG_SSUSB_EQ_RSTEP1_PE2D (0x3<<30) //31:30 ++#define RG_SSUSB_EQ_RSTEP1_PE2H (0x3<<28) //29:28 ++#define RG_SSUSB_EQ_RSTEP1_PE1D (0x3<<26) //27:26 ++#define RG_SSUSB_EQ_RSTEP1_PE1H (0x3<<24) //25:24 ++#define RG_SSUSB_EQ_RSTEP1_U3 (0x3<<22) //23:22 ++#define RG_SSUSB_LFPS_DEGLITCH_PE2D (0x3<<20) //21:20 ++#define RG_SSUSB_LFPS_DEGLITCH_PE2H (0x3<<18) //19:18 ++#define RG_SSUSB_LFPS_DEGLITCH_PE1D (0x3<<16) //17:16 ++#define RG_SSUSB_LFPS_DEGLITCH_PE1H (0x3<<14) //15:14 ++#define RG_SSUSB_LFPS_DEGLITCH_U3 (0x3<<12) //13:12 ++#define RG_SSUSB_CDR_KVSEL_PE2D (0x1<<11) //11:11 ++#define RG_SSUSB_CDR_KVSEL_PE2H (0x1<<10) //10:10 ++#define RG_SSUSB_CDR_KVSEL_PE1D (0x1<<9) //9:9 ++#define RG_SSUSB_CDR_KVSEL_PE1H (0x1<<8) //8:8 ++#define RG_SSUSB_CDR_KVSEL_U3 (0x1<<7) //7:7 ++#define RG_SSUSB_CDR_FBDIV_PE2D (0x7f<<0) //6:0 ++ ++//U3D_reg33 ++#define RG_SSUSB_RX_CMPWD_PE2D (0x1<<26) //26:26 ++#define RG_SSUSB_RX_CMPWD_PE2H (0x1<<25) //25:25 ++#define RG_SSUSB_RX_CMPWD_PE1D (0x1<<24) //24:24 ++#define RG_SSUSB_RX_CMPWD_PE1H (0x1<<23) //23:23 ++#define RG_SSUSB_RX_CMPWD_U3 (0x1<<16) //16:16 ++#define RG_SSUSB_EQ_RSTEP2_PE2D (0x3<<8) //9:8 ++#define RG_SSUSB_EQ_RSTEP2_PE2H (0x3<<6) //7:6 ++#define RG_SSUSB_EQ_RSTEP2_PE1D (0x3<<4) //5:4 ++#define RG_SSUSB_EQ_RSTEP2_PE1H (0x3<<2) //3:2 ++#define RG_SSUSB_EQ_RSTEP2_U3 (0x3<<0) //1:0 ++ ++ ++/* OFFSET */ ++ ++//U3D_reg0 ++#define RG_PCIE_SPEED_PE2D_OFST (24) ++#define RG_PCIE_SPEED_PE2H_OFST (23) ++#define RG_PCIE_SPEED_PE1D_OFST (22) ++#define RG_PCIE_SPEED_PE1H_OFST (21) ++#define RG_PCIE_SPEED_U3_OFST (20) ++#define RG_SSUSB_XTAL_EXT_EN_PE2D_OFST (18) ++#define RG_SSUSB_XTAL_EXT_EN_PE2H_OFST (16) ++#define RG_SSUSB_XTAL_EXT_EN_PE1D_OFST (14) ++#define RG_SSUSB_XTAL_EXT_EN_PE1H_OFST (12) ++#define RG_SSUSB_XTAL_EXT_EN_U3_OFST (10) ++#define RG_SSUSB_CDR_REFCK_SEL_PE2D_OFST (8) ++#define RG_SSUSB_CDR_REFCK_SEL_PE2H_OFST (6) ++#define RG_SSUSB_CDR_REFCK_SEL_PE1D_OFST (4) ++#define RG_SSUSB_CDR_REFCK_SEL_PE1H_OFST (2) ++#define RG_SSUSB_CDR_REFCK_SEL_U3_OFST (0) ++ ++//U3D_reg1 ++#define RG_USB20_REFCK_SEL_PE2D_OFST (30) ++#define RG_USB20_REFCK_SEL_PE2H_OFST (29) ++#define RG_USB20_REFCK_SEL_PE1D_OFST (28) ++#define RG_USB20_REFCK_SEL_PE1H_OFST (27) ++#define RG_USB20_REFCK_SEL_U3_OFST (26) ++#define RG_PCIE_REFCK_DIV4_PE2D_OFST (25) ++#define RG_PCIE_REFCK_DIV4_PE2H_OFST (24) ++#define RG_PCIE_REFCK_DIV4_PE1D_OFST (18) ++#define RG_PCIE_REFCK_DIV4_PE1H_OFST (17) ++#define RG_PCIE_REFCK_DIV4_U3_OFST (16) ++#define RG_PCIE_MODE_PE2D_OFST (8) ++#define RG_PCIE_MODE_PE2H_OFST (3) ++#define RG_PCIE_MODE_PE1D_OFST (2) ++#define RG_PCIE_MODE_PE1H_OFST (1) ++#define RG_PCIE_MODE_U3_OFST (0) ++ ++//U3D_reg4 ++#define RG_SSUSB_PLL_DIVEN_PE2D_OFST (22) ++#define RG_SSUSB_PLL_DIVEN_PE2H_OFST (19) ++#define RG_SSUSB_PLL_DIVEN_PE1D_OFST (16) ++#define RG_SSUSB_PLL_DIVEN_PE1H_OFST (13) ++#define RG_SSUSB_PLL_DIVEN_U3_OFST (10) ++#define RG_SSUSB_PLL_BC_PE2D_OFST (8) ++#define RG_SSUSB_PLL_BC_PE2H_OFST (6) ++#define RG_SSUSB_PLL_BC_PE1D_OFST (4) ++#define RG_SSUSB_PLL_BC_PE1H_OFST (2) ++#define RG_SSUSB_PLL_BC_U3_OFST (0) ++ ++//U3D_reg5 ++#define RG_SSUSB_PLL_BR_PE2D_OFST (27) ++#define RG_SSUSB_PLL_BR_PE2H_OFST (24) ++#define RG_SSUSB_PLL_BR_PE1D_OFST (21) ++#define RG_SSUSB_PLL_BR_PE1H_OFST (18) ++#define RG_SSUSB_PLL_BR_U3_OFST (15) ++#define RG_SSUSB_PLL_IC_PE2D_OFST (12) ++#define RG_SSUSB_PLL_IC_PE2H_OFST (9) ++#define RG_SSUSB_PLL_IC_PE1D_OFST (6) ++#define RG_SSUSB_PLL_IC_PE1H_OFST (3) ++#define RG_SSUSB_PLL_IC_U3_OFST (0) ++ ++//U3D_reg6 ++#define RG_SSUSB_PLL_IR_PE2D_OFST (24) ++#define RG_SSUSB_PLL_IR_PE2H_OFST (16) ++#define RG_SSUSB_PLL_IR_PE1D_OFST (8) ++#define RG_SSUSB_PLL_IR_PE1H_OFST (4) ++#define RG_SSUSB_PLL_IR_U3_OFST (0) ++ ++//U3D_reg7 ++#define RG_SSUSB_PLL_BP_PE2D_OFST (24) ++#define RG_SSUSB_PLL_BP_PE2H_OFST (16) ++#define RG_SSUSB_PLL_BP_PE1D_OFST (8) ++#define RG_SSUSB_PLL_BP_PE1H_OFST (4) ++#define RG_SSUSB_PLL_BP_U3_OFST (0) ++ ++//U3D_reg8 ++#define RG_SSUSB_PLL_FBKSEL_PE2D_OFST (24) ++#define RG_SSUSB_PLL_FBKSEL_PE2H_OFST (16) ++#define RG_SSUSB_PLL_FBKSEL_PE1D_OFST (8) ++#define RG_SSUSB_PLL_FBKSEL_PE1H_OFST (2) ++#define RG_SSUSB_PLL_FBKSEL_U3_OFST (0) ++ ++//U3D_reg9 ++#define RG_SSUSB_PLL_FBKDIV_PE2H_OFST (24) ++#define RG_SSUSB_PLL_FBKDIV_PE1D_OFST (16) ++#define RG_SSUSB_PLL_FBKDIV_PE1H_OFST (8) ++#define RG_SSUSB_PLL_FBKDIV_U3_OFST (0) ++ ++//U3D_reg10 ++#define RG_SSUSB_PLL_PREDIV_PE2D_OFST (26) ++#define RG_SSUSB_PLL_PREDIV_PE2H_OFST (24) ++#define RG_SSUSB_PLL_PREDIV_PE1D_OFST (18) ++#define RG_SSUSB_PLL_PREDIV_PE1H_OFST (16) ++#define RG_SSUSB_PLL_PREDIV_U3_OFST (8) ++#define RG_SSUSB_PLL_FBKDIV_PE2D_OFST (0) ++ ++//U3D_reg12 ++#define RG_SSUSB_PLL_PCW_NCPO_U3_OFST (0) ++ ++//U3D_reg13 ++#define RG_SSUSB_PLL_PCW_NCPO_PE1H_OFST (0) ++ ++//U3D_reg14 ++#define RG_SSUSB_PLL_PCW_NCPO_PE1D_OFST (0) ++ ++//U3D_reg15 ++#define RG_SSUSB_PLL_PCW_NCPO_PE2H_OFST (0) ++ ++//U3D_reg16 ++#define RG_SSUSB_PLL_PCW_NCPO_PE2D_OFST (0) ++ ++//U3D_reg19 ++#define RG_SSUSB_PLL_SSC_DELTA1_PE1H_OFST (16) ++#define RG_SSUSB_PLL_SSC_DELTA1_U3_OFST (0) ++ ++//U3D_reg20 ++#define RG_SSUSB_PLL_SSC_DELTA1_PE2H_OFST (16) ++#define RG_SSUSB_PLL_SSC_DELTA1_PE1D_OFST (0) ++ ++//U3D_reg21 ++#define RG_SSUSB_PLL_SSC_DELTA_U3_OFST (16) ++#define RG_SSUSB_PLL_SSC_DELTA1_PE2D_OFST (0) ++ ++//U3D_reg23 ++#define RG_SSUSB_PLL_SSC_DELTA_PE1D_OFST (16) ++#define RG_SSUSB_PLL_SSC_DELTA_PE1H_OFST (0) ++ ++//U3D_reg25 ++#define RG_SSUSB_PLL_SSC_DELTA_PE2D_OFST (16) ++#define RG_SSUSB_PLL_SSC_DELTA_PE2H_OFST (0) ++ ++//U3D_reg26 ++#define RG_SSUSB_PLL_REFCKDIV_PE2D_OFST (25) ++#define RG_SSUSB_PLL_REFCKDIV_PE2H_OFST (24) ++#define RG_SSUSB_PLL_REFCKDIV_PE1D_OFST (16) ++#define RG_SSUSB_PLL_REFCKDIV_PE1H_OFST (8) ++#define RG_SSUSB_PLL_REFCKDIV_U3_OFST (0) ++ ++//U3D_reg28 ++#define RG_SSUSB_CDR_BPA_PE2D_OFST (24) ++#define RG_SSUSB_CDR_BPA_PE2H_OFST (16) ++#define RG_SSUSB_CDR_BPA_PE1D_OFST (10) ++#define RG_SSUSB_CDR_BPA_PE1H_OFST (8) ++#define RG_SSUSB_CDR_BPA_U3_OFST (0) ++ ++//U3D_reg29 ++#define RG_SSUSB_CDR_BPB_PE2D_OFST (24) ++#define RG_SSUSB_CDR_BPB_PE2H_OFST (16) ++#define RG_SSUSB_CDR_BPB_PE1D_OFST (6) ++#define RG_SSUSB_CDR_BPB_PE1H_OFST (3) ++#define RG_SSUSB_CDR_BPB_U3_OFST (0) ++ ++//U3D_reg30 ++#define RG_SSUSB_CDR_BR_PE2D_OFST (24) ++#define RG_SSUSB_CDR_BR_PE2H_OFST (16) ++#define RG_SSUSB_CDR_BR_PE1D_OFST (6) ++#define RG_SSUSB_CDR_BR_PE1H_OFST (3) ++#define RG_SSUSB_CDR_BR_U3_OFST (0) ++ ++//U3D_reg31 ++#define RG_SSUSB_CDR_FBDIV_PE2H_OFST (24) ++#define RG_SSUSB_CDR_FBDIV_PE1D_OFST (16) ++#define RG_SSUSB_CDR_FBDIV_PE1H_OFST (8) ++#define RG_SSUSB_CDR_FBDIV_U3_OFST (0) ++ ++//U3D_reg32 ++#define RG_SSUSB_EQ_RSTEP1_PE2D_OFST (30) ++#define RG_SSUSB_EQ_RSTEP1_PE2H_OFST (28) ++#define RG_SSUSB_EQ_RSTEP1_PE1D_OFST (26) ++#define RG_SSUSB_EQ_RSTEP1_PE1H_OFST (24) ++#define RG_SSUSB_EQ_RSTEP1_U3_OFST (22) ++#define RG_SSUSB_LFPS_DEGLITCH_PE2D_OFST (20) ++#define RG_SSUSB_LFPS_DEGLITCH_PE2H_OFST (18) ++#define RG_SSUSB_LFPS_DEGLITCH_PE1D_OFST (16) ++#define RG_SSUSB_LFPS_DEGLITCH_PE1H_OFST (14) ++#define RG_SSUSB_LFPS_DEGLITCH_U3_OFST (12) ++#define RG_SSUSB_CDR_KVSEL_PE2D_OFST (11) ++#define RG_SSUSB_CDR_KVSEL_PE2H_OFST (10) ++#define RG_SSUSB_CDR_KVSEL_PE1D_OFST (9) ++#define RG_SSUSB_CDR_KVSEL_PE1H_OFST (8) ++#define RG_SSUSB_CDR_KVSEL_U3_OFST (7) ++#define RG_SSUSB_CDR_FBDIV_PE2D_OFST (0) ++ ++//U3D_reg33 ++#define RG_SSUSB_RX_CMPWD_PE2D_OFST (26) ++#define RG_SSUSB_RX_CMPWD_PE2H_OFST (25) ++#define RG_SSUSB_RX_CMPWD_PE1D_OFST (24) ++#define RG_SSUSB_RX_CMPWD_PE1H_OFST (23) ++#define RG_SSUSB_RX_CMPWD_U3_OFST (16) ++#define RG_SSUSB_EQ_RSTEP2_PE2D_OFST (8) ++#define RG_SSUSB_EQ_RSTEP2_PE2H_OFST (6) ++#define RG_SSUSB_EQ_RSTEP2_PE1D_OFST (4) ++#define RG_SSUSB_EQ_RSTEP2_PE1H_OFST (2) ++#define RG_SSUSB_EQ_RSTEP2_U3_OFST (0) ++ ++ ++/////////////////////////////////////////////////////////////////////////////// ++ ++struct u3phyd_reg { ++ //0x0 ++ PHY_LE32 phyd_mix0; ++ PHY_LE32 phyd_mix1; ++ PHY_LE32 phyd_lfps0; ++ PHY_LE32 phyd_lfps1; ++ //0x10 ++ PHY_LE32 phyd_impcal0; ++ PHY_LE32 phyd_impcal1; ++ PHY_LE32 phyd_txpll0; ++ PHY_LE32 phyd_txpll1; ++ //0x20 ++ PHY_LE32 phyd_txpll2; ++ PHY_LE32 phyd_fl0; ++ PHY_LE32 phyd_mix2; ++ PHY_LE32 phyd_rx0; ++ //0x30 ++ PHY_LE32 phyd_t2rlb; ++ PHY_LE32 phyd_cppat; ++ PHY_LE32 phyd_mix3; ++ PHY_LE32 phyd_ebufctl; ++ //0x40 ++ PHY_LE32 phyd_pipe0; ++ PHY_LE32 phyd_pipe1; ++ PHY_LE32 phyd_mix4; ++ PHY_LE32 phyd_ckgen0; ++ //0x50 ++ PHY_LE32 phyd_mix5; ++ PHY_LE32 phyd_reserved; ++ PHY_LE32 phyd_cdr0; ++ PHY_LE32 phyd_cdr1; ++ //0x60 ++ PHY_LE32 phyd_pll_0; ++ PHY_LE32 phyd_pll_1; ++ PHY_LE32 phyd_bcn_det_1; ++ PHY_LE32 phyd_bcn_det_2; ++ //0x70 ++ PHY_LE32 eq0; ++ PHY_LE32 eq1; ++ PHY_LE32 eq2; ++ PHY_LE32 eq3; ++ //0x80 ++ PHY_LE32 eq_eye0; ++ PHY_LE32 eq_eye1; ++ PHY_LE32 eq_eye2; ++ PHY_LE32 eq_dfe0; ++ //0x90 ++ PHY_LE32 eq_dfe1; ++ PHY_LE32 eq_dfe2; ++ PHY_LE32 eq_dfe3; ++ PHY_LE32 reserve0; ++ //0xa0 ++ PHY_LE32 phyd_mon0; ++ PHY_LE32 phyd_mon1; ++ PHY_LE32 phyd_mon2; ++ PHY_LE32 phyd_mon3; ++ //0xb0 ++ PHY_LE32 phyd_mon4; ++ PHY_LE32 phyd_mon5; ++ PHY_LE32 phyd_mon6; ++ PHY_LE32 phyd_mon7; ++ //0xc0 ++ PHY_LE32 phya_rx_mon0; ++ PHY_LE32 phya_rx_mon1; ++ PHY_LE32 phya_rx_mon2; ++ PHY_LE32 phya_rx_mon3; ++ //0xd0 ++ PHY_LE32 phya_rx_mon4; ++ PHY_LE32 phya_rx_mon5; ++ PHY_LE32 phyd_cppat2; ++ PHY_LE32 eq_eye3; ++ //0xe0 ++ PHY_LE32 kband_out; ++ PHY_LE32 kband_out1; ++}; ++ ++//U3D_PHYD_MIX0 ++#define RG_SSUSB_P_P3_TX_NG (0x1<<31) //31:31 ++#define RG_SSUSB_TSEQ_EN (0x1<<30) //30:30 ++#define RG_SSUSB_TSEQ_POLEN (0x1<<29) //29:29 ++#define RG_SSUSB_TSEQ_POL (0x1<<28) //28:28 ++#define RG_SSUSB_P_P3_PCLK_NG (0x1<<27) //27:27 ++#define RG_SSUSB_TSEQ_TH (0x7<<24) //26:24 ++#define RG_SSUSB_PRBS_BERTH (0xff<<16) //23:16 ++#define RG_SSUSB_DISABLE_PHY_U2_ON (0x1<<15) //15:15 ++#define RG_SSUSB_DISABLE_PHY_U2_OFF (0x1<<14) //14:14 ++#define RG_SSUSB_PRBS_EN (0x1<<13) //13:13 ++#define RG_SSUSB_BPSLOCK (0x1<<12) //12:12 ++#define RG_SSUSB_RTCOMCNT (0xf<<8) //11:8 ++#define RG_SSUSB_COMCNT (0xf<<4) //7:4 ++#define RG_SSUSB_PRBSEL_CALIB (0xf<<0) //3:0 ++ ++//U3D_PHYD_MIX1 ++#define RG_SSUSB_SLEEP_EN (0x1<<31) //31:31 ++#define RG_SSUSB_PRBSEL_PCS (0x7<<28) //30:28 ++#define RG_SSUSB_TXLFPS_PRD (0xf<<24) //27:24 ++#define RG_SSUSB_P_RX_P0S_CK (0x1<<23) //23:23 ++#define RG_SSUSB_P_TX_P0S_CK (0x1<<22) //22:22 ++#define RG_SSUSB_PDNCTL (0x3f<<16) //21:16 ++#define RG_SSUSB_TX_DRV_EN (0x1<<15) //15:15 ++#define RG_SSUSB_TX_DRV_SEL (0x1<<14) //14:14 ++#define RG_SSUSB_TX_DRV_DLY (0x3f<<8) //13:8 ++#define RG_SSUSB_BERT_EN (0x1<<7) //7:7 ++#define RG_SSUSB_SCP_TH (0x7<<4) //6:4 ++#define RG_SSUSB_SCP_EN (0x1<<3) //3:3 ++#define RG_SSUSB_RXANSIDEC_TEST (0x7<<0) //2:0 ++ ++//U3D_PHYD_LFPS0 ++#define RG_SSUSB_LFPS_PWD (0x1<<30) //30:30 ++#define RG_SSUSB_FORCE_LFPS_PWD (0x1<<29) //29:29 ++#define RG_SSUSB_RXLFPS_OVF (0x1f<<24) //28:24 ++#define RG_SSUSB_P3_ENTRY_SEL (0x1<<23) //23:23 ++#define RG_SSUSB_P3_ENTRY (0x1<<22) //22:22 ++#define RG_SSUSB_RXLFPS_CDRSEL (0x3<<20) //21:20 ++#define RG_SSUSB_RXLFPS_CDRTH (0xf<<16) //19:16 ++#define RG_SSUSB_LOCK5G_BLOCK (0x1<<15) //15:15 ++#define RG_SSUSB_TFIFO_EXT_D_SEL (0x1<<14) //14:14 ++#define RG_SSUSB_TFIFO_NO_EXTEND (0x1<<13) //13:13 ++#define RG_SSUSB_RXLFPS_LOB (0x1f<<8) //12:8 ++#define RG_SSUSB_TXLFPS_EN (0x1<<7) //7:7 ++#define RG_SSUSB_TXLFPS_SEL (0x1<<6) //6:6 ++#define RG_SSUSB_RXLFPS_CDRLOCK (0x1<<5) //5:5 ++#define RG_SSUSB_RXLFPS_UPB (0x1f<<0) //4:0 ++ ++//U3D_PHYD_LFPS1 ++#define RG_SSUSB_RX_IMP_BIAS (0xf<<28) //31:28 ++#define RG_SSUSB_TX_IMP_BIAS (0xf<<24) //27:24 ++#define RG_SSUSB_FWAKE_TH (0x3f<<16) //21:16 ++#define RG_SSUSB_RXLFPS_UDF (0x1f<<8) //12:8 ++#define RG_SSUSB_RXLFPS_P0IDLETH (0xff<<0) //7:0 ++ ++//U3D_PHYD_IMPCAL0 ++#define RG_SSUSB_FORCE_TX_IMPSEL (0x1<<31) //31:31 ++#define RG_SSUSB_TX_IMPCAL_EN (0x1<<30) //30:30 ++#define RG_SSUSB_FORCE_TX_IMPCAL_EN (0x1<<29) //29:29 ++#define RG_SSUSB_TX_IMPSEL (0x1f<<24) //28:24 ++#define RG_SSUSB_TX_IMPCAL_CALCYC (0x3f<<16) //21:16 ++#define RG_SSUSB_TX_IMPCAL_STBCYC (0x1f<<10) //14:10 ++#define RG_SSUSB_TX_IMPCAL_CYCCNT (0x3ff<<0) //9:0 ++ ++//U3D_PHYD_IMPCAL1 ++#define RG_SSUSB_FORCE_RX_IMPSEL (0x1<<31) //31:31 ++#define RG_SSUSB_RX_IMPCAL_EN (0x1<<30) //30:30 ++#define RG_SSUSB_FORCE_RX_IMPCAL_EN (0x1<<29) //29:29 ++#define RG_SSUSB_RX_IMPSEL (0x1f<<24) //28:24 ++#define RG_SSUSB_RX_IMPCAL_CALCYC (0x3f<<16) //21:16 ++#define RG_SSUSB_RX_IMPCAL_STBCYC (0x1f<<10) //14:10 ++#define RG_SSUSB_RX_IMPCAL_CYCCNT (0x3ff<<0) //9:0 ++ ++//U3D_PHYD_TXPLL0 ++#define RG_SSUSB_TXPLL_DDSEN_CYC (0x1f<<27) //31:27 ++#define RG_SSUSB_TXPLL_ON (0x1<<26) //26:26 ++#define RG_SSUSB_FORCE_TXPLLON (0x1<<25) //25:25 ++#define RG_SSUSB_TXPLL_STBCYC (0x1ff<<16) //24:16 ++#define RG_SSUSB_TXPLL_NCPOCHG_CYC (0xf<<12) //15:12 ++#define RG_SSUSB_TXPLL_NCPOEN_CYC (0x3<<10) //11:10 ++#define RG_SSUSB_TXPLL_DDSRSTB_CYC (0x7<<0) //2:0 ++ ++//U3D_PHYD_TXPLL1 ++#define RG_SSUSB_PLL_NCPO_EN (0x1<<31) //31:31 ++#define RG_SSUSB_PLL_FIFO_START_MAN (0x1<<30) //30:30 ++#define RG_SSUSB_PLL_NCPO_CHG (0x1<<28) //28:28 ++#define RG_SSUSB_PLL_DDS_RSTB (0x1<<27) //27:27 ++#define RG_SSUSB_PLL_DDS_PWDB (0x1<<26) //26:26 ++#define RG_SSUSB_PLL_DDSEN (0x1<<25) //25:25 ++#define RG_SSUSB_PLL_AUTOK_VCO (0x1<<24) //24:24 ++#define RG_SSUSB_PLL_PWD (0x1<<23) //23:23 ++#define RG_SSUSB_RX_AFE_PWD (0x1<<22) //22:22 ++#define RG_SSUSB_PLL_TCADJ (0x3f<<16) //21:16 ++#define RG_SSUSB_FORCE_CDR_TCADJ (0x1<<15) //15:15 ++#define RG_SSUSB_FORCE_CDR_AUTOK_VCO (0x1<<14) //14:14 ++#define RG_SSUSB_FORCE_CDR_PWD (0x1<<13) //13:13 ++#define RG_SSUSB_FORCE_PLL_NCPO_EN (0x1<<12) //12:12 ++#define RG_SSUSB_FORCE_PLL_FIFO_START_MAN (0x1<<11) //11:11 ++#define RG_SSUSB_FORCE_PLL_NCPO_CHG (0x1<<9) //9:9 ++#define RG_SSUSB_FORCE_PLL_DDS_RSTB (0x1<<8) //8:8 ++#define RG_SSUSB_FORCE_PLL_DDS_PWDB (0x1<<7) //7:7 ++#define RG_SSUSB_FORCE_PLL_DDSEN (0x1<<6) //6:6 ++#define RG_SSUSB_FORCE_PLL_TCADJ (0x1<<5) //5:5 ++#define RG_SSUSB_FORCE_PLL_AUTOK_VCO (0x1<<4) //4:4 ++#define RG_SSUSB_FORCE_PLL_PWD (0x1<<3) //3:3 ++#define RG_SSUSB_FLT_1_DISPERR_B (0x1<<2) //2:2 ++ ++//U3D_PHYD_TXPLL2 ++#define RG_SSUSB_TX_LFPS_EN (0x1<<31) //31:31 ++#define RG_SSUSB_FORCE_TX_LFPS_EN (0x1<<30) //30:30 ++#define RG_SSUSB_TX_LFPS (0x1<<29) //29:29 ++#define RG_SSUSB_FORCE_TX_LFPS (0x1<<28) //28:28 ++#define RG_SSUSB_RXPLL_STB (0x1<<27) //27:27 ++#define RG_SSUSB_TXPLL_STB (0x1<<26) //26:26 ++#define RG_SSUSB_FORCE_RXPLL_STB (0x1<<25) //25:25 ++#define RG_SSUSB_FORCE_TXPLL_STB (0x1<<24) //24:24 ++#define RG_SSUSB_RXPLL_REFCKSEL (0x1<<16) //16:16 ++#define RG_SSUSB_RXPLL_STBMODE (0x1<<11) //11:11 ++#define RG_SSUSB_RXPLL_ON (0x1<<10) //10:10 ++#define RG_SSUSB_FORCE_RXPLLON (0x1<<9) //9:9 ++#define RG_SSUSB_FORCE_RX_AFE_PWD (0x1<<8) //8:8 ++#define RG_SSUSB_CDR_AUTOK_VCO (0x1<<7) //7:7 ++#define RG_SSUSB_CDR_PWD (0x1<<6) //6:6 ++#define RG_SSUSB_CDR_TCADJ (0x3f<<0) //5:0 ++ ++//U3D_PHYD_FL0 ++#define RG_SSUSB_RX_FL_TARGET (0xffff<<16) //31:16 ++#define RG_SSUSB_RX_FL_CYCLECNT (0xffff<<0) //15:0 ++ ++//U3D_PHYD_MIX2 ++#define RG_SSUSB_RX_EQ_RST (0x1<<31) //31:31 ++#define RG_SSUSB_RX_EQ_RST_SEL (0x1<<30) //30:30 ++#define RG_SSUSB_RXVAL_RST (0x1<<29) //29:29 ++#define RG_SSUSB_RXVAL_CNT (0x1f<<24) //28:24 ++#define RG_SSUSB_CDROS_EN (0x1<<18) //18:18 ++#define RG_SSUSB_CDR_LCKOP (0x3<<16) //17:16 ++#define RG_SSUSB_RX_FL_LOCKTH (0xf<<8) //11:8 ++#define RG_SSUSB_RX_FL_OFFSET (0xff<<0) //7:0 ++ ++//U3D_PHYD_RX0 ++#define RG_SSUSB_T2RLB_BERTH (0xff<<24) //31:24 ++#define RG_SSUSB_T2RLB_PAT (0xff<<16) //23:16 ++#define RG_SSUSB_T2RLB_EN (0x1<<15) //15:15 ++#define RG_SSUSB_T2RLB_BPSCRAMB (0x1<<14) //14:14 ++#define RG_SSUSB_T2RLB_SERIAL (0x1<<13) //13:13 ++#define RG_SSUSB_T2RLB_MODE (0x3<<11) //12:11 ++#define RG_SSUSB_RX_SAOSC_EN (0x1<<10) //10:10 ++#define RG_SSUSB_RX_SAOSC_EN_SEL (0x1<<9) //9:9 ++#define RG_SSUSB_RX_DFE_OPTION (0x1<<8) //8:8 ++#define RG_SSUSB_RX_DFE_EN (0x1<<7) //7:7 ++#define RG_SSUSB_RX_DFE_EN_SEL (0x1<<6) //6:6 ++#define RG_SSUSB_RX_EQ_EN (0x1<<5) //5:5 ++#define RG_SSUSB_RX_EQ_EN_SEL (0x1<<4) //4:4 ++#define RG_SSUSB_RX_SAOSC_RST (0x1<<3) //3:3 ++#define RG_SSUSB_RX_SAOSC_RST_SEL (0x1<<2) //2:2 ++#define RG_SSUSB_RX_DFE_RST (0x1<<1) //1:1 ++#define RG_SSUSB_RX_DFE_RST_SEL (0x1<<0) //0:0 ++ ++//U3D_PHYD_T2RLB ++#define RG_SSUSB_EQTRAIN_CH_MODE (0x1<<28) //28:28 ++#define RG_SSUSB_PRB_OUT_CPPAT (0x1<<27) //27:27 ++#define RG_SSUSB_BPANSIENC (0x1<<26) //26:26 ++#define RG_SSUSB_VALID_EN (0x1<<25) //25:25 ++#define RG_SSUSB_EBUF_SRST (0x1<<24) //24:24 ++#define RG_SSUSB_K_EMP (0xf<<20) //23:20 ++#define RG_SSUSB_K_FUL (0xf<<16) //19:16 ++#define RG_SSUSB_T2RLB_BDATRST (0xf<<12) //15:12 ++#define RG_SSUSB_P_T2RLB_SKP_EN (0x1<<10) //10:10 ++#define RG_SSUSB_T2RLB_PATMODE (0x3<<8) //9:8 ++#define RG_SSUSB_T2RLB_TSEQCNT (0xff<<0) //7:0 ++ ++//U3D_PHYD_CPPAT ++#define RG_SSUSB_CPPAT_PROGRAM_EN (0x1<<24) //24:24 ++#define RG_SSUSB_CPPAT_TOZ (0x3<<21) //22:21 ++#define RG_SSUSB_CPPAT_PRBS_EN (0x1<<20) //20:20 ++#define RG_SSUSB_CPPAT_OUT_TMP2 (0xf<<16) //19:16 ++#define RG_SSUSB_CPPAT_OUT_TMP1 (0xff<<8) //15:8 ++#define RG_SSUSB_CPPAT_OUT_TMP0 (0xff<<0) //7:0 ++ ++//U3D_PHYD_MIX3 ++#define RG_SSUSB_CDR_TCADJ_MINUS (0x1<<31) //31:31 ++#define RG_SSUSB_P_CDROS_EN (0x1<<30) //30:30 ++#define RG_SSUSB_P_P2_TX_DRV_DIS (0x1<<28) //28:28 ++#define RG_SSUSB_CDR_TCADJ_OFFSET (0x7<<24) //26:24 ++#define RG_SSUSB_PLL_TCADJ_MINUS (0x1<<23) //23:23 ++#define RG_SSUSB_FORCE_PLL_BIAS_LPF_EN (0x1<<20) //20:20 ++#define RG_SSUSB_PLL_BIAS_LPF_EN (0x1<<19) //19:19 ++#define RG_SSUSB_PLL_TCADJ_OFFSET (0x7<<16) //18:16 ++#define RG_SSUSB_FORCE_PLL_SSCEN (0x1<<15) //15:15 ++#define RG_SSUSB_PLL_SSCEN (0x1<<14) //14:14 ++#define RG_SSUSB_FORCE_CDR_PI_PWD (0x1<<13) //13:13 ++#define RG_SSUSB_CDR_PI_PWD (0x1<<12) //12:12 ++#define RG_SSUSB_CDR_PI_MODE (0x1<<11) //11:11 ++#define RG_SSUSB_TXPLL_SSCEN_CYC (0x3ff<<0) //9:0 ++ ++//U3D_PHYD_EBUFCTL ++#define RG_SSUSB_EBUFCTL (0xffffffff<<0) //31:0 ++ ++//U3D_PHYD_PIPE0 ++#define RG_SSUSB_RXTERMINATION (0x1<<30) //30:30 ++#define RG_SSUSB_RXEQTRAINING (0x1<<29) //29:29 ++#define RG_SSUSB_RXPOLARITY (0x1<<28) //28:28 ++#define RG_SSUSB_TXDEEMPH (0x3<<26) //27:26 ++#define RG_SSUSB_POWERDOWN (0x3<<24) //25:24 ++#define RG_SSUSB_TXONESZEROS (0x1<<23) //23:23 ++#define RG_SSUSB_TXELECIDLE (0x1<<22) //22:22 ++#define RG_SSUSB_TXDETECTRX (0x1<<21) //21:21 ++#define RG_SSUSB_PIPE_SEL (0x1<<20) //20:20 ++#define RG_SSUSB_TXDATAK (0xf<<16) //19:16 ++#define RG_SSUSB_CDR_STABLE_SEL (0x1<<15) //15:15 ++#define RG_SSUSB_CDR_STABLE (0x1<<14) //14:14 ++#define RG_SSUSB_CDR_RSTB_SEL (0x1<<13) //13:13 ++#define RG_SSUSB_CDR_RSTB (0x1<<12) //12:12 ++#define RG_SSUSB_P_ERROR_SEL (0x3<<4) //5:4 ++#define RG_SSUSB_TXMARGIN (0x7<<1) //3:1 ++#define RG_SSUSB_TXCOMPLIANCE (0x1<<0) //0:0 ++ ++//U3D_PHYD_PIPE1 ++#define RG_SSUSB_TXDATA (0xffffffff<<0) //31:0 ++ ++//U3D_PHYD_MIX4 ++#define RG_SSUSB_CDROS_CNT (0x3f<<24) //29:24 ++#define RG_SSUSB_T2RLB_BER_EN (0x1<<16) //16:16 ++#define RG_SSUSB_T2RLB_BER_RATE (0xffff<<0) //15:0 ++ ++//U3D_PHYD_CKGEN0 ++#define RG_SSUSB_RFIFO_IMPLAT (0x1<<27) //27:27 ++#define RG_SSUSB_TFIFO_PSEL (0x7<<24) //26:24 ++#define RG_SSUSB_CKGEN_PSEL (0x3<<8) //9:8 ++#define RG_SSUSB_RXCK_INV (0x1<<0) //0:0 ++ ++//U3D_PHYD_MIX5 ++#define RG_SSUSB_PRB_SEL (0xffff<<16) //31:16 ++#define RG_SSUSB_RXPLL_STBCYC (0x7ff<<0) //10:0 ++ ++//U3D_PHYD_RESERVED ++#define RG_SSUSB_PHYD_RESERVE (0xffffffff<<0) //31:0 ++//#define RG_SSUSB_RX_SIGDET_SEL (0x1<<11) ++//#define RG_SSUSB_RX_SIGDET_EN (0x1<<12) ++//#define RG_SSUSB_RX_PI_CAL_MANUAL_SEL (0x1<<9) ++//#define RG_SSUSB_RX_PI_CAL_MANUAL_EN (0x1<<10) ++ ++//U3D_PHYD_CDR0 ++#define RG_SSUSB_CDR_BIC_LTR (0xf<<28) //31:28 ++#define RG_SSUSB_CDR_BIC_LTD0 (0xf<<24) //27:24 ++#define RG_SSUSB_CDR_BC_LTD1 (0x1f<<16) //20:16 ++#define RG_SSUSB_CDR_BC_LTR (0x1f<<8) //12:8 ++#define RG_SSUSB_CDR_BC_LTD0 (0x1f<<0) //4:0 ++ ++//U3D_PHYD_CDR1 ++#define RG_SSUSB_CDR_BIR_LTD1 (0x1f<<24) //28:24 ++#define RG_SSUSB_CDR_BIR_LTR (0x1f<<16) //20:16 ++#define RG_SSUSB_CDR_BIR_LTD0 (0x1f<<8) //12:8 ++#define RG_SSUSB_CDR_BW_SEL (0x3<<6) //7:6 ++#define RG_SSUSB_CDR_BIC_LTD1 (0xf<<0) //3:0 ++ ++//U3D_PHYD_PLL_0 ++#define RG_SSUSB_FORCE_CDR_BAND_5G (0x1<<28) //28:28 ++#define RG_SSUSB_FORCE_CDR_BAND_2P5G (0x1<<27) //27:27 ++#define RG_SSUSB_FORCE_PLL_BAND_5G (0x1<<26) //26:26 ++#define RG_SSUSB_FORCE_PLL_BAND_2P5G (0x1<<25) //25:25 ++#define RG_SSUSB_P_EQ_T_SEL (0x3ff<<15) //24:15 ++#define RG_SSUSB_PLL_ISO_EN_CYC (0x3ff<<5) //14:5 ++#define RG_SSUSB_PLLBAND_RECAL (0x1<<4) //4:4 ++#define RG_SSUSB_PLL_DDS_ISO_EN (0x1<<3) //3:3 ++#define RG_SSUSB_FORCE_PLL_DDS_ISO_EN (0x1<<2) //2:2 ++#define RG_SSUSB_PLL_DDS_PWR_ON (0x1<<1) //1:1 ++#define RG_SSUSB_FORCE_PLL_DDS_PWR_ON (0x1<<0) //0:0 ++ ++//U3D_PHYD_PLL_1 ++#define RG_SSUSB_CDR_BAND_5G (0xff<<24) //31:24 ++#define RG_SSUSB_CDR_BAND_2P5G (0xff<<16) //23:16 ++#define RG_SSUSB_PLL_BAND_5G (0xff<<8) //15:8 ++#define RG_SSUSB_PLL_BAND_2P5G (0xff<<0) //7:0 ++ ++//U3D_PHYD_BCN_DET_1 ++#define RG_SSUSB_P_BCN_OBS_PRD (0xffff<<16) //31:16 ++#define RG_SSUSB_U_BCN_OBS_PRD (0xffff<<0) //15:0 ++ ++//U3D_PHYD_BCN_DET_2 ++#define RG_SSUSB_P_BCN_OBS_SEL (0xfff<<16) //27:16 ++#define RG_SSUSB_BCN_DET_DIS (0x1<<12) //12:12 ++#define RG_SSUSB_U_BCN_OBS_SEL (0xfff<<0) //11:0 ++ ++//U3D_EQ0 ++#define RG_SSUSB_EQ_DLHL_LFI (0x7f<<24) //30:24 ++#define RG_SSUSB_EQ_DHHL_LFI (0x7f<<16) //22:16 ++#define RG_SSUSB_EQ_DD0HOS_LFI (0x7f<<8) //14:8 ++#define RG_SSUSB_EQ_DD0LOS_LFI (0x7f<<0) //6:0 ++ ++//U3D_EQ1 ++#define RG_SSUSB_EQ_DD1HOS_LFI (0x7f<<24) //30:24 ++#define RG_SSUSB_EQ_DD1LOS_LFI (0x7f<<16) //22:16 ++#define RG_SSUSB_EQ_DE0OS_LFI (0x7f<<8) //14:8 ++#define RG_SSUSB_EQ_DE1OS_LFI (0x7f<<0) //6:0 ++ ++//U3D_EQ2 ++#define RG_SSUSB_EQ_DLHLOS_LFI (0x7f<<24) //30:24 ++#define RG_SSUSB_EQ_DHHLOS_LFI (0x7f<<16) //22:16 ++#define RG_SSUSB_EQ_STOPTIME (0x1<<14) //14:14 ++#define RG_SSUSB_EQ_DHHL_LF_SEL (0x7<<11) //13:11 ++#define RG_SSUSB_EQ_DSAOS_LF_SEL (0x7<<8) //10:8 ++#define RG_SSUSB_EQ_STARTTIME (0x3<<6) //7:6 ++#define RG_SSUSB_EQ_DLEQ_LF_SEL (0x7<<3) //5:3 ++#define RG_SSUSB_EQ_DLHL_LF_SEL (0x7<<0) //2:0 ++ ++//U3D_EQ3 ++#define RG_SSUSB_EQ_DLEQ_LFI_GEN2 (0xf<<28) //31:28 ++#define RG_SSUSB_EQ_DLEQ_LFI_GEN1 (0xf<<24) //27:24 ++#define RG_SSUSB_EQ_DEYE0OS_LFI (0x7f<<16) //22:16 ++#define RG_SSUSB_EQ_DEYE1OS_LFI (0x7f<<8) //14:8 ++#define RG_SSUSB_EQ_TRI_DET_EN (0x1<<7) //7:7 ++#define RG_SSUSB_EQ_TRI_DET_TH (0x7f<<0) //6:0 ++ ++//U3D_EQ_EYE0 ++#define RG_SSUSB_EQ_EYE_XOFFSET (0x7f<<25) //31:25 ++#define RG_SSUSB_EQ_EYE_MON_EN (0x1<<24) //24:24 ++#define RG_SSUSB_EQ_EYE0_Y (0x7f<<16) //22:16 ++#define RG_SSUSB_EQ_EYE1_Y (0x7f<<8) //14:8 ++#define RG_SSUSB_EQ_PILPO_ROUT (0x1<<7) //7:7 ++#define RG_SSUSB_EQ_PI_KPGAIN (0x7<<4) //6:4 ++#define RG_SSUSB_EQ_EYE_CNT_EN (0x1<<3) //3:3 ++ ++//U3D_EQ_EYE1 ++#define RG_SSUSB_EQ_SIGDET (0x7f<<24) //30:24 ++#define RG_SSUSB_EQ_EYE_MASK (0x3ff<<7) //16:7 ++ ++//U3D_EQ_EYE2 ++#define RG_SSUSB_EQ_RX500M_CK_SEL (0x1<<31) //31:31 ++#define RG_SSUSB_EQ_SD_CNT1 (0x3f<<24) //29:24 ++#define RG_SSUSB_EQ_ISIFLAG_SEL (0x3<<22) //23:22 ++#define RG_SSUSB_EQ_SD_CNT0 (0x3f<<16) //21:16 ++ ++//U3D_EQ_DFE0 ++#define RG_SSUSB_EQ_LEQMAX (0xf<<28) //31:28 ++#define RG_SSUSB_EQ_DFEX_EN (0x1<<27) //27:27 ++#define RG_SSUSB_EQ_DFEX_LF_SEL (0x7<<24) //26:24 ++#define RG_SSUSB_EQ_CHK_EYE_H (0x1<<23) //23:23 ++#define RG_SSUSB_EQ_PIEYE_INI (0x7f<<16) //22:16 ++#define RG_SSUSB_EQ_PI90_INI (0x7f<<8) //14:8 ++#define RG_SSUSB_EQ_PI0_INI (0x7f<<0) //6:0 ++ ++//U3D_EQ_DFE1 ++#define RG_SSUSB_EQ_REV (0xffff<<16) //31:16 ++#define RG_SSUSB_EQ_DFEYEN_DUR (0x7<<12) //14:12 ++#define RG_SSUSB_EQ_DFEXEN_DUR (0x7<<8) //10:8 ++#define RG_SSUSB_EQ_DFEX_RST (0x1<<7) //7:7 ++#define RG_SSUSB_EQ_GATED_RXD_B (0x1<<6) //6:6 ++#define RG_SSUSB_EQ_PI90CK_SEL (0x3<<4) //5:4 ++#define RG_SSUSB_EQ_DFEX_DIS (0x1<<2) //2:2 ++#define RG_SSUSB_EQ_DFEYEN_STOP_DIS (0x1<<1) //1:1 ++#define RG_SSUSB_EQ_DFEXEN_SEL (0x1<<0) //0:0 ++ ++//U3D_EQ_DFE2 ++#define RG_SSUSB_EQ_MON_SEL (0x1f<<24) //28:24 ++#define RG_SSUSB_EQ_LEQOSC_DLYCNT (0x7<<16) //18:16 ++#define RG_SSUSB_EQ_DLEQOS_LFI (0x1f<<8) //12:8 ++#define RG_SSUSB_EQ_LEQ_STOP_TO (0x3<<0) //1:0 ++ ++//U3D_EQ_DFE3 ++#define RG_SSUSB_EQ_RESERVED (0xffffffff<<0) //31:0 ++ ++//U3D_PHYD_MON0 ++#define RGS_SSUSB_BERT_BERC (0xffff<<16) //31:16 ++#define RGS_SSUSB_LFPS (0xf<<12) //15:12 ++#define RGS_SSUSB_TRAINDEC (0x7<<8) //10:8 ++#define RGS_SSUSB_SCP_PAT (0xff<<0) //7:0 ++ ++//U3D_PHYD_MON1 ++#define RGS_SSUSB_RX_FL_OUT (0xffff<<0) //15:0 ++ ++//U3D_PHYD_MON2 ++#define RGS_SSUSB_T2RLB_ERRCNT (0xffff<<16) //31:16 ++#define RGS_SSUSB_RETRACK (0xf<<12) //15:12 ++#define RGS_SSUSB_RXPLL_LOCK (0x1<<10) //10:10 ++#define RGS_SSUSB_CDR_VCOCAL_CPLT_D (0x1<<9) //9:9 ++#define RGS_SSUSB_PLL_VCOCAL_CPLT_D (0x1<<8) //8:8 ++#define RGS_SSUSB_PDNCTL (0xff<<0) //7:0 ++ ++//U3D_PHYD_MON3 ++#define RGS_SSUSB_TSEQ_ERRCNT (0xffff<<16) //31:16 ++#define RGS_SSUSB_PRBS_ERRCNT (0xffff<<0) //15:0 ++ ++//U3D_PHYD_MON4 ++#define RGS_SSUSB_RX_LSLOCK_CNT (0xf<<24) //27:24 ++#define RGS_SSUSB_SCP_DETCNT (0xff<<16) //23:16 ++#define RGS_SSUSB_TSEQ_DETCNT (0xffff<<0) //15:0 ++ ++//U3D_PHYD_MON5 ++#define RGS_SSUSB_EBUFMSG (0xffff<<16) //31:16 ++#define RGS_SSUSB_BERT_LOCK (0x1<<15) //15:15 ++#define RGS_SSUSB_SCP_DET (0x1<<14) //14:14 ++#define RGS_SSUSB_TSEQ_DET (0x1<<13) //13:13 ++#define RGS_SSUSB_EBUF_UDF (0x1<<12) //12:12 ++#define RGS_SSUSB_EBUF_OVF (0x1<<11) //11:11 ++#define RGS_SSUSB_PRBS_PASSTH (0x1<<10) //10:10 ++#define RGS_SSUSB_PRBS_PASS (0x1<<9) //9:9 ++#define RGS_SSUSB_PRBS_LOCK (0x1<<8) //8:8 ++#define RGS_SSUSB_T2RLB_ERR (0x1<<6) //6:6 ++#define RGS_SSUSB_T2RLB_PASSTH (0x1<<5) //5:5 ++#define RGS_SSUSB_T2RLB_PASS (0x1<<4) //4:4 ++#define RGS_SSUSB_T2RLB_LOCK (0x1<<3) //3:3 ++#define RGS_SSUSB_RX_IMPCAL_DONE (0x1<<2) //2:2 ++#define RGS_SSUSB_TX_IMPCAL_DONE (0x1<<1) //1:1 ++#define RGS_SSUSB_RXDETECTED (0x1<<0) //0:0 ++ ++//U3D_PHYD_MON6 ++#define RGS_SSUSB_SIGCAL_DONE (0x1<<30) //30:30 ++#define RGS_SSUSB_SIGCAL_CAL_OUT (0x1<<29) //29:29 ++#define RGS_SSUSB_SIGCAL_OFFSET (0x1f<<24) //28:24 ++#define RGS_SSUSB_RX_IMP_SEL (0x1f<<16) //20:16 ++#define RGS_SSUSB_TX_IMP_SEL (0x1f<<8) //12:8 ++#define RGS_SSUSB_TFIFO_MSG (0xf<<4) //7:4 ++#define RGS_SSUSB_RFIFO_MSG (0xf<<0) //3:0 ++ ++//U3D_PHYD_MON7 ++#define RGS_SSUSB_FT_OUT (0xff<<8) //15:8 ++#define RGS_SSUSB_PRB_OUT (0xff<<0) //7:0 ++ ++//U3D_PHYA_RX_MON0 ++#define RGS_SSUSB_EQ_DCLEQ (0xf<<24) //27:24 ++#define RGS_SSUSB_EQ_DCD0H (0x7f<<16) //22:16 ++#define RGS_SSUSB_EQ_DCD0L (0x7f<<8) //14:8 ++#define RGS_SSUSB_EQ_DCD1H (0x7f<<0) //6:0 ++ ++//U3D_PHYA_RX_MON1 ++#define RGS_SSUSB_EQ_DCD1L (0x7f<<24) //30:24 ++#define RGS_SSUSB_EQ_DCE0 (0x7f<<16) //22:16 ++#define RGS_SSUSB_EQ_DCE1 (0x7f<<8) //14:8 ++#define RGS_SSUSB_EQ_DCHHL (0x7f<<0) //6:0 ++ ++//U3D_PHYA_RX_MON2 ++#define RGS_SSUSB_EQ_LEQ_STOP (0x1<<31) //31:31 ++#define RGS_SSUSB_EQ_DCLHL (0x7f<<24) //30:24 ++#define RGS_SSUSB_EQ_STATUS (0xff<<16) //23:16 ++#define RGS_SSUSB_EQ_DCEYE0 (0x7f<<8) //14:8 ++#define RGS_SSUSB_EQ_DCEYE1 (0x7f<<0) //6:0 ++ ++//U3D_PHYA_RX_MON3 ++#define RGS_SSUSB_EQ_EYE_MONITOR_ERRCNT_0 (0xfffff<<0) //19:0 ++ ++//U3D_PHYA_RX_MON4 ++#define RGS_SSUSB_EQ_EYE_MONITOR_ERRCNT_1 (0xfffff<<0) //19:0 ++ ++//U3D_PHYA_RX_MON5 ++#define RGS_SSUSB_EQ_DCLEQOS (0x1f<<8) //12:8 ++#define RGS_SSUSB_EQ_EYE_CNT_RDY (0x1<<7) //7:7 ++#define RGS_SSUSB_EQ_PILPO (0x7f<<0) //6:0 ++ ++//U3D_PHYD_CPPAT2 ++#define RG_SSUSB_CPPAT_OUT_H_TMP2 (0xf<<16) //19:16 ++#define RG_SSUSB_CPPAT_OUT_H_TMP1 (0xff<<8) //15:8 ++#define RG_SSUSB_CPPAT_OUT_H_TMP0 (0xff<<0) //7:0 ++ ++//U3D_EQ_EYE3 ++#define RG_SSUSB_EQ_LEQ_SHIFT (0x7<<24) //26:24 ++#define RG_SSUSB_EQ_EYE_CNT (0xfffff<<0) //19:0 ++ ++//U3D_KBAND_OUT ++#define RGS_SSUSB_CDR_BAND_5G (0xff<<24) //31:24 ++#define RGS_SSUSB_CDR_BAND_2P5G (0xff<<16) //23:16 ++#define RGS_SSUSB_PLL_BAND_5G (0xff<<8) //15:8 ++#define RGS_SSUSB_PLL_BAND_2P5G (0xff<<0) //7:0 ++ ++//U3D_KBAND_OUT1 ++#define RGS_SSUSB_CDR_VCOCAL_FAIL (0x1<<24) //24:24 ++#define RGS_SSUSB_CDR_VCOCAL_STATE (0xff<<16) //23:16 ++#define RGS_SSUSB_PLL_VCOCAL_FAIL (0x1<<8) //8:8 ++#define RGS_SSUSB_PLL_VCOCAL_STATE (0xff<<0) //7:0 ++ ++ ++/* OFFSET */ ++ ++//U3D_PHYD_MIX0 ++#define RG_SSUSB_P_P3_TX_NG_OFST (31) ++#define RG_SSUSB_TSEQ_EN_OFST (30) ++#define RG_SSUSB_TSEQ_POLEN_OFST (29) ++#define RG_SSUSB_TSEQ_POL_OFST (28) ++#define RG_SSUSB_P_P3_PCLK_NG_OFST (27) ++#define RG_SSUSB_TSEQ_TH_OFST (24) ++#define RG_SSUSB_PRBS_BERTH_OFST (16) ++#define RG_SSUSB_DISABLE_PHY_U2_ON_OFST (15) ++#define RG_SSUSB_DISABLE_PHY_U2_OFF_OFST (14) ++#define RG_SSUSB_PRBS_EN_OFST (13) ++#define RG_SSUSB_BPSLOCK_OFST (12) ++#define RG_SSUSB_RTCOMCNT_OFST (8) ++#define RG_SSUSB_COMCNT_OFST (4) ++#define RG_SSUSB_PRBSEL_CALIB_OFST (0) ++ ++//U3D_PHYD_MIX1 ++#define RG_SSUSB_SLEEP_EN_OFST (31) ++#define RG_SSUSB_PRBSEL_PCS_OFST (28) ++#define RG_SSUSB_TXLFPS_PRD_OFST (24) ++#define RG_SSUSB_P_RX_P0S_CK_OFST (23) ++#define RG_SSUSB_P_TX_P0S_CK_OFST (22) ++#define RG_SSUSB_PDNCTL_OFST (16) ++#define RG_SSUSB_TX_DRV_EN_OFST (15) ++#define RG_SSUSB_TX_DRV_SEL_OFST (14) ++#define RG_SSUSB_TX_DRV_DLY_OFST (8) ++#define RG_SSUSB_BERT_EN_OFST (7) ++#define RG_SSUSB_SCP_TH_OFST (4) ++#define RG_SSUSB_SCP_EN_OFST (3) ++#define RG_SSUSB_RXANSIDEC_TEST_OFST (0) ++ ++//U3D_PHYD_LFPS0 ++#define RG_SSUSB_LFPS_PWD_OFST (30) ++#define RG_SSUSB_FORCE_LFPS_PWD_OFST (29) ++#define RG_SSUSB_RXLFPS_OVF_OFST (24) ++#define RG_SSUSB_P3_ENTRY_SEL_OFST (23) ++#define RG_SSUSB_P3_ENTRY_OFST (22) ++#define RG_SSUSB_RXLFPS_CDRSEL_OFST (20) ++#define RG_SSUSB_RXLFPS_CDRTH_OFST (16) ++#define RG_SSUSB_LOCK5G_BLOCK_OFST (15) ++#define RG_SSUSB_TFIFO_EXT_D_SEL_OFST (14) ++#define RG_SSUSB_TFIFO_NO_EXTEND_OFST (13) ++#define RG_SSUSB_RXLFPS_LOB_OFST (8) ++#define RG_SSUSB_TXLFPS_EN_OFST (7) ++#define RG_SSUSB_TXLFPS_SEL_OFST (6) ++#define RG_SSUSB_RXLFPS_CDRLOCK_OFST (5) ++#define RG_SSUSB_RXLFPS_UPB_OFST (0) ++ ++//U3D_PHYD_LFPS1 ++#define RG_SSUSB_RX_IMP_BIAS_OFST (28) ++#define RG_SSUSB_TX_IMP_BIAS_OFST (24) ++#define RG_SSUSB_FWAKE_TH_OFST (16) ++#define RG_SSUSB_RXLFPS_UDF_OFST (8) ++#define RG_SSUSB_RXLFPS_P0IDLETH_OFST (0) ++ ++//U3D_PHYD_IMPCAL0 ++#define RG_SSUSB_FORCE_TX_IMPSEL_OFST (31) ++#define RG_SSUSB_TX_IMPCAL_EN_OFST (30) ++#define RG_SSUSB_FORCE_TX_IMPCAL_EN_OFST (29) ++#define RG_SSUSB_TX_IMPSEL_OFST (24) ++#define RG_SSUSB_TX_IMPCAL_CALCYC_OFST (16) ++#define RG_SSUSB_TX_IMPCAL_STBCYC_OFST (10) ++#define RG_SSUSB_TX_IMPCAL_CYCCNT_OFST (0) ++ ++//U3D_PHYD_IMPCAL1 ++#define RG_SSUSB_FORCE_RX_IMPSEL_OFST (31) ++#define RG_SSUSB_RX_IMPCAL_EN_OFST (30) ++#define RG_SSUSB_FORCE_RX_IMPCAL_EN_OFST (29) ++#define RG_SSUSB_RX_IMPSEL_OFST (24) ++#define RG_SSUSB_RX_IMPCAL_CALCYC_OFST (16) ++#define RG_SSUSB_RX_IMPCAL_STBCYC_OFST (10) ++#define RG_SSUSB_RX_IMPCAL_CYCCNT_OFST (0) ++ ++//U3D_PHYD_TXPLL0 ++#define RG_SSUSB_TXPLL_DDSEN_CYC_OFST (27) ++#define RG_SSUSB_TXPLL_ON_OFST (26) ++#define RG_SSUSB_FORCE_TXPLLON_OFST (25) ++#define RG_SSUSB_TXPLL_STBCYC_OFST (16) ++#define RG_SSUSB_TXPLL_NCPOCHG_CYC_OFST (12) ++#define RG_SSUSB_TXPLL_NCPOEN_CYC_OFST (10) ++#define RG_SSUSB_TXPLL_DDSRSTB_CYC_OFST (0) ++ ++//U3D_PHYD_TXPLL1 ++#define RG_SSUSB_PLL_NCPO_EN_OFST (31) ++#define RG_SSUSB_PLL_FIFO_START_MAN_OFST (30) ++#define RG_SSUSB_PLL_NCPO_CHG_OFST (28) ++#define RG_SSUSB_PLL_DDS_RSTB_OFST (27) ++#define RG_SSUSB_PLL_DDS_PWDB_OFST (26) ++#define RG_SSUSB_PLL_DDSEN_OFST (25) ++#define RG_SSUSB_PLL_AUTOK_VCO_OFST (24) ++#define RG_SSUSB_PLL_PWD_OFST (23) ++#define RG_SSUSB_RX_AFE_PWD_OFST (22) ++#define RG_SSUSB_PLL_TCADJ_OFST (16) ++#define RG_SSUSB_FORCE_CDR_TCADJ_OFST (15) ++#define RG_SSUSB_FORCE_CDR_AUTOK_VCO_OFST (14) ++#define RG_SSUSB_FORCE_CDR_PWD_OFST (13) ++#define RG_SSUSB_FORCE_PLL_NCPO_EN_OFST (12) ++#define RG_SSUSB_FORCE_PLL_FIFO_START_MAN_OFST (11) ++#define RG_SSUSB_FORCE_PLL_NCPO_CHG_OFST (9) ++#define RG_SSUSB_FORCE_PLL_DDS_RSTB_OFST (8) ++#define RG_SSUSB_FORCE_PLL_DDS_PWDB_OFST (7) ++#define RG_SSUSB_FORCE_PLL_DDSEN_OFST (6) ++#define RG_SSUSB_FORCE_PLL_TCADJ_OFST (5) ++#define RG_SSUSB_FORCE_PLL_AUTOK_VCO_OFST (4) ++#define RG_SSUSB_FORCE_PLL_PWD_OFST (3) ++#define RG_SSUSB_FLT_1_DISPERR_B_OFST (2) ++ ++//U3D_PHYD_TXPLL2 ++#define RG_SSUSB_TX_LFPS_EN_OFST (31) ++#define RG_SSUSB_FORCE_TX_LFPS_EN_OFST (30) ++#define RG_SSUSB_TX_LFPS_OFST (29) ++#define RG_SSUSB_FORCE_TX_LFPS_OFST (28) ++#define RG_SSUSB_RXPLL_STB_OFST (27) ++#define RG_SSUSB_TXPLL_STB_OFST (26) ++#define RG_SSUSB_FORCE_RXPLL_STB_OFST (25) ++#define RG_SSUSB_FORCE_TXPLL_STB_OFST (24) ++#define RG_SSUSB_RXPLL_REFCKSEL_OFST (16) ++#define RG_SSUSB_RXPLL_STBMODE_OFST (11) ++#define RG_SSUSB_RXPLL_ON_OFST (10) ++#define RG_SSUSB_FORCE_RXPLLON_OFST (9) ++#define RG_SSUSB_FORCE_RX_AFE_PWD_OFST (8) ++#define RG_SSUSB_CDR_AUTOK_VCO_OFST (7) ++#define RG_SSUSB_CDR_PWD_OFST (6) ++#define RG_SSUSB_CDR_TCADJ_OFST (0) ++ ++//U3D_PHYD_FL0 ++#define RG_SSUSB_RX_FL_TARGET_OFST (16) ++#define RG_SSUSB_RX_FL_CYCLECNT_OFST (0) ++ ++//U3D_PHYD_MIX2 ++#define RG_SSUSB_RX_EQ_RST_OFST (31) ++#define RG_SSUSB_RX_EQ_RST_SEL_OFST (30) ++#define RG_SSUSB_RXVAL_RST_OFST (29) ++#define RG_SSUSB_RXVAL_CNT_OFST (24) ++#define RG_SSUSB_CDROS_EN_OFST (18) ++#define RG_SSUSB_CDR_LCKOP_OFST (16) ++#define RG_SSUSB_RX_FL_LOCKTH_OFST (8) ++#define RG_SSUSB_RX_FL_OFFSET_OFST (0) ++ ++//U3D_PHYD_RX0 ++#define RG_SSUSB_T2RLB_BERTH_OFST (24) ++#define RG_SSUSB_T2RLB_PAT_OFST (16) ++#define RG_SSUSB_T2RLB_EN_OFST (15) ++#define RG_SSUSB_T2RLB_BPSCRAMB_OFST (14) ++#define RG_SSUSB_T2RLB_SERIAL_OFST (13) ++#define RG_SSUSB_T2RLB_MODE_OFST (11) ++#define RG_SSUSB_RX_SAOSC_EN_OFST (10) ++#define RG_SSUSB_RX_SAOSC_EN_SEL_OFST (9) ++#define RG_SSUSB_RX_DFE_OPTION_OFST (8) ++#define RG_SSUSB_RX_DFE_EN_OFST (7) ++#define RG_SSUSB_RX_DFE_EN_SEL_OFST (6) ++#define RG_SSUSB_RX_EQ_EN_OFST (5) ++#define RG_SSUSB_RX_EQ_EN_SEL_OFST (4) ++#define RG_SSUSB_RX_SAOSC_RST_OFST (3) ++#define RG_SSUSB_RX_SAOSC_RST_SEL_OFST (2) ++#define RG_SSUSB_RX_DFE_RST_OFST (1) ++#define RG_SSUSB_RX_DFE_RST_SEL_OFST (0) ++ ++//U3D_PHYD_T2RLB ++#define RG_SSUSB_EQTRAIN_CH_MODE_OFST (28) ++#define RG_SSUSB_PRB_OUT_CPPAT_OFST (27) ++#define RG_SSUSB_BPANSIENC_OFST (26) ++#define RG_SSUSB_VALID_EN_OFST (25) ++#define RG_SSUSB_EBUF_SRST_OFST (24) ++#define RG_SSUSB_K_EMP_OFST (20) ++#define RG_SSUSB_K_FUL_OFST (16) ++#define RG_SSUSB_T2RLB_BDATRST_OFST (12) ++#define RG_SSUSB_P_T2RLB_SKP_EN_OFST (10) ++#define RG_SSUSB_T2RLB_PATMODE_OFST (8) ++#define RG_SSUSB_T2RLB_TSEQCNT_OFST (0) ++ ++//U3D_PHYD_CPPAT ++#define RG_SSUSB_CPPAT_PROGRAM_EN_OFST (24) ++#define RG_SSUSB_CPPAT_TOZ_OFST (21) ++#define RG_SSUSB_CPPAT_PRBS_EN_OFST (20) ++#define RG_SSUSB_CPPAT_OUT_TMP2_OFST (16) ++#define RG_SSUSB_CPPAT_OUT_TMP1_OFST (8) ++#define RG_SSUSB_CPPAT_OUT_TMP0_OFST (0) ++ ++//U3D_PHYD_MIX3 ++#define RG_SSUSB_CDR_TCADJ_MINUS_OFST (31) ++#define RG_SSUSB_P_CDROS_EN_OFST (30) ++#define RG_SSUSB_P_P2_TX_DRV_DIS_OFST (28) ++#define RG_SSUSB_CDR_TCADJ_OFFSET_OFST (24) ++#define RG_SSUSB_PLL_TCADJ_MINUS_OFST (23) ++#define RG_SSUSB_FORCE_PLL_BIAS_LPF_EN_OFST (20) ++#define RG_SSUSB_PLL_BIAS_LPF_EN_OFST (19) ++#define RG_SSUSB_PLL_TCADJ_OFFSET_OFST (16) ++#define RG_SSUSB_FORCE_PLL_SSCEN_OFST (15) ++#define RG_SSUSB_PLL_SSCEN_OFST (14) ++#define RG_SSUSB_FORCE_CDR_PI_PWD_OFST (13) ++#define RG_SSUSB_CDR_PI_PWD_OFST (12) ++#define RG_SSUSB_CDR_PI_MODE_OFST (11) ++#define RG_SSUSB_TXPLL_SSCEN_CYC_OFST (0) ++ ++//U3D_PHYD_EBUFCTL ++#define RG_SSUSB_EBUFCTL_OFST (0) ++ ++//U3D_PHYD_PIPE0 ++#define RG_SSUSB_RXTERMINATION_OFST (30) ++#define RG_SSUSB_RXEQTRAINING_OFST (29) ++#define RG_SSUSB_RXPOLARITY_OFST (28) ++#define RG_SSUSB_TXDEEMPH_OFST (26) ++#define RG_SSUSB_POWERDOWN_OFST (24) ++#define RG_SSUSB_TXONESZEROS_OFST (23) ++#define RG_SSUSB_TXELECIDLE_OFST (22) ++#define RG_SSUSB_TXDETECTRX_OFST (21) ++#define RG_SSUSB_PIPE_SEL_OFST (20) ++#define RG_SSUSB_TXDATAK_OFST (16) ++#define RG_SSUSB_CDR_STABLE_SEL_OFST (15) ++#define RG_SSUSB_CDR_STABLE_OFST (14) ++#define RG_SSUSB_CDR_RSTB_SEL_OFST (13) ++#define RG_SSUSB_CDR_RSTB_OFST (12) ++#define RG_SSUSB_P_ERROR_SEL_OFST (4) ++#define RG_SSUSB_TXMARGIN_OFST (1) ++#define RG_SSUSB_TXCOMPLIANCE_OFST (0) ++ ++//U3D_PHYD_PIPE1 ++#define RG_SSUSB_TXDATA_OFST (0) ++ ++//U3D_PHYD_MIX4 ++#define RG_SSUSB_CDROS_CNT_OFST (24) ++#define RG_SSUSB_T2RLB_BER_EN_OFST (16) ++#define RG_SSUSB_T2RLB_BER_RATE_OFST (0) ++ ++//U3D_PHYD_CKGEN0 ++#define RG_SSUSB_RFIFO_IMPLAT_OFST (27) ++#define RG_SSUSB_TFIFO_PSEL_OFST (24) ++#define RG_SSUSB_CKGEN_PSEL_OFST (8) ++#define RG_SSUSB_RXCK_INV_OFST (0) ++ ++//U3D_PHYD_MIX5 ++#define RG_SSUSB_PRB_SEL_OFST (16) ++#define RG_SSUSB_RXPLL_STBCYC_OFST (0) ++ ++//U3D_PHYD_RESERVED ++#define RG_SSUSB_PHYD_RESERVE_OFST (0) ++//#define RG_SSUSB_RX_SIGDET_SEL_OFST (11) ++//#define RG_SSUSB_RX_SIGDET_EN_OFST (12) ++//#define RG_SSUSB_RX_PI_CAL_MANUAL_SEL_OFST (9) ++//#define RG_SSUSB_RX_PI_CAL_MANUAL_EN_OFST (10) ++ ++//U3D_PHYD_CDR0 ++#define RG_SSUSB_CDR_BIC_LTR_OFST (28) ++#define RG_SSUSB_CDR_BIC_LTD0_OFST (24) ++#define RG_SSUSB_CDR_BC_LTD1_OFST (16) ++#define RG_SSUSB_CDR_BC_LTR_OFST (8) ++#define RG_SSUSB_CDR_BC_LTD0_OFST (0) ++ ++//U3D_PHYD_CDR1 ++#define RG_SSUSB_CDR_BIR_LTD1_OFST (24) ++#define RG_SSUSB_CDR_BIR_LTR_OFST (16) ++#define RG_SSUSB_CDR_BIR_LTD0_OFST (8) ++#define RG_SSUSB_CDR_BW_SEL_OFST (6) ++#define RG_SSUSB_CDR_BIC_LTD1_OFST (0) ++ ++//U3D_PHYD_PLL_0 ++#define RG_SSUSB_FORCE_CDR_BAND_5G_OFST (28) ++#define RG_SSUSB_FORCE_CDR_BAND_2P5G_OFST (27) ++#define RG_SSUSB_FORCE_PLL_BAND_5G_OFST (26) ++#define RG_SSUSB_FORCE_PLL_BAND_2P5G_OFST (25) ++#define RG_SSUSB_P_EQ_T_SEL_OFST (15) ++#define RG_SSUSB_PLL_ISO_EN_CYC_OFST (5) ++#define RG_SSUSB_PLLBAND_RECAL_OFST (4) ++#define RG_SSUSB_PLL_DDS_ISO_EN_OFST (3) ++#define RG_SSUSB_FORCE_PLL_DDS_ISO_EN_OFST (2) ++#define RG_SSUSB_PLL_DDS_PWR_ON_OFST (1) ++#define RG_SSUSB_FORCE_PLL_DDS_PWR_ON_OFST (0) ++ ++//U3D_PHYD_PLL_1 ++#define RG_SSUSB_CDR_BAND_5G_OFST (24) ++#define RG_SSUSB_CDR_BAND_2P5G_OFST (16) ++#define RG_SSUSB_PLL_BAND_5G_OFST (8) ++#define RG_SSUSB_PLL_BAND_2P5G_OFST (0) ++ ++//U3D_PHYD_BCN_DET_1 ++#define RG_SSUSB_P_BCN_OBS_PRD_OFST (16) ++#define RG_SSUSB_U_BCN_OBS_PRD_OFST (0) ++ ++//U3D_PHYD_BCN_DET_2 ++#define RG_SSUSB_P_BCN_OBS_SEL_OFST (16) ++#define RG_SSUSB_BCN_DET_DIS_OFST (12) ++#define RG_SSUSB_U_BCN_OBS_SEL_OFST (0) ++ ++//U3D_EQ0 ++#define RG_SSUSB_EQ_DLHL_LFI_OFST (24) ++#define RG_SSUSB_EQ_DHHL_LFI_OFST (16) ++#define RG_SSUSB_EQ_DD0HOS_LFI_OFST (8) ++#define RG_SSUSB_EQ_DD0LOS_LFI_OFST (0) ++ ++//U3D_EQ1 ++#define RG_SSUSB_EQ_DD1HOS_LFI_OFST (24) ++#define RG_SSUSB_EQ_DD1LOS_LFI_OFST (16) ++#define RG_SSUSB_EQ_DE0OS_LFI_OFST (8) ++#define RG_SSUSB_EQ_DE1OS_LFI_OFST (0) ++ ++//U3D_EQ2 ++#define RG_SSUSB_EQ_DLHLOS_LFI_OFST (24) ++#define RG_SSUSB_EQ_DHHLOS_LFI_OFST (16) ++#define RG_SSUSB_EQ_STOPTIME_OFST (14) ++#define RG_SSUSB_EQ_DHHL_LF_SEL_OFST (11) ++#define RG_SSUSB_EQ_DSAOS_LF_SEL_OFST (8) ++#define RG_SSUSB_EQ_STARTTIME_OFST (6) ++#define RG_SSUSB_EQ_DLEQ_LF_SEL_OFST (3) ++#define RG_SSUSB_EQ_DLHL_LF_SEL_OFST (0) ++ ++//U3D_EQ3 ++#define RG_SSUSB_EQ_DLEQ_LFI_GEN2_OFST (28) ++#define RG_SSUSB_EQ_DLEQ_LFI_GEN1_OFST (24) ++#define RG_SSUSB_EQ_DEYE0OS_LFI_OFST (16) ++#define RG_SSUSB_EQ_DEYE1OS_LFI_OFST (8) ++#define RG_SSUSB_EQ_TRI_DET_EN_OFST (7) ++#define RG_SSUSB_EQ_TRI_DET_TH_OFST (0) ++ ++//U3D_EQ_EYE0 ++#define RG_SSUSB_EQ_EYE_XOFFSET_OFST (25) ++#define RG_SSUSB_EQ_EYE_MON_EN_OFST (24) ++#define RG_SSUSB_EQ_EYE0_Y_OFST (16) ++#define RG_SSUSB_EQ_EYE1_Y_OFST (8) ++#define RG_SSUSB_EQ_PILPO_ROUT_OFST (7) ++#define RG_SSUSB_EQ_PI_KPGAIN_OFST (4) ++#define RG_SSUSB_EQ_EYE_CNT_EN_OFST (3) ++ ++//U3D_EQ_EYE1 ++#define RG_SSUSB_EQ_SIGDET_OFST (24) ++#define RG_SSUSB_EQ_EYE_MASK_OFST (7) ++ ++//U3D_EQ_EYE2 ++#define RG_SSUSB_EQ_RX500M_CK_SEL_OFST (31) ++#define RG_SSUSB_EQ_SD_CNT1_OFST (24) ++#define RG_SSUSB_EQ_ISIFLAG_SEL_OFST (22) ++#define RG_SSUSB_EQ_SD_CNT0_OFST (16) ++ ++//U3D_EQ_DFE0 ++#define RG_SSUSB_EQ_LEQMAX_OFST (28) ++#define RG_SSUSB_EQ_DFEX_EN_OFST (27) ++#define RG_SSUSB_EQ_DFEX_LF_SEL_OFST (24) ++#define RG_SSUSB_EQ_CHK_EYE_H_OFST (23) ++#define RG_SSUSB_EQ_PIEYE_INI_OFST (16) ++#define RG_SSUSB_EQ_PI90_INI_OFST (8) ++#define RG_SSUSB_EQ_PI0_INI_OFST (0) ++ ++//U3D_EQ_DFE1 ++#define RG_SSUSB_EQ_REV_OFST (16) ++#define RG_SSUSB_EQ_DFEYEN_DUR_OFST (12) ++#define RG_SSUSB_EQ_DFEXEN_DUR_OFST (8) ++#define RG_SSUSB_EQ_DFEX_RST_OFST (7) ++#define RG_SSUSB_EQ_GATED_RXD_B_OFST (6) ++#define RG_SSUSB_EQ_PI90CK_SEL_OFST (4) ++#define RG_SSUSB_EQ_DFEX_DIS_OFST (2) ++#define RG_SSUSB_EQ_DFEYEN_STOP_DIS_OFST (1) ++#define RG_SSUSB_EQ_DFEXEN_SEL_OFST (0) ++ ++//U3D_EQ_DFE2 ++#define RG_SSUSB_EQ_MON_SEL_OFST (24) ++#define RG_SSUSB_EQ_LEQOSC_DLYCNT_OFST (16) ++#define RG_SSUSB_EQ_DLEQOS_LFI_OFST (8) ++#define RG_SSUSB_EQ_LEQ_STOP_TO_OFST (0) ++ ++//U3D_EQ_DFE3 ++#define RG_SSUSB_EQ_RESERVED_OFST (0) ++ ++//U3D_PHYD_MON0 ++#define RGS_SSUSB_BERT_BERC_OFST (16) ++#define RGS_SSUSB_LFPS_OFST (12) ++#define RGS_SSUSB_TRAINDEC_OFST (8) ++#define RGS_SSUSB_SCP_PAT_OFST (0) ++ ++//U3D_PHYD_MON1 ++#define RGS_SSUSB_RX_FL_OUT_OFST (0) ++ ++//U3D_PHYD_MON2 ++#define RGS_SSUSB_T2RLB_ERRCNT_OFST (16) ++#define RGS_SSUSB_RETRACK_OFST (12) ++#define RGS_SSUSB_RXPLL_LOCK_OFST (10) ++#define RGS_SSUSB_CDR_VCOCAL_CPLT_D_OFST (9) ++#define RGS_SSUSB_PLL_VCOCAL_CPLT_D_OFST (8) ++#define RGS_SSUSB_PDNCTL_OFST (0) ++ ++//U3D_PHYD_MON3 ++#define RGS_SSUSB_TSEQ_ERRCNT_OFST (16) ++#define RGS_SSUSB_PRBS_ERRCNT_OFST (0) ++ ++//U3D_PHYD_MON4 ++#define RGS_SSUSB_RX_LSLOCK_CNT_OFST (24) ++#define RGS_SSUSB_SCP_DETCNT_OFST (16) ++#define RGS_SSUSB_TSEQ_DETCNT_OFST (0) ++ ++//U3D_PHYD_MON5 ++#define RGS_SSUSB_EBUFMSG_OFST (16) ++#define RGS_SSUSB_BERT_LOCK_OFST (15) ++#define RGS_SSUSB_SCP_DET_OFST (14) ++#define RGS_SSUSB_TSEQ_DET_OFST (13) ++#define RGS_SSUSB_EBUF_UDF_OFST (12) ++#define RGS_SSUSB_EBUF_OVF_OFST (11) ++#define RGS_SSUSB_PRBS_PASSTH_OFST (10) ++#define RGS_SSUSB_PRBS_PASS_OFST (9) ++#define RGS_SSUSB_PRBS_LOCK_OFST (8) ++#define RGS_SSUSB_T2RLB_ERR_OFST (6) ++#define RGS_SSUSB_T2RLB_PASSTH_OFST (5) ++#define RGS_SSUSB_T2RLB_PASS_OFST (4) ++#define RGS_SSUSB_T2RLB_LOCK_OFST (3) ++#define RGS_SSUSB_RX_IMPCAL_DONE_OFST (2) ++#define RGS_SSUSB_TX_IMPCAL_DONE_OFST (1) ++#define RGS_SSUSB_RXDETECTED_OFST (0) ++ ++//U3D_PHYD_MON6 ++#define RGS_SSUSB_SIGCAL_DONE_OFST (30) ++#define RGS_SSUSB_SIGCAL_CAL_OUT_OFST (29) ++#define RGS_SSUSB_SIGCAL_OFFSET_OFST (24) ++#define RGS_SSUSB_RX_IMP_SEL_OFST (16) ++#define RGS_SSUSB_TX_IMP_SEL_OFST (8) ++#define RGS_SSUSB_TFIFO_MSG_OFST (4) ++#define RGS_SSUSB_RFIFO_MSG_OFST (0) ++ ++//U3D_PHYD_MON7 ++#define RGS_SSUSB_FT_OUT_OFST (8) ++#define RGS_SSUSB_PRB_OUT_OFST (0) ++ ++//U3D_PHYA_RX_MON0 ++#define RGS_SSUSB_EQ_DCLEQ_OFST (24) ++#define RGS_SSUSB_EQ_DCD0H_OFST (16) ++#define RGS_SSUSB_EQ_DCD0L_OFST (8) ++#define RGS_SSUSB_EQ_DCD1H_OFST (0) ++ ++//U3D_PHYA_RX_MON1 ++#define RGS_SSUSB_EQ_DCD1L_OFST (24) ++#define RGS_SSUSB_EQ_DCE0_OFST (16) ++#define RGS_SSUSB_EQ_DCE1_OFST (8) ++#define RGS_SSUSB_EQ_DCHHL_OFST (0) ++ ++//U3D_PHYA_RX_MON2 ++#define RGS_SSUSB_EQ_LEQ_STOP_OFST (31) ++#define RGS_SSUSB_EQ_DCLHL_OFST (24) ++#define RGS_SSUSB_EQ_STATUS_OFST (16) ++#define RGS_SSUSB_EQ_DCEYE0_OFST (8) ++#define RGS_SSUSB_EQ_DCEYE1_OFST (0) ++ ++//U3D_PHYA_RX_MON3 ++#define RGS_SSUSB_EQ_EYE_MONITOR_ERRCNT_0_OFST (0) ++ ++//U3D_PHYA_RX_MON4 ++#define RGS_SSUSB_EQ_EYE_MONITOR_ERRCNT_1_OFST (0) ++ ++//U3D_PHYA_RX_MON5 ++#define RGS_SSUSB_EQ_DCLEQOS_OFST (8) ++#define RGS_SSUSB_EQ_EYE_CNT_RDY_OFST (7) ++#define RGS_SSUSB_EQ_PILPO_OFST (0) ++ ++//U3D_PHYD_CPPAT2 ++#define RG_SSUSB_CPPAT_OUT_H_TMP2_OFST (16) ++#define RG_SSUSB_CPPAT_OUT_H_TMP1_OFST (8) ++#define RG_SSUSB_CPPAT_OUT_H_TMP0_OFST (0) ++ ++//U3D_EQ_EYE3 ++#define RG_SSUSB_EQ_LEQ_SHIFT_OFST (24) ++#define RG_SSUSB_EQ_EYE_CNT_OFST (0) ++ ++//U3D_KBAND_OUT ++#define RGS_SSUSB_CDR_BAND_5G_OFST (24) ++#define RGS_SSUSB_CDR_BAND_2P5G_OFST (16) ++#define RGS_SSUSB_PLL_BAND_5G_OFST (8) ++#define RGS_SSUSB_PLL_BAND_2P5G_OFST (0) ++ ++//U3D_KBAND_OUT1 ++#define RGS_SSUSB_CDR_VCOCAL_FAIL_OFST (24) ++#define RGS_SSUSB_CDR_VCOCAL_STATE_OFST (16) ++#define RGS_SSUSB_PLL_VCOCAL_FAIL_OFST (8) ++#define RGS_SSUSB_PLL_VCOCAL_STATE_OFST (0) ++ ++ ++/////////////////////////////////////////////////////////////////////////////// ++ ++struct u3phyd_bank2_reg { ++ //0x0 ++ PHY_LE32 b2_phyd_top1; ++ PHY_LE32 b2_phyd_top2; ++ PHY_LE32 b2_phyd_top3; ++ PHY_LE32 b2_phyd_top4; ++ //0x10 ++ PHY_LE32 b2_phyd_top5; ++ PHY_LE32 b2_phyd_top6; ++ PHY_LE32 b2_phyd_top7; ++ PHY_LE32 b2_phyd_p_sigdet1; ++ //0x20 ++ PHY_LE32 b2_phyd_p_sigdet2; ++ PHY_LE32 b2_phyd_p_sigdet_cal1; ++ PHY_LE32 b2_phyd_rxdet1; ++ PHY_LE32 b2_phyd_rxdet2; ++ //0x30 ++ PHY_LE32 b2_phyd_misc0; ++ PHY_LE32 b2_phyd_misc2; ++ PHY_LE32 b2_phyd_misc3; ++ PHY_LE32 reserve0; ++ //0x40 ++ PHY_LE32 b2_rosc_0; ++ PHY_LE32 b2_rosc_1; ++ PHY_LE32 b2_rosc_2; ++ PHY_LE32 b2_rosc_3; ++ //0x50 ++ PHY_LE32 b2_rosc_4; ++ PHY_LE32 b2_rosc_5; ++ PHY_LE32 b2_rosc_6; ++ PHY_LE32 b2_rosc_7; ++ //0x60 ++ PHY_LE32 b2_rosc_8; ++ PHY_LE32 b2_rosc_9; ++ PHY_LE32 b2_rosc_a; ++ PHY_LE32 reserve1; ++ //0x70~0xd0 ++ PHY_LE32 reserve2[28]; ++ //0xe0 ++ PHY_LE32 phyd_version; ++ PHY_LE32 phyd_model; ++}; ++ ++//U3D_B2_PHYD_TOP1 ++#define RG_SSUSB_PCIE2_K_EMP (0xf<<28) //31:28 ++#define RG_SSUSB_PCIE2_K_FUL (0xf<<24) //27:24 ++#define RG_SSUSB_TX_EIDLE_LP_EN (0x1<<17) //17:17 ++#define RG_SSUSB_FORCE_TX_EIDLE_LP_EN (0x1<<16) //16:16 ++#define RG_SSUSB_SIGDET_EN (0x1<<15) //15:15 ++#define RG_SSUSB_FORCE_SIGDET_EN (0x1<<14) //14:14 ++#define RG_SSUSB_CLKRX_EN (0x1<<13) //13:13 ++#define RG_SSUSB_FORCE_CLKRX_EN (0x1<<12) //12:12 ++#define RG_SSUSB_CLKTX_EN (0x1<<11) //11:11 ++#define RG_SSUSB_FORCE_CLKTX_EN (0x1<<10) //10:10 ++#define RG_SSUSB_CLK_REQ_N_I (0x1<<9) //9:9 ++#define RG_SSUSB_FORCE_CLK_REQ_N_I (0x1<<8) //8:8 ++#define RG_SSUSB_RATE (0x1<<6) //6:6 ++#define RG_SSUSB_FORCE_RATE (0x1<<5) //5:5 ++#define RG_SSUSB_PCIE_MODE_SEL (0x1<<4) //4:4 ++#define RG_SSUSB_FORCE_PCIE_MODE_SEL (0x1<<3) //3:3 ++#define RG_SSUSB_PHY_MODE (0x3<<1) //2:1 ++#define RG_SSUSB_FORCE_PHY_MODE (0x1<<0) //0:0 ++ ++//U3D_B2_PHYD_TOP2 ++#define RG_SSUSB_FORCE_IDRV_6DB (0x1<<30) //30:30 ++#define RG_SSUSB_IDRV_6DB (0x3f<<24) //29:24 ++#define RG_SSUSB_FORCE_IDEM_3P5DB (0x1<<22) //22:22 ++#define RG_SSUSB_IDEM_3P5DB (0x3f<<16) //21:16 ++#define RG_SSUSB_FORCE_IDRV_3P5DB (0x1<<14) //14:14 ++#define RG_SSUSB_IDRV_3P5DB (0x3f<<8) //13:8 ++#define RG_SSUSB_FORCE_IDRV_0DB (0x1<<6) //6:6 ++#define RG_SSUSB_IDRV_0DB (0x3f<<0) //5:0 ++ ++//U3D_B2_PHYD_TOP3 ++#define RG_SSUSB_TX_BIASI (0x7<<25) //27:25 ++#define RG_SSUSB_FORCE_TX_BIASI_EN (0x1<<24) //24:24 ++#define RG_SSUSB_TX_BIASI_EN (0x1<<16) //16:16 ++#define RG_SSUSB_FORCE_TX_BIASI (0x1<<13) //13:13 ++#define RG_SSUSB_FORCE_IDEM_6DB (0x1<<8) //8:8 ++#define RG_SSUSB_IDEM_6DB (0x3f<<0) //5:0 ++ ++//U3D_B2_PHYD_TOP4 ++#define RG_SSUSB_G1_CDR_BIC_LTR (0xf<<28) //31:28 ++#define RG_SSUSB_G1_CDR_BIC_LTD0 (0xf<<24) //27:24 ++#define RG_SSUSB_G1_CDR_BC_LTD1 (0x1f<<16) //20:16 ++#define RG_SSUSB_G1_CDR_BC_LTR (0x1f<<8) //12:8 ++#define RG_SSUSB_G1_CDR_BC_LTD0 (0x1f<<0) //4:0 ++ ++//U3D_B2_PHYD_TOP5 ++#define RG_SSUSB_G1_CDR_BIR_LTD1 (0x1f<<24) //28:24 ++#define RG_SSUSB_G1_CDR_BIR_LTR (0x1f<<16) //20:16 ++#define RG_SSUSB_G1_CDR_BIR_LTD0 (0x1f<<8) //12:8 ++#define RG_SSUSB_G1_CDR_BIC_LTD1 (0xf<<0) //3:0 ++ ++//U3D_B2_PHYD_TOP6 ++#define RG_SSUSB_G2_CDR_BIC_LTR (0xf<<28) //31:28 ++#define RG_SSUSB_G2_CDR_BIC_LTD0 (0xf<<24) //27:24 ++#define RG_SSUSB_G2_CDR_BC_LTD1 (0x1f<<16) //20:16 ++#define RG_SSUSB_G2_CDR_BC_LTR (0x1f<<8) //12:8 ++#define RG_SSUSB_G2_CDR_BC_LTD0 (0x1f<<0) //4:0 ++ ++//U3D_B2_PHYD_TOP7 ++#define RG_SSUSB_G2_CDR_BIR_LTD1 (0x1f<<24) //28:24 ++#define RG_SSUSB_G2_CDR_BIR_LTR (0x1f<<16) //20:16 ++#define RG_SSUSB_G2_CDR_BIR_LTD0 (0x1f<<8) //12:8 ++#define RG_SSUSB_G2_CDR_BIC_LTD1 (0xf<<0) //3:0 ++ ++//U3D_B2_PHYD_P_SIGDET1 ++#define RG_SSUSB_P_SIGDET_FLT_DIS (0x1<<31) //31:31 ++#define RG_SSUSB_P_SIGDET_FLT_G2_DEAST_SEL (0x7f<<24) //30:24 ++#define RG_SSUSB_P_SIGDET_FLT_G1_DEAST_SEL (0x7f<<16) //22:16 ++#define RG_SSUSB_P_SIGDET_FLT_P2_AST_SEL (0x7f<<8) //14:8 ++#define RG_SSUSB_P_SIGDET_FLT_PX_AST_SEL (0x7f<<0) //6:0 ++ ++//U3D_B2_PHYD_P_SIGDET2 ++#define RG_SSUSB_P_SIGDET_RX_VAL_S (0x1<<29) //29:29 ++#define RG_SSUSB_P_SIGDET_L0S_DEAS_SEL (0x1<<28) //28:28 ++#define RG_SSUSB_P_SIGDET_L0_EXIT_S (0x1<<27) //27:27 ++#define RG_SSUSB_P_SIGDET_L0S_EXIT_T_S (0x3<<25) //26:25 ++#define RG_SSUSB_P_SIGDET_L0S_EXIT_S (0x1<<24) //24:24 ++#define RG_SSUSB_P_SIGDET_L0S_ENTRY_S (0x1<<16) //16:16 ++#define RG_SSUSB_P_SIGDET_PRB_SEL (0x1<<10) //10:10 ++#define RG_SSUSB_P_SIGDET_BK_SIG_T (0x3<<8) //9:8 ++#define RG_SSUSB_P_SIGDET_P2_RXLFPS (0x1<<6) //6:6 ++#define RG_SSUSB_P_SIGDET_NON_BK_AD (0x1<<5) //5:5 ++#define RG_SSUSB_P_SIGDET_BK_B_RXEQ (0x1<<4) //4:4 ++#define RG_SSUSB_P_SIGDET_G2_KO_SEL (0x3<<2) //3:2 ++#define RG_SSUSB_P_SIGDET_G1_KO_SEL (0x3<<0) //1:0 ++ ++//U3D_B2_PHYD_P_SIGDET_CAL1 ++#define RG_SSUSB_P_SIGDET_CAL_OFFSET (0x1f<<24) //28:24 ++#define RG_SSUSB_P_FORCE_SIGDET_CAL_OFFSET (0x1<<16) //16:16 ++#define RG_SSUSB_P_SIGDET_CAL_EN (0x1<<8) //8:8 ++#define RG_SSUSB_P_FORCE_SIGDET_CAL_EN (0x1<<3) //3:3 ++#define RG_SSUSB_P_SIGDET_FLT_EN (0x1<<2) //2:2 ++#define RG_SSUSB_P_SIGDET_SAMPLE_PRD (0x1<<1) //1:1 ++#define RG_SSUSB_P_SIGDET_REK (0x1<<0) //0:0 ++ ++//U3D_B2_PHYD_RXDET1 ++#define RG_SSUSB_RXDET_PRB_SEL (0x1<<31) //31:31 ++#define RG_SSUSB_FORCE_CMDET (0x1<<30) //30:30 ++#define RG_SSUSB_RXDET_EN (0x1<<29) //29:29 ++#define RG_SSUSB_FORCE_RXDET_EN (0x1<<28) //28:28 ++#define RG_SSUSB_RXDET_K_TWICE (0x1<<27) //27:27 ++#define RG_SSUSB_RXDET_STB3_SET (0x1ff<<18) //26:18 ++#define RG_SSUSB_RXDET_STB2_SET (0x1ff<<9) //17:9 ++#define RG_SSUSB_RXDET_STB1_SET (0x1ff<<0) //8:0 ++ ++//U3D_B2_PHYD_RXDET2 ++#define RG_SSUSB_PHYD_TRAINDEC_FORCE_CGEN (0x1<<31) //31:31 ++#define RG_SSUSB_PHYD_BERTLB_FORCE_CGEN (0x1<<30) //30:30 ++#define RG_SSUSB_PHYD_T2RLB_FORCE_CGEN (0x1<<29) //29:29 ++#define RG_SSUSB_PDN_T_SEL (0x3<<18) //19:18 ++#define RG_SSUSB_RXDET_STB3_SET_P3 (0x1ff<<9) //17:9 ++#define RG_SSUSB_RXDET_STB2_SET_P3 (0x1ff<<0) //8:0 ++ ++//U3D_B2_PHYD_MISC0 ++#define RG_SSUSB_FORCE_PLL_DDS_HF_EN (0x1<<22) //22:22 ++#define RG_SSUSB_PLL_DDS_HF_EN_MAN (0x1<<21) //21:21 ++#define RG_SSUSB_RXLFPS_ENTXDRV (0x1<<20) //20:20 ++#define RG_SSUSB_RX_FL_UNLOCKTH (0xf<<16) //19:16 ++#define RG_SSUSB_LFPS_PSEL (0x1<<15) //15:15 ++#define RG_SSUSB_RX_SIGDET_EN (0x1<<14) //14:14 ++#define RG_SSUSB_RX_SIGDET_EN_SEL (0x1<<13) //13:13 ++#define RG_SSUSB_RX_PI_CAL_EN (0x1<<12) //12:12 ++#define RG_SSUSB_RX_PI_CAL_EN_SEL (0x1<<11) //11:11 ++#define RG_SSUSB_P3_CLS_CK_SEL (0x1<<10) //10:10 ++#define RG_SSUSB_T2RLB_PSEL (0x3<<8) //9:8 ++#define RG_SSUSB_PPCTL_PSEL (0x7<<5) //7:5 ++#define RG_SSUSB_PHYD_TX_DATA_INV (0x1<<4) //4:4 ++#define RG_SSUSB_BERTLB_PSEL (0x3<<2) //3:2 ++#define RG_SSUSB_RETRACK_DIS (0x1<<1) //1:1 ++#define RG_SSUSB_PPERRCNT_CLR (0x1<<0) //0:0 ++ ++//U3D_B2_PHYD_MISC2 ++#define RG_SSUSB_FRC_PLL_DDS_PREDIV2 (0x1<<31) //31:31 ++#define RG_SSUSB_FRC_PLL_DDS_IADJ (0xf<<27) //30:27 ++#define RG_SSUSB_P_SIGDET_125FILTER (0x1<<26) //26:26 ++#define RG_SSUSB_P_SIGDET_RST_FILTER (0x1<<25) //25:25 ++#define RG_SSUSB_P_SIGDET_EID_USE_RAW (0x1<<24) //24:24 ++#define RG_SSUSB_P_SIGDET_LTD_USE_RAW (0x1<<23) //23:23 ++#define RG_SSUSB_EIDLE_BF_RXDET (0x1<<22) //22:22 ++#define RG_SSUSB_EIDLE_LP_STBCYC (0x1ff<<13) //21:13 ++#define RG_SSUSB_TX_EIDLE_LP_POSTDLY (0x3f<<7) //12:7 ++#define RG_SSUSB_TX_EIDLE_LP_PREDLY (0x3f<<1) //6:1 ++#define RG_SSUSB_TX_EIDLE_LP_EN_ADV (0x1<<0) //0:0 ++ ++//U3D_B2_PHYD_MISC3 ++#define RGS_SSUSB_DDS_CALIB_C_STATE (0x7<<16) //18:16 ++#define RGS_SSUSB_PPERRCNT (0xffff<<0) //15:0 ++ ++//U3D_B2_ROSC_0 ++#define RG_SSUSB_RING_OSC_CNTEND (0x1ff<<23) //31:23 ++#define RG_SSUSB_XTAL_OSC_CNTEND (0x7f<<16) //22:16 ++#define RG_SSUSB_RING_OSC_EN (0x1<<3) //3:3 ++#define RG_SSUSB_RING_OSC_FORCE_EN (0x1<<2) //2:2 ++#define RG_SSUSB_FRC_RING_BYPASS_DET (0x1<<1) //1:1 ++#define RG_SSUSB_RING_BYPASS_DET (0x1<<0) //0:0 ++ ++//U3D_B2_ROSC_1 ++#define RG_SSUSB_RING_OSC_FRC_P3 (0x1<<20) //20:20 ++#define RG_SSUSB_RING_OSC_P3 (0x1<<19) //19:19 ++#define RG_SSUSB_RING_OSC_FRC_RECAL (0x3<<17) //18:17 ++#define RG_SSUSB_RING_OSC_RECAL (0x1<<16) //16:16 ++#define RG_SSUSB_RING_OSC_SEL (0xff<<8) //15:8 ++#define RG_SSUSB_RING_OSC_FRC_SEL (0x1<<0) //0:0 ++ ++//U3D_B2_ROSC_2 ++#define RG_SSUSB_RING_DET_STRCYC2 (0xffff<<16) //31:16 ++#define RG_SSUSB_RING_DET_STRCYC1 (0xffff<<0) //15:0 ++ ++//U3D_B2_ROSC_3 ++#define RG_SSUSB_RING_DET_DETWIN1 (0xffff<<16) //31:16 ++#define RG_SSUSB_RING_DET_STRCYC3 (0xffff<<0) //15:0 ++ ++//U3D_B2_ROSC_4 ++#define RG_SSUSB_RING_DET_DETWIN3 (0xffff<<16) //31:16 ++#define RG_SSUSB_RING_DET_DETWIN2 (0xffff<<0) //15:0 ++ ++//U3D_B2_ROSC_5 ++#define RG_SSUSB_RING_DET_LBOND1 (0xffff<<16) //31:16 ++#define RG_SSUSB_RING_DET_UBOND1 (0xffff<<0) //15:0 ++ ++//U3D_B2_ROSC_6 ++#define RG_SSUSB_RING_DET_LBOND2 (0xffff<<16) //31:16 ++#define RG_SSUSB_RING_DET_UBOND2 (0xffff<<0) //15:0 ++ ++//U3D_B2_ROSC_7 ++#define RG_SSUSB_RING_DET_LBOND3 (0xffff<<16) //31:16 ++#define RG_SSUSB_RING_DET_UBOND3 (0xffff<<0) //15:0 ++ ++//U3D_B2_ROSC_8 ++#define RG_SSUSB_RING_RESERVE (0xffff<<16) //31:16 ++#define RG_SSUSB_ROSC_PROB_SEL (0xf<<2) //5:2 ++#define RG_SSUSB_RING_FREQMETER_EN (0x1<<1) //1:1 ++#define RG_SSUSB_RING_DET_BPS_UBOND (0x1<<0) //0:0 ++ ++//U3D_B2_ROSC_9 ++#define RGS_FM_RING_CNT (0xffff<<16) //31:16 ++#define RGS_SSUSB_RING_OSC_STATE (0x3<<10) //11:10 ++#define RGS_SSUSB_RING_OSC_STABLE (0x1<<9) //9:9 ++#define RGS_SSUSB_RING_OSC_CAL_FAIL (0x1<<8) //8:8 ++#define RGS_SSUSB_RING_OSC_CAL (0xff<<0) //7:0 ++ ++//U3D_B2_ROSC_A ++#define RGS_SSUSB_ROSC_PROB_OUT (0xff<<0) //7:0 ++ ++//U3D_PHYD_VERSION ++#define RGS_SSUSB_PHYD_VERSION (0xffffffff<<0) //31:0 ++ ++//U3D_PHYD_MODEL ++#define RGS_SSUSB_PHYD_MODEL (0xffffffff<<0) //31:0 ++ ++ ++/* OFFSET */ ++ ++//U3D_B2_PHYD_TOP1 ++#define RG_SSUSB_PCIE2_K_EMP_OFST (28) ++#define RG_SSUSB_PCIE2_K_FUL_OFST (24) ++#define RG_SSUSB_TX_EIDLE_LP_EN_OFST (17) ++#define RG_SSUSB_FORCE_TX_EIDLE_LP_EN_OFST (16) ++#define RG_SSUSB_SIGDET_EN_OFST (15) ++#define RG_SSUSB_FORCE_SIGDET_EN_OFST (14) ++#define RG_SSUSB_CLKRX_EN_OFST (13) ++#define RG_SSUSB_FORCE_CLKRX_EN_OFST (12) ++#define RG_SSUSB_CLKTX_EN_OFST (11) ++#define RG_SSUSB_FORCE_CLKTX_EN_OFST (10) ++#define RG_SSUSB_CLK_REQ_N_I_OFST (9) ++#define RG_SSUSB_FORCE_CLK_REQ_N_I_OFST (8) ++#define RG_SSUSB_RATE_OFST (6) ++#define RG_SSUSB_FORCE_RATE_OFST (5) ++#define RG_SSUSB_PCIE_MODE_SEL_OFST (4) ++#define RG_SSUSB_FORCE_PCIE_MODE_SEL_OFST (3) ++#define RG_SSUSB_PHY_MODE_OFST (1) ++#define RG_SSUSB_FORCE_PHY_MODE_OFST (0) ++ ++//U3D_B2_PHYD_TOP2 ++#define RG_SSUSB_FORCE_IDRV_6DB_OFST (30) ++#define RG_SSUSB_IDRV_6DB_OFST (24) ++#define RG_SSUSB_FORCE_IDEM_3P5DB_OFST (22) ++#define RG_SSUSB_IDEM_3P5DB_OFST (16) ++#define RG_SSUSB_FORCE_IDRV_3P5DB_OFST (14) ++#define RG_SSUSB_IDRV_3P5DB_OFST (8) ++#define RG_SSUSB_FORCE_IDRV_0DB_OFST (6) ++#define RG_SSUSB_IDRV_0DB_OFST (0) ++ ++//U3D_B2_PHYD_TOP3 ++#define RG_SSUSB_TX_BIASI_OFST (25) ++#define RG_SSUSB_FORCE_TX_BIASI_EN_OFST (24) ++#define RG_SSUSB_TX_BIASI_EN_OFST (16) ++#define RG_SSUSB_FORCE_TX_BIASI_OFST (13) ++#define RG_SSUSB_FORCE_IDEM_6DB_OFST (8) ++#define RG_SSUSB_IDEM_6DB_OFST (0) ++ ++//U3D_B2_PHYD_TOP4 ++#define RG_SSUSB_G1_CDR_BIC_LTR_OFST (28) ++#define RG_SSUSB_G1_CDR_BIC_LTD0_OFST (24) ++#define RG_SSUSB_G1_CDR_BC_LTD1_OFST (16) ++#define RG_SSUSB_G1_CDR_BC_LTR_OFST (8) ++#define RG_SSUSB_G1_CDR_BC_LTD0_OFST (0) ++ ++//U3D_B2_PHYD_TOP5 ++#define RG_SSUSB_G1_CDR_BIR_LTD1_OFST (24) ++#define RG_SSUSB_G1_CDR_BIR_LTR_OFST (16) ++#define RG_SSUSB_G1_CDR_BIR_LTD0_OFST (8) ++#define RG_SSUSB_G1_CDR_BIC_LTD1_OFST (0) ++ ++//U3D_B2_PHYD_TOP6 ++#define RG_SSUSB_G2_CDR_BIC_LTR_OFST (28) ++#define RG_SSUSB_G2_CDR_BIC_LTD0_OFST (24) ++#define RG_SSUSB_G2_CDR_BC_LTD1_OFST (16) ++#define RG_SSUSB_G2_CDR_BC_LTR_OFST (8) ++#define RG_SSUSB_G2_CDR_BC_LTD0_OFST (0) ++ ++//U3D_B2_PHYD_TOP7 ++#define RG_SSUSB_G2_CDR_BIR_LTD1_OFST (24) ++#define RG_SSUSB_G2_CDR_BIR_LTR_OFST (16) ++#define RG_SSUSB_G2_CDR_BIR_LTD0_OFST (8) ++#define RG_SSUSB_G2_CDR_BIC_LTD1_OFST (0) ++ ++//U3D_B2_PHYD_P_SIGDET1 ++#define RG_SSUSB_P_SIGDET_FLT_DIS_OFST (31) ++#define RG_SSUSB_P_SIGDET_FLT_G2_DEAST_SEL_OFST (24) ++#define RG_SSUSB_P_SIGDET_FLT_G1_DEAST_SEL_OFST (16) ++#define RG_SSUSB_P_SIGDET_FLT_P2_AST_SEL_OFST (8) ++#define RG_SSUSB_P_SIGDET_FLT_PX_AST_SEL_OFST (0) ++ ++//U3D_B2_PHYD_P_SIGDET2 ++#define RG_SSUSB_P_SIGDET_RX_VAL_S_OFST (29) ++#define RG_SSUSB_P_SIGDET_L0S_DEAS_SEL_OFST (28) ++#define RG_SSUSB_P_SIGDET_L0_EXIT_S_OFST (27) ++#define RG_SSUSB_P_SIGDET_L0S_EXIT_T_S_OFST (25) ++#define RG_SSUSB_P_SIGDET_L0S_EXIT_S_OFST (24) ++#define RG_SSUSB_P_SIGDET_L0S_ENTRY_S_OFST (16) ++#define RG_SSUSB_P_SIGDET_PRB_SEL_OFST (10) ++#define RG_SSUSB_P_SIGDET_BK_SIG_T_OFST (8) ++#define RG_SSUSB_P_SIGDET_P2_RXLFPS_OFST (6) ++#define RG_SSUSB_P_SIGDET_NON_BK_AD_OFST (5) ++#define RG_SSUSB_P_SIGDET_BK_B_RXEQ_OFST (4) ++#define RG_SSUSB_P_SIGDET_G2_KO_SEL_OFST (2) ++#define RG_SSUSB_P_SIGDET_G1_KO_SEL_OFST (0) ++ ++//U3D_B2_PHYD_P_SIGDET_CAL1 ++#define RG_SSUSB_P_SIGDET_CAL_OFFSET_OFST (24) ++#define RG_SSUSB_P_FORCE_SIGDET_CAL_OFFSET_OFST (16) ++#define RG_SSUSB_P_SIGDET_CAL_EN_OFST (8) ++#define RG_SSUSB_P_FORCE_SIGDET_CAL_EN_OFST (3) ++#define RG_SSUSB_P_SIGDET_FLT_EN_OFST (2) ++#define RG_SSUSB_P_SIGDET_SAMPLE_PRD_OFST (1) ++#define RG_SSUSB_P_SIGDET_REK_OFST (0) ++ ++//U3D_B2_PHYD_RXDET1 ++#define RG_SSUSB_RXDET_PRB_SEL_OFST (31) ++#define RG_SSUSB_FORCE_CMDET_OFST (30) ++#define RG_SSUSB_RXDET_EN_OFST (29) ++#define RG_SSUSB_FORCE_RXDET_EN_OFST (28) ++#define RG_SSUSB_RXDET_K_TWICE_OFST (27) ++#define RG_SSUSB_RXDET_STB3_SET_OFST (18) ++#define RG_SSUSB_RXDET_STB2_SET_OFST (9) ++#define RG_SSUSB_RXDET_STB1_SET_OFST (0) ++ ++//U3D_B2_PHYD_RXDET2 ++#define RG_SSUSB_PHYD_TRAINDEC_FORCE_CGEN_OFST (31) ++#define RG_SSUSB_PHYD_BERTLB_FORCE_CGEN_OFST (30) ++#define RG_SSUSB_PHYD_T2RLB_FORCE_CGEN_OFST (29) ++#define RG_SSUSB_PDN_T_SEL_OFST (18) ++#define RG_SSUSB_RXDET_STB3_SET_P3_OFST (9) ++#define RG_SSUSB_RXDET_STB2_SET_P3_OFST (0) ++ ++//U3D_B2_PHYD_MISC0 ++#define RG_SSUSB_FORCE_PLL_DDS_HF_EN_OFST (22) ++#define RG_SSUSB_PLL_DDS_HF_EN_MAN_OFST (21) ++#define RG_SSUSB_RXLFPS_ENTXDRV_OFST (20) ++#define RG_SSUSB_RX_FL_UNLOCKTH_OFST (16) ++#define RG_SSUSB_LFPS_PSEL_OFST (15) ++#define RG_SSUSB_RX_SIGDET_EN_OFST (14) ++#define RG_SSUSB_RX_SIGDET_EN_SEL_OFST (13) ++#define RG_SSUSB_RX_PI_CAL_EN_OFST (12) ++#define RG_SSUSB_RX_PI_CAL_EN_SEL_OFST (11) ++#define RG_SSUSB_P3_CLS_CK_SEL_OFST (10) ++#define RG_SSUSB_T2RLB_PSEL_OFST (8) ++#define RG_SSUSB_PPCTL_PSEL_OFST (5) ++#define RG_SSUSB_PHYD_TX_DATA_INV_OFST (4) ++#define RG_SSUSB_BERTLB_PSEL_OFST (2) ++#define RG_SSUSB_RETRACK_DIS_OFST (1) ++#define RG_SSUSB_PPERRCNT_CLR_OFST (0) ++ ++//U3D_B2_PHYD_MISC2 ++#define RG_SSUSB_FRC_PLL_DDS_PREDIV2_OFST (31) ++#define RG_SSUSB_FRC_PLL_DDS_IADJ_OFST (27) ++#define RG_SSUSB_P_SIGDET_125FILTER_OFST (26) ++#define RG_SSUSB_P_SIGDET_RST_FILTER_OFST (25) ++#define RG_SSUSB_P_SIGDET_EID_USE_RAW_OFST (24) ++#define RG_SSUSB_P_SIGDET_LTD_USE_RAW_OFST (23) ++#define RG_SSUSB_EIDLE_BF_RXDET_OFST (22) ++#define RG_SSUSB_EIDLE_LP_STBCYC_OFST (13) ++#define RG_SSUSB_TX_EIDLE_LP_POSTDLY_OFST (7) ++#define RG_SSUSB_TX_EIDLE_LP_PREDLY_OFST (1) ++#define RG_SSUSB_TX_EIDLE_LP_EN_ADV_OFST (0) ++ ++//U3D_B2_PHYD_MISC3 ++#define RGS_SSUSB_DDS_CALIB_C_STATE_OFST (16) ++#define RGS_SSUSB_PPERRCNT_OFST (0) ++ ++//U3D_B2_ROSC_0 ++#define RG_SSUSB_RING_OSC_CNTEND_OFST (23) ++#define RG_SSUSB_XTAL_OSC_CNTEND_OFST (16) ++#define RG_SSUSB_RING_OSC_EN_OFST (3) ++#define RG_SSUSB_RING_OSC_FORCE_EN_OFST (2) ++#define RG_SSUSB_FRC_RING_BYPASS_DET_OFST (1) ++#define RG_SSUSB_RING_BYPASS_DET_OFST (0) ++ ++//U3D_B2_ROSC_1 ++#define RG_SSUSB_RING_OSC_FRC_P3_OFST (20) ++#define RG_SSUSB_RING_OSC_P3_OFST (19) ++#define RG_SSUSB_RING_OSC_FRC_RECAL_OFST (17) ++#define RG_SSUSB_RING_OSC_RECAL_OFST (16) ++#define RG_SSUSB_RING_OSC_SEL_OFST (8) ++#define RG_SSUSB_RING_OSC_FRC_SEL_OFST (0) ++ ++//U3D_B2_ROSC_2 ++#define RG_SSUSB_RING_DET_STRCYC2_OFST (16) ++#define RG_SSUSB_RING_DET_STRCYC1_OFST (0) ++ ++//U3D_B2_ROSC_3 ++#define RG_SSUSB_RING_DET_DETWIN1_OFST (16) ++#define RG_SSUSB_RING_DET_STRCYC3_OFST (0) ++ ++//U3D_B2_ROSC_4 ++#define RG_SSUSB_RING_DET_DETWIN3_OFST (16) ++#define RG_SSUSB_RING_DET_DETWIN2_OFST (0) ++ ++//U3D_B2_ROSC_5 ++#define RG_SSUSB_RING_DET_LBOND1_OFST (16) ++#define RG_SSUSB_RING_DET_UBOND1_OFST (0) ++ ++//U3D_B2_ROSC_6 ++#define RG_SSUSB_RING_DET_LBOND2_OFST (16) ++#define RG_SSUSB_RING_DET_UBOND2_OFST (0) ++ ++//U3D_B2_ROSC_7 ++#define RG_SSUSB_RING_DET_LBOND3_OFST (16) ++#define RG_SSUSB_RING_DET_UBOND3_OFST (0) ++ ++//U3D_B2_ROSC_8 ++#define RG_SSUSB_RING_RESERVE_OFST (16) ++#define RG_SSUSB_ROSC_PROB_SEL_OFST (2) ++#define RG_SSUSB_RING_FREQMETER_EN_OFST (1) ++#define RG_SSUSB_RING_DET_BPS_UBOND_OFST (0) ++ ++//U3D_B2_ROSC_9 ++#define RGS_FM_RING_CNT_OFST (16) ++#define RGS_SSUSB_RING_OSC_STATE_OFST (10) ++#define RGS_SSUSB_RING_OSC_STABLE_OFST (9) ++#define RGS_SSUSB_RING_OSC_CAL_FAIL_OFST (8) ++#define RGS_SSUSB_RING_OSC_CAL_OFST (0) ++ ++//U3D_B2_ROSC_A ++#define RGS_SSUSB_ROSC_PROB_OUT_OFST (0) ++ ++//U3D_PHYD_VERSION ++#define RGS_SSUSB_PHYD_VERSION_OFST (0) ++ ++//U3D_PHYD_MODEL ++#define RGS_SSUSB_PHYD_MODEL_OFST (0) ++ ++ ++/////////////////////////////////////////////////////////////////////////////// ++ ++struct sifslv_chip_reg { ++ PHY_LE32 xtalbias; ++ PHY_LE32 syspll1; ++ PHY_LE32 gpio_ctla; ++ PHY_LE32 gpio_ctlb; ++ PHY_LE32 gpio_ctlc; ++}; ++ ++//U3D_GPIO_CTLA ++#define RG_C60802_GPIO_CTLA (0xffffffff<<0) //31:0 ++ ++//U3D_GPIO_CTLB ++#define RG_C60802_GPIO_CTLB (0xffffffff<<0) //31:0 ++ ++//U3D_GPIO_CTLC ++#define RG_C60802_GPIO_CTLC (0xffffffff<<0) //31:0 ++ ++/* OFFSET */ ++ ++//U3D_GPIO_CTLA ++#define RG_C60802_GPIO_CTLA_OFST (0) ++ ++//U3D_GPIO_CTLB ++#define RG_C60802_GPIO_CTLB_OFST (0) ++ ++//U3D_GPIO_CTLC ++#define RG_C60802_GPIO_CTLC_OFST (0) ++ ++/////////////////////////////////////////////////////////////////////////////// ++ ++struct sifslv_fm_feg { ++ //0x0 ++ PHY_LE32 fmcr0; ++ PHY_LE32 fmcr1; ++ PHY_LE32 fmcr2; ++ PHY_LE32 fmmonr0; ++ //0x10 ++ PHY_LE32 fmmonr1; ++}; ++ ++//U3D_FMCR0 ++#define RG_LOCKTH (0xf<<28) //31:28 ++#define RG_MONCLK_SEL (0x3<<26) //27:26 ++#define RG_FM_MODE (0x1<<25) //25:25 ++#define RG_FREQDET_EN (0x1<<24) //24:24 ++#define RG_CYCLECNT (0xffffff<<0) //23:0 ++ ++//U3D_FMCR1 ++#define RG_TARGET (0xffffffff<<0) //31:0 ++ ++//U3D_FMCR2 ++#define RG_OFFSET (0xffffffff<<0) //31:0 ++ ++//U3D_FMMONR0 ++#define USB_FM_OUT (0xffffffff<<0) //31:0 ++ ++//U3D_FMMONR1 ++#define RG_MONCLK_SEL_3 (0x1<<9) //9:9 ++#define RG_FRCK_EN (0x1<<8) //8:8 ++#define USBPLL_LOCK (0x1<<1) //1:1 ++#define USB_FM_VLD (0x1<<0) //0:0 ++ ++ ++/* OFFSET */ ++ ++//U3D_FMCR0 ++#define RG_LOCKTH_OFST (28) ++#define RG_MONCLK_SEL_OFST (26) ++#define RG_FM_MODE_OFST (25) ++#define RG_FREQDET_EN_OFST (24) ++#define RG_CYCLECNT_OFST (0) ++ ++//U3D_FMCR1 ++#define RG_TARGET_OFST (0) ++ ++//U3D_FMCR2 ++#define RG_OFFSET_OFST (0) ++ ++//U3D_FMMONR0 ++#define USB_FM_OUT_OFST (0) ++ ++//U3D_FMMONR1 ++#define RG_MONCLK_SEL_3_OFST (9) ++#define RG_FRCK_EN_OFST (8) ++#define USBPLL_LOCK_OFST (1) ++#define USB_FM_VLD_OFST (0) ++ ++ ++/////////////////////////////////////////////////////////////////////////////// ++ ++PHY_INT32 phy_init(struct u3phy_info *info); ++PHY_INT32 phy_change_pipe_phase(struct u3phy_info *info, PHY_INT32 phy_drv, PHY_INT32 pipe_phase); ++PHY_INT32 eyescan_init(struct u3phy_info *info); ++PHY_INT32 phy_eyescan(struct u3phy_info *info, PHY_INT32 x_t1, PHY_INT32 y_t1, PHY_INT32 x_br, PHY_INT32 y_br, PHY_INT32 delta_x, PHY_INT32 delta_y ++ , PHY_INT32 eye_cnt, PHY_INT32 num_cnt, PHY_INT32 PI_cal_en, PHY_INT32 num_ignore_cnt); ++PHY_INT32 u2_save_cur_en(struct u3phy_info *info); ++PHY_INT32 u2_save_cur_re(struct u3phy_info *info); ++PHY_INT32 u2_slew_rate_calibration(struct u3phy_info *info); ++ ++#endif ++#endif +--- /dev/null ++++ b/drivers/usb/host/mtk-phy-ahb.c +@@ -0,0 +1,58 @@ ++#include "mtk-phy.h" ++#ifdef CONFIG_U3D_HAL_SUPPORT ++#include "mu3d_hal_osal.h" ++#endif ++ ++#ifdef CONFIG_U3_PHY_AHB_SUPPORT ++#include <linux/gfp.h> ++#include <linux/kernel.h> ++#include <linux/slab.h> ++ ++#ifndef CONFIG_U3D_HAL_SUPPORT ++#define os_writel(addr,data) {\ ++ (*((volatile PHY_UINT32*)(addr)) = data);\ ++ } ++#define os_readl(addr) *((volatile PHY_UINT32*)(addr)) ++#define os_writelmsk(addr, data, msk) \ ++ { os_writel(addr, ((os_readl(addr) & ~(msk)) | ((data) & (msk)))); \ ++ } ++#define os_setmsk(addr, msk) \ ++ { os_writel(addr, os_readl(addr) | msk); \ ++ } ++#define os_clrmsk(addr, msk) \ ++ { os_writel(addr, os_readl(addr) &~ msk); \ ++ } ++/*msk the data first, then umsk with the umsk.*/ ++#define os_writelmskumsk(addr, data, msk, umsk) \ ++{\ ++ os_writel(addr, ((os_readl(addr) & ~(msk)) | ((data) & (msk))) & (umsk));\ ++} ++ ++#endif ++ ++PHY_INT32 U3PhyWriteReg32(PHY_UINT32 addr, PHY_UINT32 data) ++{ ++ os_writel(addr, data); ++ ++ return 0; ++} ++ ++PHY_INT32 U3PhyReadReg32(PHY_UINT32 addr) ++{ ++ return os_readl(addr); ++} ++ ++PHY_INT32 U3PhyWriteReg8(PHY_UINT32 addr, PHY_UINT8 data) ++{ ++ os_writelmsk(addr&0xfffffffc, data<<((addr%4)*8), 0xff<<((addr%4)*8)); ++ ++ return 0; ++} ++ ++PHY_INT8 U3PhyReadReg8(PHY_UINT32 addr) ++{ ++ return ((os_readl(addr)>>((addr%4)*8))&0xff); ++} ++ ++#endif ++ +--- /dev/null ++++ b/drivers/usb/host/mtk-phy.c +@@ -0,0 +1,102 @@ ++#include <linux/gfp.h> ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#define U3_PHY_LIB ++#include "mtk-phy.h" ++#ifdef CONFIG_PROJECT_7621 ++#include "mtk-phy-7621.h" ++#endif ++#ifdef CONFIG_PROJECT_PHY ++static struct u3phy_operator project_operators = { ++ .init = phy_init, ++ .change_pipe_phase = phy_change_pipe_phase, ++ .eyescan_init = eyescan_init, ++ .eyescan = phy_eyescan, ++ .u2_slew_rate_calibration = u2_slew_rate_calibration, ++}; ++#endif ++ ++ ++PHY_INT32 u3phy_init(){ ++#ifndef CONFIG_PROJECT_PHY ++ PHY_INT32 u3phy_version; ++#endif ++ ++ if(u3phy != NULL){ ++ return PHY_TRUE; ++ } ++ ++ u3phy = kmalloc(sizeof(struct u3phy_info), GFP_NOIO); ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ u3phy_p1 = kmalloc(sizeof(struct u3phy_info), GFP_NOIO); ++#endif ++#ifdef CONFIG_U3_PHY_GPIO_SUPPORT ++ u3phy->phyd_version_addr = 0x2000e4; ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ u3phy_p1->phyd_version_addr = 0x2000e4; ++#endif ++#else ++ u3phy->phyd_version_addr = U3_PHYD_B2_BASE + 0xe4; ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ u3phy_p1->phyd_version_addr = U3_PHYD_B2_BASE_P1 + 0xe4; ++#endif ++#endif ++ ++#ifdef CONFIG_PROJECT_PHY ++ ++ u3phy->u2phy_regs = (struct u2phy_reg *)U2_PHY_BASE; ++ u3phy->u3phyd_regs = (struct u3phyd_reg *)U3_PHYD_BASE; ++ u3phy->u3phyd_bank2_regs = (struct u3phyd_bank2_reg *)U3_PHYD_B2_BASE; ++ u3phy->u3phya_regs = (struct u3phya_reg *)U3_PHYA_BASE; ++ u3phy->u3phya_da_regs = (struct u3phya_da_reg *)U3_PHYA_DA_BASE; ++ u3phy->sifslv_chip_regs = (struct sifslv_chip_reg *)SIFSLV_CHIP_BASE; ++ u3phy->sifslv_fm_regs = (struct sifslv_fm_feg *)SIFSLV_FM_FEG_BASE; ++ u3phy_ops = &project_operators; ++ ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ u3phy_p1->u2phy_regs = (struct u2phy_reg *)U2_PHY_BASE_P1; ++ u3phy_p1->u3phyd_regs = (struct u3phyd_reg *)U3_PHYD_BASE_P1; ++ u3phy_p1->u3phyd_bank2_regs = (struct u3phyd_bank2_reg *)U3_PHYD_B2_BASE_P1; ++ u3phy_p1->u3phya_regs = (struct u3phya_reg *)U3_PHYA_BASE_P1; ++ u3phy_p1->u3phya_da_regs = (struct u3phya_da_reg *)U3_PHYA_DA_BASE_P1; ++ u3phy_p1->sifslv_chip_regs = (struct sifslv_chip_reg *)SIFSLV_CHIP_BASE; ++ u3phy_p1->sifslv_fm_regs = (struct sifslv_fm_feg *)SIFSLV_FM_FEG_BASE; ++#endif ++#endif ++ ++ return PHY_TRUE; ++} ++ ++PHY_INT32 U3PhyWriteField8(PHY_INT32 addr, PHY_INT32 offset, PHY_INT32 mask, PHY_INT32 value){ ++ PHY_INT8 cur_value; ++ PHY_INT8 new_value; ++ ++ cur_value = U3PhyReadReg8(addr); ++ new_value = (cur_value & (~mask)) | (value << offset); ++ //udelay(i2cdelayus); ++ U3PhyWriteReg8(addr, new_value); ++ return PHY_TRUE; ++} ++ ++PHY_INT32 U3PhyWriteField32(PHY_INT32 addr, PHY_INT32 offset, PHY_INT32 mask, PHY_INT32 value){ ++ PHY_INT32 cur_value; ++ PHY_INT32 new_value; ++ ++ cur_value = U3PhyReadReg32(addr); ++ new_value = (cur_value & (~mask)) | ((value << offset) & mask); ++ U3PhyWriteReg32(addr, new_value); ++ //DRV_MDELAY(100); ++ ++ return PHY_TRUE; ++} ++ ++PHY_INT32 U3PhyReadField8(PHY_INT32 addr,PHY_INT32 offset,PHY_INT32 mask){ ++ ++ return ((U3PhyReadReg8(addr) & mask) >> offset); ++} ++ ++PHY_INT32 U3PhyReadField32(PHY_INT32 addr, PHY_INT32 offset, PHY_INT32 mask){ ++ ++ return ((U3PhyReadReg32(addr) & mask) >> offset); ++} ++ +--- /dev/null ++++ b/drivers/usb/host/mtk-phy.h +@@ -0,0 +1,179 @@ ++#ifndef __MTK_PHY_NEW_H ++#define __MTK_PHY_NEW_H ++ ++//#define CONFIG_U3D_HAL_SUPPORT ++ ++/* include system library */ ++#include <linux/gfp.h> ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/delay.h> ++ ++/* Choose PHY R/W implementation */ ++//#define CONFIG_U3_PHY_GPIO_SUPPORT //SW I2C implemented by GPIO ++#define CONFIG_U3_PHY_AHB_SUPPORT //AHB, only on SoC ++ ++/* Choose PHY version */ ++//Select your project by defining one of the followings ++#define CONFIG_PROJECT_7621 //7621 ++#define CONFIG_PROJECT_PHY ++ ++/* BASE ADDRESS DEFINE, should define this on ASIC */ ++#define PHY_BASE 0xBE1D0000 ++#define SIFSLV_FM_FEG_BASE (PHY_BASE+0x100) ++#define SIFSLV_CHIP_BASE (PHY_BASE+0x700) ++#define U2_PHY_BASE (PHY_BASE+0x800) ++#define U3_PHYD_BASE (PHY_BASE+0x900) ++#define U3_PHYD_B2_BASE (PHY_BASE+0xa00) ++#define U3_PHYA_BASE (PHY_BASE+0xb00) ++#define U3_PHYA_DA_BASE (PHY_BASE+0xc00) ++ ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++#define SIFSLV_FM_FEG_BASE_P1 (PHY_BASE+0x100) ++#define SIFSLV_CHIP_BASE_P1 (PHY_BASE+0x700) ++#define U2_PHY_BASE_P1 (PHY_BASE+0x1000) ++#define U3_PHYD_BASE_P1 (PHY_BASE+0x1100) ++#define U3_PHYD_B2_BASE_P1 (PHY_BASE+0x1200) ++#define U3_PHYA_BASE_P1 (PHY_BASE+0x1300) ++#define U3_PHYA_DA_BASE_P1 (PHY_BASE+0x1400) ++#endif ++ ++/* ++ ++0x00000100 MODULE ssusb_sifslv_fmreg ssusb_sifslv_fmreg ++0x00000700 MODULE ssusb_sifslv_ippc ssusb_sifslv_ippc ++0x00000800 MODULE ssusb_sifslv_u2phy_com ssusb_sifslv_u2_phy_com_T28 ++0x00000900 MODULE ssusb_sifslv_u3phyd ssusb_sifslv_u3phyd_T28 ++0x00000a00 MODULE ssusb_sifslv_u3phyd_bank2 ssusb_sifslv_u3phyd_bank2_T28 ++0x00000b00 MODULE ssusb_sifslv_u3phya ssusb_sifslv_u3phya_T28 ++0x00000c00 MODULE ssusb_sifslv_u3phya_da ssusb_sifslv_u3phya_da_T28 ++*/ ++ ++ ++/* TYPE DEFINE */ ++typedef unsigned int PHY_UINT32; ++typedef int PHY_INT32; ++typedef unsigned short PHY_UINT16; ++typedef short PHY_INT16; ++typedef unsigned char PHY_UINT8; ++typedef char PHY_INT8; ++ ++typedef PHY_UINT32 __bitwise PHY_LE32; ++ ++/* CONSTANT DEFINE */ ++#define PHY_FALSE 0 ++#define PHY_TRUE 1 ++ ++/* MACRO DEFINE */ ++#define DRV_WriteReg32(addr,data) ((*(volatile PHY_UINT32 *)(addr)) = (unsigned long)(data)) ++#define DRV_Reg32(addr) (*(volatile PHY_UINT32 *)(addr)) ++ ++#define DRV_MDELAY mdelay ++#define DRV_MSLEEP msleep ++#define DRV_UDELAY udelay ++#define DRV_USLEEP usleep ++ ++/* PHY FUNCTION DEFINE, implemented in platform files, ex. ahb, gpio */ ++PHY_INT32 U3PhyWriteReg32(PHY_UINT32 addr, PHY_UINT32 data); ++PHY_INT32 U3PhyReadReg32(PHY_UINT32 addr); ++PHY_INT32 U3PhyWriteReg8(PHY_UINT32 addr, PHY_UINT8 data); ++PHY_INT8 U3PhyReadReg8(PHY_UINT32 addr); ++ ++/* PHY GENERAL USAGE FUNC, implemented in mtk-phy.c */ ++PHY_INT32 U3PhyWriteField8(PHY_INT32 addr, PHY_INT32 offset, PHY_INT32 mask, PHY_INT32 value); ++PHY_INT32 U3PhyWriteField32(PHY_INT32 addr, PHY_INT32 offset, PHY_INT32 mask, PHY_INT32 value); ++PHY_INT32 U3PhyReadField8(PHY_INT32 addr, PHY_INT32 offset, PHY_INT32 mask); ++PHY_INT32 U3PhyReadField32(PHY_INT32 addr, PHY_INT32 offset, PHY_INT32 mask); ++ ++struct u3phy_info { ++ PHY_INT32 phy_version; ++ PHY_INT32 phyd_version_addr; ++ ++#ifdef CONFIG_PROJECT_PHY ++ struct u2phy_reg *u2phy_regs; ++ struct u3phya_reg *u3phya_regs; ++ struct u3phya_da_reg *u3phya_da_regs; ++ struct u3phyd_reg *u3phyd_regs; ++ struct u3phyd_bank2_reg *u3phyd_bank2_regs; ++ struct sifslv_chip_reg *sifslv_chip_regs; ++ struct sifslv_fm_feg *sifslv_fm_regs; ++#endif ++}; ++ ++struct u3phy_operator { ++ PHY_INT32 (*init) (struct u3phy_info *info); ++ PHY_INT32 (*change_pipe_phase) (struct u3phy_info *info, PHY_INT32 phy_drv, PHY_INT32 pipe_phase); ++ PHY_INT32 (*eyescan_init) (struct u3phy_info *info); ++ PHY_INT32 (*eyescan) (struct u3phy_info *info, PHY_INT32 x_t1, PHY_INT32 y_t1, PHY_INT32 x_br, PHY_INT32 y_br, PHY_INT32 delta_x, PHY_INT32 delta_y, PHY_INT32 eye_cnt, PHY_INT32 num_cnt, PHY_INT32 PI_cal_en, PHY_INT32 num_ignore_cnt); ++ PHY_INT32 (*u2_save_current_entry) (struct u3phy_info *info); ++ PHY_INT32 (*u2_save_current_recovery) (struct u3phy_info *info); ++ PHY_INT32 (*u2_slew_rate_calibration) (struct u3phy_info *info); ++}; ++ ++#ifdef U3_PHY_LIB ++#define AUTOEXT ++#else ++#define AUTOEXT extern ++#endif ++ ++AUTOEXT struct u3phy_info *u3phy; ++AUTOEXT struct u3phy_info *u3phy_p1; ++AUTOEXT struct u3phy_operator *u3phy_ops; ++ ++/*********eye scan required*********/ ++ ++#define LO_BYTE(x) ((PHY_UINT8)((x) & 0xFF)) ++#define HI_BYTE(x) ((PHY_UINT8)(((x) & 0xFF00) >> 8)) ++ ++typedef enum ++{ ++ SCAN_UP, ++ SCAN_DN ++} enumScanDir; ++ ++struct strucScanRegion ++{ ++ PHY_INT8 bX_tl; ++ PHY_INT8 bY_tl; ++ PHY_INT8 bX_br; ++ PHY_INT8 bY_br; ++ PHY_INT8 bDeltaX; ++ PHY_INT8 bDeltaY; ++}; ++ ++struct strucTestCycle ++{ ++ PHY_UINT16 wEyeCnt; ++ PHY_INT8 bNumOfEyeCnt; ++ PHY_INT8 bPICalEn; ++ PHY_INT8 bNumOfIgnoreCnt; ++}; ++ ++#define ERRCNT_MAX 128 ++#define CYCLE_COUNT_MAX 15 ++ ++/// the map resolution is 128 x 128 pts ++#define MAX_X 127 ++#define MAX_Y 127 ++#define MIN_X 0 ++#define MIN_Y 0 ++ ++PHY_INT32 u3phy_init(void); ++ ++AUTOEXT struct strucScanRegion _rEye1; ++AUTOEXT struct strucScanRegion _rEye2; ++AUTOEXT struct strucTestCycle _rTestCycle; ++AUTOEXT PHY_UINT8 _bXcurr; ++AUTOEXT PHY_UINT8 _bYcurr; ++AUTOEXT enumScanDir _eScanDir; ++AUTOEXT PHY_INT8 _fgXChged; ++AUTOEXT PHY_INT8 _bPIResult; ++/* use local variable instead to save memory use */ ++#if 0 ++AUTOEXT PHY_UINT32 pwErrCnt0[CYCLE_COUNT_MAX][ERRCNT_MAX][ERRCNT_MAX]; ++AUTOEXT PHY_UINT32 pwErrCnt1[CYCLE_COUNT_MAX][ERRCNT_MAX][ERRCNT_MAX]; ++#endif ++ ++/***********************************/ ++#endif ++ +--- a/drivers/usb/host/pci-quirks.h ++++ b/drivers/usb/host/pci-quirks.h +@@ -1,7 +1,7 @@ + #ifndef __LINUX_USB_PCI_QUIRKS_H + #define __LINUX_USB_PCI_QUIRKS_H + +-#ifdef CONFIG_PCI ++#if defined (CONFIG_PCI) && !defined (CONFIG_USB_MT7621_XHCI_PLATFORM) + void uhci_reset_hc(struct pci_dev *pdev, unsigned long base); + int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base); + #endif /* CONFIG_PCI */ +--- a/drivers/usb/host/xhci-dbg.c ++++ b/drivers/usb/host/xhci-dbg.c +@@ -21,6 +21,9 @@ + */ + + #include "xhci.h" ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++#include "xhci-mtk.h" ++#endif + + #define XHCI_INIT_VALUE 0x0 + +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -67,6 +67,9 @@ static struct xhci_segment *xhci_segment + + static void xhci_segment_free(struct xhci_hcd *xhci, struct xhci_segment *seg) + { ++ if (!seg) ++ return; ++ + if (seg->trbs) { + dma_pool_free(xhci->segment_pool, seg->trbs, seg->dma); + seg->trbs = NULL; +@@ -1475,9 +1478,17 @@ int xhci_endpoint_init(struct xhci_hcd * + max_burst = (usb_endpoint_maxp(&ep->desc) + & 0x1800) >> 11; + } ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ if ((max_packet % 4 == 2) && (max_packet % 16 != 14) && (max_burst == 0) && usb_endpoint_dir_in(&ep->desc)) ++ max_packet += 2; ++#endif + break; + case USB_SPEED_FULL: + case USB_SPEED_LOW: ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ if ((max_packet % 4 == 2) && (max_packet % 16 != 14) && (max_burst == 0) && usb_endpoint_dir_in(&ep->desc)) ++ max_packet += 2; ++#endif + break; + default: + BUG(); +--- /dev/null ++++ b/drivers/usb/host/xhci-mtk-power.c +@@ -0,0 +1,115 @@ ++#include "xhci-mtk.h" ++#include "xhci-mtk-power.h" ++#include "xhci.h" ++#include <linux/kernel.h> /* printk() */ ++#include <linux/slab.h> ++#include <linux/delay.h> ++ ++static int g_num_u3_port; ++static int g_num_u2_port; ++ ++ ++void enableXhciAllPortPower(struct xhci_hcd *xhci){ ++ int i; ++ u32 port_id, temp; ++ u32 __iomem *addr; ++ ++ g_num_u3_port = SSUSB_U3_PORT_NUM(readl(SSUSB_IP_CAP)); ++ g_num_u2_port = SSUSB_U2_PORT_NUM(readl(SSUSB_IP_CAP)); ++ ++ for(i=1; i<=g_num_u3_port; i++){ ++ port_id=i; ++ addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS*(port_id-1 & 0xff); ++ temp = readl(addr); ++ temp = xhci_port_state_to_neutral(temp); ++ temp |= PORT_POWER; ++ writel(temp, addr); ++ } ++ for(i=1; i<=g_num_u2_port; i++){ ++ port_id=i+g_num_u3_port; ++ addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS*(port_id-1 & 0xff); ++ temp = readl(addr); ++ temp = xhci_port_state_to_neutral(temp); ++ temp |= PORT_POWER; ++ writel(temp, addr); ++ } ++} ++ ++void enableAllClockPower(){ ++ ++ int i; ++ u32 temp; ++ ++ g_num_u3_port = SSUSB_U3_PORT_NUM(readl(SSUSB_IP_CAP)); ++ g_num_u2_port = SSUSB_U2_PORT_NUM(readl(SSUSB_IP_CAP)); ++ ++ //2. Enable xHC ++ writel(readl(SSUSB_IP_PW_CTRL) | (SSUSB_IP_SW_RST), SSUSB_IP_PW_CTRL); ++ writel(readl(SSUSB_IP_PW_CTRL) & (~SSUSB_IP_SW_RST), SSUSB_IP_PW_CTRL); ++ writel(readl(SSUSB_IP_PW_CTRL_1) & (~SSUSB_IP_PDN), SSUSB_IP_PW_CTRL_1); ++ ++ //1. Enable target ports ++ for(i=0; i<g_num_u3_port; i++){ ++ temp = readl(SSUSB_U3_CTRL(i)); ++ temp = temp & (~SSUSB_U3_PORT_PDN) & (~SSUSB_U3_PORT_DIS); ++ writel(temp, SSUSB_U3_CTRL(i)); ++ } ++ for(i=0; i<g_num_u2_port; i++){ ++ temp = readl(SSUSB_U2_CTRL(i)); ++ temp = temp & (~SSUSB_U2_PORT_PDN) & (~SSUSB_U2_PORT_DIS); ++ writel(temp, SSUSB_U2_CTRL(i)); ++ } ++ msleep(100); ++} ++ ++ ++//(X)disable clock/power of a port ++//(X)if all ports are disabled, disable IP ctrl power ++//disable all ports and IP clock/power, this is just mention HW that the power/clock of port ++//and IP could be disable if suspended. ++//If doesn't not disable all ports at first, the IP clock/power will never be disabled ++//(some U2 and U3 ports are binded to the same connection, that is, they will never enter suspend at the same time ++//port_index: port number ++//port_rev: 0x2 - USB2.0, 0x3 - USB3.0 (SuperSpeed) ++void disablePortClockPower(void){ ++ int i; ++ u32 temp; ++ ++ g_num_u3_port = SSUSB_U3_PORT_NUM(readl(SSUSB_IP_CAP)); ++ g_num_u2_port = SSUSB_U2_PORT_NUM(readl(SSUSB_IP_CAP)); ++ ++ for(i=0; i<g_num_u3_port; i++){ ++ temp = readl(SSUSB_U3_CTRL(i)); ++ temp = temp | (SSUSB_U3_PORT_PDN); ++ writel(temp, SSUSB_U3_CTRL(i)); ++ } ++ for(i=0; i<g_num_u2_port; i++){ ++ temp = readl(SSUSB_U2_CTRL(i)); ++ temp = temp | (SSUSB_U2_PORT_PDN); ++ writel(temp, SSUSB_U2_CTRL(i)); ++ } ++ writel(readl(SSUSB_IP_PW_CTRL_1) | (SSUSB_IP_PDN), SSUSB_IP_PW_CTRL_1); ++} ++ ++//if IP ctrl power is disabled, enable it ++//enable clock/power of a port ++//port_index: port number ++//port_rev: 0x2 - USB2.0, 0x3 - USB3.0 (SuperSpeed) ++void enablePortClockPower(int port_index, int port_rev){ ++ int i; ++ u32 temp; ++ ++ writel(readl(SSUSB_IP_PW_CTRL_1) & (~SSUSB_IP_PDN), SSUSB_IP_PW_CTRL_1); ++ ++ if(port_rev == 0x3){ ++ temp = readl(SSUSB_U3_CTRL(port_index)); ++ temp = temp & (~SSUSB_U3_PORT_PDN); ++ writel(temp, SSUSB_U3_CTRL(port_index)); ++ } ++ else if(port_rev == 0x2){ ++ temp = readl(SSUSB_U2_CTRL(port_index)); ++ temp = temp & (~SSUSB_U2_PORT_PDN); ++ writel(temp, SSUSB_U2_CTRL(port_index)); ++ } ++} ++ +--- /dev/null ++++ b/drivers/usb/host/xhci-mtk-power.h +@@ -0,0 +1,13 @@ ++#ifndef _XHCI_MTK_POWER_H ++#define _XHCI_MTK_POWER_H ++ ++#include <linux/usb.h> ++#include "xhci.h" ++#include "xhci-mtk.h" ++ ++void enableXhciAllPortPower(struct xhci_hcd *xhci); ++void enableAllClockPower(void); ++void disablePortClockPower(void); ++void enablePortClockPower(int port_index, int port_rev); ++ ++#endif +--- /dev/null ++++ b/drivers/usb/host/xhci-mtk-scheduler.c +@@ -0,0 +1,608 @@ ++#include "xhci-mtk-scheduler.h" ++#include <linux/kernel.h> /* printk() */ ++ ++static struct sch_ep **ss_out_eps[MAX_EP_NUM]; ++static struct sch_ep **ss_in_eps[MAX_EP_NUM]; ++static struct sch_ep **hs_eps[MAX_EP_NUM]; //including tt isoc ++static struct sch_ep **tt_intr_eps[MAX_EP_NUM]; ++ ++ ++int mtk_xhci_scheduler_init(void){ ++ int i; ++ ++ for(i=0; i<MAX_EP_NUM; i++){ ++ ss_out_eps[i] = NULL; ++ } ++ for(i=0; i<MAX_EP_NUM; i++){ ++ ss_in_eps[i] = NULL; ++ } ++ for(i=0; i<MAX_EP_NUM; i++){ ++ hs_eps[i] = NULL; ++ } ++ for(i=0; i<MAX_EP_NUM; i++){ ++ tt_intr_eps[i] = NULL; ++ } ++ return 0; ++} ++ ++int add_sch_ep(int dev_speed, int is_in, int isTT, int ep_type, int maxp, int interval, int burst ++ , int mult, int offset, int repeat, int pkts, int cs_count, int burst_mode ++ , int bw_cost, mtk_u32 *ep, struct sch_ep *tmp_ep){ ++ ++ struct sch_ep **ep_array; ++ int i; ++ ++ if(is_in && dev_speed == USB_SPEED_SUPER ){ ++ ep_array = (struct sch_ep **)ss_in_eps; ++ } ++ else if(dev_speed == USB_SPEED_SUPER){ ++ ep_array = (struct sch_ep **)ss_out_eps; ++ } ++ else if(dev_speed == USB_SPEED_HIGH || (isTT && ep_type == USB_EP_ISOC)){ ++ ep_array = (struct sch_ep **)hs_eps; ++ } ++ else{ ++ ep_array = (struct sch_ep **)tt_intr_eps; ++ } ++ for(i=0; i<MAX_EP_NUM; i++){ ++ if(ep_array[i] == NULL){ ++ tmp_ep->dev_speed = dev_speed; ++ tmp_ep->isTT = isTT; ++ tmp_ep->is_in = is_in; ++ tmp_ep->ep_type = ep_type; ++ tmp_ep->maxp = maxp; ++ tmp_ep->interval = interval; ++ tmp_ep->burst = burst; ++ tmp_ep->mult = mult; ++ tmp_ep->offset = offset; ++ tmp_ep->repeat = repeat; ++ tmp_ep->pkts = pkts; ++ tmp_ep->cs_count = cs_count; ++ tmp_ep->burst_mode = burst_mode; ++ tmp_ep->bw_cost = bw_cost; ++ tmp_ep->ep = ep; ++ ep_array[i] = tmp_ep; ++ return SCH_SUCCESS; ++ } ++ } ++ return SCH_FAIL; ++} ++ ++int count_ss_bw(int is_in, int ep_type, int maxp, int interval, int burst, int mult, int offset, int repeat ++ , int td_size){ ++ int i, j, k; ++ int bw_required[3]; ++ int final_bw_required; ++ int bw_required_per_repeat; ++ int tmp_bw_required; ++ struct sch_ep *cur_sch_ep; ++ struct sch_ep **ep_array; ++ int cur_offset; ++ int cur_ep_offset; ++ int tmp_offset; ++ int tmp_interval; ++ int ep_offset; ++ int ep_interval; ++ int ep_repeat; ++ int ep_mult; ++ ++ if(is_in){ ++ ep_array = (struct sch_ep **)ss_in_eps; ++ } ++ else{ ++ ep_array = (struct sch_ep **)ss_out_eps; ++ } ++ ++ bw_required[0] = 0; ++ bw_required[1] = 0; ++ bw_required[2] = 0; ++ ++ if(repeat == 0){ ++ final_bw_required = 0; ++ for(i=0; i<MAX_EP_NUM; i++){ ++ cur_sch_ep = ep_array[i]; ++ if(cur_sch_ep == NULL){ ++ continue; ++ } ++ ep_interval = cur_sch_ep->interval; ++ ep_offset = cur_sch_ep->offset; ++ if(cur_sch_ep->repeat == 0){ ++ if(ep_interval >= interval){ ++ tmp_offset = ep_offset + ep_interval - offset; ++ tmp_interval = interval; ++ } ++ else{ ++ tmp_offset = offset + interval - ep_offset; ++ tmp_interval = ep_interval; ++ } ++ if(tmp_offset % tmp_interval == 0){ ++ final_bw_required += cur_sch_ep->bw_cost; ++ } ++ } ++ else{ ++ ep_repeat = cur_sch_ep->repeat; ++ ep_mult = cur_sch_ep->mult; ++ for(k=0; k<=ep_mult; k++){ ++ cur_ep_offset = ep_offset+(k*ep_mult); ++ if(ep_interval >= interval){ ++ tmp_offset = cur_ep_offset + ep_interval - offset; ++ tmp_interval = interval; ++ } ++ else{ ++ tmp_offset = offset + interval - cur_ep_offset; ++ tmp_interval = ep_interval; ++ } ++ if(tmp_offset % tmp_interval == 0){ ++ final_bw_required += cur_sch_ep->bw_cost; ++ break; ++ } ++ } ++ } ++ } ++ final_bw_required += td_size; ++ } ++ else{ ++ bw_required_per_repeat = maxp * (burst+1); ++ for(j=0; j<=mult; j++){ ++ tmp_bw_required = 0; ++ cur_offset = offset+(j*repeat); ++ for(i=0; i<MAX_EP_NUM; i++){ ++ cur_sch_ep = ep_array[i]; ++ if(cur_sch_ep == NULL){ ++ continue; ++ } ++ ep_interval = cur_sch_ep->interval; ++ ep_offset = cur_sch_ep->offset; ++ if(cur_sch_ep->repeat == 0){ ++ if(ep_interval >= interval){ ++ tmp_offset = ep_offset + ep_interval - cur_offset; ++ tmp_interval = interval; ++ } ++ else{ ++ tmp_offset = cur_offset + interval - ep_offset; ++ tmp_interval = ep_interval; ++ } ++ if(tmp_offset % tmp_interval == 0){ ++ tmp_bw_required += cur_sch_ep->bw_cost; ++ } ++ } ++ else{ ++ ep_repeat = cur_sch_ep->repeat; ++ ep_mult = cur_sch_ep->mult; ++ for(k=0; k<=ep_mult; k++){ ++ cur_ep_offset = ep_offset+(k*ep_repeat); ++ if(ep_interval >= interval){ ++ tmp_offset = cur_ep_offset + ep_interval - cur_offset; ++ tmp_interval = interval; ++ } ++ else{ ++ tmp_offset = cur_offset + interval - cur_ep_offset; ++ tmp_interval = ep_interval; ++ } ++ if(tmp_offset % tmp_interval == 0){ ++ tmp_bw_required += cur_sch_ep->bw_cost; ++ break; ++ } ++ } ++ } ++ } ++ bw_required[j] = tmp_bw_required; ++ } ++ final_bw_required = SS_BW_BOUND; ++ for(j=0; j<=mult; j++){ ++ if(bw_required[j] < final_bw_required){ ++ final_bw_required = bw_required[j]; ++ } ++ } ++ final_bw_required += bw_required_per_repeat; ++ } ++ return final_bw_required; ++} ++ ++int count_hs_bw(int ep_type, int maxp, int interval, int offset, int td_size){ ++ int i; ++ int bw_required; ++ struct sch_ep *cur_sch_ep; ++ int tmp_offset; ++ int tmp_interval; ++ int ep_offset; ++ int ep_interval; ++ int cur_tt_isoc_interval; //for isoc tt check ++ ++ bw_required = 0; ++ for(i=0; i<MAX_EP_NUM; i++){ ++ ++ cur_sch_ep = (struct sch_ep *)hs_eps[i]; ++ if(cur_sch_ep == NULL){ ++ continue; ++ } ++ ep_offset = cur_sch_ep->offset; ++ ep_interval = cur_sch_ep->interval; ++ ++ if(cur_sch_ep->isTT && cur_sch_ep->ep_type == USB_EP_ISOC){ ++ cur_tt_isoc_interval = ep_interval<<3; ++ if(ep_interval >= interval){ ++ tmp_offset = ep_offset + cur_tt_isoc_interval - offset; ++ tmp_interval = interval; ++ } ++ else{ ++ tmp_offset = offset + interval - ep_offset; ++ tmp_interval = cur_tt_isoc_interval; ++ } ++ if(cur_sch_ep->is_in){ ++ if((tmp_offset%tmp_interval >=2) && (tmp_offset%tmp_interval <= cur_sch_ep->cs_count)){ ++ bw_required += 188; ++ } ++ } ++ else{ ++ if(tmp_offset%tmp_interval <= cur_sch_ep->cs_count){ ++ bw_required += 188; ++ } ++ } ++ } ++ else{ ++ if(ep_interval >= interval){ ++ tmp_offset = ep_offset + ep_interval - offset; ++ tmp_interval = interval; ++ } ++ else{ ++ tmp_offset = offset + interval - ep_offset; ++ tmp_interval = ep_interval; ++ } ++ if(tmp_offset%tmp_interval == 0){ ++ bw_required += cur_sch_ep->bw_cost; ++ } ++ } ++ } ++ bw_required += td_size; ++ return bw_required; ++} ++ ++int count_tt_isoc_bw(int is_in, int maxp, int interval, int offset, int td_size){ ++ char is_cs; ++ int mframe_idx, frame_idx, s_frame, s_mframe, cur_mframe; ++ int bw_required, max_bw; ++ int ss_cs_count; ++ int cs_mframe; ++ int max_frame; ++ int i,j; ++ struct sch_ep *cur_sch_ep; ++ int ep_offset; ++ int ep_interval; ++ int ep_cs_count; ++ int tt_isoc_interval; //for isoc tt check ++ int cur_tt_isoc_interval; //for isoc tt check ++ int tmp_offset; ++ int tmp_interval; ++ ++ is_cs = 0; ++ ++ tt_isoc_interval = interval<<3; //frame to mframe ++ if(is_in){ ++ is_cs = 1; ++ } ++ s_frame = offset/8; ++ s_mframe = offset%8; ++ ss_cs_count = (maxp + (188 - 1))/188; ++ if(is_cs){ ++ cs_mframe = offset%8 + 2 + ss_cs_count; ++ if (cs_mframe <= 6) ++ ss_cs_count += 2; ++ else if (cs_mframe == 7) ++ ss_cs_count++; ++ else if (cs_mframe > 8) ++ return -1; ++ } ++ max_bw = 0; ++ if(is_in){ ++ i=2; ++ } ++ for(cur_mframe = offset+i; i<ss_cs_count; cur_mframe++, i++){ ++ bw_required = 0; ++ for(j=0; j<MAX_EP_NUM; j++){ ++ cur_sch_ep = (struct sch_ep *)hs_eps[j]; ++ if(cur_sch_ep == NULL){ ++ continue; ++ } ++ ep_offset = cur_sch_ep->offset; ++ ep_interval = cur_sch_ep->interval; ++ if(cur_sch_ep->isTT && cur_sch_ep->ep_type == USB_EP_ISOC){ ++ //isoc tt ++ //check if mframe offset overlap ++ //if overlap, add 188 to the bw ++ cur_tt_isoc_interval = ep_interval<<3; ++ if(cur_tt_isoc_interval >= tt_isoc_interval){ ++ tmp_offset = (ep_offset+cur_tt_isoc_interval) - cur_mframe; ++ tmp_interval = tt_isoc_interval; ++ } ++ else{ ++ tmp_offset = (cur_mframe+tt_isoc_interval) - ep_offset; ++ tmp_interval = cur_tt_isoc_interval; ++ } ++ if(cur_sch_ep->is_in){ ++ if((tmp_offset%tmp_interval >=2) && (tmp_offset%tmp_interval <= cur_sch_ep->cs_count)){ ++ bw_required += 188; ++ } ++ } ++ else{ ++ if(tmp_offset%tmp_interval <= cur_sch_ep->cs_count){ ++ bw_required += 188; ++ } ++ } ++ ++ } ++ else if(cur_sch_ep->ep_type == USB_EP_INT || cur_sch_ep->ep_type == USB_EP_ISOC){ ++ //check if mframe ++ if(ep_interval >= tt_isoc_interval){ ++ tmp_offset = (ep_offset+ep_interval) - cur_mframe; ++ tmp_interval = tt_isoc_interval; ++ } ++ else{ ++ tmp_offset = (cur_mframe+tt_isoc_interval) - ep_offset; ++ tmp_interval = ep_interval; ++ } ++ if(tmp_offset%tmp_interval == 0){ ++ bw_required += cur_sch_ep->bw_cost; ++ } ++ } ++ } ++ bw_required += 188; ++ if(bw_required > max_bw){ ++ max_bw = bw_required; ++ } ++ } ++ return max_bw; ++} ++ ++int count_tt_intr_bw(int interval, int frame_offset){ ++ //check all eps in tt_intr_eps ++ int ret; ++ int i,j; ++ int ep_offset; ++ int ep_interval; ++ int tmp_offset; ++ int tmp_interval; ++ ret = SCH_SUCCESS; ++ struct sch_ep *cur_sch_ep; ++ ++ for(i=0; i<MAX_EP_NUM; i++){ ++ cur_sch_ep = (struct sch_ep *)tt_intr_eps[i]; ++ if(cur_sch_ep == NULL){ ++ continue; ++ } ++ ep_offset = cur_sch_ep->offset; ++ ep_interval = cur_sch_ep->interval; ++ if(ep_interval >= interval){ ++ tmp_offset = ep_offset + ep_interval - frame_offset; ++ tmp_interval = interval; ++ } ++ else{ ++ tmp_offset = frame_offset + interval - ep_offset; ++ tmp_interval = ep_interval; ++ } ++ ++ if(tmp_offset%tmp_interval==0){ ++ return SCH_FAIL; ++ } ++ } ++ return SCH_SUCCESS; ++} ++ ++struct sch_ep * mtk_xhci_scheduler_remove_ep(int dev_speed, int is_in, int isTT, int ep_type, mtk_u32 *ep){ ++ int i; ++ struct sch_ep **ep_array; ++ struct sch_ep *cur_ep; ++ ++ if (is_in && dev_speed == USB_SPEED_SUPER) { ++ ep_array = (struct sch_ep **)ss_in_eps; ++ } ++ else if (dev_speed == USB_SPEED_SUPER) { ++ ep_array = (struct sch_ep **)ss_out_eps; ++ } ++ else if (dev_speed == USB_SPEED_HIGH || (isTT && ep_type == USB_EP_ISOC)) { ++ ep_array = (struct sch_ep **)hs_eps; ++ } ++ else { ++ ep_array = (struct sch_ep **)tt_intr_eps; ++ } ++ for (i = 0; i < MAX_EP_NUM; i++) { ++ cur_ep = (struct sch_ep *)ep_array[i]; ++ if(cur_ep != NULL && cur_ep->ep == ep){ ++ ep_array[i] = NULL; ++ return cur_ep; ++ } ++ } ++ return NULL; ++} ++ ++int mtk_xhci_scheduler_add_ep(int dev_speed, int is_in, int isTT, int ep_type, int maxp, int interval, int burst ++ , int mult, mtk_u32 *ep, mtk_u32 *ep_ctx, struct sch_ep *sch_ep){ ++ mtk_u32 bPkts = 0; ++ mtk_u32 bCsCount = 0; ++ mtk_u32 bBm = 1; ++ mtk_u32 bOffset = 0; ++ mtk_u32 bRepeat = 0; ++ int ret; ++ struct mtk_xhci_ep_ctx *temp_ep_ctx; ++ int td_size; ++ int mframe_idx, frame_idx; ++ int bw_cost; ++ int cur_bw, best_bw, best_bw_idx,repeat, max_repeat, best_bw_repeat; ++ int cur_offset, cs_mframe; ++ int break_out; ++ int frame_interval; ++ ++ printk(KERN_ERR "add_ep parameters, dev_speed %d, is_in %d, isTT %d, ep_type %d, maxp %d, interval %d, burst %d, mult %d, ep 0x%x, ep_ctx 0x%x, sch_ep 0x%x\n", dev_speed, is_in, isTT, ep_type, maxp ++ , interval, burst, mult, ep, ep_ctx, sch_ep); ++ if(isTT && ep_type == USB_EP_INT && ((dev_speed == USB_SPEED_LOW) || (dev_speed == USB_SPEED_FULL))){ ++ frame_interval = interval >> 3; ++ for(frame_idx=0; frame_idx<frame_interval; frame_idx++){ ++ printk(KERN_ERR "check tt_intr_bw interval %d, frame_idx %d\n", frame_interval, frame_idx); ++ if(count_tt_intr_bw(frame_interval, frame_idx) == SCH_SUCCESS){ ++ printk(KERN_ERR "check OK............\n"); ++ bOffset = frame_idx<<3; ++ bPkts = 1; ++ bCsCount = 3; ++ bw_cost = maxp; ++ bRepeat = 0; ++ if(add_sch_ep(dev_speed, is_in, isTT, ep_type, maxp, frame_interval, burst, mult ++ , bOffset, bRepeat, bPkts, bCsCount, bBm, maxp, ep, sch_ep) == SCH_FAIL){ ++ return SCH_FAIL; ++ } ++ ret = SCH_SUCCESS; ++ break; ++ } ++ } ++ } ++ else if(isTT && ep_type == USB_EP_ISOC){ ++ best_bw = HS_BW_BOUND; ++ best_bw_idx = -1; ++ cur_bw = 0; ++ td_size = maxp; ++ break_out = 0; ++ frame_interval = interval>>3; ++ for(frame_idx=0; frame_idx<frame_interval && !break_out; frame_idx++){ ++ for(mframe_idx=0; mframe_idx<8; mframe_idx++){ ++ cur_offset = (frame_idx*8) + mframe_idx; ++ cur_bw = count_tt_isoc_bw(is_in, maxp, frame_interval, cur_offset, td_size); ++ if(cur_bw > 0 && cur_bw < best_bw){ ++ best_bw_idx = cur_offset; ++ best_bw = cur_bw; ++ if(cur_bw == td_size || cur_bw < (HS_BW_BOUND>>1)){ ++ break_out = 1; ++ break; ++ } ++ } ++ } ++ } ++ if(best_bw_idx == -1){ ++ return SCH_FAIL; ++ } ++ else{ ++ bOffset = best_bw_idx; ++ bPkts = 1; ++ bCsCount = (maxp + (188 - 1)) / 188; ++ if(is_in){ ++ cs_mframe = bOffset%8 + 2 + bCsCount; ++ if (cs_mframe <= 6) ++ bCsCount += 2; ++ else if (cs_mframe == 7) ++ bCsCount++; ++ } ++ bw_cost = 188; ++ bRepeat = 0; ++ if(add_sch_ep( dev_speed, is_in, isTT, ep_type, maxp, interval, burst, mult ++ , bOffset, bRepeat, bPkts, bCsCount, bBm, bw_cost, ep, sch_ep) == SCH_FAIL){ ++ return SCH_FAIL; ++ } ++ ret = SCH_SUCCESS; ++ } ++ } ++ else if((dev_speed == USB_SPEED_FULL || dev_speed == USB_SPEED_LOW) && ep_type == USB_EP_INT){ ++ bPkts = 1; ++ ret = SCH_SUCCESS; ++ } ++ else if(dev_speed == USB_SPEED_FULL && ep_type == USB_EP_ISOC){ ++ bPkts = 1; ++ ret = SCH_SUCCESS; ++ } ++ else if(dev_speed == USB_SPEED_HIGH && (ep_type == USB_EP_INT || ep_type == USB_EP_ISOC)){ ++ best_bw = HS_BW_BOUND; ++ best_bw_idx = -1; ++ cur_bw = 0; ++ td_size = maxp*(burst+1); ++ for(cur_offset = 0; cur_offset<interval; cur_offset++){ ++ cur_bw = count_hs_bw(ep_type, maxp, interval, cur_offset, td_size); ++ if(cur_bw > 0 && cur_bw < best_bw){ ++ best_bw_idx = cur_offset; ++ best_bw = cur_bw; ++ if(cur_bw == td_size || cur_bw < (HS_BW_BOUND>>1)){ ++ break; ++ } ++ } ++ } ++ if(best_bw_idx == -1){ ++ return SCH_FAIL; ++ } ++ else{ ++ bOffset = best_bw_idx; ++ bPkts = burst + 1; ++ bCsCount = 0; ++ bw_cost = td_size; ++ bRepeat = 0; ++ if(add_sch_ep(dev_speed, is_in, isTT, ep_type, maxp, interval, burst, mult ++ , bOffset, bRepeat, bPkts, bCsCount, bBm, bw_cost, ep, sch_ep) == SCH_FAIL){ ++ return SCH_FAIL; ++ } ++ ret = SCH_SUCCESS; ++ } ++ } ++ else if(dev_speed == USB_SPEED_SUPER && (ep_type == USB_EP_INT || ep_type == USB_EP_ISOC)){ ++ best_bw = SS_BW_BOUND; ++ best_bw_idx = -1; ++ cur_bw = 0; ++ td_size = maxp * (mult+1) * (burst+1); ++ if(mult == 0){ ++ max_repeat = 0; ++ } ++ else{ ++ max_repeat = (interval-1)/(mult+1); ++ } ++ break_out = 0; ++ for(frame_idx = 0; (frame_idx < interval) && !break_out; frame_idx++){ ++ for(repeat = max_repeat; repeat >= 0; repeat--){ ++ cur_bw = count_ss_bw(is_in, ep_type, maxp, interval, burst, mult, frame_idx ++ , repeat, td_size); ++ printk(KERN_ERR "count_ss_bw, frame_idx %d, repeat %d, td_size %d, result bw %d\n" ++ , frame_idx, repeat, td_size, cur_bw); ++ if(cur_bw > 0 && cur_bw < best_bw){ ++ best_bw_idx = frame_idx; ++ best_bw_repeat = repeat; ++ best_bw = cur_bw; ++ if(cur_bw <= td_size || cur_bw < (HS_BW_BOUND>>1)){ ++ break_out = 1; ++ break; ++ } ++ } ++ } ++ } ++ printk(KERN_ERR "final best idx %d, best repeat %d\n", best_bw_idx, best_bw_repeat); ++ if(best_bw_idx == -1){ ++ return SCH_FAIL; ++ } ++ else{ ++ bOffset = best_bw_idx; ++ bCsCount = 0; ++ bRepeat = best_bw_repeat; ++ if(bRepeat == 0){ ++ bw_cost = (burst+1)*(mult+1)*maxp; ++ bPkts = (burst+1)*(mult+1); ++ } ++ else{ ++ bw_cost = (burst+1)*maxp; ++ bPkts = (burst+1); ++ } ++ if(add_sch_ep(dev_speed, is_in, isTT, ep_type, maxp, interval, burst, mult ++ , bOffset, bRepeat, bPkts, bCsCount, bBm, bw_cost, ep, sch_ep) == SCH_FAIL){ ++ return SCH_FAIL; ++ } ++ ret = SCH_SUCCESS; ++ } ++ } ++ else{ ++ bPkts = 1; ++ ret = SCH_SUCCESS; ++ } ++ if(ret == SCH_SUCCESS){ ++ temp_ep_ctx = (struct mtk_xhci_ep_ctx *)ep_ctx; ++ temp_ep_ctx->reserved[0] |= (BPKTS(bPkts) | BCSCOUNT(bCsCount) | BBM(bBm)); ++ temp_ep_ctx->reserved[1] |= (BOFFSET(bOffset) | BREPEAT(bRepeat)); ++ ++ printk(KERN_DEBUG "[DBG] BPKTS: %x, BCSCOUNT: %x, BBM: %x\n", bPkts, bCsCount, bBm); ++ printk(KERN_DEBUG "[DBG] BOFFSET: %x, BREPEAT: %x\n", bOffset, bRepeat); ++ return SCH_SUCCESS; ++ } ++ else{ ++ return SCH_FAIL; ++ } ++} +--- /dev/null ++++ b/drivers/usb/host/xhci-mtk-scheduler.h +@@ -0,0 +1,77 @@ ++#ifndef _XHCI_MTK_SCHEDULER_H ++#define _XHCI_MTK_SCHEDULER_H ++ ++#define MTK_SCH_NEW 1 ++ ++#define SCH_SUCCESS 1 ++#define SCH_FAIL 0 ++ ++#define MAX_EP_NUM 64 ++#define SS_BW_BOUND 51000 ++#define HS_BW_BOUND 6144 ++ ++#define USB_EP_CONTROL 0 ++#define USB_EP_ISOC 1 ++#define USB_EP_BULK 2 ++#define USB_EP_INT 3 ++ ++#define USB_SPEED_LOW 1 ++#define USB_SPEED_FULL 2 ++#define USB_SPEED_HIGH 3 ++#define USB_SPEED_SUPER 5 ++ ++/* mtk scheduler bitmasks */ ++#define BPKTS(p) ((p) & 0x3f) ++#define BCSCOUNT(p) (((p) & 0x7) << 8) ++#define BBM(p) ((p) << 11) ++#define BOFFSET(p) ((p) & 0x3fff) ++#define BREPEAT(p) (((p) & 0x7fff) << 16) ++ ++ ++#if 1 ++typedef unsigned int mtk_u32; ++typedef unsigned long long mtk_u64; ++#endif ++ ++#define NULL ((void *)0) ++ ++struct mtk_xhci_ep_ctx { ++ mtk_u32 ep_info; ++ mtk_u32 ep_info2; ++ mtk_u64 deq; ++ mtk_u32 tx_info; ++ /* offset 0x14 - 0x1f reserved for HC internal use */ ++ mtk_u32 reserved[3]; ++}; ++ ++ ++struct sch_ep ++{ ++ //device info ++ int dev_speed; ++ int isTT; ++ //ep info ++ int is_in; ++ int ep_type; ++ int maxp; ++ int interval; ++ int burst; ++ int mult; ++ //scheduling info ++ int offset; ++ int repeat; ++ int pkts; ++ int cs_count; ++ int burst_mode; ++ //other ++ int bw_cost; //bandwidth cost in each repeat; including overhead ++ mtk_u32 *ep; //address of usb_endpoint pointer ++}; ++ ++int mtk_xhci_scheduler_init(void); ++int mtk_xhci_scheduler_add_ep(int dev_speed, int is_in, int isTT, int ep_type, int maxp, int interval, int burst ++ , int mult, mtk_u32 *ep, mtk_u32 *ep_ctx, struct sch_ep *sch_ep); ++struct sch_ep * mtk_xhci_scheduler_remove_ep(int dev_speed, int is_in, int isTT, int ep_type, mtk_u32 *ep); ++ ++ ++#endif +--- /dev/null ++++ b/drivers/usb/host/xhci-mtk.c +@@ -0,0 +1,265 @@ ++#include "xhci-mtk.h" ++#include "xhci-mtk-power.h" ++#include "xhci.h" ++#include "mtk-phy.h" ++#ifdef CONFIG_C60802_SUPPORT ++#include "mtk-phy-c60802.h" ++#endif ++#include "xhci-mtk-scheduler.h" ++#include <linux/kernel.h> /* printk() */ ++#include <linux/slab.h> ++#include <linux/delay.h> ++#include <asm/uaccess.h> ++#include <linux/dma-mapping.h> ++#include <linux/platform_device.h> ++ ++void setInitialReg(void ) ++{ ++ __u32 __iomem *addr; ++ u32 temp; ++ ++ /* set SSUSB DMA burst size to 128B */ ++ addr = SSUSB_U3_XHCI_BASE + SSUSB_HDMA_CFG; ++ temp = SSUSB_HDMA_CFG_MT7621_VALUE; ++ writel(temp, addr); ++ ++ /* extend U3 LTSSM Polling.LFPS timeout value */ ++ addr = SSUSB_U3_XHCI_BASE + U3_LTSSM_TIMING_PARAMETER3; ++ temp = U3_LTSSM_TIMING_PARAMETER3_VALUE; ++ writel(temp, addr); ++ ++ /* EOF */ ++ addr = SSUSB_U3_XHCI_BASE + SYNC_HS_EOF; ++ temp = SYNC_HS_EOF_VALUE; ++ writel(temp, addr); ++ ++#if defined (CONFIG_PERIODIC_ENP) ++ /* HSCH_CFG1: SCH2_FIFO_DEPTH */ ++ addr = SSUSB_U3_XHCI_BASE + HSCH_CFG1; ++ temp = readl(addr); ++ temp &= ~(0x3 << SCH2_FIFO_DEPTH_OFFSET); ++ writel(temp, addr); ++#endif ++ ++ /* Doorbell handling */ ++ addr = SIFSLV_IPPC + SSUSB_IP_SPAR0; ++ temp = 0x1; ++ writel(temp, addr); ++ ++ /* Set SW PLL Stable mode to 1 for U2 LPM device remote wakeup */ ++ /* Port 0 */ ++ addr = U2_PHY_BASE + U2_PHYD_CR1; ++ temp = readl(addr); ++ temp &= ~(0x3 << 18); ++ temp |= (1 << 18); ++ writel(temp, addr); ++ ++ /* Port 1 */ ++ addr = U2_PHY_BASE_P1 + U2_PHYD_CR1; ++ temp = readl(addr); ++ temp &= ~(0x3 << 18); ++ temp |= (1 << 18); ++ writel(temp, addr); ++} ++ ++ ++void setLatchSel(void){ ++ __u32 __iomem *latch_sel_addr; ++ u32 latch_sel_value; ++ latch_sel_addr = U3_PIPE_LATCH_SEL_ADD; ++ latch_sel_value = ((U3_PIPE_LATCH_TX)<<2) | (U3_PIPE_LATCH_RX); ++ writel(latch_sel_value, latch_sel_addr); ++} ++ ++void reinitIP(void){ ++ __u32 __iomem *ip_reset_addr; ++ u32 ip_reset_value; ++ ++ enableAllClockPower(); ++ mtk_xhci_scheduler_init(); ++} ++ ++void dbg_prb_out(void){ ++ mtk_probe_init(0x0f0f0f0f); ++ mtk_probe_out(0xffffffff); ++ mtk_probe_out(0x01010101); ++ mtk_probe_out(0x02020202); ++ mtk_probe_out(0x04040404); ++ mtk_probe_out(0x08080808); ++ mtk_probe_out(0x10101010); ++ mtk_probe_out(0x20202020); ++ mtk_probe_out(0x40404040); ++ mtk_probe_out(0x80808080); ++ mtk_probe_out(0x55555555); ++ mtk_probe_out(0xaaaaaaaa); ++} ++ ++ ++ ++/////////////////////////////////////////////////////////////////////////////// ++ ++#define RET_SUCCESS 0 ++#define RET_FAIL 1 ++ ++static int dbg_u3w(int argc, char**argv) ++{ ++ int u4TimingValue; ++ char u1TimingValue; ++ int u4TimingAddress; ++ ++ if (argc<3) ++ { ++ printk(KERN_ERR "Arg: address value\n"); ++ return RET_FAIL; ++ } ++ u3phy_init(); ++ ++ u4TimingAddress = (int)simple_strtol(argv[1], &argv[1], 16); ++ u4TimingValue = (int)simple_strtol(argv[2], &argv[2], 16); ++ u1TimingValue = u4TimingValue & 0xff; ++ /* access MMIO directly */ ++ writel(u1TimingValue, u4TimingAddress); ++ printk(KERN_ERR "Write done\n"); ++ return RET_SUCCESS; ++ ++} ++ ++static int dbg_u3r(int argc, char**argv) ++{ ++ char u1ReadTimingValue; ++ int u4TimingAddress; ++ if (argc<2) ++ { ++ printk(KERN_ERR "Arg: address\n"); ++ return 0; ++ } ++ u3phy_init(); ++ mdelay(500); ++ u4TimingAddress = (int)simple_strtol(argv[1], &argv[1], 16); ++ /* access MMIO directly */ ++ u1ReadTimingValue = readl(u4TimingAddress); ++ printk(KERN_ERR "Value = 0x%x\n", u1ReadTimingValue); ++ return 0; ++} ++ ++static int dbg_u3init(int argc, char**argv) ++{ ++ int ret; ++ ret = u3phy_init(); ++ printk(KERN_ERR "phy registers and operations initial done\n"); ++ if(u3phy_ops->u2_slew_rate_calibration){ ++ u3phy_ops->u2_slew_rate_calibration(u3phy); ++ } ++ else{ ++ printk(KERN_ERR "WARN: PHY doesn't implement u2 slew rate calibration function\n"); ++ } ++ if(u3phy_ops->init(u3phy) == PHY_TRUE) ++ return RET_SUCCESS; ++ return RET_FAIL; ++} ++ ++void dbg_setU1U2(int argc, char**argv){ ++ struct xhci_hcd *xhci; ++ int u1_value; ++ int u2_value; ++ u32 port_id, temp; ++ u32 __iomem *addr; ++ ++ if (argc<3) ++ { ++ printk(KERN_ERR "Arg: u1value u2value\n"); ++ return RET_FAIL; ++ } ++ ++ u1_value = (int)simple_strtol(argv[1], &argv[1], 10); ++ u2_value = (int)simple_strtol(argv[2], &argv[2], 10); ++ addr = (SSUSB_U3_XHCI_BASE + 0x424); ++ temp = readl(addr); ++ temp = temp & (~(0x0000ffff)); ++ temp = temp | u1_value | (u2_value<<8); ++ writel(temp, addr); ++} ++/////////////////////////////////////////////////////////////////////////////// ++ ++int call_function(char *buf) ++{ ++ int i; ++ int argc; ++ char *argv[80]; ++ ++ argc = 0; ++ do ++ { ++ argv[argc] = strsep(&buf, " "); ++ printk(KERN_DEBUG "[%d] %s\r\n", argc, argv[argc]); ++ argc++; ++ } while (buf); ++ if (!strcmp("dbg.r", argv[0])) ++ dbg_prb_out(); ++ else if (!strcmp("dbg.u3w", argv[0])) ++ dbg_u3w(argc, argv); ++ else if (!strcmp("dbg.u3r", argv[0])) ++ dbg_u3r(argc, argv); ++ else if (!strcmp("dbg.u3i", argv[0])) ++ dbg_u3init(argc, argv); ++ else if (!strcmp("pw.u1u2", argv[0])) ++ dbg_setU1U2(argc, argv); ++ return 0; ++} ++ ++long xhci_mtk_test_unlock_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ char w_buf[200]; ++ char r_buf[200] = "this is a test"; ++ int len = 200; ++ ++ switch (cmd) { ++ case IOCTL_READ: ++ copy_to_user((char *) arg, r_buf, len); ++ printk(KERN_DEBUG "IOCTL_READ: %s\r\n", r_buf); ++ break; ++ case IOCTL_WRITE: ++ copy_from_user(w_buf, (char *) arg, len); ++ printk(KERN_DEBUG "IOCTL_WRITE: %s\r\n", w_buf); ++ ++ //invoke function ++ return call_function(w_buf); ++ break; ++ default: ++ return -ENOTTY; ++ } ++ ++ return len; ++} ++ ++int xhci_mtk_test_open(struct inode *inode, struct file *file) ++{ ++ ++ printk(KERN_DEBUG "xhci_mtk_test open: successful\n"); ++ return 0; ++} ++ ++int xhci_mtk_test_release(struct inode *inode, struct file *file) ++{ ++ ++ printk(KERN_DEBUG "xhci_mtk_test release: successful\n"); ++ return 0; ++} ++ ++ssize_t xhci_mtk_test_read(struct file *file, char *buf, size_t count, loff_t *ptr) ++{ ++ ++ printk(KERN_DEBUG "xhci_mtk_test read: returning zero bytes\n"); ++ return 0; ++} ++ ++ssize_t xhci_mtk_test_write(struct file *file, const char *buf, size_t count, loff_t * ppos) ++{ ++ ++ printk(KERN_DEBUG "xhci_mtk_test write: accepting zero bytes\n"); ++ return 0; ++} ++ ++ ++ ++ +--- /dev/null ++++ b/drivers/usb/host/xhci-mtk.h +@@ -0,0 +1,120 @@ ++#ifndef _XHCI_MTK_H ++#define _XHCI_MTK_H ++ ++#include <linux/usb.h> ++#include "xhci.h" ++ ++#define SSUSB_U3_XHCI_BASE 0xBE1C0000 ++#define SSUSB_U3_MAC_BASE 0xBE1C2400 ++#define SSUSB_U3_SYS_BASE 0xBE1C2600 ++#define SSUSB_U2_SYS_BASE 0xBE1C3400 ++#define SSUB_SIF_SLV_TOP 0xBE1D0000 ++#define SIFSLV_IPPC (SSUB_SIF_SLV_TOP + 0x700) ++ ++#define U3_PIPE_LATCH_SEL_ADD SSUSB_U3_MAC_BASE + 0x130 ++#define U3_PIPE_LATCH_TX 0 ++#define U3_PIPE_LATCH_RX 0 ++ ++#define U3_UX_EXIT_LFPS_TIMING_PAR 0xa0 ++#define U3_REF_CK_PAR 0xb0 ++#define U3_RX_UX_EXIT_LFPS_REF_OFFSET 8 ++#define U3_RX_UX_EXIT_LFPS_REF 3 ++#define U3_REF_CK_VAL 10 ++ ++#define U3_TIMING_PULSE_CTRL 0xb4 ++#define CNT_1US_VALUE 63 //62.5MHz:63, 70MHz:70, 80MHz:80, 100MHz:100, 125MHz:125 ++ ++#define USB20_TIMING_PARAMETER 0x40 ++#define TIME_VALUE_1US 63 //62.5MHz:63, 80MHz:80, 100MHz:100, 125MHz:125 ++ ++#define LINK_PM_TIMER 0x8 ++#define PM_LC_TIMEOUT_VALUE 3 ++ ++#define XHCI_IMOD 0x624 ++#define XHCI_IMOD_MT7621_VALUE 0x10 ++ ++#define SSUSB_HDMA_CFG 0x950 ++#define SSUSB_HDMA_CFG_MT7621_VALUE 0x10E0E0C ++ ++#define U3_LTSSM_TIMING_PARAMETER3 0x2514 ++#define U3_LTSSM_TIMING_PARAMETER3_VALUE 0x3E8012C ++ ++#define U2_PHYD_CR1 0x64 ++ ++#define SSUSB_IP_SPAR0 0xC8 ++ ++#define SYNC_HS_EOF 0x938 ++#define SYNC_HS_EOF_VALUE 0x201F3 ++ ++#define HSCH_CFG1 0x960 ++#define SCH2_FIFO_DEPTH_OFFSET 16 ++ ++ ++#define SSUSB_IP_PW_CTRL (SIFSLV_IPPC+0x0) ++#define SSUSB_IP_SW_RST (1<<0) ++#define SSUSB_IP_PW_CTRL_1 (SIFSLV_IPPC+0x4) ++#define SSUSB_IP_PDN (1<<0) ++#define SSUSB_U3_CTRL(p) (SIFSLV_IPPC+0x30+(p*0x08)) ++#define SSUSB_U3_PORT_DIS (1<<0) ++#define SSUSB_U3_PORT_PDN (1<<1) ++#define SSUSB_U3_PORT_HOST_SEL (1<<2) ++#define SSUSB_U3_PORT_CKBG_EN (1<<3) ++#define SSUSB_U3_PORT_MAC_RST (1<<4) ++#define SSUSB_U3_PORT_PHYD_RST (1<<5) ++#define SSUSB_U2_CTRL(p) (SIFSLV_IPPC+(0x50)+(p*0x08)) ++#define SSUSB_U2_PORT_DIS (1<<0) ++#define SSUSB_U2_PORT_PDN (1<<1) ++#define SSUSB_U2_PORT_HOST_SEL (1<<2) ++#define SSUSB_U2_PORT_CKBG_EN (1<<3) ++#define SSUSB_U2_PORT_MAC_RST (1<<4) ++#define SSUSB_U2_PORT_PHYD_RST (1<<5) ++#define SSUSB_IP_CAP (SIFSLV_IPPC+0x024) ++ ++#define SSUSB_U3_PORT_NUM(p) (p & 0xff) ++#define SSUSB_U2_PORT_NUM(p) ((p>>8) & 0xff) ++ ++ ++#define XHCI_MTK_TEST_MAJOR 234 ++#define DEVICE_NAME "xhci_mtk_test" ++ ++#define CLI_MAGIC 'CLI' ++#define IOCTL_READ _IOR(CLI_MAGIC, 0, int) ++#define IOCTL_WRITE _IOW(CLI_MAGIC, 1, int) ++ ++void reinitIP(void); ++void setInitialReg(void); ++void dbg_prb_out(void); ++int call_function(char *buf); ++ ++long xhci_mtk_test_unlock_ioctl(struct file *file, unsigned int cmd, unsigned long arg); ++int xhci_mtk_test_open(struct inode *inode, struct file *file); ++int xhci_mtk_test_release(struct inode *inode, struct file *file); ++ssize_t xhci_mtk_test_read(struct file *file, char *buf, size_t count, loff_t *ptr); ++ssize_t xhci_mtk_test_write(struct file *file, const char *buf, size_t count, loff_t * ppos); ++ ++/* ++ mediatek probe out ++*/ ++/************************************************************************************/ ++ ++#define SW_PRB_OUT_ADDR (SIFSLV_IPPC+0xc0) ++#define PRB_MODULE_SEL_ADDR (SIFSLV_IPPC+0xbc) ++ ++static inline void mtk_probe_init(const u32 byte){ ++ __u32 __iomem *ptr = (__u32 __iomem *) PRB_MODULE_SEL_ADDR; ++ writel(byte, ptr); ++} ++ ++static inline void mtk_probe_out(const u32 value){ ++ __u32 __iomem *ptr = (__u32 __iomem *) SW_PRB_OUT_ADDR; ++ writel(value, ptr); ++} ++ ++static inline u32 mtk_probe_value(void){ ++ __u32 __iomem *ptr = (__u32 __iomem *) SW_PRB_OUT_ADDR; ++ ++ return readl(ptr); ++} ++ ++ ++#endif +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -33,6 +33,13 @@ static void xhci_plat_quirks(struct devi + * dev struct in order to setup MSI + */ + xhci->quirks |= XHCI_PLAT; ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ /* MTK host controller gives a spurious successful event after a ++ * short transfer. Ignore it. ++ */ ++ xhci->quirks |= XHCI_SPURIOUS_SUCCESS; ++ xhci->quirks |= XHCI_LPM_SUPPORT; ++#endif + } + + /* called during probe() after chip reset completes */ +@@ -79,7 +86,11 @@ static int xhci_plat_probe(struct platfo + + driver = &xhci_plat_hc_driver; + ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ irq = XHC_IRQ; ++#else + irq = platform_get_irq(pdev, 0); ++#endif + if (irq < 0) + return -ENODEV; + +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -254,16 +254,20 @@ static void inc_enq(struct xhci_hcd *xhc + static inline int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring, + unsigned int num_trbs) + { ++#if !defined (CONFIG_USB_MT7621_XHCI_PLATFORM) + int num_trbs_in_deq_seg; ++#endif + + if (ring->num_trbs_free < num_trbs) + return 0; + ++#if !defined (CONFIG_USB_MT7621_XHCI_PLATFORM) + if (ring->type != TYPE_COMMAND && ring->type != TYPE_EVENT) { + num_trbs_in_deq_seg = ring->dequeue - ring->deq_seg->trbs; + if (ring->num_trbs_free < num_trbs + num_trbs_in_deq_seg) + return 0; + } ++#endif + + return 1; + } +@@ -2810,6 +2814,7 @@ static int prepare_ring(struct xhci_hcd + next = ring->enqueue; + + while (last_trb(xhci, ring, ring->enq_seg, next)) { ++#if !defined (CONFIG_USB_MT7621_XHCI_PLATFORM) + /* If we're not dealing with 0.95 hardware or isoc rings + * on AMD 0.96 host, clear the chain bit. + */ +@@ -2819,6 +2824,9 @@ static int prepare_ring(struct xhci_hcd + next->link.control &= cpu_to_le32(~TRB_CHAIN); + else + next->link.control |= cpu_to_le32(TRB_CHAIN); ++#else ++ next->link.control &= cpu_to_le32(~TRB_CHAIN); ++#endif + + wmb(); + next->link.control ^= cpu_to_le32(TRB_CYCLE); +@@ -2949,6 +2957,9 @@ static void giveback_first_trb(struct xh + start_trb->field[3] |= cpu_to_le32(start_cycle); + else + start_trb->field[3] &= cpu_to_le32(~TRB_CYCLE); ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ wmb(); ++#endif + xhci_ring_ep_doorbell(xhci, slot_id, ep_index, stream_id); + } + +@@ -3004,6 +3015,29 @@ static u32 xhci_td_remainder(unsigned in + return (remainder >> 10) << 17; + } + ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++static u32 mtk_xhci_td_remainder(unsigned int td_transfer_size, unsigned int td_running_total, unsigned int maxp, unsigned trb_buffer_length) ++{ ++ u32 max = 31; ++ int remainder, td_packet_count, packet_transferred; ++ ++ //0 for the last TRB ++ //FIXME: need to workaround if there is ZLP in this TD ++ if (td_running_total + trb_buffer_length == td_transfer_size) ++ return 0; ++ ++ //FIXME: need to take care of high-bandwidth (MAX_ESIT) ++ packet_transferred = (td_running_total /*+ trb_buffer_length*/) / maxp; ++ td_packet_count = DIV_ROUND_UP(td_transfer_size, maxp); ++ remainder = td_packet_count - packet_transferred; ++ ++ if (remainder > max) ++ return max << 17; ++ else ++ return remainder << 17; ++} ++#endif ++ + /* + * For xHCI 1.0 host controllers, TD size is the number of max packet sized + * packets remaining in the TD (*not* including this TRB). +@@ -3161,6 +3195,7 @@ static int queue_bulk_sg_tx(struct xhci_ + } + + /* Set the TRB length, TD size, and interrupter fields. */ ++#if !defined (CONFIG_USB_MT7621_XHCI_PLATFORM) + if (xhci->hci_version < 0x100) { + remainder = xhci_td_remainder( + urb->transfer_buffer_length - +@@ -3170,6 +3205,12 @@ static int queue_bulk_sg_tx(struct xhci_ + trb_buff_len, total_packet_count, urb, + num_trbs - 1); + } ++#else ++ if (num_trbs > 1) ++ remainder = mtk_xhci_td_remainder(urb->transfer_buffer_length, ++ running_total, urb->ep->desc.wMaxPacketSize, trb_buff_len); ++#endif ++ + length_field = TRB_LEN(trb_buff_len) | + remainder | + TRB_INTR_TARGET(0); +@@ -3234,6 +3275,9 @@ int xhci_queue_bulk_tx(struct xhci_hcd * + int running_total, trb_buff_len, ret; + unsigned int total_packet_count; + u64 addr; ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ int max_packet; ++#endif + + if (urb->num_sgs) + return queue_bulk_sg_tx(xhci, mem_flags, urb, slot_id, ep_index); +@@ -3258,6 +3302,25 @@ int xhci_queue_bulk_tx(struct xhci_hcd * + num_trbs++; + running_total += TRB_MAX_BUFF_SIZE; + } ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ switch(urb->dev->speed){ ++ case USB_SPEED_SUPER: ++ max_packet = urb->ep->desc.wMaxPacketSize; ++ break; ++ case USB_SPEED_HIGH: ++ case USB_SPEED_FULL: ++ case USB_SPEED_LOW: ++ case USB_SPEED_WIRELESS: ++ case USB_SPEED_UNKNOWN: ++ default: ++ max_packet = urb->ep->desc.wMaxPacketSize & 0x7ff; ++ break; ++ } ++ if((urb->transfer_flags & URB_ZERO_PACKET) ++ && ((urb->transfer_buffer_length % max_packet) == 0)){ ++ num_trbs++; ++ } ++#endif + + ret = prepare_transfer(xhci, xhci->devs[slot_id], + ep_index, urb->stream_id, +@@ -3334,6 +3397,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd * + field |= TRB_ISP; + + /* Set the TRB length, TD size, and interrupter fields. */ ++#if !defined (CONFIG_USB_MT7621_XHCI_PLATFORM) + if (xhci->hci_version < 0x100) { + remainder = xhci_td_remainder( + urb->transfer_buffer_length - +@@ -3343,6 +3407,10 @@ int xhci_queue_bulk_tx(struct xhci_hcd * + trb_buff_len, total_packet_count, urb, + num_trbs - 1); + } ++#else ++ remainder = mtk_xhci_td_remainder(urb->transfer_buffer_length, running_total, max_packet, trb_buff_len); ++#endif ++ + length_field = TRB_LEN(trb_buff_len) | + remainder | + TRB_INTR_TARGET(0); +@@ -3432,7 +3500,11 @@ int xhci_queue_ctrl_tx(struct xhci_hcd * + field |= 0x1; + + /* xHCI 1.0/1.1 6.4.1.2.1: Transfer Type field */ ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ if (1) { ++#else + if (xhci->hci_version >= 0x100) { ++#endif + if (urb->transfer_buffer_length > 0) { + if (setup->bRequestType & USB_DIR_IN) + field |= TRB_TX_TYPE(TRB_DATA_IN); +@@ -3456,7 +3528,12 @@ int xhci_queue_ctrl_tx(struct xhci_hcd * + field = TRB_TYPE(TRB_DATA); + + length_field = TRB_LEN(urb->transfer_buffer_length) | ++#if !defined (CONFIG_USB_MT7621_XHCI_PLATFORM) + xhci_td_remainder(urb->transfer_buffer_length) | ++#else ++ //CC: MTK style, no scatter-gather for control transfer ++ 0 | ++#endif + TRB_INTR_TARGET(0); + if (urb->transfer_buffer_length > 0) { + if (setup->bRequestType & USB_DIR_IN) +@@ -3579,6 +3656,9 @@ static int xhci_queue_isoc_tx(struct xhc + u64 start_addr, addr; + int i, j; + bool more_trbs_coming; ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ int max_packet; ++#endif + + ep_ring = xhci->devs[slot_id]->eps[ep_index].ring; + +@@ -3592,6 +3672,21 @@ static int xhci_queue_isoc_tx(struct xhc + start_trb = &ep_ring->enqueue->generic; + start_cycle = ep_ring->cycle_state; + ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ switch(urb->dev->speed){ ++ case USB_SPEED_SUPER: ++ max_packet = urb->ep->desc.wMaxPacketSize; ++ break; ++ case USB_SPEED_HIGH: ++ case USB_SPEED_FULL: ++ case USB_SPEED_LOW: ++ case USB_SPEED_WIRELESS: ++ case USB_SPEED_UNKNOWN: ++ max_packet = urb->ep->desc.wMaxPacketSize & 0x7ff; ++ break; ++ } ++#endif ++ + urb_priv = urb->hcpriv; + /* Queue the first TRB, even if it's zero-length */ + for (i = 0; i < num_tds; i++) { +@@ -3663,9 +3758,13 @@ static int xhci_queue_isoc_tx(struct xhc + } else { + td->last_trb = ep_ring->enqueue; + field |= TRB_IOC; ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ if (!(xhci->quirks & XHCI_AVOID_BEI)) { ++#else + if (xhci->hci_version == 0x100 && + !(xhci->quirks & + XHCI_AVOID_BEI)) { ++#endif + /* Set BEI bit except for the last td */ + if (i < num_tds - 1) + field |= TRB_BEI; +@@ -3680,6 +3779,7 @@ static int xhci_queue_isoc_tx(struct xhc + trb_buff_len = td_remain_len; + + /* Set the TRB length, TD size, & interrupter fields. */ ++#if !defined (CONFIG_USB_MT7621_XHCI_PLATFORM) + if (xhci->hci_version < 0x100) { + remainder = xhci_td_remainder( + td_len - running_total); +@@ -3689,6 +3789,10 @@ static int xhci_queue_isoc_tx(struct xhc + total_packet_count, urb, + (trbs_per_td - j - 1)); + } ++#else ++ remainder = mtk_xhci_td_remainder(urb->transfer_buffer_length, running_total, max_packet, trb_buff_len); ++#endif ++ + length_field = TRB_LEN(trb_buff_len) | + remainder | + TRB_INTR_TARGET(0); +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -32,6 +32,16 @@ + #include "xhci.h" + #include "xhci-trace.h" + ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++#include <asm/uaccess.h> ++#include <linux/dma-mapping.h> ++#include <linux/platform_device.h> ++#include "mtk-phy.h" ++#include "xhci-mtk-scheduler.h" ++#include "xhci-mtk-power.h" ++#include "xhci-mtk.h" ++#endif ++ + #define DRIVER_AUTHOR "Sarah Sharp" + #define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver" + +@@ -46,6 +56,18 @@ static unsigned int quirks; + module_param(quirks, uint, S_IRUGO); + MODULE_PARM_DESC(quirks, "Bit flags for quirks to be enabled as default"); + ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++long xhci_mtk_test_unlock_ioctl(struct file *file, unsigned int cmd, unsigned long arg); ++static struct file_operations xhci_mtk_test_fops = { ++ .owner = THIS_MODULE, ++ .read = xhci_mtk_test_read, ++ .write = xhci_mtk_test_write, ++ .unlocked_ioctl = xhci_mtk_test_unlock_ioctl, ++ .open = xhci_mtk_test_open, ++ .release = xhci_mtk_test_release, ++}; ++#endif ++ + /* TODO: copied from ehci-hcd.c - can this be refactored? */ + /* + * xhci_handshake - spin reading hc until handshake completes or fails +@@ -199,7 +221,7 @@ int xhci_reset(struct xhci_hcd *xhci) + return ret; + } + +-#ifdef CONFIG_PCI ++#if defined (CONFIG_PCI) && !defined (CONFIG_USB_MT7621_XHCI_PLATFORM) + static int xhci_free_msi(struct xhci_hcd *xhci) + { + int i; +@@ -449,6 +471,11 @@ static void compliance_mode_recovery(uns + "Attempting compliance mode recovery"); + hcd = xhci->shared_hcd; + ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ temp |= (1 << 31); ++ writel(temp, xhci->usb3_ports[i]); ++#endif ++ + if (hcd->state == HC_STATE_SUSPENDED) + usb_hcd_resume_root_hub(hcd); + +@@ -498,6 +525,9 @@ static bool xhci_compliance_mode_recover + { + const char *dmi_product_name, *dmi_sys_vendor; + ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ return true; ++#endif + dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME); + dmi_sys_vendor = dmi_get_system_info(DMI_SYS_VENDOR); + if (!dmi_product_name || !dmi_sys_vendor) +@@ -543,6 +573,10 @@ int xhci_init(struct usb_hcd *hcd) + xhci_dbg_trace(xhci, trace_xhci_dbg_init, + "xHCI doesn't need link TRB QUIRK"); + } ++ ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ mtk_xhci_scheduler_init(); ++#endif + retval = xhci_mem_init(xhci, GFP_KERNEL); + xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Finished xhci_init"); + +@@ -627,7 +661,11 @@ int xhci_run(struct usb_hcd *hcd) + "// Set the interrupt modulation register"); + temp = readl(&xhci->ir_set->irq_control); + temp &= ~ER_IRQ_INTERVAL_MASK; ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ temp |= (u32) 16; ++#else + temp |= (u32) 160; ++#endif + writel(temp, &xhci->ir_set->irq_control); + + /* Set the HCD state before we enable the irqs */ +@@ -652,6 +690,9 @@ int xhci_run(struct usb_hcd *hcd) + xhci_queue_vendor_command(xhci, command, 0, 0, 0, + TRB_TYPE(TRB_NEC_GET_FW)); + } ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ enableXhciAllPortPower(xhci); ++#endif + xhci_dbg_trace(xhci, trace_xhci_dbg_init, + "Finished xhci_run for USB2 roothub"); + return 0; +@@ -1648,6 +1689,14 @@ int xhci_drop_endpoint(struct usb_hcd *h + u32 drop_flag; + u32 new_add_flags, new_drop_flags; + int ret; ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++#if MTK_SCH_NEW ++ struct xhci_slot_ctx *slot_ctx; ++ struct sch_ep *sch_ep = NULL; ++ int isTT; ++ int ep_type; ++#endif ++#endif + + ret = xhci_check_args(hcd, udev, ep, 1, true, __func__); + if (ret <= 0) +@@ -1695,6 +1744,40 @@ int xhci_drop_endpoint(struct usb_hcd *h + + xhci_endpoint_zero(xhci, xhci->devs[udev->slot_id], ep); + ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++#if MTK_SCH_NEW ++ slot_ctx = xhci_get_slot_ctx(xhci, xhci->devs[udev->slot_id]->out_ctx); ++ if ((slot_ctx->tt_info & 0xff) > 0) { ++ isTT = 1; ++ } ++ else { ++ isTT = 0; ++ } ++ if (usb_endpoint_xfer_int(&ep->desc)) { ++ ep_type = USB_EP_INT; ++ } ++ else if (usb_endpoint_xfer_isoc(&ep->desc)) { ++ ep_type = USB_EP_ISOC; ++ } ++ else if (usb_endpoint_xfer_bulk(&ep->desc)) { ++ ep_type = USB_EP_BULK; ++ } ++ else ++ ep_type = USB_EP_CONTROL; ++ ++ sch_ep = mtk_xhci_scheduler_remove_ep(udev->speed, usb_endpoint_dir_in(&ep->desc) ++ , isTT, ep_type, (mtk_u32 *)ep); ++ if (sch_ep != NULL) { ++ kfree(sch_ep); ++ } ++ else { ++ xhci_dbg(xhci, "[MTK]Doesn't find ep_sch instance when removing endpoint\n"); ++ } ++#else ++ mtk_xhci_scheduler_remove_ep(xhci, udev, ep); ++#endif ++#endif ++ + xhci_dbg(xhci, "drop ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x\n", + (unsigned int) ep->desc.bEndpointAddress, + udev->slot_id, +@@ -1727,6 +1810,19 @@ int xhci_add_endpoint(struct usb_hcd *hc + u32 new_add_flags, new_drop_flags; + struct xhci_virt_device *virt_dev; + int ret = 0; ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ struct xhci_ep_ctx *in_ep_ctx; ++#if MTK_SCH_NEW ++ struct xhci_slot_ctx *slot_ctx; ++ struct sch_ep *sch_ep; ++ int isTT; ++ int ep_type; ++ int maxp = 0; ++ int burst = 0; ++ int mult = 0; ++ int interval; ++#endif ++#endif + + ret = xhci_check_args(hcd, udev, ep, 1, true, __func__); + if (ret <= 0) { +@@ -1793,6 +1889,56 @@ int xhci_add_endpoint(struct usb_hcd *hc + return -ENOMEM; + } + ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ in_ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index); ++#if MTK_SCH_NEW ++ slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx); ++ if ((slot_ctx->tt_info & 0xff) > 0) { ++ isTT = 1; ++ } ++ else { ++ isTT = 0; ++ } ++ if (usb_endpoint_xfer_int(&ep->desc)) { ++ ep_type = USB_EP_INT; ++ } ++ else if (usb_endpoint_xfer_isoc(&ep->desc)) { ++ ep_type = USB_EP_ISOC; ++ } ++ else if (usb_endpoint_xfer_bulk(&ep->desc)) { ++ ep_type = USB_EP_BULK; ++ } ++ else ++ ep_type = USB_EP_CONTROL; ++ ++ if (udev->speed == USB_SPEED_FULL || udev->speed == USB_SPEED_HIGH ++ || udev->speed == USB_SPEED_LOW) { ++ maxp = ep->desc.wMaxPacketSize & 0x7FF; ++ burst = ep->desc.wMaxPacketSize >> 11; ++ mult = 0; ++ } ++ else if (udev->speed == USB_SPEED_SUPER) { ++ maxp = ep->desc.wMaxPacketSize & 0x7FF; ++ burst = ep->ss_ep_comp.bMaxBurst; ++ mult = ep->ss_ep_comp.bmAttributes & 0x3; ++ } ++ interval = (1 << ((in_ep_ctx->ep_info >> 16) & 0xff)); ++ sch_ep = kmalloc(sizeof(struct sch_ep), GFP_KERNEL); ++ if (mtk_xhci_scheduler_add_ep(udev->speed, usb_endpoint_dir_in(&ep->desc), ++ isTT, ep_type, maxp, interval, burst, mult, (mtk_u32 *)ep ++ , (mtk_u32 *)in_ep_ctx, sch_ep) != SCH_SUCCESS) { ++ xhci_err(xhci, "[MTK] not enough bandwidth\n"); ++ ++ return -ENOSPC; ++ } ++#else ++ if (mtk_xhci_scheduler_add_ep(xhci, udev, ep, in_ep_ctx) != SCH_SUCCESS) { ++ xhci_err(xhci, "[MTK] not enough bandwidth\n"); ++ ++ return -ENOSPC; ++ } ++#endif ++#endif + ctrl_ctx->add_flags |= cpu_to_le32(added_ctxs); + new_add_flags = le32_to_cpu(ctrl_ctx->add_flags); + +@@ -4463,8 +4609,14 @@ static u16 xhci_call_host_update_timeout + u16 *timeout) + { + if (state == USB3_LPM_U1) ++#if !defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ if (xhci->quirks & XHCI_INTEL_HOST) ++#endif + return xhci_calculate_u1_timeout(xhci, udev, desc); + else if (state == USB3_LPM_U2) ++#if !defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ if (xhci->quirks & XHCI_INTEL_HOST) ++#endif + return xhci_calculate_u2_timeout(xhci, udev, desc); + + return USB3_LPM_DISABLED; +@@ -4849,7 +5001,9 @@ int xhci_gen_setup(struct usb_hcd *hcd, + hcd->self.no_sg_constraint = 1; + + /* XHCI controllers don't stop the ep queue on short packets :| */ ++#if !defined (CONFIG_USB_MT7621_XHCI_PLATFORM) + hcd->self.no_stop_on_short = 1; ++#endif + + if (usb_hcd_is_primary_hcd(hcd)) { + xhci = kzalloc(sizeof(struct xhci_hcd), GFP_KERNEL); +@@ -4912,6 +5066,10 @@ int xhci_gen_setup(struct usb_hcd *hcd, + goto error; + xhci_dbg(xhci, "Reset complete\n"); + ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ setInitialReg(); ++#endif ++ + /* Set dma_mask and coherent_dma_mask to 64-bits, + * if xHC supports 64-bit addressing */ + if (HCC_64BIT_ADDR(xhci->hcc_params) && +@@ -5006,8 +5164,57 @@ MODULE_DESCRIPTION(DRIVER_DESC); + MODULE_AUTHOR(DRIVER_AUTHOR); + MODULE_LICENSE("GPL"); + ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++static struct resource xhci_resouce[] = { ++ { ++ .name = "xhci-hcd", ++ .start = XHC_IO_START, ++ .end = XHC_IO_START + XHC_IO_LENGTH -1, ++ .flags = IORESOURCE_MEM, ++ } ++}; ++ ++static struct platform_device xhci_platform_dev = { ++ .name = "xhci-hcd", ++ .id = -1, ++ .dev = { ++ .coherent_dma_mask = 0xffffffff, ++ }, ++ .resource = xhci_resouce, ++}; ++#endif ++ + static int __init xhci_hcd_init(void) + { ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++ struct platform_device *pPlatformDev; ++ ++ register_chrdev(XHCI_MTK_TEST_MAJOR, DEVICE_NAME, &xhci_mtk_test_fops); ++ ++ u3phy_init(); ++ if (u3phy_ops->u2_slew_rate_calibration) { ++ u3phy_ops->u2_slew_rate_calibration(u3phy); ++ u3phy_ops->u2_slew_rate_calibration(u3phy_p1); ++ } ++ else{ ++ printk(KERN_ERR "WARN: PHY doesn't implement u2 slew rate calibration function\n"); ++ } ++ u3phy_ops->init(u3phy); ++ reinitIP(); ++ ++ pPlatformDev = &xhci_platform_dev; ++ memset(pPlatformDev, 0, sizeof(struct platform_device)); ++ pPlatformDev->name = "xhci-hcd"; ++ pPlatformDev->id = -1; ++ pPlatformDev->dev.coherent_dma_mask = 0xffffffff; ++ pPlatformDev->dev.dma_mask = &pPlatformDev->dev.coherent_dma_mask; ++ pPlatformDev->resource = xhci_resouce; ++ pPlatformDev->num_resources = ARRAY_SIZE(xhci_resouce); ++ ++ platform_device_register(&xhci_platform_dev); ++ ++#endif ++ + /* + * Check the compiler generated sizes of structures that must be laid + * out in specific ways for hardware access. +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -33,6 +33,21 @@ + #include "xhci-ext-caps.h" + #include "pci-quirks.h" + ++#if defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++#define XHC_IRQ (22 + 8) ++#define XHC_IO_START 0x1E1C0000 ++#define XHC_IO_LENGTH 0x10000 ++/* mtk scheduler bitmasks */ ++#define BPKTS(p) ((p) & 0x3f) ++#define BCSCOUNT(p) (((p) & 0x7) << 8) ++#define BBM(p) ((p) << 11) ++#define BOFFSET(p) ((p) & 0x3fff) ++#define BREPEAT(p) (((p) & 0x7fff) << 16) ++#endif ++ ++ ++ ++ + /* xHCI PCI Configuration Registers */ + #define XHCI_SBRN_OFFSET (0x60) + +@@ -1587,8 +1602,12 @@ struct xhci_hcd { + /* Compliance Mode Recovery Data */ + struct timer_list comp_mode_recovery_timer; + u32 port_status_u0; ++#ifdef CONFIG_USB_MT7621_XHCI_PLATFORM ++#define COMP_MODE_RCVRY_MSECS 5000 ++#else + /* Compliance Mode Timer Triggered every 2 seconds */ + #define COMP_MODE_RCVRY_MSECS 2000 ++#endif + }; + + /* convert between an HCD pointer and the corresponding EHCI_HCD */ +@@ -1736,6 +1755,26 @@ void xhci_urb_free_priv(struct xhci_hcd + void xhci_free_command(struct xhci_hcd *xhci, + struct xhci_command *command); + ++#if defined (CONFIG_PCI) && !defined (CONFIG_USB_MT7621_XHCI_PLATFORM) ++/* xHCI PCI glue */ ++int xhci_register_pci(void); ++void xhci_unregister_pci(void); ++#else ++static inline int xhci_register_pci(void) { return 0; } ++static inline void xhci_unregister_pci(void) {} ++#endif ++ ++#if defined(CONFIG_USB_XHCI_PLATFORM) \ ++ || defined(CONFIG_USB_XHCI_PLATFORM_MODULE) ++int xhci_register_plat(void); ++void xhci_unregister_plat(void); ++#else ++static inline int xhci_register_plat(void) ++{ return 0; } ++static inline void xhci_unregister_plat(void) ++{ } ++#endif ++ + /* xHCI host controller glue */ + typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *); + int xhci_handshake(struct xhci_hcd *xhci, void __iomem *ptr, diff --git a/target/linux/ramips/patches-3.18/0063-cevt-rt3352.patch b/target/linux/ramips/patches-3.18/0063-cevt-rt3352.patch new file mode 100644 index 0000000..749701f --- /dev/null +++ b/target/linux/ramips/patches-3.18/0063-cevt-rt3352.patch @@ -0,0 +1,11 @@ +--- a/arch/mips/ralink/cevt-rt3352.c ++++ b/arch/mips/ralink/cevt-rt3352.c +@@ -54,7 +54,7 @@ static int systick_next_event(unsigned l + sdev = container_of(evt, struct systick_device, dev); + count = ioread32(sdev->membase + SYSTICK_COUNT); + count = (count + delta) % SYSTICK_FREQ; +- iowrite32(count + delta, sdev->membase + SYSTICK_COMPARE); ++ iowrite32(count, sdev->membase + SYSTICK_COMPARE); + + return 0; + } diff --git a/target/linux/ramips/patches-3.18/0064-MIPS-ralink-fix-clearing-the-illegal-access-interrup.patch b/target/linux/ramips/patches-3.18/0064-MIPS-ralink-fix-clearing-the-illegal-access-interrup.patch new file mode 100644 index 0000000..8153272 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0064-MIPS-ralink-fix-clearing-the-illegal-access-interrup.patch @@ -0,0 +1,31 @@ +From f5d9bea58b576b50cdc0d7a607646b0849ff79c4 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski <jogo@openwrt.org> +Date: Mon, 25 May 2015 16:51:34 +0200 +Subject: [PATCH] MIPS: ralink: fix clearing the illegal access interrupt + +Due to a typo the illegal access interrupt is never cleared in by +the interupt handler, causing an effective deadlock on the first +illegal access. + +This was broken since the code was introduced in 5433acd81e87 ("MIPS: +ralink: add illegal access driver"), but only exposed when the Kconfig +symbol was added, thus enabling the code. + +Cc: <stable@vger.kernel.org> [3.18+] +Fixes: a7b7aad383c ("MIPS: ralink: add missing symbol for RALINK_ILL_ACC") +Signed-off-by: Jonas Gorski <jogo@openwrt.org> +--- + arch/mips/ralink/ill_acc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/mips/ralink/ill_acc.c ++++ b/arch/mips/ralink/ill_acc.c +@@ -41,7 +41,7 @@ static irqreturn_t ill_acc_irq_handler(i + addr, (type >> ILL_ACC_OFF_S) & ILL_ACC_OFF_M, + type & ILL_ACC_LEN_M); + +- rt_memc_w32(REG_ILL_ACC_TYPE, REG_ILL_ACC_TYPE); ++ rt_memc_w32(ILL_INT_STATUS, REG_ILL_ACC_TYPE); + + return IRQ_HANDLED; + } diff --git a/target/linux/ramips/patches-3.18/0065-fix_dts_cache_issues.patch b/target/linux/ramips/patches-3.18/0065-fix_dts_cache_issues.patch new file mode 100644 index 0000000..520c570 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0065-fix_dts_cache_issues.patch @@ -0,0 +1,18 @@ +--- a/arch/mips/kernel/setup.c ++++ b/arch/mips/kernel/setup.c +@@ -675,7 +675,6 @@ static void __init arch_mem_init(char ** + crashk_res.end - crashk_res.start + 1, + BOOTMEM_DEFAULT); + #endif +- device_tree_init(); + sparse_init(); + plat_swiotlb_setup(); + paging_init(); +@@ -784,6 +783,7 @@ void __init setup_arch(char **cmdline_p) + prefill_possible_map(); + + cpu_cache_init(); ++ device_tree_init(); + } + + unsigned long kernelsp[NR_CPUS]; diff --git a/target/linux/ramips/patches-3.18/0065-mt7628-pww.patch b/target/linux/ramips/patches-3.18/0065-mt7628-pww.patch new file mode 100644 index 0000000..dc2ca95 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0065-mt7628-pww.patch @@ -0,0 +1,204 @@ +--- a/drivers/pwm/Kconfig ++++ b/drivers/pwm/Kconfig +@@ -177,6 +177,15 @@ config PWM_LPSS_PLATFORM + To compile this driver as a module, choose M here: the module + will be called pwm-lpss-platform. + ++config PWM_MEDIATEK ++ tristate "Mediatek PWM support" ++ depends on RALINK && OF ++ help ++ Generic PWM framework driver for Mediatek ARM SoC. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called pwm-mxs. ++ + config PWM_MXS + tristate "Freescale MXS PWM support" + depends on ARCH_MXS && OF +--- a/drivers/pwm/Makefile ++++ b/drivers/pwm/Makefile +@@ -15,6 +15,7 @@ obj-$(CONFIG_PWM_LPC32XX) += pwm-lpc32xx + obj-$(CONFIG_PWM_LPSS) += pwm-lpss.o + obj-$(CONFIG_PWM_LPSS_PCI) += pwm-lpss-pci.o + obj-$(CONFIG_PWM_LPSS_PLATFORM) += pwm-lpss-platform.o ++obj-$(CONFIG_PWM_MEDIATEK) += pwm-mediatek.o + obj-$(CONFIG_PWM_MXS) += pwm-mxs.o + obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o + obj-$(CONFIG_PWM_PUV3) += pwm-puv3.o +--- /dev/null ++++ b/drivers/pwm/pwm-mediatek.c +@@ -0,0 +1,173 @@ ++/* ++ * Mediatek Pulse Width Modulator driver ++ * ++ * Copyright (C) 2015 John Crispin <blogic@openwrt.org> ++ * ++ * 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/err.h> ++#include <linux/io.h> ++#include <linux/ioport.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/of.h> ++#include <linux/platform_device.h> ++#include <linux/pwm.h> ++#include <linux/slab.h> ++#include <linux/types.h> ++ ++#define NUM_PWM 4 ++ ++/* PWM registers and bits definitions */ ++#define PWMCON 0x00 ++#define PWMHDUR 0x04 ++#define PWMLDUR 0x08 ++#define PWMGDUR 0x0c ++#define PWMWAVENUM 0x28 ++#define PWMDWIDTH 0x2c ++#define PWMTHRES 0x30 ++ ++/** ++ * struct mtk_pwm_chip - struct representing pwm chip ++ * ++ * @mmio_base: base address of pwm chip ++ * @chip: linux pwm chip representation ++ */ ++struct mtk_pwm_chip { ++ void __iomem *mmio_base; ++ struct pwm_chip chip; ++}; ++ ++static inline struct mtk_pwm_chip *to_mtk_pwm_chip(struct pwm_chip *chip) ++{ ++ return container_of(chip, struct mtk_pwm_chip, chip); ++} ++ ++static inline u32 mtk_pwm_readl(struct mtk_pwm_chip *chip, unsigned int num, ++ unsigned long offset) ++{ ++ return ioread32(chip->mmio_base + 0x10 + (num * 0x40) + offset); ++} ++ ++static inline void mtk_pwm_writel(struct mtk_pwm_chip *chip, ++ unsigned int num, unsigned long offset, ++ unsigned long val) ++{ ++ iowrite32(val, chip->mmio_base + 0x10 + (num * 0x40) + offset); ++} ++ ++static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, ++ int duty_ns, int period_ns) ++{ ++ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); ++ u32 resolution = 100 / 4; ++ u32 clkdiv = 0; ++ ++ while (period_ns / resolution > 8191) { ++ clkdiv++; ++ resolution *= 2; ++ } ++ ++ if (clkdiv > 7) ++ return -1; ++ ++ mtk_pwm_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | BIT(3) | clkdiv); ++ mtk_pwm_writel(pc, pwm->hwpwm, PWMDWIDTH, period_ns / resolution); ++ mtk_pwm_writel(pc, pwm->hwpwm, PWMTHRES, duty_ns / resolution); ++ return 0; ++} ++ ++static int mtk_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); ++ u32 val; ++ ++ val = ioread32(pc->mmio_base); ++ val |= BIT(pwm->hwpwm); ++ iowrite32(val, pc->mmio_base); ++ ++ return 0; ++} ++ ++static void mtk_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); ++ u32 val; ++ ++ val = ioread32(pc->mmio_base); ++ val &= ~BIT(pwm->hwpwm); ++ iowrite32(val, pc->mmio_base); ++} ++ ++static const struct pwm_ops mtk_pwm_ops = { ++ .config = mtk_pwm_config, ++ .enable = mtk_pwm_enable, ++ .disable = mtk_pwm_disable, ++ .owner = THIS_MODULE, ++}; ++ ++static int mtk_pwm_probe(struct platform_device *pdev) ++{ ++ struct mtk_pwm_chip *pc; ++ struct resource *r; ++ int ret; ++ ++ pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); ++ if (!pc) ++ return -ENOMEM; ++ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ pc->mmio_base = devm_ioremap_resource(&pdev->dev, r); ++ if (IS_ERR(pc->mmio_base)) ++ return PTR_ERR(pc->mmio_base); ++ ++ platform_set_drvdata(pdev, pc); ++ ++ pc->chip.dev = &pdev->dev; ++ pc->chip.ops = &mtk_pwm_ops; ++ pc->chip.base = -1; ++ pc->chip.npwm = NUM_PWM; ++ ++ ret = pwmchip_add(&pc->chip); ++ if (ret < 0) ++ dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); ++ ++ return ret; ++} ++ ++static int mtk_pwm_remove(struct platform_device *pdev) ++{ ++ struct mtk_pwm_chip *pc = platform_get_drvdata(pdev); ++ int i; ++ ++ for (i = 0; i < NUM_PWM; i++) ++ pwm_disable(&pc->chip.pwms[i]); ++ ++ return pwmchip_remove(&pc->chip); ++} ++ ++static const struct of_device_id mtk_pwm_of_match[] = { ++ { .compatible = "mediatek,mt7628-pwm" }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(of, mtk_pwm_of_match); ++ ++static struct platform_driver mtk_pwm_driver = { ++ .driver = { ++ .name = "mtk-pwm", ++ .owner = THIS_MODULE, ++ .of_match_table = mtk_pwm_of_match, ++ }, ++ .probe = mtk_pwm_probe, ++ .remove = mtk_pwm_remove, ++}; ++ ++module_platform_driver(mtk_pwm_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); ++MODULE_ALIAS("platform:mtk-pwm"); diff --git a/target/linux/ramips/patches-3.18/0066-cevt.patch b/target/linux/ramips/patches-3.18/0066-cevt.patch new file mode 100644 index 0000000..9eb6cb6 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0066-cevt.patch @@ -0,0 +1,151 @@ +--- a/arch/mips/ralink/cevt-rt3352.c ++++ b/arch/mips/ralink/cevt-rt3352.c +@@ -45,18 +45,33 @@ static void (*systick_freq_scaling)(stru + static void systick_set_clock_mode(enum clock_event_mode mode, + struct clock_event_device *evt); + ++static inline unsigned int read_count(struct systick_device *sdev) ++{ ++ return ioread32(sdev->membase + SYSTICK_COUNT); ++} ++ ++static inline unsigned int read_compare(struct systick_device *sdev) ++{ ++ return ioread32(sdev->membase + SYSTICK_COMPARE); ++} ++ ++static inline void write_compare(struct systick_device *sdev, unsigned int val) ++{ ++ iowrite32(val, sdev->membase + SYSTICK_COMPARE); ++} ++ + static int systick_next_event(unsigned long delta, + struct clock_event_device *evt) + { + struct systick_device *sdev; +- u32 count; ++ int res; + + sdev = container_of(evt, struct systick_device, dev); +- count = ioread32(sdev->membase + SYSTICK_COUNT); +- count = (count + delta) % SYSTICK_FREQ; +- iowrite32(count, sdev->membase + SYSTICK_COMPARE); ++ delta += read_count(sdev); ++ write_compare(sdev, delta); ++ res = ((int)(read_count(sdev) - delta) >= 0) ? -ETIME : 0; + +- return 0; ++ return res; + } + + static void systick_event_handler(struct clock_event_device *dev) +@@ -66,20 +81,25 @@ static void systick_event_handler(struct + + static irqreturn_t systick_interrupt(int irq, void *dev_id) + { +- struct clock_event_device *dev = (struct clock_event_device *) dev_id; ++ int ret = 0; ++ struct clock_event_device *cdev; ++ struct systick_device *sdev; + +- dev->event_handler(dev); ++ if (read_c0_cause() & STATUSF_IP7) { ++ cdev = (struct clock_event_device *) dev_id; ++ sdev = container_of(cdev, struct systick_device, dev); ++ ++ /* Clear Count/Compare Interrupt */ ++ write_compare(sdev, read_compare(sdev)); ++ cdev->event_handler(cdev); ++ ret = 1; ++ } + +- return IRQ_HANDLED; ++ return IRQ_RETVAL(ret); + } + + static struct systick_device systick = { + .dev = { +- /* +- * cevt-r4k uses 300, make sure systick +- * gets used if available +- */ +- .rating = 310, + .features = CLOCK_EVT_FEAT_ONESHOT, + .set_next_event = systick_next_event, + .set_mode = systick_set_clock_mode, +@@ -126,13 +146,14 @@ static void systick_set_clock_mode(enum + systick_freq_scaling(sdev, 1); + break; + ++ case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + if (systick_freq_scaling) + systick_freq_scaling(sdev, 0); + if (sdev->irq_requested) +- free_irq(systick.dev.irq, &systick_irqaction); ++ remove_irq(systick.dev.irq, &systick_irqaction); + sdev->irq_requested = 0; +- iowrite32(0, systick.membase + SYSTICK_CONFIG); ++ iowrite32(CFG_CNT_EN, systick.membase + SYSTICK_CONFIG); + break; + + default: +@@ -142,38 +163,45 @@ static void systick_set_clock_mode(enum + } + + static const struct of_device_id systick_match[] = { +- { .compatible = "ralink,mt7620-systick", .data = mt7620_freq_scaling}, ++ { .compatible = "ralink,mt7620a-systick", .data = mt7620_freq_scaling}, + {}, + }; + + static void __init ralink_systick_init(struct device_node *np) + { + const struct of_device_id *match; ++ int rating = 200; + + systick.membase = of_iomap(np, 0); + if (!systick.membase) + return; + + match = of_match_node(systick_match, np); +- if (match) ++ if (match) { + systick_freq_scaling = match->data; ++ /* ++ * cevt-r4k uses 300, make sure systick ++ * gets used if available ++ */ ++ rating = 310; ++ } + +- systick_irqaction.name = np->name; +- systick.dev.name = np->name; +- clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60); +- systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev); +- systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev); ++ /* enable counter than register clock source */ ++ iowrite32(CFG_CNT_EN, systick.membase + SYSTICK_CONFIG); ++ clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name, ++ SYSTICK_FREQ, rating, 16, clocksource_mmio_readl_up); ++ ++ /* register clock event */ + systick.dev.irq = irq_of_parse_and_map(np, 0); + if (!systick.dev.irq) { + pr_err("%s: request_irq failed", np->name); + return; + } +- +- clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name, +- SYSTICK_FREQ, 301, 16, clocksource_mmio_readl_up); +- +- clockevents_register_device(&systick.dev); +- ++ systick_irqaction.name = np->name; ++ systick.dev.name = np->name; ++ systick.dev.rating = rating; ++ systick.dev.cpumask = cpumask_of(0); ++ clockevents_config_and_register(&systick.dev, SYSTICK_FREQ, 0x3, 0x7fff); + pr_info("%s: running - mult: %d, shift: %d\n", + np->name, systick.dev.mult, systick.dev.shift); + } diff --git a/target/linux/ramips/patches-3.18/0067-disable_illacc.patch b/target/linux/ramips/patches-3.18/0067-disable_illacc.patch new file mode 100644 index 0000000..590b501 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0067-disable_illacc.patch @@ -0,0 +1,14 @@ +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -13,9 +13,9 @@ config CLKEVT_RT3352 + select CEVT_SYSTICK_QUIRK + + config RALINK_ILL_ACC +- bool ++ bool "illegal access irq" + depends on SOC_RT305X +- default y ++ default n + + config IRQ_INTC + bool diff --git a/target/linux/ramips/patches-3.18/0068-non-pci-mt7620.patch b/target/linux/ramips/patches-3.18/0068-non-pci-mt7620.patch new file mode 100644 index 0000000..ce56ae2 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0068-non-pci-mt7620.patch @@ -0,0 +1,12 @@ +--- a/arch/mips/ralink/mt7620.c ++++ b/arch/mips/ralink/mt7620.c +@@ -513,9 +513,6 @@ void prom_soc_init(struct ralink_soc_inf + ralink_soc = MT762X_SOC_MT7620N; + name = "MT7620N"; + soc_info->compatible = "ralink,mt7620n-soc"; +-#ifdef CONFIG_PCI +- panic("mt7620n is only supported for non pci kernels"); +-#endif + } + } else if (n0 == MT7620_CHIP_NAME0 && n1 == MT7628_CHIP_NAME1) { + ralink_soc = MT762X_SOC_MT7628AN; diff --git a/target/linux/ramips/patches-3.18/0069-no-pm_poweroff.patch b/target/linux/ramips/patches-3.18/0069-no-pm_poweroff.patch new file mode 100644 index 0000000..fedfe37 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0069-no-pm_poweroff.patch @@ -0,0 +1,10 @@ +--- a/arch/mips/ralink/reset.c ++++ b/arch/mips/ralink/reset.c +@@ -98,7 +98,6 @@ static int __init mips_reboot_setup(void + { + _machine_restart = ralink_restart; + _machine_halt = ralink_halt; +- pm_power_off = ralink_halt; + + return 0; + } diff --git a/target/linux/ramips/patches-3.18/0070-pci-reset.patch b/target/linux/ramips/patches-3.18/0070-pci-reset.patch new file mode 100644 index 0000000..6055731 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0070-pci-reset.patch @@ -0,0 +1,35 @@ +--- a/arch/mips/ralink/reset.c ++++ b/arch/mips/ralink/reset.c +@@ -11,6 +11,7 @@ + #include <linux/pm.h> + #include <linux/io.h> + #include <linux/of.h> ++#include <linux/delay.h> + #include <linux/reset-controller.h> + + #include <asm/reboot.h> +@@ -18,8 +19,10 @@ + #include <asm/mach-ralink/ralink_regs.h> + + /* Reset Control */ +-#define SYSC_REG_RESET_CTRL 0x034 +-#define RSTCTL_RESET_SYSTEM BIT(0) ++#define SYSC_REG_RESET_CTRL 0x034 ++ ++#define RSTCTL_RESET_PCI BIT(26) ++#define RSTCTL_RESET_SYSTEM BIT(0) + + static int ralink_assert_device(struct reset_controller_dev *rcdev, + unsigned long id) +@@ -83,6 +86,11 @@ void ralink_rst_init(void) + + static void ralink_restart(char *command) + { ++ if (IS_ENABLED(CONFIG_PCI)) { ++ rt_sysc_m32(0, RSTCTL_RESET_PCI, SYSC_REG_RESET_CTRL); ++ mdelay(50); ++ } ++ + local_irq_disable(); + rt_sysc_w32(RSTCTL_RESET_SYSTEM, SYSC_REG_RESET_CTRL); + unreachable(); diff --git a/target/linux/ramips/patches-3.18/0071-mt7621-add-cpu-feature-overrides.patch b/target/linux/ramips/patches-3.18/0071-mt7621-add-cpu-feature-overrides.patch new file mode 100644 index 0000000..f6f94f0 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0071-mt7621-add-cpu-feature-overrides.patch @@ -0,0 +1,68 @@ +--- /dev/null ++++ b/arch/mips/include/asm/mach-ralink/mt7621/cpu-feature-overrides.h +@@ -0,0 +1,65 @@ ++/* ++ * Ralink MT7621 specific CPU feature overrides ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * Copyright (C) 2015 Felix Fietkau <nbd@openwrt.org> ++ * ++ * This file was derived from: include/asm-mips/cpu-features.h ++ * Copyright (C) 2003, 2004 Ralf Baechle ++ * Copyright (C) 2004 Maciej W. Rozycki ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ */ ++#ifndef _MT7621_CPU_FEATURE_OVERRIDES_H ++#define _MT7621_CPU_FEATURE_OVERRIDES_H ++ ++#define cpu_has_tlb 1 ++#define cpu_has_4kex 1 ++#define cpu_has_3k_cache 0 ++#define cpu_has_4k_cache 1 ++#define cpu_has_tx39_cache 0 ++#define cpu_has_sb1_cache 0 ++#define cpu_has_fpu 0 ++#define cpu_has_32fpr 0 ++#define cpu_has_counter 1 ++#define cpu_has_watch 1 ++#define cpu_has_divec 1 ++ ++#define cpu_has_prefetch 1 ++#define cpu_has_ejtag 1 ++#define cpu_has_llsc 1 ++ ++#define cpu_has_mips16 1 ++#define cpu_has_mdmx 0 ++#define cpu_has_mips3d 0 ++#define cpu_has_smartmips 0 ++ ++#define cpu_has_mips32r1 1 ++#define cpu_has_mips32r2 1 ++#define cpu_has_mips64r1 0 ++#define cpu_has_mips64r2 0 ++ ++#define cpu_has_dsp 1 ++#define cpu_has_dsp2 0 ++#define cpu_has_mipsmt 1 ++ ++#define cpu_has_64bits 0 ++#define cpu_has_64bit_zero_reg 0 ++#define cpu_has_64bit_gp_regs 0 ++#define cpu_has_64bit_addresses 0 ++ ++#define cpu_dcache_line_size() 32 ++#define cpu_icache_line_size() 32 ++ ++#define cpu_has_dc_aliases 0 ++#define cpu_has_vtag_icache 0 ++ ++#define cpu_has_rixi 0 ++#define cpu_has_tlbinv 0 ++#define cpu_has_userlocal 1 ++ ++#endif /* _MT7621_CPU_FEATURE_OVERRIDES_H */ diff --git a/target/linux/ramips/patches-3.18/0072-mt7621-add-highmem.patch b/target/linux/ramips/patches-3.18/0072-mt7621-add-highmem.patch new file mode 100644 index 0000000..0a98151 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0072-mt7621-add-highmem.patch @@ -0,0 +1,10 @@ +--- a/arch/mips/ralink/Kconfig ++++ b/arch/mips/ralink/Kconfig +@@ -51,6 +51,7 @@ choice + select SYS_SUPPORTS_MULTITHREADING + select SYS_SUPPORTS_SMP + select SYS_SUPPORTS_MIPS_CMP ++ select SYS_SUPPORTS_HIGHMEM + select IRQ_GIC + select HW_HAS_PCI + diff --git a/target/linux/ramips/patches-3.18/0074-i2c-MIPS-add-mt7621-I2C-driver.patch b/target/linux/ramips/patches-3.18/0074-i2c-MIPS-add-mt7621-I2C-driver.patch new file mode 100644 index 0000000..9b9a72b --- /dev/null +++ b/target/linux/ramips/patches-3.18/0074-i2c-MIPS-add-mt7621-I2C-driver.patch @@ -0,0 +1,329 @@ +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -715,6 +715,10 @@ config I2C_RALINK + tristate "Ralink I2C Controller" + select OF_I2C + ++config I2C_MT7621 ++ tristate "MT7621 I2C Controller" ++ select OF_I2C ++ + config HAVE_S3C2410_I2C + bool + help +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -67,6 +67,7 @@ obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o + obj-$(CONFIG_I2C_PXA) += i2c-pxa.o + obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o + obj-$(CONFIG_I2C_RALINK) += i2c-ralink.o ++obj-$(CONFIG_I2C_MT7621) += i2c-mt7621.o + obj-$(CONFIG_I2C_QUP) += i2c-qup.o + obj-$(CONFIG_I2C_RIIC) += i2c-riic.o + obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o +--- /dev/null ++++ b/drivers/i2c/busses/i2c-mt7621.c +@@ -0,0 +1,303 @@ ++/* ++ * drivers/i2c/busses/i2c-mt7621.c ++ * ++ * Copyright (C) 2013 Steven Liu <steven_liu@mediatek.com> ++ * ++ * Improve driver for i2cdetect from i2c-tools to detect i2c devices on the bus. ++ * (C) 2014 Sittisak <sittisaks@hotmail.com> ++ * ++ * 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/interrupt.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/reset.h> ++#include <linux/delay.h> ++#include <linux/slab.h> ++#include <linux/init.h> ++#include <linux/errno.h> ++#include <linux/platform_device.h> ++#include <linux/i2c.h> ++#include <linux/io.h> ++#include <linux/err.h> ++ ++#include <asm/mach-ralink/ralink_regs.h> ++ ++#define REG_CONFIG_REG 0x00 ++#define REG_CLKDIV_REG 0x04 ++#define REG_DEVADDR_REG 0x08 ++#define REG_ADDR_REG 0x0C ++#define REG_DATAOUT_REG 0x10 ++#define REG_DATAIN_REG 0x14 ++#define REG_STATUS_REG 0x18 ++#define REG_STARTXFR_REG 0x1C ++#define REG_BYTECNT_REG 0x20 ++#define REG_SM0_IS_AUTOMODE 0x28 ++#define REG_SM0CTL0 0x40 ++ ++ ++#define I2C_STARTERR 0x10 ++#define I2C_ACKERR 0x08 ++#define I2C_DATARDY 0x04 ++#define I2C_SDOEMPTY 0x02 ++#define I2C_BUSY 0x01 ++ ++/* I2C_CFG register bit field */ ++#define I2C_CFG_ADDRLEN_8 (7<<5) /* 8 bits */ ++#define I2C_CFG_DEVADLEN_7 (6<<2) ++#define I2C_CFG_ADDRDIS BIT(1) ++#define I2C_CFG_DEVADDIS BIT(0) ++ ++#define I2C_CFG_DEFAULT (I2C_CFG_ADDRLEN_8 | \ ++ I2C_CFG_DEVADLEN_7 | \ ++ I2C_CFG_ADDRDIS) ++ ++#define I2C_RETRY 0x1000 ++ ++#define CLKDIV_VALUE 333 ++#define i2c_busy_loop (CLKDIV_VALUE*30) ++ ++#define READ_CMD 0x01 ++#define WRITE_CMD 0x00 ++#define READ_BLOCK 16 ++ ++#define SM0_ODRAIN BIT(31) ++#define SM0_VSYNC_MODE BIT(28) ++#define SM0_CLK_DIV (CLKDIV_VALUE << 16) ++#define SM0_WAIT_LEVEL BIT(6) ++#define SM0_EN BIT(1) ++ ++#define SM0_CFG_DEFUALT (SM0_ODRAIN | SM0_VSYNC_MODE | \ ++ SM0_CLK_DIV | SM0_WAIT_LEVEL | \ ++ SM0_EN) ++/***********************************************************/ ++ ++static void __iomem *membase; ++static struct i2c_adapter *adapter; ++ ++static void rt_i2c_w32(u32 val, unsigned reg) ++{ ++ iowrite32(val, membase + reg); ++} ++ ++static u32 rt_i2c_r32(unsigned reg) ++{ ++ return ioread32(membase + reg); ++} ++ ++static void mt7621_i2c_reset(struct i2c_adapter *a) ++{ ++ device_reset(a->dev.parent); ++} ++static void mt7621_i2c_enable(struct i2c_msg *msg) ++{ ++ rt_i2c_w32(msg->addr,REG_DEVADDR_REG); ++ rt_i2c_w32(0,REG_ADDR_REG); ++} ++ ++static void i2c_master_init(struct i2c_adapter *a) ++{ ++ mt7621_i2c_reset(a); ++ rt_i2c_w32(I2C_CFG_DEFAULT,REG_CONFIG_REG); ++ rt_i2c_w32(SM0_CFG_DEFUALT,REG_SM0CTL0); ++ rt_i2c_w32(1,REG_SM0_IS_AUTOMODE);//auto mode ++} ++ ++ ++static inline int rt_i2c_wait_rx_done(void) ++{ ++ int i=0; ++ while((!(rt_i2c_r32(REG_STATUS_REG) & I2C_DATARDY)) && (i<i2c_busy_loop)) ++ i++; ++ if(i>=i2c_busy_loop){ ++ pr_err("err,wait for idle timeout"); ++ return -ETIMEDOUT; ++ } ++ return 0; ++} ++ ++static inline int rt_i2c_wait_idle(void) ++{ ++ int i=0; ++ while((rt_i2c_r32(REG_STATUS_REG) & I2C_BUSY) && (i<i2c_busy_loop)) ++ i++; ++ if(i>=i2c_busy_loop){ ++ pr_err("err,wait for idle timeout"); ++ return -ETIMEDOUT; ++ } ++ return 0; ++} ++ ++static inline int rt_i2c_wait_tx_done(void) ++{ ++ int i=0; ++ while((!(rt_i2c_r32(REG_STATUS_REG) & I2C_SDOEMPTY)) && (i<i2c_busy_loop)) ++ i++; ++ if(i>=i2c_busy_loop){ ++ pr_err("err,wait for idle timeout"); ++ return -ETIMEDOUT; ++ } ++ return 0; ++} ++ ++static int rt_i2c_handle_msg(struct i2c_adapter *a, struct i2c_msg* msg) ++{ ++ int i = 0, j = 0, pos = 0; ++ int nblock = msg->len / READ_BLOCK; ++ int rem = msg->len % READ_BLOCK; ++ ++ if (msg->flags & I2C_M_TEN) { ++ printk("10 bits addr not supported\n"); ++ return -EINVAL; ++ } ++ ++ if (msg->flags & I2C_M_RD) { ++ for (i = 0; i < nblock; i++) { ++ if (rt_i2c_wait_idle()) ++ goto err_timeout; ++ rt_i2c_w32(READ_BLOCK - 1, REG_BYTECNT_REG); ++ rt_i2c_w32(READ_CMD, REG_STARTXFR_REG); ++ for (j = 0; j < READ_BLOCK; j++) { ++ if (rt_i2c_wait_rx_done()) ++ goto err_timeout; ++ msg->buf[pos++] = rt_i2c_r32(REG_DATAIN_REG); ++ } ++ } ++ ++ if (rt_i2c_wait_idle()) ++ goto err_timeout; ++ rt_i2c_w32(rem - 1, REG_BYTECNT_REG); ++ rt_i2c_w32(READ_CMD, REG_STARTXFR_REG); ++ ++ for (i = 0; i < rem; i++) { ++ if (rt_i2c_wait_rx_done()) ++ goto err_timeout; ++ msg->buf[pos++] = rt_i2c_r32(REG_DATAIN_REG); ++ } ++ } else { ++ if (rt_i2c_wait_idle()) ++ goto err_timeout; ++ rt_i2c_w32(msg->len - 1, REG_BYTECNT_REG); ++ for (i = 0; i < msg->len; i++) { ++ rt_i2c_w32(msg->buf[i], REG_DATAOUT_REG); ++ if(i == 0) ++ rt_i2c_w32(WRITE_CMD, REG_STARTXFR_REG); ++ ++ if (rt_i2c_wait_tx_done()) ++ goto err_timeout; ++ } ++ } ++ ++ return 0; ++err_timeout: ++ return -ETIMEDOUT; ++} ++ ++static int rt_i2c_master_xfer(struct i2c_adapter *a, struct i2c_msg *m, int n) ++{ ++ int i = 0; ++ int ret = 0; ++ i2c_master_init(a); ++ mt7621_i2c_enable(m); ++ ++ for (i = 0; i != n && ret==0; i++) { ++ ret = rt_i2c_handle_msg(a, &m[i]); ++ if (ret) ++ return ret; ++ } ++ return i; ++} ++ ++static u32 rt_i2c_func(struct i2c_adapter *a) ++{ ++ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; ++} ++ ++static const struct i2c_algorithm rt_i2c_algo = { ++ .master_xfer = rt_i2c_master_xfer, ++ .functionality = rt_i2c_func, ++}; ++ ++static int rt_i2c_probe(struct platform_device *pdev) ++{ ++ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ int ret; ++ ++ adapter = devm_kzalloc(&pdev->dev,sizeof(struct i2c_adapter), GFP_KERNEL); ++ if (!adapter) { ++ dev_err(&pdev->dev, "failed to allocate i2c_adapter\n"); ++ return -ENOMEM; ++ } ++ membase = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(membase)) ++ return PTR_ERR(membase); ++ ++ strlcpy(adapter->name, dev_name(&pdev->dev), sizeof(adapter->name)); ++ ++ adapter->owner = THIS_MODULE; ++ adapter->nr = pdev->id; ++ adapter->timeout = HZ; ++ adapter->algo = &rt_i2c_algo; ++ adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; ++ adapter->dev.parent = &pdev->dev; ++ adapter->dev.of_node = pdev->dev.of_node; ++ ++ platform_set_drvdata(pdev, adapter); ++ ++ ret = i2c_add_numbered_adapter(adapter); ++ if (ret) ++ return ret; ++ ++ dev_info(&pdev->dev,"loaded"); ++ ++ return 0; ++} ++ ++static int rt_i2c_remove(struct platform_device *pdev) ++{ ++ platform_set_drvdata(pdev, NULL); ++ return 0; ++} ++ ++static const struct of_device_id i2c_rt_dt_ids[] = { ++ { .compatible = "ralink,i2c-mt7621", }, ++ { /* sentinel */ } ++}; ++ ++MODULE_DEVICE_TABLE(of, i2c_rt_dt_ids); ++ ++static struct platform_driver rt_i2c_driver = { ++ .probe = rt_i2c_probe, ++ .remove = rt_i2c_remove, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "i2c-mt7621", ++ .of_match_table = i2c_rt_dt_ids, ++ }, ++}; ++ ++static int __init i2c_rt_init (void) ++{ ++ return platform_driver_register(&rt_i2c_driver); ++} ++ ++static void __exit i2c_rt_exit (void) ++{ ++ platform_driver_unregister(&rt_i2c_driver); ++} ++module_init (i2c_rt_init); ++module_exit (i2c_rt_exit); ++ ++MODULE_AUTHOR("Steven Liu <steven_liu@mediatek.com>"); ++MODULE_DESCRIPTION("MT7621 I2c host driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:MT7621-I2C"); diff --git a/target/linux/ramips/patches-3.18/0100-mtd-split-remove-padding.patch b/target/linux/ramips/patches-3.18/0100-mtd-split-remove-padding.patch new file mode 100644 index 0000000..81702c2 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0100-mtd-split-remove-padding.patch @@ -0,0 +1,12 @@ +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -819,9 +819,6 @@ static void split_uimage(struct mtd_info + return; + + len = be32_to_cpu(hdr.size) + 0x40; +- len = mtd_pad_erasesize(master, part->offset, len); +- if (len + master->erasesize > part->mtd.size) +- return; + + if (config_enabled(CONFIG_MTD_SPLIT_UIMAGE_FW)) + pr_err("Dedicated partitioner didn't split firmware partition, please fill a bug report!\n"); diff --git a/target/linux/ramips/patches-3.18/0101-mtd-add-rtn56u-support.patch b/target/linux/ramips/patches-3.18/0101-mtd-add-rtn56u-support.patch new file mode 100644 index 0000000..50b88db --- /dev/null +++ b/target/linux/ramips/patches-3.18/0101-mtd-add-rtn56u-support.patch @@ -0,0 +1,27 @@ +--- a/drivers/mtd/mtdpart.c ++++ b/drivers/mtd/mtdpart.c +@@ -807,8 +807,11 @@ static void split_uimage(struct mtd_info + { + struct { + __be32 magic; +- __be32 pad[2]; ++ __be32 pad0[2]; + __be32 size; ++ __be32 pad1[4]; ++ __be32 name[7]; ++ __be32 kern_size; + } hdr; + size_t len; + +@@ -818,7 +821,10 @@ static void split_uimage(struct mtd_info + if (len != sizeof(hdr) || hdr.magic != cpu_to_be32(UBOOT_MAGIC)) + return; + +- len = be32_to_cpu(hdr.size) + 0x40; ++ if (hdr.kern_size != 0 && hdr.name[0] == 0) ++ len = be32_to_cpu(hdr.kern_size); ++ else ++ len = be32_to_cpu(hdr.size) + 0x40; + + if (config_enabled(CONFIG_MTD_SPLIT_UIMAGE_FW)) + pr_err("Dedicated partitioner didn't split firmware partition, please fill a bug report!\n"); diff --git a/target/linux/ramips/patches-3.18/0103-MIPS-OWRTDTB.patch b/target/linux/ramips/patches-3.18/0103-MIPS-OWRTDTB.patch new file mode 100644 index 0000000..b901383 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0103-MIPS-OWRTDTB.patch @@ -0,0 +1,44 @@ +From c174d2250e402399ad7dbdd57d51883d8804bba0 Mon Sep 17 00:00:00 2001 +From: John Crispin <blogic@openwrt.org> +Date: Mon, 15 Jul 2013 00:40:37 +0200 +Subject: [PATCH 31/33] owrt: MIPS: add OWRTDTB secion + +Signed-off-by: John Crispin <blogic@openwrt.org> +--- + arch/mips/kernel/head.S | 3 +++ + arch/mips/ralink/Makefile | 2 +- + arch/mips/ralink/of.c | 4 +++- + 3 files changed, 7 insertions(+), 2 deletions(-) + +--- a/arch/mips/kernel/head.S ++++ b/arch/mips/kernel/head.S +@@ -86,6 +86,9 @@ EXPORT(__image_cmdline) + .fill 0x400 + #endif /* CONFIG_IMAGE_CMDLINE_HACK */ + ++ .ascii "OWRTDTB:" ++ EXPORT(__image_dtb) ++ .fill 0x4000 + __REF + + NESTED(kernel_entry, 16, sp) # kernel entry point +--- a/arch/mips/ralink/of.c ++++ b/arch/mips/ralink/of.c +@@ -66,6 +66,8 @@ static int __init early_init_dt_find_mem + return 0; + } + ++extern struct boot_param_header __image_dtb; ++ + void __init plat_mem_setup(void) + { + set_io_port_base(KSEG1); +@@ -74,7 +76,7 @@ void __init plat_mem_setup(void) + * Load the builtin devicetree. This causes the chosen node to be + * parsed resulting in our memory appearing + */ +- __dt_setup_arch(__dtb_start); ++ __dt_setup_arch(&__image_dtb); + + strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); + diff --git a/target/linux/ramips/patches-3.18/0104-fix_bootargs_handling.patch b/target/linux/ramips/patches-3.18/0104-fix_bootargs_handling.patch new file mode 100644 index 0000000..9f76aa1 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0104-fix_bootargs_handling.patch @@ -0,0 +1,40 @@ +--- a/arch/mips/ralink/of.c ++++ b/arch/mips/ralink/of.c +@@ -3,7 +3,7 @@ + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * +- * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * Copyright (C) 2008-2014 Imre Kaloz <kaloz@openwrt.org> + * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> + */ +@@ -66,6 +66,17 @@ static int __init early_init_dt_find_mem + return 0; + } + ++static int chosen_dtb; ++ ++static int __init early_init_dt_find_chosen(unsigned long node, const char *uname, ++ int depth, void *data) ++{ ++ if (depth == 1 && !strcmp(uname, "chosen")) ++ chosen_dtb = 1; ++ ++ return 0; ++} ++ + extern struct boot_param_header __image_dtb; + + void __init plat_mem_setup(void) +@@ -78,7 +89,9 @@ void __init plat_mem_setup(void) + */ + __dt_setup_arch(&__image_dtb); + +- strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); ++ of_scan_flat_dt(early_init_dt_find_chosen, NULL); ++ if (chosen_dtb) ++ strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); + + of_scan_flat_dt(early_init_dt_find_memory, NULL); + if (memory_dtb) diff --git a/target/linux/ramips/patches-3.18/0200-linkit_bootstrap.patch b/target/linux/ramips/patches-3.18/0200-linkit_bootstrap.patch new file mode 100644 index 0000000..70e8170 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0200-linkit_bootstrap.patch @@ -0,0 +1,94 @@ +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -56,3 +56,4 @@ obj-$(CONFIG_GENWQE) += genwqe/ + obj-$(CONFIG_ECHO) += echo/ + obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o + obj-$(CONFIG_CXL_BASE) += cxl/ ++obj-$(CONFIG_SOC_MT7620) += linkit.o +--- /dev/null ++++ b/drivers/misc/linkit.c +@@ -0,0 +1,84 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * publishhed by the Free Software Foundation. ++ * ++ * Copyright (C) 2015 John Crispin <blogic@openwrt.org> ++ */ ++ ++#include <linux/module.h> ++#include <linux/platform_device.h> ++#include <linux/of.h> ++#include <linux/mtd/mtd.h> ++#include <linux/gpio.h> ++ ++#define LINKIT_LATCH_GPIO 11 ++ ++struct linkit_hw_data { ++ char board[16]; ++ char rev[16]; ++}; ++ ++static void sanify_string(char *s) ++{ ++ int i; ++ ++ for (i = 0; i < 15; i++) ++ if (s[i] <= 0x20) ++ s[i] = '\0'; ++ s[15] = '\0'; ++} ++ ++static int linkit_probe(struct platform_device *pdev) ++{ ++ struct linkit_hw_data hw; ++ struct mtd_info *mtd; ++ size_t retlen; ++ int ret; ++ ++ mtd = get_mtd_device_nm("factory"); ++ if (IS_ERR(mtd)) ++ return PTR_ERR(mtd); ++ ++ ret = mtd_read(mtd, 0x400, sizeof(hw), &retlen, (u_char *) &hw); ++ put_mtd_device(mtd); ++ ++ sanify_string(hw.board); ++ sanify_string(hw.rev); ++ ++ dev_info(&pdev->dev, "Version : %s\n", hw.board); ++ dev_info(&pdev->dev, "Revision : %s\n", hw.rev); ++ ++ if (!strcmp(hw.board, "LINKITS7688")) { ++ dev_info(&pdev->dev, "setting up bootstrap latch\n"); ++ ++ if (devm_gpio_request(&pdev->dev, LINKIT_LATCH_GPIO, "bootstrap")) { ++ dev_err(&pdev->dev, "failed to setup bootstrap gpio\n"); ++ return -1; ++ } ++ gpio_direction_output(LINKIT_LATCH_GPIO, 0); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id linkit_match[] = { ++ { .compatible = "mediatek,linkit" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, linkit_match); ++ ++static struct platform_driver linkit_driver = { ++ .probe = linkit_probe, ++ .driver = { ++ .name = "mtk-linkit", ++ .owner = THIS_MODULE, ++ .of_match_table = linkit_match, ++ }, ++}; ++ ++int __init linkit_init(void) ++{ ++ return platform_driver_register(&linkit_driver); ++} ++late_initcall_sync(linkit_init); diff --git a/target/linux/ramips/patches-3.18/0300-mt7628_fixes.patch b/target/linux/ramips/patches-3.18/0300-mt7628_fixes.patch new file mode 100644 index 0000000..443e07a --- /dev/null +++ b/target/linux/ramips/patches-3.18/0300-mt7628_fixes.patch @@ -0,0 +1,131 @@ +--- a/arch/mips/ralink/mt7620.c ++++ b/arch/mips/ralink/mt7620.c +@@ -101,28 +101,28 @@ static struct rt2880_pmx_group mt7620a_p + }; + + static struct rt2880_pmx_func pwm1_grp_mt7628[] = { +- FUNC("sdxc", 3, 19, 1), ++ FUNC("sdxc d6", 3, 19, 1), + FUNC("utif", 2, 19, 1), + FUNC("gpio", 1, 19, 1), +- FUNC("pwm", 0, 19, 1), ++ FUNC("pwm1", 0, 19, 1), + }; + + static struct rt2880_pmx_func pwm0_grp_mt7628[] = { +- FUNC("sdxc", 3, 18, 1), ++ FUNC("sdxc d7", 3, 18, 1), + FUNC("utif", 2, 18, 1), + FUNC("gpio", 1, 18, 1), +- FUNC("pwm", 0, 18, 1), ++ FUNC("pwm0", 0, 18, 1), + }; + + static struct rt2880_pmx_func uart2_grp_mt7628[] = { +- FUNC("sdxc", 3, 20, 2), ++ FUNC("sdxc d5 d4", 3, 20, 2), + FUNC("pwm", 2, 20, 2), + FUNC("gpio", 1, 20, 2), + FUNC("uart2", 0, 20, 2), + }; + + static struct rt2880_pmx_func uart1_grp_mt7628[] = { +- FUNC("sdxc", 3, 45, 2), ++ FUNC("sw_r", 3, 45, 2), + FUNC("pwm", 2, 45, 2), + FUNC("gpio", 1, 45, 2), + FUNC("uart1", 0, 45, 2), +@@ -165,7 +165,7 @@ static struct rt2880_pmx_func spi_cs1_gr + FUNC("-", 3, 6, 1), + FUNC("refclk", 2, 6, 1), + FUNC("gpio", 1, 6, 1), +- FUNC("spi", 0, 6, 1), ++ FUNC("spi cs1", 0, 6, 1), + }; + + static struct rt2880_pmx_func spis_grp_mt7628[] = { +@@ -182,27 +182,43 @@ static struct rt2880_pmx_func gpio_grp_m + FUNC("gpio", 0, 11, 1), + }; + +-#define MT7628_GPIO_MODE_MASK 0x3 +- +-#define MT7628_GPIO_MODE_PWM1 30 +-#define MT7628_GPIO_MODE_PWM0 28 +-#define MT7628_GPIO_MODE_UART2 26 +-#define MT7628_GPIO_MODE_UART1 24 +-#define MT7628_GPIO_MODE_I2C 20 +-#define MT7628_GPIO_MODE_REFCLK 18 +-#define MT7628_GPIO_MODE_PERST 16 +-#define MT7628_GPIO_MODE_WDT 14 +-#define MT7628_GPIO_MODE_SPI 12 +-#define MT7628_GPIO_MODE_SDMODE 10 +-#define MT7628_GPIO_MODE_UART0 8 +-#define MT7628_GPIO_MODE_I2S 6 +-#define MT7628_GPIO_MODE_CS1 4 +-#define MT7628_GPIO_MODE_SPIS 2 +-#define MT7628_GPIO_MODE_GPIO 0 ++static struct rt2880_pmx_func wled_kn_grp_mt7628[] = { ++ FUNC("rsvd", 3, 35, 1), ++ FUNC("rsvd", 2, 35, 1), ++ FUNC("gpio", 1, 35, 1), ++ FUNC("wled_kn", 0, 35, 1), ++}; ++ ++static struct rt2880_pmx_func wled_an_grp_mt7628[] = { ++ FUNC("rsvd", 3, 35, 1), ++ FUNC("rsvd", 2, 35, 1), ++ FUNC("gpio", 1, 35, 1), ++ FUNC("wled_an", 0, 35, 1), ++}; ++ ++#define MT7628_GPIO_MODE_MASK 0x3 ++ ++#define MT7628_GPIO_MODE_WLED_KN 48 ++#define MT7628_GPIO_MODE_WLED_AN 32 ++#define MT7628_GPIO_MODE_PWM1 30 ++#define MT7628_GPIO_MODE_PWM0 28 ++#define MT7628_GPIO_MODE_UART2 26 ++#define MT7628_GPIO_MODE_UART1 24 ++#define MT7628_GPIO_MODE_I2C 20 ++#define MT7628_GPIO_MODE_REFCLK 18 ++#define MT7628_GPIO_MODE_PERST 16 ++#define MT7628_GPIO_MODE_WDT 14 ++#define MT7628_GPIO_MODE_SPI 12 ++#define MT7628_GPIO_MODE_SDMODE 10 ++#define MT7628_GPIO_MODE_UART0 8 ++#define MT7628_GPIO_MODE_I2S 6 ++#define MT7628_GPIO_MODE_CS1 4 ++#define MT7628_GPIO_MODE_SPIS 2 ++#define MT7628_GPIO_MODE_GPIO 0 + + static struct rt2880_pmx_group mt7628an_pinmux_data[] = { +- GRP_G("pmw1", pwm1_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_PWM1), +- GRP_G("pmw0", pwm0_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_PWM0), ++ GRP_G("pwm1", pwm1_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_PWM1), ++ GRP_G("pwm0", pwm0_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_PWM0), + GRP_G("uart2", uart2_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_UART2), + GRP_G("uart1", uart1_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_UART1), + GRP_G("i2c", i2c_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_I2C), +@@ -216,6 +232,8 @@ static struct rt2880_pmx_group mt7628an_ + GRP_G("spi cs1", spi_cs1_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_CS1), + GRP_G("spis", spis_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_SPIS), + GRP_G("gpio", gpio_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_GPIO), ++ GRP_G("wled_an", wled_an_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_WLED_AN), ++ GRP_G("wled_kn", wled_kn_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_WLED_KN), + { 0 } + }; + +@@ -529,7 +547,11 @@ void prom_soc_init(struct ralink_soc_inf + (rev & CHIP_REV_ECO_MASK)); + + cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0); +- dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK; ++ ++ if (ralink_soc == MT762X_SOC_MT7628AN) ++ dram_type = ((cfg0&0x00000001) == 0x00000001)?SYSCFG0_DRAM_TYPE_DDR1_MT7628:SYSCFG0_DRAM_TYPE_DDR2_MT7628; ++ else ++ dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK; + + soc_info->mem_base = MT7620_DRAM_BASE; + if (ralink_soc == MT762X_SOC_MT7628AN) diff --git a/target/linux/ramips/patches-3.18/0301-mt7688-detect.patch b/target/linux/ramips/patches-3.18/0301-mt7688-detect.patch new file mode 100644 index 0000000..1fddf11 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0301-mt7688-detect.patch @@ -0,0 +1,114 @@ +--- a/arch/mips/include/asm/mach-ralink/mt7620.h ++++ b/arch/mips/include/asm/mach-ralink/mt7620.h +@@ -17,6 +17,7 @@ + + #define SYSC_REG_CHIP_NAME0 0x00 + #define SYSC_REG_CHIP_NAME1 0x04 ++#define SYSC_REG_EFUSE_CFG 0x08 + #define SYSC_REG_CHIP_REV 0x0c + #define SYSC_REG_SYSTEM_CONFIG0 0x10 + #define SYSC_REG_SYSTEM_CONFIG1 0x14 +--- a/arch/mips/ralink/mt7620.c ++++ b/arch/mips/ralink/mt7620.c +@@ -43,6 +43,9 @@ + #define CLKCFG_FFRAC_MASK 0x001f + #define CLKCFG_FFRAC_USB_VAL 0x0003 + ++/* EFUSE bits */ ++#define EFUSE_MT7688 0x100000 ++ + /* does the board have sdram or ddram */ + static int dram_type; + +@@ -391,7 +394,7 @@ void __init ralink_clk_init(void) + #define RINT(x) ((x) / 1000000) + #define RFRAC(x) (((x) / 1000) % 1000) + +- if (ralink_soc == MT762X_SOC_MT7628AN) { ++ if (ralink_soc == MT762X_SOC_MT7628AN || ralink_soc == MT762X_SOC_MT7688) { + if (xtal_rate == MHZ(40)) + cpu_rate = MHZ(580); + else +@@ -436,7 +439,8 @@ void __init ralink_clk_init(void) + ralink_clk_add("10000e00.uart2", periph_rate); + ralink_clk_add("10180000.wmac", xtal_rate); + +- if (IS_ENABLED(CONFIG_USB) && ralink_soc != MT762X_SOC_MT7628AN) { ++ if (IS_ENABLED(CONFIG_USB) && ++ (ralink_soc == MT762X_SOC_MT7620A || ralink_soc == MT762X_SOC_MT7620N)) { + /* + * When the CPU goes into sleep mode, the BUS clock will be too low for + * USB to function properly +@@ -533,8 +537,15 @@ void prom_soc_init(struct ralink_soc_inf + soc_info->compatible = "ralink,mt7620n-soc"; + } + } else if (n0 == MT7620_CHIP_NAME0 && n1 == MT7628_CHIP_NAME1) { +- ralink_soc = MT762X_SOC_MT7628AN; +- name = "MT7628AN"; ++ u32 efuse = __raw_readl(sysc + SYSC_REG_EFUSE_CFG); ++ ++ if (efuse & EFUSE_MT7688) { ++ ralink_soc = MT762X_SOC_MT7688; ++ name = "MT7688"; ++ } else { ++ ralink_soc = MT762X_SOC_MT7628AN; ++ name = "MT7628AN"; ++ } + soc_info->compatible = "ralink,mt7628an-soc"; + } else { + panic("mt762x: unknown SoC, n0:%08x n1:%08x\n", n0, n1); +@@ -548,13 +559,13 @@ void prom_soc_init(struct ralink_soc_inf + + cfg0 = __raw_readl(sysc + SYSC_REG_SYSTEM_CONFIG0); + +- if (ralink_soc == MT762X_SOC_MT7628AN) ++ if (ralink_soc == MT762X_SOC_MT7628AN || ralink_soc == MT762X_SOC_MT7688) + dram_type = ((cfg0&0x00000001) == 0x00000001)?SYSCFG0_DRAM_TYPE_DDR1_MT7628:SYSCFG0_DRAM_TYPE_DDR2_MT7628; + else + dram_type = (cfg0 >> SYSCFG0_DRAM_TYPE_SHIFT) & SYSCFG0_DRAM_TYPE_MASK; + + soc_info->mem_base = MT7620_DRAM_BASE; +- if (ralink_soc == MT762X_SOC_MT7628AN) ++ if (ralink_soc == MT762X_SOC_MT7628AN || ralink_soc == MT762X_SOC_MT7688) + mt7628_dram_init(soc_info); + else + mt7620_dram_init(soc_info); +@@ -567,7 +578,7 @@ void prom_soc_init(struct ralink_soc_inf + pr_info("Digital PMU set to %s control\n", + (pmu1 & DIG_SW_SEL) ? ("sw") : ("hw")); + +- if (ralink_soc == MT762X_SOC_MT7628AN) ++ if (ralink_soc == MT762X_SOC_MT7628AN || ralink_soc == MT762X_SOC_MT7688) + rt2880_pinmux_data = mt7628an_pinmux_data; + else + rt2880_pinmux_data = mt7620a_pinmux_data; +--- a/arch/mips/include/asm/mach-ralink/ralink_regs.h ++++ b/arch/mips/include/asm/mach-ralink/ralink_regs.h +@@ -24,6 +24,7 @@ enum ralink_soc_type { + MT762X_SOC_MT7620N, + MT762X_SOC_MT7621AT, + MT762X_SOC_MT7628AN, ++ MT762X_SOC_MT7688, + }; + extern enum ralink_soc_type ralink_soc; + +--- a/drivers/net/ethernet/ralink/esw_rt3052.c ++++ b/drivers/net/ethernet/ralink/esw_rt3052.c +@@ -611,7 +611,7 @@ static void esw_hw_init(struct rt305x_es + rt305x_mii_write(esw, 0, 29, 0x598b); + /* select local register */ + rt305x_mii_write(esw, 0, 31, 0x8000); +- } else if (ralink_soc == MT762X_SOC_MT7628AN) { ++ } else if (ralink_soc == MT762X_SOC_MT7628AN || ralink_soc == MT762X_SOC_MT7688) { + int i; + // u32 phy_val; + u32 val; +@@ -1042,7 +1042,7 @@ esw_get_port_tr_badgood(struct switch_de + int shift = attr->id == RT5350_ESW_ATTR_PORT_TR_GOOD ? 0 : 16; + u32 reg; + +- if ((ralink_soc != RT305X_SOC_RT5350) && (ralink_soc != MT762X_SOC_MT7628AN)) ++ if ((ralink_soc != RT305X_SOC_RT5350) && (ralink_soc != MT762X_SOC_MT7628AN) && (ralink_soc != MT762X_SOC_MT7688)) + return -EINVAL; + + if (idx < 0 || idx >= RT305X_ESW_NUM_LANWAN) diff --git a/target/linux/ramips/patches-3.18/0302-mt762x-vendor-id.patch b/target/linux/ramips/patches-3.18/0302-mt762x-vendor-id.patch new file mode 100644 index 0000000..ca56f5c --- /dev/null +++ b/target/linux/ramips/patches-3.18/0302-mt762x-vendor-id.patch @@ -0,0 +1,22 @@ +--- a/arch/mips/ralink/mt7620.c ++++ b/arch/mips/ralink/mt7620.c +@@ -552,7 +552,7 @@ void prom_soc_init(struct ralink_soc_inf + } + + snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, +- "Ralink %s ver:%u eco:%u", ++ "MediaTek %s ver:%u eco:%u", + name, + (rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK, + (rev & CHIP_REV_ECO_MASK)); +--- a/arch/mips/ralink/mt7621.c ++++ b/arch/mips/ralink/mt7621.c +@@ -185,7 +185,7 @@ void prom_soc_init(struct ralink_soc_inf + rev = __raw_readl(sysc + SYSC_REG_CHIP_REV); + + snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, +- "Mediatek %s ver:%u eco:%u", ++ "MediaTek %s ver:%u eco:%u", + name, + (rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK, + (rev & CHIP_REV_ECO_MASK)); diff --git a/target/linux/ramips/patches-3.18/0303-alsa.patch b/target/linux/ramips/patches-3.18/0303-alsa.patch new file mode 100644 index 0000000..d6d4892 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0303-alsa.patch @@ -0,0 +1,8388 @@ +--- a/sound/soc/Kconfig ++++ b/sound/soc/Kconfig +@@ -56,6 +56,7 @@ source "sound/soc/spear/Kconfig" + source "sound/soc/tegra/Kconfig" + source "sound/soc/txx9/Kconfig" + source "sound/soc/ux500/Kconfig" ++source "sound/soc/mtk/Kconfig" + + # Supported codecs + source "sound/soc/codecs/Kconfig" +--- a/sound/soc/Makefile ++++ b/sound/soc/Makefile +@@ -33,3 +33,4 @@ obj-$(CONFIG_SND_SOC) += spear/ + obj-$(CONFIG_SND_SOC) += tegra/ + obj-$(CONFIG_SND_SOC) += txx9/ + obj-$(CONFIG_SND_SOC) += ux500/ ++obj-$(CONFIG_SND_SOC) += mtk/ +--- a/sound/soc/codecs/Kconfig ++++ b/sound/soc/codecs/Kconfig +@@ -725,7 +725,7 @@ config SND_SOC_WM8955 + tristate + + config SND_SOC_WM8960 +- tristate ++ tristate "WM8960" + + config SND_SOC_WM8961 + tristate +--- /dev/null ++++ b/sound/soc/mtk/Kconfig +@@ -0,0 +1,35 @@ ++config SND_MT76XX_SOC ++ tristate "SoC Audio for MT76XX APSoC Machine" ++ depends on SND_SOC && (SOC_MT7620 || SOC_MT7621) ++ ++ help ++ Say Y or M if you want to add support for codecs attached to ++ the MTK I2S interface. ++ ++choice ++ prompt "Selected SoC type" ++ depends on SND_MT76XX_SOC ++ default SND_MT76XX_SOC_MT7620 ++ ++config SND_MT76XX_SOC_MT7620 ++ bool "MT7620" ++ depends on SOC_MT7620 ++ ++config SND_MT76XX_SOC_MT7628 ++ bool "MT7628" ++ depends on SOC_MT7620 ++ ++config SND_MT76XX_SOC_MT7621 ++ bool "MT7621" ++ depends on SOC_MT7621 ++ ++endchoice ++ ++config SND_MT76XX_PCM ++ tristate "MTK SoC Audio PCM Platform" ++ depends on SND_MT76XX_SOC ++ ++config SND_MT76XX_I2S ++ tristate "MTK SoC I2S Support" ++ depends on SND_MT76XX_SOC ++ +--- /dev/null ++++ b/sound/soc/mtk/Makefile +@@ -0,0 +1,39 @@ ++KBUILD_CFLAGS += -I$(srctree) ++ ++ifeq ($(CONFIG_SND_MT76XX_SOC_MT7620),y) ++KBUILD_CFLAGS += -DCONFIG_MT7620 -DCONFIG_RALINK_MT7620 ++endif ++ifeq ($(CONFIG_SND_MT76XX_SOC_MT7628),y) ++KBUILD_CFLAGS += -DCONFIG_MT7628 -DCONFIG_RALINK_MT7628 ++endif ++ifeq ($(CONFIG_SOC_MT7620),y) ++KBUILD_CFLAGS += -DRALINK_SYSCTL_BASE=0xB0000000 ++KBUILD_CFLAGS += -DRALINK_INTCL_BASE=0xB0000200 ++KBUILD_CFLAGS += -DRALINK_PIO_BASE=0xB0000600 ++KBUILD_CFLAGS += -DRALINK_I2S_BASE=0xB0000A00 ++KBUILD_CFLAGS += -DRALINK_GDMA_BASE=0xB0002800 ++KBUILD_CFLAGS += -DCONFIG_GDMA_EVERYBODY ++KBUILD_CFLAGS += -DCONFIG_SND_MT76XX_SOC ++KBUILD_CFLAGS += -DCONFIG_I2S_WM8960 ++KBUILD_CFLAGS += -DCONFIG_I2S_MCLK_12P288MHZ ++KBUILD_CFLAGS += -DCONFIG_GDMA_EVERYBODY ++KBUILD_CFLAGS += -DSURFBOARDINT_DMA=15 ++KBUILD_CFLAGS += -DRALINK_INTCTL_DMA=128 ++KBUILD_CFLAGS += -DCONFIG_SND_SOC_WM8960 ++endif ++ ++# MTK APSoC Platform Support ++snd-soc-mt76xx-i2s-ctl-objs := i2s_ctrl.o i2s_debug.o #i2c_wm8960.o ++snd-soc-mt76xx-pcm-objs := mt76xx_pcm.o ++snd-soc-mt76xx-i2s-objs := mt76xx_i2s.o ++ ++obj-$(CONFIG_SND_MT76XX_PCM) += snd-soc-mt76xx-pcm.o ++obj-$(CONFIG_SND_MT76XX_I2S) += snd-soc-mt76xx-i2s-ctl.o snd-soc-mt76xx-i2s.o ++ ++# MTK APSoC Machine Support ++snd-soc-mt76xx-machine-objs := mt76xx_machine.o ++ ++obj-$(CONFIG_SND_MT76XX_SOC) += i2c_wm8960.o ralink_gdma.o snd-soc-mt76xx-machine.o ++ ++ ++ +--- /dev/null ++++ b/sound/soc/mtk/i2c_wm8960.c +@@ -0,0 +1,492 @@ ++#include <linux/kernel.h> ++#include <linux/version.h> ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/i2c.h> ++#include <linux/delay.h> ++#include <linux/interrupt.h> ++#include <linux/fs.h> ++#include <linux/fcntl.h> ++#include <linux/cdev.h> ++#if defined(CONFIG_ARCH_MT7623) ++#include <mt_i2c.h> ++#include <mach/mt_gpio.h> ++#endif ++#include "i2c_wm8960.h" ++#include "i2s_ctrl.h" ++ ++ ++#define BUF_SIZE 20 ++ ++#undef MSG ++#define MSG printk ++ ++ ++#if defined(CONFIG_ARCH_MT7623) ++/*FIXME*/ ++//static struct i2c_board_info __initdata i2c_devs1 = { I2C_BOARD_INFO("codec_wm8960", (0X34>>1))}; ++static struct i2c_board_info __initdata i2c_devs1 = { I2C_BOARD_INFO("codec_wm8960", (0X34))}; ++ ++#endif ++unsigned long wm_reg_data[56]; ++struct wm8960_data *wmio; ++ ++struct wm8960_data { ++ struct i2c_client *client; ++ struct device *dev; ++ const char *name; ++}; ++ ++ ++void i2c_WM8960_write(u32 reg, u32 data) ++{ ++ int ret; ++ struct i2c_msg msg; ++ u8 buf[2]={0}; ++ ++#if defined(CONFIG_ARCH_MT7623) ++ unsigned int ext_flag = 0; ++ ++ ext_flag &= 0x7FFFFFFF; ++ ext_flag |= I2C_A_FILTER_MSG; ++ ext_flag |= I2C_POLLING_FLAG; ++#endif ++ ++ wm_reg_data[reg] = data; ++ ++ buf[0]= (reg<<1)|(0x01&(data>>8)); ++ buf[1]= (data&0xFF); ++ ++#if defined(CONFIG_ARCH_MT7623) ++ /*FIXME*/ ++ //msg.addr = wmio->client->addr; ++ msg.addr = wmio->client->addr>>1; ++ ++#else ++ msg.addr = wmio->client->addr>>1; ++#endif ++ msg.flags = 0; ++ msg.buf = (char *)buf; ++ msg.len = 2; ++#if defined(CONFIG_ARCH_MT7623) ++ msg.timing = 80; ++ msg.ext_flag = ext_flag & 0x7FFFFFFF; ++#endif ++ ++ ret = i2c_transfer(wmio->client->adapter, &msg, 1); ++ MSG("[WM8960(%02X)=0x%08X]\n",(unsigned int)reg,(unsigned int)data); ++ ++ if (ret <= 0) ++ printk("%s: i2c write error!\n", __func__); ++} ++ ++ ++ ++// Reset and power up the WM8960 ++void audiohw_preinit(void) ++{ ++ memset(wm_reg_data, 0 , sizeof(unsigned long)*55); ++ ++ i2c_WM8960_write(RESET, RESET_RESET); // Reset (0x0F) ++ ++ mdelay(50); ++ wm_reg_data[RESET] = 0xFFFF; ++ mdelay(50); ++} ++ ++void audiohw_set_apll(int srate) ++{ ++ unsigned long data; ++ ++ if((srate==8000) || (srate==12000) || (srate==16000) || (srate==24000) || (srate==32000) || (srate==48000)) ++ { ++ // Provide 12.288MHz SYSCLK ++ data = wm_reg_data[PLL1]; ++ i2c_WM8960_write(PLL1, data | PLL1_OPCLKDIV_1 | PLL1_SDM_FRACTIONAL | PLL1_PLLPRESCALE_1 | PLL1_PLLN(0x8)); // PLL1 (0x34) ++ ++ i2c_WM8960_write(PLL2, PLL2_PLLK_23_16(0x31)); // PLL2 (0x35) ++ i2c_WM8960_write(PLL3, PLL3_PLLK_15_8(0x26)); // PLL3 (0x36) ++ i2c_WM8960_write(PLL4, PLL4_PLLK_7_0(0xe9)); // PLL4 (0x37) ++ } ++ else if ((srate==11025) || (srate==22050) || (srate==44100)) ++ { ++ //Provide 11.2896MHz SYSCLK ++ data = wm_reg_data[PLL1]; ++ i2c_WM8960_write(PLL1, data | PLL1_OPCLKDIV_1 | PLL1_SDM_FRACTIONAL | PLL1_PLLPRESCALE_1 | PLL1_PLLN(0x7)); //PLL1 (0x34) ++ ++ i2c_WM8960_write(PLL2, PLL2_PLLK_23_16(0x86)); //PLL2 (0x35) ++ i2c_WM8960_write(PLL3, PLL3_PLLK_15_8(0xc2)); //PLL3 (0x36) ++ i2c_WM8960_write(PLL4, PLL4_PLLK_7_0(0x26)); //PLL4 (0x37) ++ } ++ else ++ { ++ printk("Not support this srate\n"); ++ } ++ mdelay(3); ++} ++ ++ ++void audiohw_set_frequency(int fsel, int pll_en) ++{ ++ MSG("audiohw_set_frequency_=0x%08X\n",fsel); ++ ++ if (pll_en) ++ { ++ printk("PLL enable\n"); ++ i2c_WM8960_write(CLOCKING1, (fsel<<3) | CLOCKING1_SYSCLKDIV_2 | CLOCKING1_CLKSEL_PLL); //CLOCKING (0x04)=>0x05 ++ ++ } ++ else ++ { ++ printk("PLL disable\n"); ++ i2c_WM8960_write(CLOCKING1, (fsel<<3));//| CLOCKING1_SYSCLKDIV_2); //CLOCKING (0x04) ++ } ++ ++} ++ ++//FIXME ++int audiohw_set_lineout_vol(int Aout, int vol_l, int vol_r) ++{ ++ MSG("audiohw_set_lineout_vol_\n"); ++ switch(Aout) ++ { ++ case 1: ++ //i2c_WM8960_write(LOUT1, LOUT1_LO1VU|LOUT1_LO1ZC|LOUT1_LOUT1VOL(0x7f)); //LOUT1(0x02) ++ //i2c_WM8960_write(ROUT1, ROUT1_RO1VU|ROUT1_RO1ZC|ROUT1_ROUT1VOL(0x7f)); //ROUT1(0x03) ++ i2c_WM8960_write(LOUT1, LOUT1_LO1VU|LOUT1_LO1ZC|LOUT1_LOUT1VOL(vol_l)); //LOUT1(0x02) ++ i2c_WM8960_write(ROUT1, ROUT1_RO1VU|ROUT1_RO1ZC|ROUT1_ROUT1VOL(vol_r)); //ROUT1(0x03) ++ break; ++ case 2: ++ i2c_WM8960_write(LSPK, LSPK_SPKLVU|LSPK_SPKLZC| LSPK_SPKLVOL(vol_l)); ++ i2c_WM8960_write(RSPK, RSPK_SPKRVU|RSPK_SPKRZC| RSPK_SPKRVOL(vol_r)); ++ break; ++ default: ++ break; ++ } ++ return 0; ++} ++ ++//FIXME ++int audiohw_set_linein_vol(int vol_l, int vol_r) ++{ ++ MSG("audiohw_set_linein_vol_\n"); ++ ++ i2c_WM8960_write(LINV, LINV_IPVU|LINV_LINVOL(vol_l)); //LINV(0x00)=>0x12b ++ i2c_WM8960_write(RINV, RINV_IPVU|RINV_RINVOL(vol_r)); //LINV(0x01)=>0x12b ++ ++ return 0; ++} ++ ++//Set signal path ++int audiohw_postinit(int bSlave, int AIn, int AOut, int pll_en, int wordLen24b) ++{ ++ ++ int i; ++ unsigned long data; ++ ++ if(wm_reg_data[RESET]!=0xFFFF) ++ return 0; ++ ++ if(bSlave) ++ { ++ MSG("WM8960 slave.....\n"); ++ if(wordLen24b) ++ { ++ printk("24 bit word length\n"); ++ i2c_WM8960_write(AINTFCE1, AINTFCE1_WL_24 | AINTFCE1_FORMAT_I2S); //AINTFCE1(0x07) ++ } ++ else ++ { ++ printk("16 bit word length\n"); ++ i2c_WM8960_write(AINTFCE1, AINTFCE1_WL_16 | AINTFCE1_FORMAT_I2S); //AINTFCE1(0x07) ++ } ++ } ++ else ++ { ++ MSG("WM8960 master.....\n"); ++ i2c_WM8960_write(CLOCKING2, 0x1c4);//CLOCKING2_BCLKDIV(0x1c4)); //CLOCKING2(0x08) ++ ++ if(wordLen24b) ++ { ++ printk("24 bit word length\n"); ++ i2c_WM8960_write(AINTFCE1, AINTFCE1_MS | AINTFCE1_WL_24 | AINTFCE1_FORMAT_I2S); //AINTFCE1(0x07) ++ } ++ else ++ { ++ printk("16 bit word length\n"); ++ i2c_WM8960_write(AINTFCE1, AINTFCE1_MS | AINTFCE1_WL_16 | AINTFCE1_FORMAT_I2S); //AINTFCE1(0x07) ++ } ++ mdelay(5); ++ } ++ ++ ++ //From app notes: allow Vref to stabilize to reduce clicks ++ for(i = 0; i < 1000*HZ; i++); ++ ++ if(AIn > 0) ++ { ++ data = wm_reg_data[PWRMGMT1]; ++ i2c_WM8960_write(PWRMGMT1, data|PWRMGMT1_ADCL|PWRMGMT1_ADCR|PWRMGMT1_AINL |PWRMGMT1_AINR);//|PWRMGMT1_MICB);//PWRMGMT1(0x19) ++ ++ data = wm_reg_data[ADDITIONAL1]; ++ i2c_WM8960_write(ADDITIONAL1, data|ADDITIONAL1_DATSEL(0x01)); //ADDITIONAL1(0x17) ++ i2c_WM8960_write(LADCVOL, LADCVOL_LAVU_EN|LADCVOL_LADCVOL(0xc3)); //LADCVOL(0x15) ++ i2c_WM8960_write(RADCVOL, RADCVOL_RAVU_EN|RADCVOL_RADCVOL(0xc3)); //RADCVOL(0x16) ++ i2c_WM8960_write(ADCLPATH, ADCLPATH_LMN1|ADCLPATH_LMIC2B);//|ADCLPATH_LMICBOOST_13DB); //ADCLPATH(0x20)=>(0x108) ++ i2c_WM8960_write(ADCRPATH, ADCRPATH_RMN1|ADCRPATH_RMIC2B);//|ADCRPATH_RMICBOOST_13DB); //ADCRPATH(0x21)=>(0x108) ++ i2c_WM8960_write(PWRMGMT3, PWRMGMT3_LMIC|PWRMGMT3_RMIC); //PWRMGMT3(0x2f) ++ ++ //i2c_WM8960_write(LINBMIX, 0x000); //LINBMIX(0x2B) ++ ++ if (AOut<=0) ++ { ++ i2c_WM8960_write(AINTFCE2, 0x40); //FIXME:(0x09) ++ ++ data = wm_reg_data[PWRMGMT2]; ++ if(pll_en) ++ { ++ i2c_WM8960_write(PWRMGMT2, data|PWRMGMT2_PLL_EN|PWRMGMT2_DACL|PWRMGMT2_DACR); //PWRMGMT2(0x1a) ++ } ++ else ++ { ++ i2c_WM8960_write(PWRMGMT2, data|PWRMGMT2_DACL|PWRMGMT2_DACR); //PWRMGMT2(0x1a) ++ ++ } ++ } ++ } ++ if(AOut>0) ++ { ++ //Power management 2 setting ++ data = wm_reg_data[PWRMGMT2]; ++ ++ if(pll_en) ++ { ++ i2c_WM8960_write(PWRMGMT2, data|PWRMGMT2_PLL_EN|PWRMGMT2_DACL|PWRMGMT2_DACR|PWRMGMT2_LOUT1|PWRMGMT2_ROUT1|PWRMGMT2_SPKL|PWRMGMT2_SPKR); //PWRMGMT2(0x1a) ++ } ++ else ++ { ++ i2c_WM8960_write(PWRMGMT2, data|PWRMGMT2_DACL|PWRMGMT2_DACR|PWRMGMT2_LOUT1|PWRMGMT2_ROUT1|PWRMGMT2_SPKL|PWRMGMT2_SPKR); //PWRMGMT2(0x1a) ++ ++ } ++ ++ mdelay(10); ++ ++ i2c_WM8960_write(AINTFCE2, 0x40); //FIXME:(0x09) ++ ++ i2c_WM8960_write(LEFTGAIN, LEFTGAIN_LDVU|LEFTGAIN_LDACVOL(0xff)); //LEFTGAIN(0x0a) ++ i2c_WM8960_write(RIGHTGAIN, RIGHTGAIN_RDVU|RIGHTGAIN_RDACVOL(0xff)); //RIGHTGAIN(0x0b) ++ ++ i2c_WM8960_write(LEFTMIX1, 0x100); //LEFTMIX1(0x22) ++ i2c_WM8960_write(RIGHTMIX2, 0x100); //RIGHTMIX2(0x25) ++ ++ data = wm_reg_data[PWRMGMT3]; //FIXME ++ i2c_WM8960_write(PWRMGMT3, data|PWRMGMT3_ROMIX|PWRMGMT3_LOMIX); //PWRMGMT3(0x2f) ++ ++ data = wm_reg_data[CLASSDCTRL1]; //CLASSDCTRL1(0x31) SPEAKER FIXME ++ i2c_WM8960_write(CLASSDCTRL1, 0xf7);//data|CLASSDCTRL1_OP_LRSPK); ++ ++ data = wm_reg_data[CLASSDCTRL3]; //CLASSDCTRL3(0x33) ++ i2c_WM8960_write(CLASSDCTRL3, 0xad);//data|(0x1b)); ++ } ++ ++ i2c_WM8960_write(DACCTRL1, 0x000); //DACCTRL1(0x05) ++ ++ data = wm_reg_data[PWRMGMT1]; ++ i2c_WM8960_write(PWRMGMT1, data|0x1c0); //FIXME:PWRMGMT1(0x19) ++ ++ ++ printk("WM8960 All initial ok!\n"); ++ ++ return 0; ++ ++} ++ ++void audiohw_micboost(int boostgain) ++{ ++ unsigned long data; ++ ++ data = wm_reg_data[ADCLPATH]; ++ i2c_WM8960_write(ADCLPATH, data|(boostgain << 4)); ++ ++ data = wm_reg_data[ADCRPATH]; ++ i2c_WM8960_write(ADCRPATH, data|(boostgain << 4)); ++} ++ ++void audiohw_micin(int enableMic) ++{ ++ unsigned long data; ++ ++ if (enableMic==1) ++ { ++ data = wm_reg_data[PWRMGMT1]; ++ i2c_WM8960_write(PWRMGMT1, data|PWRMGMT1_MICB); ++ } ++#if 1 ++ else ++ { ++ data = wm_reg_data[PWRMGMT1]; ++ i2c_WM8960_write(PWRMGMT1, data & (~(PWRMGMT1_MICB))); ++ } ++#endif ++} ++ ++void audiohw_mute( bool mute) ++{ ++ //Mute: Set DACMU = 1 to soft-mute the audio DACs. ++ //Unmute: Set DACMU = 0 to soft-un-mute the audio DACs. ++ i2c_WM8960_write(DACCTRL1, mute ? DACCTRL1_DACMU : 0); ++} ++ ++ ++//Nice shutdown of WM8960 codec ++void audiohw_close(void) ++{ ++ i2c_WM8960_write(DACCTRL1,DACCTRL1_DACMU); //0x05->0x08 ++ i2c_WM8960_write(PWRMGMT1, 0x000); //0x19->0x000 ++ mdelay(400); ++ i2c_WM8960_write(PWRMGMT2, 0x000); //0x1a->0x000 ++ ++} ++ ++void audiohw_loopback(int fsel) ++{ ++} ++ ++void audiohw_codec_exlbk(void) ++{ ++ memset(wm_reg_data, 0 , sizeof(unsigned long)*55); ++ ++ i2c_WM8960_write(LINV, 0x117); //0x00->0x117 ++ i2c_WM8960_write(RINV, 0x117); //0x01->0x117 ++ i2c_WM8960_write(LOUT1, 0x179); //0x02->0x179 ++ i2c_WM8960_write(ROUT1, 0x179); //0x03->0x179 ++ i2c_WM8960_write(CLOCKING1, 0x00); //0x04->0x00 ++ //i2c_WM8960_write(CLOCKING1, 0x40); //0x04->0x00 ++ i2c_WM8960_write(DACCTRL1, 0x00); //0x05->0x00 ++ i2c_WM8960_write(AINTFCE2, 0x41); //0x09->0x41 ++ i2c_WM8960_write(LADCVOL, 0x1c3); //0x15->0x1c3 ++ i2c_WM8960_write(RADCVOL, 0x1c3); //0x16->0x1c3 ++ i2c_WM8960_write(PWRMGMT1, 0xfc); //0x19->0xfc ++ i2c_WM8960_write(PWRMGMT2, 0x1e0); //0x1a->0x1e0 ++ i2c_WM8960_write(ADCLPATH, 0x108); //0x20->0x108 ++ i2c_WM8960_write(ADCRPATH, 0x108); //0x21->0x108 ++ i2c_WM8960_write(LEFTMIX1, 0x150); //0x22->0x150 ++ i2c_WM8960_write(RIGHTMIX2, 0x150); //0x25->0x150 ++ i2c_WM8960_write(BYPASS1, 0x00); //0x2d->0x00 ++ i2c_WM8960_write(BYPASS2, 0x00); //0x2e->0x00 ++ i2c_WM8960_write(PWRMGMT3, 0x3c); //0x2f->0x3c ++} ++ ++void audiohw_bypass(void) ++{ ++ int i; ++ ++ memset(wm_reg_data, 0 , sizeof(unsigned long)*55); ++ i2c_WM8960_write(RESET, 0x000); //0x0f(R15)->0x000 ++ ++ for(i = 0; i < 1000*HZ; i++); ++ ++ i2c_WM8960_write(PWRMGMT1, 0xf0); //0x19(R25)->0xf0 ++ i2c_WM8960_write(PWRMGMT2, 0x60); //0x1a(R26)->0x60 ++ i2c_WM8960_write(PWRMGMT3, 0x3c); //0x2f(R47)->0x3c ++ i2c_WM8960_write(LINV, 0x117); // 0x00(R0)->0x117 ++ i2c_WM8960_write(RINV, 0x117); // 0x01(R1)->0x117 ++ i2c_WM8960_write(ADCLPATH, 0x108); //0x20(R32)->0x108 ++ i2c_WM8960_write(ADCRPATH, 0x108); //0x21(R33)->0x108 ++ i2c_WM8960_write(BYPASS1, 0x80); //0x2d(R45)->0x80 ++ i2c_WM8960_write(BYPASS2, 0x80); //0x2e(R46)->0x80 ++ i2c_WM8960_write(LOUT1, 0x179); // 0x02(R2)->0x179 ++ i2c_WM8960_write(ROUT1, 0x179); // 0x03(R3)->0x179 ++} ++EXPORT_SYMBOL(audiohw_set_frequency); ++EXPORT_SYMBOL(audiohw_close); ++EXPORT_SYMBOL(audiohw_postinit); ++EXPORT_SYMBOL(audiohw_preinit); ++EXPORT_SYMBOL(audiohw_set_apll); ++EXPORT_SYMBOL(audiohw_codec_exlbk); ++EXPORT_SYMBOL(audiohw_bypass); ++EXPORT_SYMBOL(audiohw_set_lineout_vol); ++EXPORT_SYMBOL(audiohw_set_linein_vol); ++EXPORT_SYMBOL(audiohw_micin); ++EXPORT_SYMBOL(audiohw_mute); ++EXPORT_SYMBOL(audiohw_loopback); ++EXPORT_SYMBOL(audiohw_micboost); ++ ++static int codec_wm8960_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) ++{ ++ struct wm8960_data *wm; ++ ++printk("*******Enter %s********\n", __func__); ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) ++ return -EIO; ++ ++ wm = devm_kzalloc(&client->dev, sizeof(struct wm8960_data), GFP_KERNEL); ++ if (!wm) ++ return -ENOMEM; ++ ++#if defined(CONFIG_ARCH_MT7623) ++ mt_set_gpio_mode(GPIO242, GPIO_MODE_04); ++ mt_set_gpio_mode(GPIO243, GPIO_MODE_04); ++#endif ++ wm->client = client; ++ wm->dev = &client->dev; ++ wm->name = id->name; ++ i2c_set_clientdata(client, wm); ++ wmio = wm; ++ ++ memset(wm_reg_data, 0 , sizeof(unsigned long)*55); ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) ++static int codec_wm8960_i2c_remove(struct i2c_client *client) ++#else ++static int __devexit codec_wm8960_i2c_remove(struct i2c_client *client) ++#endif ++{ ++ struct wm8960_data *wm = i2c_get_clientdata(client); ++ kfree(wm); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id wm8960_id[] = { ++ { "codec_wm8960", 0 }, ++ {} ++}; ++ ++static struct i2c_driver codec_wm8960_i2c_driver = { ++ .driver = { ++ .name = "codec_wm8960" ++ }, ++ .probe = codec_wm8960_i2c_probe, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) ++ .remove = codec_wm8960_i2c_remove, ++#else ++ .remove = __devexit_p(codec_wm8960_i2c_remove), ++#endif ++ .id_table = wm8960_id, ++}; ++static int __init wm8960_i2c_init(void) ++{ ++#if defined(CONFIG_ARCH_MT7623) ++ i2c_register_board_info(1, &i2c_devs1, 1); ++#endif ++ return i2c_add_driver(&codec_wm8960_i2c_driver);; ++} ++ ++static void __exit wm8960_i2c_exit(void) ++{ ++ i2c_del_driver(&codec_wm8960_i2c_driver); ++} ++ ++module_init(wm8960_i2c_init); ++module_exit(wm8960_i2c_exit); ++ ++MODULE_AUTHOR("Ryder Lee <ryder.lee@mediatek.com>"); ++MODULE_DESCRIPTION("WM8960 I2C client driver"); ++MODULE_LICENSE("GPL"); ++ +--- /dev/null ++++ b/sound/soc/mtk/i2c_wm8960.h +@@ -0,0 +1,288 @@ ++/* wm8960.h -- WM8960 Soc Audio driver */ ++#ifndef _WM8960_H ++#define _WM8960_H ++ ++#define bool unsigned char ++#define false 0 ++#define true 1 ++ ++/* volume/balance/treble/bass interdependency */ ++#define VOLUME_MIN -730 ++#define VOLUME_MAX 60 ++ ++ ++/* Register addresses and bits */ ++#define OUTPUT_MUTED 0x2f ++#define OUTPUT_0DB 0x79 ++ ++#define LINV 0x00 ++#define LINV_IPVU (1 << 8) /* FIXME */ ++#define LINV_LINMUTE (1 << 7) ++#define LINV_LIZC (1 << 6) ++#define LINV_LINVOL(x) ((x) & 0x3f) ++ ++#define RINV 0x01 ++#define RINV_IPVU (1 << 8) /* FIXME */ ++#define RINV_RINMUTE (1 << 7) ++#define RINV_RIZC (1 << 6) ++#define RINV_RINVOL(x) ((x) & 0x3f) ++ ++#define LOUT1 0x02 ++#define LOUT1_LO1VU (1 << 8) ++#define LOUT1_LO1ZC (1 << 7) ++#define LOUT1_LOUT1VOL(x) ((x) & 0x7f) ++ ++#define ROUT1 0x03 ++#define ROUT1_RO1VU (1 << 8) ++#define ROUT1_RO1ZC (1 << 7) ++#define ROUT1_ROUT1VOL(x) ((x) & 0x7f) ++ ++#define CLOCKING1 0x04 /* FIXME */ ++#define CLOCKING1_ADCDIV(x) (((x) & 0x7) << 6) ++#define CLOCKING1_DACDIV(x) (((x) & 0x7) << 3) ++#define CLOCKING1_SYSCLKDIV_1 (0 << 1) ++#define CLOCKING1_SYSCLKDIV_2 (2 << 1) ++#define CLOCKING1_CLKSEL_MCLK (0 << 0) ++#define CLOCKING1_CLKSEL_PLL (1 << 0) ++ ++#define DACCTRL1 0x05 ++#define DACCTRL1_DATTENUATE (1 << 7) ++#define DACCTRL1_DACMU (1 << 3) ++#define DACCTRL1_DEEMPH_48 (3 << 1) ++#define DACCTRL1_DEEMPH_44 (2 << 1) ++#define DACCTRL1_DEEMPH_32 (1 << 1) ++#define DACCTRL1_DEEMPH_NONE (0 << 1) ++#define DACCTRL1_DEEMPH(x) ((x) & (0x3 << 1)) ++ ++#define DACCTRL2 0x06 ++ ++#define AINTFCE1 0x07 ++#define AINTFCE1_BCLKINV (1 << 7) ++#define AINTFCE1_MS (1 << 6) ++#define AINTFCE1_LRSWAP (1 << 5) ++#define AINTFCE1_LRP (1 << 4) ++#define AINTFCE1_WL_32 (3 << 2) ++#define AINTFCE1_WL_24 (2 << 2) ++#define AINTFCE1_WL_20 (1 << 2) ++#define AINTFCE1_WL_16 (0 << 2) ++#define AINTFCE1_WL(x) (((x) & 0x3) << 2) ++#define AINTFCE1_FORMAT_DSP (3 << 0) ++#define AINTFCE1_FORMAT_I2S (2 << 0) ++#define AINTFCE1_FORMAT_LJUST (1 << 0) ++#define AINTFCE1_FORMAT_RJUST (0 << 0) ++#define AINTFCE1_FORMAT(x) ((x) & 0x3) ++ ++/* FIXME */ ++#define CLOCKING2 0x08 ++#define CLOCKING2_DCLKDIV(x) (((x) & 0x7) << 6) ++#define CLOCKING2_BCLKDIV(x) (((x) & 0xf) << 0) ++ ++#define AINTFCE2 0x09 ++#define AINTFCE2_ALRCGPIO_ALRC (0 << 6) ++#define AINTFCE2_ALRCGPIO_GPIO (1 << 6) ++#define AINTFCE2_LOOPBACK (1 << 0) ++ ++#define LEFTGAIN 0x0a ++#define LEFTGAIN_LDVU (1 << 8) ++#define LEFTGAIN_LDACVOL(x) ((x) & 0xff) ++ ++#define RIGHTGAIN 0x0b ++#define RIGHTGAIN_RDVU (1 << 8) ++#define RIGHTGAIN_RDACVOL(x) ((x) & 0xff) ++ ++#define RESET 0x0f ++#define RESET_RESET 0x000 ++ ++#define ALC1 0x11 ++#define ALC1_ALCOFF (0x0 << 7) ++#define ALC1_ALCRONLY (0x1 << 7) ++#define ALC1_ALCLONLY (0x2 << 7) ++#define ALC1_ALCSTEREO (0x3 << 7) ++#define ALC1_ALCSEL(x) (((x) & 0x3) << 7) ++#define ALC1_SET_MAXGAIN(x) ((x & 0x7) << 4) ++#define ALC1_GET_MAXGAIN(x) ((x) & (0x7 << 4)) ++#define ALC1_ALCL(x) ((x) & 0x0f) ++ ++#define ALC2 0x12 ++#define ALC2_MINGAIN(x) ((x & 0x7) << 4) ++#define ALC2_HLD(x) ((x) & 0x0f) ++ ++#define ALC3 0x13 ++#define ALC3_SET_DCY(x) ((x & 0x0f) << 4) ++#define ALC3_GET_DCY(x) ((x) & (0x0f << 4)) ++#define ALC3_ATK(x) ((x) & 0x0f) ++ ++#define NOISEGATE 0x14 ++#define NOISEGATE_SET_NGTH(x) ((x & 0x1f) << 3) ++#define NOISEGATE_GET_NGTH(x) ((x) & (0x1f << 3)) ++#define NOISEGATE_NGAT_ENABLE 1 ++ ++#define LADCVOL 0x15 ++#define LADCVOL_LAVU_EN (1 << 8) ++#define LADCVOL_LADCVOL(x) ((x) & 0x0ff) ++ ++#define RADCVOL 0x16 ++#define RADCVOL_RAVU_EN (1 << 8) ++#define RADCVOL_RADCVOL(x) ((x) & 0x0ff) ++ ++#define ADDITIONAL1 0x17 ++#define ADDITIONAL1_TSDEN (1 << 8) ++#define ADDITIONAL1_VSEL_LOWEST (0 << 6) ++#define ADDITIONAL1_VSEL_LOW (1 << 6) ++#define ADDITIONAL1_VSEL_DEFAULT2 (2 << 6) ++#define ADDITIONAL1_VSEL_DEFAULT (3 << 6) ++#define ADDITIONAL1_VSEL(x) (((x) & 0x3) << 6) ++#define ADDITIONAL1_DMONOMIX_STEREO (0 << 4) ++#define ADDITIONAL1_DMONOMIX_MONO (1 << 4) ++#define ADDITIONAL1_DATSEL(x) (((x) & 0x3) << 2) ++#define ADDITIONAL1_TOCLKSEL (1 << 1) ++#define ADDITIONAL1_TOEN (1 << 0) ++ ++#define ADDITIONAL2 0x18 ++#define ADDITIONAL2_HPSWEN (1 << 6) ++#define ADDITIONAL2_HPSWPOL (1 << 5) ++#define ADDITIONAL2_TRIS (1 << 3) ++#define ADDITIONAL2_LRCM_ON (1 << 2) ++ ++#define PWRMGMT1 0x19 ++#define PWRMGMT1_VMIDSEL_DISABLED (0 << 7) ++#define PWRMGMT1_VMIDSEL_50K (1 << 7) ++#define PWRMGMT1_VMIDSEL_250K (2 << 7) ++#define PWRMGMT1_VMIDSEL_5K (3 << 7) ++#define PWRMGMT1_VREF (1 << 6) ++#define PWRMGMT1_AINL (1 << 5) ++#define PWRMGMT1_AINR (1 << 4) ++#define PWRMGMT1_ADCL (1 << 3) ++#define PWRMGMT1_ADCR (1 << 2) ++#define PWRMGMT1_MICB (1 << 1) ++#define PWRMGMT1_DIGENB (1 << 0) ++ ++#define PWRMGMT2 0x1a ++#define PWRMGMT2_DACL (1 << 8) ++#define PWRMGMT2_DACR (1 << 7) ++#define PWRMGMT2_LOUT1 (1 << 6) ++#define PWRMGMT2_ROUT1 (1 << 5) ++#define PWRMGMT2_SPKL (1 << 4) ++#define PWRMGMT2_SPKR (1 << 3) ++#define PWRMGMT2_OUT3 (1 << 1) ++#define PWRMGMT2_PLL_EN (1 << 0) ++ ++#define ADDITIONAL3 0x1b ++#define ADDITIONAL3_VROI (1 << 6) ++#define ADDITIONAL3_OUT3CAP (1 << 3) ++#define ADDITIONAL3_ADC_ALC_SR(x) ((x) & 0x7) ++ ++#define ANTIPOP1 0x1c ++#define ANTIPOP2 0x1d ++ ++#define ADCLPATH 0x20 ++#define ADCLPATH_LMN1 (1 << 8) ++#define ADCLPATH_LMP3 (1 << 7) ++#define ADCLPATH_LMP2 (1 << 6) ++#define ADCLPATH_LMICBOOST_29DB (0x3 << 4) ++#define ADCLPATH_LMICBOOST_20DB (0x2 << 4) ++#define ADCLPATH_LMICBOOST_13DB (0x1 << 4) ++#define ADCLPATH_SET_LMICBOOST(x) ((x & 0x3) << 4) ++#define ADCLPATH_LMIC2B (1 << 3) ++ ++ ++#define ADCRPATH 0x21 ++#define ADCRPATH_RMN1 (1 << 8) ++#define ADCRPATH_RMP3 (1 << 7) ++#define ADCRPATH_RMP2 (1 << 6) ++#define ADCRPATH_RMICBOOST_29DB (0x3 << 4) ++#define ADCRPATH_RMICBOOST_20DB (0x2 << 4) ++#define ADCRPATH_RMICBOOST_13DB (0x1 << 4) ++#define ADCRPATH_SET_RMICBOOST(x) ((x & 0x3) << 4) ++#define ADCRPATH_RMIC2B (1 << 3) ++ ++ ++#define LEFTMIX1 0x22 ++#define LEFTMIX1_LD2LO (1 << 8) ++#define LEFTMIX1_LI2LO (1 << 7) ++#define LEFTMIX1_LI2LO_DEFAULT (5 << 4) ++#define LEFTMIX1_LI2LOVOL(x) (((x) & 0x7) << 4) ++ ++#define RIGHTMIX2 0x25 ++#define RIGHTMIX2_RD2RO (1 << 8) ++#define RIGHTMIX2_RI2RO (1 << 7) ++#define RIGHTMIX2_RI2RO_DEFAULT (5 << 4) ++#define RIGHTMIX2_RI2ROVOL(x) (((x) & 0x7) << 4) ++ ++#define MONOMIX1 0x26 ++#define MONOMIX1_L2MO (1 << 7) ++ ++#define MONOMIX2 0x27 ++#define MONOMIX2_R2MO (1 << 7) ++ ++#define LSPK 0x28 ++#define LSPK_SPKLVU (1 << 8) ++#define LSPK_SPKLZC (1 << 7) ++#define LSPK_SPKLVOL(x) ((x) & 0x7f) ++ ++#define RSPK 0x29 ++#define RSPK_SPKRVU (1 << 8) ++#define RSPK_SPKRZC (1 << 7) ++#define RSPK_SPKRVOL(x) ((x) & 0x7f) ++ ++#define OUT3V 0x2a ++#define LINBMIX 0x2b ++#define RINBMIX 0x2c ++#define BYPASS1 0x2d ++#define BYPASS2 0x2e ++ ++#define PWRMGMT3 0x2f ++#define PWRMGMT3_LMIC (1<<5) ++#define PWRMGMT3_RMIC (1<<4) ++#define PWRMGMT3_LOMIX (1<<3) ++#define PWRMGMT3_ROMIX (1<<2) ++ ++#define ADDITIONAL4 0x30 ++ ++#define CLASSDCTRL1 0x31 ++#define CLASSDCTRL1_OP_OFF (0<<6) ++#define CLASSDCTRL1_OP_LSPK (1<<6) ++#define CLASSDCTRL1_OP_RSPK (2<<6) ++#define CLASSDCTRL1_OP_LRSPK (3<<6) ++ ++#define CLASSDCTRL3 0x33 ++ ++#define PLL1 0x34 ++#define PLL1_OPCLKDIV_1 (0<<6) ++#define PLL1_OPCLKDIV_2 (1<<6) ++#define PLL1_OPCLKDIV_3 (2<<6) ++#define PLL1_OPCLKDIV_4 (3<<6) ++#define PLL1_OPCLKDIV_5p5 (4<<6) ++#define PLL1_OPCLKDIV_6 (5<<6) ++#define PLL1_SDM_INTERGER (0<<5) ++#define PLL1_SDM_FRACTIONAL (1<<5) ++#define PLL1_PLLPRESCALE_1 (0<<4) ++#define PLL1_PLLPRESCALE_2 (1<<4) ++#define PLL1_PLLN(x) ((x) & 0xf) ++ ++#define PLL2 0x35 ++#define PLL2_PLLK_23_16(x) ((x) & 0x1ff) ++ ++#define PLL3 0x36 ++#define PLL3_PLLK_15_8(x) ((x) & 0x1ff) ++ ++#define PLL4 0x37 ++#define PLL4_PLLK_7_0(x) ((x) & 0x1ff) ++ ++/* codec API */ ++void audiohw_preinit(void); ++int audiohw_postinit(int bSlave, int AIn, int AOut, int pll_en, int wordLen24b); ++void audiohw_close(void); ++void audiohw_set_frequency(int fsel, int pll_en); ++void audiohw_mute(bool mute); ++void audiohw_micboost(int boostgain); ++void audiohw_micin(int enableMic); ++void audiohw_set_apll(int srate); ++int audiohw_set_lineout_vol(int Aout, int vol_l, int vol_r); ++int audiohw_set_linein_vol(int vol_l, int vol_r); ++void audiohw_mute( bool mute); ++void audiohw_loopback(int fsel); ++void audiohw_codec_exlbk(void); ++void audiohw_bypass(void); ++ ++#endif /* _WM875x_H */ +--- /dev/null ++++ b/sound/soc/mtk/i2s_ctrl.c +@@ -0,0 +1,3524 @@ ++#include <linux/init.h> ++#include <linux/version.h> ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++#include <linux/sched.h> ++#endif ++#include <linux/module.h> ++#include <linux/kernel.h> /* _printk() */ ++#include <linux/slab.h> /* kmalloc() */ ++#include <linux/fs.h> /* everything... */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/proc_fs.h> ++#include <linux/fcntl.h> /* O_ACCMODE */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,14) ++#include <asm/system.h> /* cli(), *_flags */ ++#endif ++#include <asm/uaccess.h> /* copy_from/to_user */ ++#include <linux/interrupt.h> ++#include <linux/mm.h> ++#include <linux/mm_types.h> ++#include <linux/pci.h> ++#include <linux/delay.h> ++#include "ralink_gdma.h" ++#if defined(CONFIG_I2S_WITH_AEC) ++#include "../aec/aec_api.h" ++#endif ++ ++#ifdef CONFIG_DEVFS_FS ++#include <linux/devfs_fs_kernel.h> ++static devfs_handle_t devfs_handle; ++#endif ++ ++#include "i2s_ctrl.h" ++ ++#if defined(CONFIG_SND_MT76XX_SOC) ++#include <sound/soc/mtk/mt76xx_machine.h> ++#endif ++ ++#if defined(CONFIG_I2S_WM8750) ++#include "../codec/i2c_wm8750.h" ++#endif ++#if defined(CONFIG_I2S_WM8751) ++#include "../codec/i2c_wm8751.h" ++#endif ++#if defined(CONFIG_I2S_WM8960) ++#include "i2c_wm8960.h" ++#endif ++ ++static int i2sdrv_major = 191; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++#else ++static struct class *i2smodule_class; ++#endif ++ ++static int _printk(char *fmt, ...) ++{ ++ return 0; ++} ++ ++/* external functions declarations */ ++#if defined(CONFIG_I2S_WM8960) ++extern void audiohw_set_frequency(int fsel, int codec_pll_en); ++void audiohw_set_apll(int srate); ++#elif defined(CONFIG_I2S_WM8750)||defined(CONFIG_I2S_WM8751) ++extern void audiohw_set_frequency(int fsel); ++#endif ++#if defined(CONFIG_I2S_WM8960)||defined(CONFIG_I2S_WM8750)||defined(CONFIG_I2S_WM8751) ++extern int audiohw_set_lineout_vol(int Aout, int vol_l, int vol_r); ++extern int audiohw_set_master_vol(int vol_l, int vol_r); ++extern int audiohw_set_linein_vol(int vol_l, int vol_r); ++#endif ++ ++extern void audiohw_micboost(int boostgain); ++ ++extern int GdmaI2sTx(uint32_t Src, uint32_t Dst, uint8_t TxNo, uint16_t TransCount, ++ void (*DoneIntCallback)(uint32_t data), ++ void (*UnMaskIntCallback)(uint32_t data)); ++ ++extern int GdmaI2sRx(uint32_t Src, uint32_t Dst, uint8_t RxNo, uint16_t TransCount, ++ void (*DoneIntCallback)(uint32_t data), ++ void (*UnMaskIntCallback)(uint32_t data)); ++ ++extern int GdmaMaskChannel(uint32_t ChNum); ++ ++extern int GdmaUnMaskChannel(uint32_t ChNum); ++ ++/* internal functions declarations */ ++irqreturn_t i2s_irq_isr(int irq, void *irqaction); ++int i2s_debug_cmd(unsigned int cmd, unsigned long arg); ++ ++/* forward declarations for _fops */ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++static long i2s_ioctl(struct file *file, unsigned int cmd, unsigned long arg); ++#else ++static int i2s_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); ++#endif ++static int i2s_mmap(struct file *file, struct vm_area_struct *vma); ++static int i2s_open(struct inode *inode, struct file *file); ++static int i2s_release(struct inode *inode, struct file *file); ++int i2s_mmap_alloc(unsigned long size); ++int i2s_mmap_remap(struct vm_area_struct *vma, unsigned long size); ++ ++/* global varable definitions */ ++i2s_config_type i2s_config; ++i2s_status_type i2s_status; ++i2s_config_type* pi2s_config = &i2s_config;; ++i2s_status_type* pi2s_status = &i2s_status;; ++ ++static inline long ++ugly_hack_sleep_on_timeout(wait_queue_head_t *q, long timeout) ++{ ++ unsigned long flags; ++ wait_queue_t wait; ++ ++ init_waitqueue_entry(&wait, current); ++ ++ __set_current_state(TASK_INTERRUPTIBLE); ++ spin_lock_irqsave(&q->lock, flags); ++ __add_wait_queue(q, &wait); ++ spin_unlock(&q->lock); ++ ++ timeout = schedule_timeout(timeout); ++ ++ spin_lock_irq(&q->lock); ++ __remove_wait_queue(q, &wait); ++ spin_unlock_irqrestore(&q->lock, flags); ++ ++ return timeout; ++} ++ ++#define interruptible_sleep_on(x) \ ++ ugly_hack_sleep_on_timeout(x, MAX_SCHEDULE_TIMEOUT); ++ ++ ++#if defined(ARM_ARCH) ++static dma_addr_t i2s_txdma_addr0, i2s_txdma_addr1; ++static dma_addr_t i2s_rxdma_addr0, i2s_rxdma_addr1; ++#define I2S_TX_FIFO_WREG_PHY (I2S_TX_FIFO_WREG & 0x1FFFFFFF) ++#define I2S_RX_FIFO_RREG_PHY (I2S_RX_FIFO_RREG & 0x1FFFFFFF) ++#else ++static dma_addr_t i2s_txdma_addr, i2s_rxdma_addr; ++#endif ++static dma_addr_t i2s_mmap_addr[MAX_I2S_PAGE*2]; ++ /* 8khz 11.025khz 12khz 16khz 22.05khz 24Khz 32khz 44.1khz 48khz 88.2khz 96khz*/ ++unsigned long i2s_inclk_15p625Mhz[11] = {60<<8, 43<<8, 40<<8, 30<<8, 21<<8, 19<<8, 14<<8, 10<<8, 9<<8, 7<<8, 4<<8}; ++unsigned long i2s_exclk_12p288Mhz[11] = {47<<8, 34<<8, 31<<8, 23<<8, 16<<8, 15<<8, 11<<8, 8<<8, 7<<8, 5<<8, 3<<8}; ++unsigned long i2s_exclk_12Mhz[11] = {46<<8, 33<<8, 30<<8, 22<<8, 16<<8, 15<<8, 11<<8, 8<<8, 7<<8, 5<<8, 3<<8}; ++#if defined(CONFIG_I2S_WM8750) || defined(CONFIG_SND_SOC_WM8750) ++ /* 8k 11.025k 12k 16k 22.05k 24k 32k 44.1k 48k 88.2k 96k*/ ++unsigned long i2s_codec_12p288Mhz[11] = {0x0C, 0x00, 0x10, 0x14, 0x38, 0x38, 0x18, 0x20, 0x00, 0x00, 0x1C}; ++unsigned long i2s_codec_12Mhz[11] = {0x0C, 0x32, 0x10, 0x14, 0x37, 0x38, 0x18, 0x22, 0x00, 0x3E, 0x1C}; ++unsigned long i2s_codec_24p576Mhz[11] = {0x4C, 0x00, 0x50, 0x54, 0x00, 0x78, 0x58, 0x00, 0x40, 0x00, 0x5C}; ++unsigned long i2s_codec_18p432Mhz[11] = {0x0e, 0x32, 0x12, 0x16, 0x36, 0x3a, 0x1a, 0x22, 0x02, 0x3e, 0x1e}; ++#endif ++#if defined(CONFIG_I2S_WM8751) || defined(CONFIG_SND_SOC_WM8751) ++unsigned long i2s_codec_12p288Mhz[11] = {0x04, 0x00, 0x10, 0x14, 0x38, 0x38, 0x18, 0x20, 0x00, 0x00, 0x1C}; ++unsigned long i2s_codec_12Mhz[11] = {0x04, 0x32, 0x10, 0x14, 0x37, 0x38, 0x18, 0x22, 0x00, 0x3E, 0x1C}; ++#endif ++#if defined(CONFIG_I2S_WM8960) || defined(CONFIG_SND_SOC_WM8960) ++unsigned long i2s_codec_12p288Mhz[11] = {0x36, 0x24, 0x24, 0x1b, 0x12, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00}; ++unsigned long i2s_codec_12Mhz[11] = {0x36, 0x24, 0x24, 0x1b, 0x12, 0x12, 0x09, 0x00, 0x00, 0x00, 0x00}; ++#endif ++EXPORT_SYMBOL(i2s_codec_12p288Mhz); ++EXPORT_SYMBOL(i2s_codec_12Mhz); ++ ++#if defined(CONFIG_RALINK_RT6855A) ++ /* 8K 11.025k 12k 16k 22.05k 24k 32k 44.1K 48k 88.2k 96k */ ++unsigned long i2s_inclk_int[11] = { 97, 70, 65, 48, 35, 32, 24, 17, 16, 12, 8}; ++unsigned long i2s_inclk_comp[11] = { 336, 441, 53, 424, 220, 282, 212, 366, 141, 185, 70}; ++#elif defined (CONFIG_RALINK_MT7621) ++#ifdef MT7621_ASIC_BOARD ++#if defined (CONFIG_I2S_MCLK_12P288MHZ) ++unsigned long i2s_inclk_int[11] = { 576, 384, 0, 288, 192, 192, 144, 96, 96, 48, 48}; ++unsigned long i2s_inclk_comp[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; ++#elif defined(CONFIG_I2S_MCLK_12MHZ) ++unsigned long i2s_inclk_int[11] = {1171, 850, 0, 585, 425, 390, 292, 212, 195, 106, 97}; ++unsigned long i2s_inclk_comp[11] = { 448, 174, 0, 480, 87, 320, 496, 299, 160, 149, 336}; ++#endif ++#else //MT7621_FPGA_BOARD ++unsigned long i2s_inclk_int[11] = { 529, 384, 0, 264, 192, 176, 132, 96, 88, 48, 44}; ++unsigned long i2s_inclk_comp[11] = { 102, 0, 0, 307, 0, 204, 153, 0, 102, 0, 51}; ++#endif ++#elif defined (CONFIG_RALINK_MT7628) ++#ifdef MT7628_ASIC_BOARD ++ /* 8K 11.025k 12k 16k 22.05k 24k 32k 44.1K 48k 88.2k 96k 176k 192k */ ++unsigned long i2s_inclk_int_16bit[13] = {937, 680, 0, 468, 340, 312, 234, 170, 156, 85, 78, 42, 39}; ++unsigned long i2s_inclk_comp_16bit[13]= {256, 139, 0, 384, 69, 256, 192, 34, 128, 17, 64, 267, 32}; ++unsigned long i2s_inclk_int_24bit[13] = {625, 404, 0, 312, 226, 208, 156, 113, 104, 56, 52, 28, 26}; ++unsigned long i2s_inclk_comp_24bit[13]= { 0, 404, 0, 256, 387, 170, 128, 193, 85, 352, 42, 176, 21}; ++#else ++ /* 8K 11.025k 12k 16k 22.05k 24k 32k 44.1K 48k 88.2k 96k 176k 192k */ ++unsigned long i2s_inclk_int_16bit[13] = {468, 340, 0, 234, 170, 156, 117, 85, 78, 42, 39, 21, 19}; ++unsigned long i2s_inclk_comp_16bit[13]= {384, 69, 0, 192, 34, 128, 96, 17, 64, 264, 32, 133, 272}; ++unsigned long i2s_inclk_int_24bit[13] = {312, 202, 0, 156, 113, 104, 78, 56, 52, 28, 26, 14, 13}; ++unsigned long i2s_inclk_comp_24bit[13]= {256, 202, 0, 128, 193, 85, 64, 352, 42, 176, 21, 88, 10}; ++#endif ++#elif defined (CONFIG_ARCH_MT7623) ++#if defined MT7623_ASIC_BOARD ++ /* 8K 11.025k 12k 16k 22.05k 24k 32k 44.1K 48k 88.2k 96k 176k 192k */ ++unsigned long i2s_inclk_int_16bit[13] = {576, 384, 0, 288, 192, 192, 144, 96, 96, 48, 48, 24, 24}; ++unsigned long i2s_inclk_comp_16bit[13]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; ++unsigned long i2s_inclk_int_24bit[13] = {384, 256, 0, 192, 128, 128, 96, 64, 64, 32, 32, 16, 16}; ++unsigned long i2s_inclk_comp_24bit[13]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; ++#else ++ /* 8K 11.025k 12k 16k 22.05k 24k 32k 44.1K 48k 88.2k 96k 176k 192k */ ++unsigned long i2s_inclk_int_16bit[13] = {72, 48, 0, 36, 24, 24, 18, 12, 12, 6, 6, 3, 3}; ++unsigned long i2s_inclk_comp_16bit[13]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; ++unsigned long i2s_inclk_int_24bit[13] = {48, 32, 0, 24, 16, 16, 12, 8, 8, 4, 4, 2, 2}; ++unsigned long i2s_inclk_comp_24bit[13]= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; ++#endif ++#else ++ /* 8K 11.025k 12k 16k 22.05k 24k 32k 44.1K 48k 88.2k 96k */ ++unsigned long i2s_inclk_int[11] = { 78, 56, 52, 39, 28, 26, 19, 14, 13, 9, 6}; ++unsigned long i2s_inclk_comp[11] = { 64, 352, 42, 32, 176, 21, 272, 88, 10, 455, 261}; ++#endif ++ ++#if defined(CONFIG_I2S_WITH_AEC) ++aecFuncTbl_t *aecFuncP; ++#endif ++/* USB mode 22.05Khz register value in datasheet is 0x36 but will cause slow clock, 0x37 is correct value */ ++/* USB mode 44.1Khz register value in datasheet is 0x22 but will cause slow clock, 0x23 is correct value */ ++ ++struct tasklet_struct i2s_tx_tasklet; ++struct tasklet_struct i2s_rx_tasklet; ++EXPORT_SYMBOL(i2s_tx_tasklet); ++EXPORT_SYMBOL(i2s_rx_tasklet); ++ ++char test_buf[I2S_PAGE_SIZE]; ++char test_buf_1[I2S_PAGE_SIZE]; ++char test_buf_2[I2S_PAGE_SIZE]; ++ ++static const struct file_operations i2s_fops = { ++ owner : THIS_MODULE, ++ mmap : i2s_mmap, ++ open : i2s_open, ++ release : i2s_release, ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ unlocked_ioctl: i2s_ioctl, ++#else ++ ioctl : i2s_ioctl, ++#endif ++}; ++ ++int __init i2s_mod_init(void) ++{ ++ int result; ++ ++ _printk("******* i2s module init **********\n"); ++ /* register device with kernel */ ++#ifdef CONFIG_DEVFS_FS ++ if(devfs_register_chrdev(i2sdrv_major, I2SDRV_DEVNAME , &i2s_fops)) { ++ _printk(KERN_WARNING " i2s: can't create device node - %s\n", I2SDRV_DEVNAME); ++ return -EIO; ++ } ++ ++ devfs_handle = devfs_register(NULL, I2SDRV_DEVNAME, DEVFS_FL_DEFAULT, i2sdrv_major, 0, ++ S_IFCHR | S_IRUGO | S_IWUGO, &i2s_fops, NULL); ++#else ++ result = register_chrdev(i2sdrv_major, I2SDRV_DEVNAME, &i2s_fops); ++ if (result < 0) { ++ _printk(KERN_WARNING "i2s: can't get major %d\n",i2sdrv_major); ++ return result; ++ } ++ ++ if (i2sdrv_major == 0) { ++ i2sdrv_major = result; /* dynamic */ ++ } ++#endif ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++#else ++ i2smodule_class=class_create(THIS_MODULE, I2SDRV_DEVNAME); ++ if (IS_ERR(i2smodule_class)) ++ return -EFAULT; ++ device_create(i2smodule_class, NULL, MKDEV(i2sdrv_major, 0), I2SDRV_DEVNAME); ++#endif ++ ++#if defined(CONFIG_I2S_WITH_AEC) ++ _printk("AEC FuncP init \n"); ++ /*Add by mtk04880*/ ++ aecFuncP = kmalloc(sizeof(aecFuncTbl_t), GFP_KERNEL); ++ /*If aecFuncP cannot request memory,it will be ignored in I2S module. Since AEC & I2S are independent ++ * when AEC module is inserted,It will return err message (but I2S will keep running without AEC support) ++ * */ ++ if(aecFuncP){ ++ memset(aecFuncP,0,sizeof(aecFuncTbl_t)); ++ } ++#endif ++ ++ return 0; ++} ++ ++void i2s_mod_exit(void) ++{ ++ _printk("************ i2s module exit *************\n"); ++#ifdef CONFIG_DEVFS_FS ++ devfs_unregister_chrdev(i2sdrv_major, I2SDRV_DEVNAME); ++ devfs_unregister(devfs_handle); ++#else ++ unregister_chrdev(i2sdrv_major, I2SDRV_DEVNAME); ++#endif ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++#else ++ device_destroy(i2smodule_class,MKDEV(i2sdrv_major, 0)); ++ class_destroy(i2smodule_class); ++#endif ++ return ; ++} ++ ++ ++int i2s_open(struct inode *inode, struct file *filp) ++{ ++#if defined(I2S_HW_INTERRUPT_EN)&&(I2S_SW_IRQ_EN) ++ int Ret; ++#endif ++ int minor = iminor(inode); ++ ++ if (minor >= I2S_MAX_DEV) ++ return -ENODEV; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ++ MOD_INC_USE_COUNT; ++#else ++ try_module_get(THIS_MODULE); ++#endif ++ ++ if (filp->f_flags & O_NONBLOCK) { ++ MSG("filep->f_flags O_NONBLOCK set\n"); ++ return -EAGAIN; ++ } ++ ++ /* set i2s_config */ ++ filp->private_data = pi2s_config; ++ memset(pi2s_config, 0, sizeof(i2s_config_type)); ++#ifdef I2S_STATISTIC ++ memset(pi2s_status, 0, sizeof(i2s_status_type)); ++#endif ++ i2s_param_init(pi2s_config); ++ ++#if defined(I2S_HW_INTERRUPT_EN)&&(I2S_SW_IRQ_EN) ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ Ret = request_irq(SURFBOARDINT_I2S, i2s_irq_isr, IRQF_DISABLED, "Ralink_I2S", NULL); ++#else ++ Ret = request_irq(SURFBOARDINT_I2S, i2s_irq_isr, SA_INTERRUPT, "Ralink_I2S", NULL); ++#endif ++ ++ if(Ret){ ++ MSG("IRQ %d is not free.\n", SURFBOARDINT_I2S); ++ i2s_release(inode, filp); ++ return -1; ++ } ++#endif ++ ++ init_waitqueue_head(&(pi2s_config->i2s_tx_qh)); ++ init_waitqueue_head(&(pi2s_config->i2s_rx_qh)); ++ spin_lock_init(&pi2s_config->lock); ++ ++ return 0; ++} ++ ++ ++static int i2s_release(struct inode *inode, struct file *filp) ++{ ++ i2s_config_type* ptri2s_config; ++ ++ /* decrement usage count */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ++ MOD_DEC_USE_COUNT; ++#else ++ module_put(THIS_MODULE); ++#endif ++ ++#if defined(I2S_HW_INTERRUPT_EN)&&(I2S_SW_IRQ_EN) ++ free_irq(SURFBOARDINT_I2S, NULL); ++#endif ++ ++ ptri2s_config = filp->private_data; ++ if(ptri2s_config==NULL) ++ goto EXIT; ++#ifdef CONFIG_I2S_MMAP ++ i2s_mem_unmap(ptri2s_config); ++#else ++ i2s_txbuf_free(ptri2s_config); ++ i2s_rxbuf_free(ptri2s_config); ++#endif ++ /* free buffer */ ++ i2s_txPagebuf_free(ptri2s_config); ++ i2s_rxPagebuf_free(ptri2s_config); ++EXIT: ++ MSG("i2s_release succeeds\n"); ++ return 0; ++} ++ ++int i2s_mmap_alloc(unsigned long size) ++{ ++ int i; ++ u32 page_size; ++ int first_index; ++ ++ page_size = I2S_PAGE_SIZE; ++ ++ if ((pi2s_config->mmap_index == 0) || (pi2s_config->mmap_index == MAX_I2S_PAGE)) ++ { ++ MSG("mmap_index=%d\n", pi2s_config->mmap_index); ++ ++ first_index = pi2s_config->mmap_index; ++ pi2s_config->pMMAPBufPtr[pi2s_config->mmap_index] = kmalloc(size, GFP_DMA); ++ i2s_mmap_addr[pi2s_config->mmap_index] = (dma_addr_t)dma_map_single(NULL, pi2s_config->pMMAPBufPtr[pi2s_config->mmap_index], size, DMA_BIDIRECTIONAL); ++ ++ if( pi2s_config->pMMAPBufPtr[pi2s_config->mmap_index] == NULL ) ++ { ++ MSG("i2s_mmap failed\n"); ++ return -1; ++ } ++ } ++ else ++ { ++ _printk("illegal index:%d\n", pi2s_config->mmap_index); ++ return -1; ++ } ++ ++ _printk("MMAP[%d]=0x%08X, i2s_mmap_addr[%d]=0x%08x\n", ++ pi2s_config->mmap_index, (u32)pi2s_config->pMMAPBufPtr[pi2s_config->mmap_index], ++ pi2s_config->mmap_index, i2s_mmap_addr[pi2s_config->mmap_index]); ++ ++ memset(pi2s_config->pMMAPBufPtr[pi2s_config->mmap_index], 0, size); ++ pi2s_config->mmap_index++; ++ ++ for (i=1; i<MAX_I2S_PAGE; i++) ++ { ++ i2s_mmap_addr[pi2s_config->mmap_index] = i2s_mmap_addr[first_index] + i*page_size; ++ pi2s_config->pMMAPBufPtr[pi2s_config->mmap_index] = pi2s_config->pMMAPBufPtr[first_index] + i*page_size; ++ ++ _printk("MMAP[%d]=0x%08X, i2s_mmap_addr[%d]=0x%08x\n",pi2s_config->mmap_index, (u32)pi2s_config->pMMAPBufPtr[pi2s_config->mmap_index], pi2s_config->mmap_index, i2s_mmap_addr[pi2s_config->mmap_index]); ++ ++ /* Notice: The last mmap_index's value should be MAX_I2S_PAGE or MAX_I2S_PAGE*2 */ ++ pi2s_config->mmap_index++; ++ } ++ ++ return 0; ++} ++ ++int i2s_mmap_remap(struct vm_area_struct *vma, unsigned long size) ++{ ++ int nRet; ++ ++ if((pi2s_config->pMMAPBufPtr[0]!=NULL) && (pi2s_config->mmap_index == MAX_I2S_PAGE)) ++ { ++ MSG("i2s_mmap_remap:0\n"); ++ nRet = remap_pfn_range(vma, vma->vm_start, virt_to_phys((void *)pi2s_config->pMMAPBufPtr[0]) >> PAGE_SHIFT, size, vma->vm_page_prot); ++ ++ if( nRet != 0 ) ++ { ++ _printk("i2s_mmap->remap_pfn_range failed\n"); ++ return -EIO; ++ } ++ } ++ ++ if((pi2s_config->pMMAPBufPtr[MAX_I2S_PAGE]!=NULL) && (pi2s_config->mmap_index == MAX_I2S_PAGE*2)) ++ { ++ MSG("i2s_mmap_remap:%d\n", MAX_I2S_PAGE); ++ ++ nRet = remap_pfn_range(vma, vma->vm_start, virt_to_phys((void *)pi2s_config->pMMAPBufPtr[MAX_I2S_PAGE]) >> PAGE_SHIFT, size, vma->vm_page_prot); ++ ++ if( nRet != 0 ) ++ { ++ _printk("i2s_mmap->remap_pfn_range failed\n"); ++ return -EIO; ++ } ++ } ++ ++ return 0; ++} ++ ++static int i2s_mmap(struct file *filp, struct vm_area_struct *vma) ++{ ++ unsigned long size = vma->vm_end-vma->vm_start; ++ _printk("page_size=%d, ksize=%lu\n", I2S_PAGE_SIZE, size); ++ ++ if((pi2s_config->pMMAPBufPtr[0]==NULL)&&(pi2s_config->mmap_index!=0)) ++ pi2s_config->mmap_index = 0; ++ ++ _printk("%s: vm_start=%08X,vm_end=%08X\n", __func__, (u32)vma->vm_start, (u32)vma->vm_end); ++ ++ /* Do memory allocate and dma sync */ ++ i2s_mmap_alloc(size); ++ ++ i2s_mmap_remap(vma, size); ++ ++ ++ return 0; ++} ++ ++int i2s_mem_unmap(i2s_config_type* ptri2s_config) ++{ ++ u32 page_size; ++ ++ page_size = I2S_PAGE_SIZE; ++ ++ if(ptri2s_config->pMMAPBufPtr[0]) ++ { ++ _printk("ummap MMAP[0]=0x%08X\n", (u32)ptri2s_config->pMMAPBufPtr[0]); ++ dma_unmap_single(NULL, i2s_mmap_addr[0], MAX_I2S_PAGE*page_size, DMA_BIDIRECTIONAL); ++ kfree(ptri2s_config->pMMAPBufPtr[0]); ++ } ++ ++ if(ptri2s_config->pMMAPBufPtr[MAX_I2S_PAGE]) ++ { ++ _printk("ummap MMAP[%d]=0x%08X\n", MAX_I2S_PAGE, (u32)ptri2s_config->pMMAPBufPtr[MAX_I2S_PAGE]); ++ dma_unmap_single(NULL, i2s_mmap_addr[MAX_I2S_PAGE], MAX_I2S_PAGE*page_size, DMA_BIDIRECTIONAL); ++ kfree(ptri2s_config->pMMAPBufPtr[MAX_I2S_PAGE]); ++ } ++ ++ ptri2s_config->mmap_index = 0; ++ ++ return 0; ++} ++ ++int i2s_param_init(i2s_config_type* ptri2s_config) ++{ ++ ptri2s_config->dmach = GDMA_I2S_TX0; ++ ptri2s_config->tx_ff_thres = CONFIG_I2S_TFF_THRES; ++ ptri2s_config->tx_ch_swap = CONFIG_I2S_CH_SWAP; ++ ptri2s_config->rx_ff_thres = CONFIG_I2S_TFF_THRES; ++ ptri2s_config->rx_ch_swap = CONFIG_I2S_CH_SWAP; ++ ptri2s_config->slave_en = CONFIG_I2S_SLAVE_EN; ++ ptri2s_config->codec_pll_en = CONFIG_I2S_CODEC_PLL_EN; ++ ++ ptri2s_config->bRxDMAEnable = 0; ++ ptri2s_config->bTxDMAEnable = 0; ++ //ptri2s_config->bALSAEnable = 0; ++ ptri2s_config->srate = 44100; ++ ptri2s_config->txvol = 0; ++ ptri2s_config->rxvol = 0; ++ ptri2s_config->lbk = 0; ++ ptri2s_config->extlbk = 0; ++ ptri2s_config->txrx_coexist = 0; ++ ptri2s_config->wordlen_24b = 0; ++#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623) ++ ptri2s_config->sys_endian = 0; ++ ptri2s_config->fmt = 0; ++#endif ++ ptri2s_config->micboost = 0; ++ ptri2s_config->micin = 0; ++ ++ return 0; ++} ++ ++int i2s_txbuf_alloc(i2s_config_type* ptri2s_config) ++{ ++ int i; ++ ++ for( i = 0 ; i < MAX_I2S_PAGE ; i ++ ) ++ { ++#if defined(CONFIG_I2S_MMAP) ++ ptri2s_config->pMMAPTxBufPtr[i] = ptri2s_config->pMMAPBufPtr[i]; ++#else ++ if(ptri2s_config->pMMAPTxBufPtr[i]==NULL) ++ ptri2s_config->pMMAPTxBufPtr[i] = kmalloc(I2S_PAGE_SIZE, GFP_KERNEL); ++#endif ++ memset(ptri2s_config->pMMAPTxBufPtr[i], 0, I2S_PAGE_SIZE); ++ } ++ ++ return 0; ++} ++ ++int i2s_rxbuf_alloc(i2s_config_type* ptri2s_config) ++{ ++ int i; ++ ++ for( i = 0 ; i < MAX_I2S_PAGE ; i ++ ) ++ { ++#if defined(CONFIG_I2S_MMAP) ++ ptri2s_config->pMMAPRxBufPtr[i] = ptri2s_config->pMMAPBufPtr[i+(ptri2s_config->mmap_index-MAX_I2S_PAGE)]; ++#else ++ if(ptri2s_config->pMMAPRxBufPtr[i]==NULL) ++ ptri2s_config->pMMAPRxBufPtr[i] = kmalloc(I2S_PAGE_SIZE, GFP_KERNEL); ++#endif ++ memset(ptri2s_config->pMMAPRxBufPtr[i], 0, I2S_PAGE_SIZE); ++ } ++ ++ return 0; ++} ++ ++int i2s_txPagebuf_alloc(i2s_config_type* ptri2s_config) ++{ ++#if defined(ARM_ARCH) ++ ptri2s_config->pPage0TxBuf8ptr = (u8*)pci_alloc_consistent(NULL, I2S_PAGE_SIZE , &i2s_txdma_addr0); ++ ptri2s_config->pPage1TxBuf8ptr = (u8*)pci_alloc_consistent(NULL, I2S_PAGE_SIZE , &i2s_txdma_addr1); ++ if(ptri2s_config->pPage0TxBuf8ptr==NULL) ++ { ++ MSG("Allocate Tx Page0 Buffer Failed\n"); ++ return -1; ++ } ++ if(ptri2s_config->pPage1TxBuf8ptr==NULL) ++ { ++ MSG("Allocate Tx Page1 Buffer Failed\n"); ++ return -1; ++ } ++#else ++ ptri2s_config->pPage0TxBuf8ptr = (u8*)pci_alloc_consistent(NULL, I2S_PAGE_SIZE*2 , &i2s_txdma_addr); ++ if(ptri2s_config->pPage0TxBuf8ptr==NULL) ++ { ++ MSG("Allocate Tx Page Buffer Failed\n"); ++ return -1; ++ } ++ ptri2s_config->pPage1TxBuf8ptr = ptri2s_config->pPage0TxBuf8ptr + I2S_PAGE_SIZE; ++#endif ++ return 0; ++} ++ ++int i2s_rxPagebuf_alloc(i2s_config_type* ptri2s_config) ++{ ++#if defined(ARM_ARCH) ++ ptri2s_config->pPage0RxBuf8ptr = (u8*)pci_alloc_consistent(NULL, I2S_PAGE_SIZE, &i2s_rxdma_addr0); ++ ptri2s_config->pPage1RxBuf8ptr = (u8*)pci_alloc_consistent(NULL, I2S_PAGE_SIZE, &i2s_rxdma_addr1); ++ if(ptri2s_config->pPage0RxBuf8ptr==NULL) ++ { ++ MSG("Allocate Rx Page Buffer Failed\n"); ++ return -1; ++ } ++ if(ptri2s_config->pPage1RxBuf8ptr==NULL) ++ { ++ MSG("Allocate Rx Page Buffer Failed\n"); ++ return -1; ++ } ++#else ++ ptri2s_config->pPage0RxBuf8ptr = (u8*)pci_alloc_consistent(NULL, I2S_PAGE_SIZE*2 , &i2s_rxdma_addr); ++ if(ptri2s_config->pPage0RxBuf8ptr==NULL) ++ { ++ MSG("Allocate Rx Page Buffer Failed\n"); ++ return -1; ++ } ++ ptri2s_config->pPage1RxBuf8ptr = ptri2s_config->pPage0RxBuf8ptr + I2S_PAGE_SIZE; ++#endif ++ return 0; ++} ++ ++int i2s_txbuf_free(i2s_config_type* ptri2s_config) ++{ ++ int i; ++ ++ for(i = 0 ; i < MAX_I2S_PAGE ; i ++) ++ { ++ if(ptri2s_config->pMMAPTxBufPtr[i] != NULL) ++ { ++#if defined(CONFIG_I2S_MMAP) ++ ptri2s_config->pMMAPTxBufPtr[i] = NULL; ++#else ++ kfree(ptri2s_config->pMMAPTxBufPtr[i]); ++ ptri2s_config->pMMAPTxBufPtr[i] = NULL; ++#endif ++ } ++ } ++ return 0; ++} ++ ++int i2s_rxbuf_free(i2s_config_type* ptri2s_config) ++{ ++ int i; ++ ++ for(i = 0 ; i < MAX_I2S_PAGE ; i ++) ++ { ++ if(ptri2s_config->pMMAPRxBufPtr[i] != NULL) ++ { ++#if defined(CONFIG_I2S_MMAP) ++ ptri2s_config->pMMAPRxBufPtr[i] = NULL; ++#else ++ kfree(ptri2s_config->pMMAPRxBufPtr[i]); ++ ptri2s_config->pMMAPRxBufPtr[i] = NULL; ++#endif ++ } ++ } ++ ++ return 0; ++} ++ ++int i2s_txPagebuf_free(i2s_config_type* ptri2s_config) ++{ ++#if defined(ARM_ARCH) ++ if (ptri2s_config->pPage0TxBuf8ptr) ++ { ++ pci_free_consistent(NULL, I2S_PAGE_SIZE, ptri2s_config->pPage0TxBuf8ptr, i2s_txdma_addr0); ++ ptri2s_config->pPage0TxBuf8ptr = NULL; ++ } ++ ++ if (ptri2s_config->pPage1TxBuf8ptr) ++ { ++ pci_free_consistent(NULL, I2S_PAGE_SIZE, ptri2s_config->pPage1TxBuf8ptr, i2s_txdma_addr1); ++ ptri2s_config->pPage1TxBuf8ptr = NULL; ++ } ++ _printk("Free tx page buffer\n"); ++#else ++ if (ptri2s_config->pPage0TxBuf8ptr) ++ { ++ pci_free_consistent(NULL, I2S_PAGE_SIZE*2, ptri2s_config->pPage0TxBuf8ptr, i2s_txdma_addr); ++ ptri2s_config->pPage0TxBuf8ptr = NULL; ++ } ++#endif ++ return 0; ++ ++} ++ ++int i2s_rxPagebuf_free(i2s_config_type* ptri2s_config) ++{ ++#if defined(ARM_ARCH) ++ if (ptri2s_config->pPage0RxBuf8ptr) ++ { ++ pci_free_consistent(NULL, I2S_PAGE_SIZE, ptri2s_config->pPage0RxBuf8ptr, i2s_rxdma_addr0); ++ ptri2s_config->pPage0RxBuf8ptr = NULL; ++ } ++ if (ptri2s_config->pPage1RxBuf8ptr) ++ { ++ pci_free_consistent(NULL, I2S_PAGE_SIZE, ptri2s_config->pPage1RxBuf8ptr, i2s_rxdma_addr1); ++ ptri2s_config->pPage1RxBuf8ptr = NULL; ++ } ++ _printk("Free rx page buffer\n"); ++#else ++ if (ptri2s_config->pPage0RxBuf8ptr) ++ { ++ pci_free_consistent(NULL, I2S_PAGE_SIZE*2, ptri2s_config->pPage0RxBuf8ptr, i2s_rxdma_addr); ++ ptri2s_config->pPage0RxBuf8ptr = NULL; ++ } ++#endif ++ return 0; ++} ++ ++int i2s_reset_tx_param(i2s_config_type* ptri2s_config) ++{ ++ ptri2s_config->tx_isr_cnt = 0; ++ ptri2s_config->tx_w_idx = 0; ++ ptri2s_config->tx_r_idx = 0; ++ ptri2s_config->enLable = 0; ++ ptri2s_config->tx_pause_en = 0; ++ ptri2s_config->end_cnt = 0; ++ ptri2s_config->tx_stop_cnt = 0; ++ ++#ifdef I2S_STATISTIC ++ pi2s_status->txbuffer_unrun = 0; ++ pi2s_status->txbuffer_ovrun = 0; ++ pi2s_status->txdmafault = 0; ++ pi2s_status->txovrun = 0; ++ pi2s_status->txunrun = 0; ++ pi2s_status->txthres = 0; ++ pi2s_status->txbuffer_len = 0; ++#endif ++ ++ return 0; ++} ++ ++int i2s_reset_rx_param(i2s_config_type* ptri2s_config) ++{ ++ ptri2s_config->rx_isr_cnt = 0; ++ ptri2s_config->rx_w_idx = 0; ++ ptri2s_config->rx_r_idx = 0; ++ ptri2s_config->enLable = 0; ++ ptri2s_config->rx_pause_en = 0; ++ ptri2s_config->rx_stop_cnt = 0; ++ ++#ifdef I2S_STATISTIC ++ pi2s_status->rxbuffer_unrun = 0; ++ pi2s_status->rxbuffer_ovrun = 0; ++ pi2s_status->rxdmafault = 0; ++ pi2s_status->rxovrun = 0; ++ pi2s_status->rxunrun = 0; ++ pi2s_status->rxthres = 0; ++ pi2s_status->rxbuffer_len = 0; ++#endif ++ ++ return 0; ++} ++#ifdef MT7621_ASIC_BOARD ++int i2s_pll_config_mt7621(unsigned long index) ++{ ++ unsigned long data; ++ unsigned long regValue; ++ bool xtal_20M_en = 0; ++// bool xtal_25M_en = 0; ++ bool xtal_40M_en = 0; ++ ++ regValue = i2s_inw(RALINK_SYSCTL_BASE + 0x10); ++ regValue = (regValue >> 6) & 0x7; ++ if (regValue < 3) ++ { ++ xtal_20M_en = 1; ++ MSG("Xtal is 20MHz. \n"); ++ } ++ else if (regValue < 6) ++ { ++ xtal_40M_en = 1; ++ MSG("Xtal is 40M.\n"); ++ } ++ else ++ { ++ //xtal_25M_en = 1; ++ MSG("Xtal is 25M.\n"); ++ } ++ ++#if defined (CONFIG_I2S_MCLK_12P288MHZ) ++ _printk("MT7621 provide 12.288M/11.298MHz REFCLK\n"); ++ /* Firstly, reset all required register to default value */ ++ i2s_outw(RALINK_ANA_CTRL_BASE, 0x00008000); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x0014, 0x01001d61);//0x01401d61); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x0018, 0x38233d0e); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, 0x80100004);//0x80120004); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x0020, 0x1c7dbf48); ++ ++ /* toggle RG_XPTL_CHG */ ++ i2s_outw(RALINK_ANA_CTRL_BASE, 0x00008800); ++ i2s_outw(RALINK_ANA_CTRL_BASE, 0x00008c00); ++ ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x0014); ++ data &= ~(0x0000ffc0); ++ if ((xtal_40M_en) || (xtal_20M_en)) ++ { ++ data |= REGBIT(0x1d, 8); /* for 40M or 20M */ ++ } ++ else ++ { ++ data |= REGBIT(0x17, 8); /* for 25M */ ++ } ++ ++ if (xtal_40M_en) ++ { ++ data |= REGBIT(0x1, 6); /* for 40M */ ++ } ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x0014, data); ++ ++ ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x0018); ++ data &= ~(0xf0773f00); ++ data |= REGBIT(0x3, 28); ++ data |= REGBIT(0x2, 20); ++ if ((xtal_40M_en) || (xtal_20M_en)) ++ { ++ data |= REGBIT(0x3, 16); /* for 40M or 20M */ ++ } ++ else ++ { ++ data |= REGBIT(0x2, 16); /* for 25M */ ++ } ++ data |= REGBIT(0x3, 12); ++ if ((xtal_40M_en) || (xtal_20M_en)) ++ { ++ data |= REGBIT(0xd, 8); /* for 40M or 20M */ ++ } ++ else ++ { ++ data |= REGBIT(0x7, 8); /* for 25M */ ++ } ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x0018, data); ++ ++ if((index==1)|(index==4)|(index==7)|(index==9))// 270 MHz for 22.05K, 44.1K, 88.2K, 176.4K ++ { ++ if ((xtal_40M_en) || (xtal_20M_en)) ++ { ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x0020, 0x1a18548a); /* for 40M or 20M */ ++ } ++ else ++ { ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x0020, 0x14ad106e); /* for 25M */ ++ } ++ } ++ else if ((index==0)|(index==3)|(index==5)|(index==6)|(index==8)|(index==10))// 294 MHZ for 24K, 48K, 96K, 192K ++ { ++ if ((xtal_40M_en) || (xtal_20M_en)) ++ { ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x0020, 0x1c7dbf48); /* for 40M or 20M */ ++ } ++ else ++ { ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x0020, 0x1697cc39); /* for 25M */ ++ } ++ } ++ else if (index==2) ++ { ++ _printk("Not support 12KHz sampling rate!\n"); ++ return -1; ++ } ++ else ++ { ++ _printk("Wrong sampling rate!\n"); ++ return -1; ++ } ++ ++ //*Common setting - Set PLLGP_CTRL_4 *// ++ /* 1. Bit 31 */ ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c); ++ data &= ~(REGBIT(0x1, 31)); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data); ++ ndelay(10); ++ ++ /* 2. Bit 0 */ ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c); ++ data |= REGBIT(0x1, 0); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data); ++ udelay(200); ++ ++ /* 3. Bit 3 */ ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c); ++ data |= REGBIT(0x1, 3); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data); ++ udelay(1); ++ ++ /* 4. Bit 8 */ ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c); ++ data |= REGBIT(0x1, 8); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data); ++ ndelay(40); ++ ++ /* 5. Bit 6 */ ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c); ++ data |= REGBIT(0x1, 6); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data); ++ ndelay(40); ++ ++ /* 6. Bit 5 & Bit 7*/ ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c); ++ data |= REGBIT(0x1, 5); ++ data |= REGBIT(0x1, 7); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data); ++ udelay(1); ++ ++ /* 7. Bit 17 */ ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c); ++ data |= REGBIT(0x1, 17); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data); ++ ++#elif defined(CONFIG_I2S_MCLK_12MHZ) ++ _printk("MT7621 provide 12MHz REFCLK\n"); ++ /* Firstly, reset all required register to default value */ ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x0014, 0x01401d61);//0x01401d61); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, 0x80120004);//0x80100004); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x0018, 0x38233d0e); ++ ++ if (xtal_40M_en) ++ { ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c); ++ data &= ~REGBIT(0x1, 17); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data); ++ ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x0014); ++ data &= ~REGBIT(0x3, 4); ++ data |= REGBIT(0x1, 4); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x0014, data); ++ ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c); ++ data &= ~REGBIT(0x1, 31); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data); ++ } ++ else if (xtal_20M_en) ++ { ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c); ++ data &= ~REGBIT(0x1, 17); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data); ++ ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x0014); ++ data &= ~REGBIT(0x3, 6); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x0014, data); ++ ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x0014); ++ data &= ~REGBIT(0x3, 4); ++ data |= REGBIT(0x1, 4); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x0014, data); ++ ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c); ++ data &= ~REGBIT(0x1, 31); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data); ++ } ++ else ++ { ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c); ++ data &= ~REGBIT(0x1, 17); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data); ++ ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x0014); ++ data &= ~REGBIT(0x7f, 8); ++ data |= REGBIT(0x17, 8); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x0014, data); ++ ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x0014); ++ data &= ~REGBIT(0x3, 6); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x0014, data); ++ ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x0018); ++ data &= ~REGBIT(0x7, 16); ++ data |= REGBIT(0x2, 16); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x0018, data); ++ ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x0018); ++ data &= ~REGBIT(0xf, 8); ++ data |= REGBIT(0x7, 8); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x0018, data); ++ ++ ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x0014); ++ data &= ~REGBIT(0x3, 4); ++ data |= REGBIT(0x1, 4); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x0014, data); ++ ++ data = i2s_inw(RALINK_ANA_CTRL_BASE+0x001c); ++ data &= ~REGBIT(0x1, 31); ++ i2s_outw(RALINK_ANA_CTRL_BASE+0x001c, data); ++ ++ } ++#endif ++ return 0; ++} ++#if defined(CONFIG_I2S_IN_MCLK) ++int i2s_pll_refclk_set(void) ++{ ++ unsigned long data; ++ ++ /* Set APLL register for REFCLK */ ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x90); ++ data &= ~(0x0000f000); ++ data |= REGBIT(0x1, 12); ++ i2s_outw(RALINK_SYSCTL_BASE+0x0090, data); ++ ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x0090); ++ data &= ~(0x00000300); ++ i2s_outw(RALINK_SYSCTL_BASE+0x0090, data); ++ MSG("Set 0x90 register\n"); ++ ++ return 0; ++} ++#endif ++#endif ++ ++#ifdef MT7623_ASIC_BOARD ++int i2s_pll_config_mt7623(unsigned long index) ++{ ++ unsigned long data; ++ ++ /* xPLL PWR ON */ ++ data = i2s_inw(AUD2PLL_PWR_CON0); ++ data |= 0x1; ++ i2s_outw(AUD2PLL_PWR_CON0, data); ++ udelay(5); ++ ++ /* xPLL ISO Disable */ ++ data = i2s_inw(AUD2PLL_PWR_CON0); ++ data &= ~(0x2); ++ i2s_outw(AUD2PLL_PWR_CON0, data); ++ ++ /* xPLL Frequency Set */ ++ data = i2s_inw(AUD2PLL_CON0); ++ data |= 0x1; ++ i2s_outw(AUD2PLL_CON0, data); ++ ++ /* AUD1PLL Frequency Set(change from 98.304MHz to 294.912MHz) */ ++ i2s_outw(AUD1PLL_CON0, 0x121); ++ i2s_outw(AUD1PLL_CON1, 0xad5efee6); ++ udelay(40); ++ ++ /* Audio clock setting */ ++ if((index==1)|(index==4)|(index==7)|(index==9)|(index==11))// for 22.05K, 44.1K, 88.2K, 176.4K ++ { ++ _printk("\n*****%s:index=%d(270MHz)*****\n", __func__, (int)index); ++ data = i2s_inw(0xFB00002c); ++ //data &= ~REGBIT(0x8, 1); ++ data &= ~(0x80); ++ i2s_outw(0xFB00002C, data); /* AUD1PLL 270.9204MHz */ ++ } ++ else if ((index==0)|(index==3)|(index==5)|(index==6)|(index==8)|(index==10)|(index==12)) //for 24K, 48K, 96K, 192K ++ { ++ _printk("\n*****%s:index=%d(294MHz)*****\n", __func__, (int)index); ++ data = i2s_inw(0xFB00002c); ++ //data |= REGBIT(0x8, 1); ++ data |= (0x80); ++ i2s_outw(0xFB00002c, data); /* AUD1PLL 294.912MHz */ ++ } ++ else if (index==2) ++ { ++ _printk("Not support 12KHz sampling rate!\n"); ++ return -1; ++ } ++ else ++ { ++ _printk("Wrong sampling rate!\n"); ++ return -1; ++ } ++ return 0; ++} ++#endif ++ ++#if defined(MT7628_ASIC_BOARD) || defined(CONFIG_ARCH_MT7623) ++int i2s_driving_strength_adjust(void) ++{ ++#if defined(MT7628_ASIC_BOARD) ++ unsigned long data; ++ ++ MSG("Adjust MT7628 current's driving strngth\n"); ++ /* Adjust REFCLK0's driving strength of current which can avoid ++ * the glitch of REFCKL0 ++ * E4 = 0xb0001354[5]; E8 = 0xb0001364[5] ++ * (E4,E8)=(0,0)-> 4 mA; ++ * =(1,0)-> 8 mA; ++ * =(0,1)-> 12 mA; ++ * =(1,1)-> 16 mA*/ ++ ++ /* Set to 12mA */ ++ data = i2s_inw(0xb0001354); ++ data &= ~(0x1<<5); ++ i2s_outw(0xb0001354, data); ++ ++ data = i2s_inw(0xb0001364); ++ data |= (0x1<<5); ++ i2s_outw(0xb0001364, data); ++#endif ++#if defined(CONFIG_ARCH_MT7623) ++ MSG("Adjust MT7623 current's driving strngth\n"); ++ ++ i2s_outw(0xF0005F80, 0x7777); ++#endif ++ ++ return 0; ++} ++#endif ++ ++#if defined(CONFIG_I2S_IN_MCLK) ++#if defined(CONFIG_I2S_MCLK_12MHZ) ++int i2s_refclk_12m_enable(void) ++{ ++ unsigned long data; ++ ++ MSG("Enable SoC MCLK 12Mhz\n"); ++ ++#if defined(CONFIG_RALINK_RT6855A) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x860); ++ data |= (0x1<<17); ++ data &= ~(0x7<<18); ++ data |= (0x1<<18); ++ i2s_outw(RALINK_SYSCTL_BASE+0x860, data); ++#elif defined(CONFIG_RALINK_RT3350) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x2c); ++ data |= (0x1<<8); ++ i2s_outw(RALINK_SYSCTL_BASE+0x2c, data); ++#elif defined(CONFIG_RALINK_RT3883) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x2c); ++ data &= ~(0x03<<13); ++ data |= (0x1<<13); ++ i2s_outw(RALINK_SYSCTL_BASE+0x2c, data); ++#elif defined(CONFIG_RALINK_RT3352)||defined(CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x2c); ++ data &= ~(0x0F<<8); ++ data |= (0x3<<8); ++ i2s_outw(RALINK_SYSCTL_BASE+0x2c, data); ++#elif defined(CONFIG_RALINK_MT7620) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x2c); ++ data &= ~(0x07<<9); ++ data |= (1<<9); ++ i2s_outw(RALINK_SYSCTL_BASE+0x2c, data); ++#elif defined(CONFIG_RALINK_MT7621) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x2c); ++ data &= ~(0x1f<<18); ++ data |= REGBIT(0x19, 18); ++ data &= ~(0x1f<<12); ++ data |= REGBIT(0x1, 12); ++ data &= ~(0x7<<9); ++ data |= REGBIT(0x5, 9); ++ i2s_outw(RALINK_SYSCTL_BASE+0x2c, data); ++#elif defined(CONFIG_RALINK_MT7628) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x2c); ++ MSG("turn on REFCLK output for MCLK1\n"); ++ data &= ~(0x7<<9); ++ data |= (0x1<<9); /* output for MCLK */ ++ i2s_outw(RALINK_SYSCTL_BASE+0x2c, data); ++#else ++ #error "This SoC does not provide 12MHz clock to audio codec\n"); ++#endif ++ i2s_refclk_gpio_out_config(); ++ ++ return 0; ++} ++#endif ++ ++#if defined(CONFIG_I2S_MCLK_12P288MHZ) ++int i2s_refclk_12p288m_enable(void) ++{ ++ unsigned long data; ++ MSG("Enable SoC MCLK 12.288Mhz\n"); ++ ++#if defined(CONFIG_RALINK_RT3352)||defined(CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x2c); ++ data &= ~(0x01F<<18); ++ data |= 31<<18; ++ data &= ~(0x01F<<12); ++ data |= 1<<12; ++ data |= (0xF<<8); ++ i2s_outw(RALINK_SYSCTL_BASE+0x2c, data); ++#elif defined(CONFIG_RALINK_MT7621) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x2c); ++ data &= ~(0x1f<<18); ++ data |= REGBIT(0xc, 18); ++ data &= ~(0x1f<<12); ++ data |= REGBIT(0x1, 12); ++ data &= ~(0x7<<9); ++ data |= REGBIT(0x5, 9); ++ i2s_outw(RALINK_SYSCTL_BASE+0x2c, data); ++ _printk("MT7621 provide REFCLK 12.288MHz/11.289MHz\n"); ++#elif defined(CONFIG_ARCH_MT7623) ++ /* MT7623 does not need to set divider for REFCLK */ ++ /* GPIO126 - I2S0_MCLK */ ++ data = i2s_inw(0xF00058F0); ++ data &= ~(0x7<<3); ++ data |= (0x6<<3); ++ i2s_outw(0xF00058F0, data); ++ /* GPIO_DIR8: OUT */ ++ data = i2s_inw(0xF0005070); ++ data |= (0x1<<14); ++ i2s_outw(0xF0005070, data); ++#else ++ #error "This SoC does not provide 12.288Mhz clock to audio codec\n"); ++#endif ++ ++ return 0; ++} ++#endif ++ ++#if defined(CONFIG_I2S_MCLK_18P432MHZ) ++int i2s_refclk_18p432m_enable(unsigned long index) ++{ ++ unsigned long data; ++ MSG("Enable SoC MCLK 18.432MHz/16.934MHz"); ++ ++ if((index==1)|(index==4)|(index==7)|(index==9))// 16.934MHz for 22.05K, 44.1K, 88.2K, 176.4K ++ { ++ data = i2s_inw(ETHDMASYS_SYSCTL_BASE+0x2c); ++ data &= ~(0x1<<7); ++ i2s_outw(ETHDMASYS_SYSCTL_BASE+0x2c, data); ++ } ++ else if((index==0)|(index==3)|(index==5)|(index==6)|(index==8)|(index==10))// 18.432MHZ for 24K, 48K, 96K, 192K ++ { ++ data = i2s_inw(ETHDMASYS_SYSCTL_BASE+0x2c); ++ data |= (0x1<<7); ++ i2s_outw(ETHDMASYS_SYSCTL_BASE+0x2c, data); ++ } ++ ++ data = i2s_inw(ETHDMASYS_SYSCTL_BASE+0x30); ++ data |= (0x1<<17); ++ i2s_outw(ETHDMASYS_SYSCTL_BASE+0x30, data); ++ ++ return 0; ++} ++#endif ++#endif ++ ++int i2s_refclk_disable(void) ++{ ++ unsigned long data; ++ ++#if defined(CONFIG_RALINK_RT6855A) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x860); ++ data &= ~(1<<17); ++ i2s_outw(RALINK_SYSCTL_BASE+0x860, data); ++#elif defined(CONFIG_RALINK_RT3350) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x2c); ++ data &= ~(0x1<<8); ++ i2s_outw(RALINK_SYSCTL_BASE+0x2c, data); ++#elif defined(CONFIG_RALINK_RT3883) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x2c); ++ data &= ~(0x0F<<13); ++ i2s_outw(RALINK_SYSCTL_BASE+0x2c, data); ++#elif defined(CONFIG_RALINK_RT3352)||defined(CONFIG_RALINK_RT5350)||defined (CONFIG_RALINK_RT6855) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x2c); ++ data &= ~(0x0F<<8); ++ i2s_outw(RALINK_SYSCTL_BASE+0x2c, data); ++#elif defined (CONFIG_RALINK_MT7620)||defined (CONFIG_RALINK_MT7621)||defined (CONFIG_RALINK_MT7628) ++ _printk("turn off REFCLK output from internal CLK\n"); ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x2c); ++ data &= ~(0x07<<9); ++ i2s_outw(RALINK_SYSCTL_BASE+0x2c, data); ++#elif defined (CONFIG_ARCH_MT7623) /*FIXME:2*/ ++#ifdef MT7623_ASIC_BOARD ++ _printk("turn off REFCLK output from internal CLK\n"); ++ /* GPIO126 - I2S0_MCLK */ ++ data = i2s_inw(0xF00058F0); ++ data &= ~(0x7<<3); ++ //data |= (0x2<<3); ++ i2s_outw(0xF00058F0, data); ++ /* GPIO126 => GPIO_DIR8: IN */ ++ data = i2s_inw(0xF0005070); ++ data &= ~(0x1<<14); ++ i2s_outw(0xF0005070, data); ++#else ++ _printk("turn off REFCLK output from internal CLK\n"); ++ data = i2s_inw(ETHDMASYS_SYSCTL_BASE+0x30); ++ data &= ~(0x1<<17); ++ i2s_outw(ETHDMASYS_SYSCTL_BASE+0x30, data); ++#endif ++#endif ++ return 0; ++} ++ ++int i2s_refclk_gpio_out_config(void) ++{ ++#ifndef CONFIG_ARCH_MT7623 ++ unsigned long data; /* FIXME */ ++#endif ++ ++ /* Set REFCLK GPIO pin as REFCLK mode*/ ++#if defined(CONFIG_RALINK_MT7620) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x60); ++ data &= ~(0x03<<21); /* WDT */ ++ data |= (1<<21); ++ //data &= ~(0x03<<16); /* PERST */ ++ //data |= (1<<16); ++ i2s_outw(RALINK_SYSCTL_BASE+0x60, data); ++#endif ++#if defined(CONFIG_RALINK_MT7621) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x60); ++ //data &= ~(0x3<<10); /* PERST */ ++ //data |= (0x2<<10); ++ data &= ~(0x3<<8); /* WDT */ ++ data |= (0x2<<8); ++ i2s_outw(RALINK_SYSCTL_BASE+0x60, data); ++ MSG("Set 0x60 register\n"); ++#endif ++#if defined(CONFIG_RALINK_MT7628) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x60); ++ data &= ~(0x1<<18); ++ i2s_outw(RALINK_SYSCTL_BASE+0x60, data); ++#endif ++ ++ return 0; ++} ++ ++int i2s_refclk_gpio_in_config(void) ++{ ++#ifndef CONFIG_ARCH_MT7623 ++ unsigned long data; /* FIXME */ ++#endif ++ ++#if defined (CONFIG_RALINK_MT7620) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x60); ++ data &= ~(0x03<<21); /* WDT */ ++ data |= (1<<21); ++ //data &= ~(0x03<<16); /* PERST */ ++ //data |= (1<<16); ++ i2s_outw(RALINK_SYSCTL_BASE+0x60, data); ++ ++ data = i2s_inw(RALINK_PIO_BASE); ++ data &= ~(0x1<<17); /* GPIO share ping 17 for WDT */ ++ i2s_outw(RALINK_PIO_BASE, data); ++ ++ //data = i2s_inw(RALINK_PIO_BASE+0x04); ++ //data &= ~(0x1<<4); /* GPIO share ping 36 for PERST */ ++ //i2s_outw(RALINK_PIO_BASE+0x04, data); ++#endif ++#if defined (CONFIG_RALINK_MT7621) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x60); ++ //data &= ~(0x3<<10); /* PERST */ ++ //data |= (0x1<<10); ++ data &= ~(0x3<<8); /* WDT */ ++ data |= (0x1<<8); ++ i2s_outw(RALINK_SYSCTL_BASE+0x60, data); ++ ++ data = i2s_inw(RALINK_PIO_BASE); ++ //data &= ~(0x1<<19); /* GPIO share ping 19 for RERST */ ++ data &= ~(0x1<<18); /* GPIO share ping 18 for WDT */ ++ i2s_outw(RALINK_PIO_BASE, data); ++#endif ++#if defined (CONFIG_RALINK_MT7628) ++ /* To use external OSC, set REFCLK_GPIO ping as GPIO mode and set it as input direction */ ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x60); ++ data |= (0x1<<18); ++ i2s_outw(RALINK_SYSCTL_BASE+0x60, data); ++ ++ data = i2s_inw(RALINK_PIO_BASE+0x04); ++ data &= ~(0x1<<5); /* GPIO share ping 37*/ ++ i2s_outw(RALINK_PIO_BASE+0x04, data); ++#endif ++ ++ return 0; ++} ++ ++int i2s_slave_clock_gpio_in_mt7623(void) ++{ ++ unsigned long data; ++ ++ /* GPIO74(I2S0_BCLK)=>GPIO_DIR5: IN */ ++ data = i2s_inw(0xF0005040); ++ data &= ~(0x1<<10); ++ i2s_outw(0xF0005040, data); ++ ++ /* GPIO73(I2S0_LRCK)=>GPIO_DIR5: IN */ ++ data = i2s_inw(0xF0005040); ++ data &= ~(0x1<<9); ++ i2s_outw(0xF0005040, data); ++ ++ _printk("i2s_slave_clock_gpio_in_mt7623\n"); ++ ++ return 0; ++} ++ ++int i2s_master_clock_gpio_out_mt7623(void) ++{ ++ unsigned long data; ++ ++ /* GPIO74(I2S0_BCLK)=>GPIO_DIR5: OUT */ ++ data = i2s_inw(0xF0005040); ++ data |= (0x1<<10); ++ i2s_outw(0xF0005040, data); ++ ++ /* GPIO73(I2S0_LRCK)=>GPIO_DIR5: OUT */ ++ data = i2s_inw(0xF0005040); ++ data |= (0x1<<9); ++ i2s_outw(0xF0005040, data); ++ ++ _printk("i2s_master_clock_gpio_out_mt7623\n"); ++ ++ return 0; ++} ++ ++int i2s_share_pin_mt7623(i2s_config_type* ptri2s_config) ++{ ++ unsigned long data; ++ ++ _printk("\nConfig MT7623 I2S pinmux\n"); ++ /* GPIO74 - I2S0_BCLK */ ++ data = i2s_inw(0xF0005840); ++ data &= ~(0x7<<12); ++ data |= (0x6<<12); ++ i2s_outw(0xF0005840, data); ++ ++ /* GPIO73 - I2S0_LRCK */ ++ data = i2s_inw(0xF0005840); ++ data &= ~(0x7<<9); ++ data |= (0x6<<9); ++ i2s_outw(0xF0005840, data); ++ ++ if(ptri2s_config->slave_en==0) ++ i2s_master_clock_gpio_out_mt7623(); ++ else ++ i2s_slave_clock_gpio_in_mt7623(); ++ ++ /* GPIO49 - I2S0_DATA */ ++ data = i2s_inw(0xF00057F0); ++ data &= ~(0x7<<12); ++ data |= (0x6<<12); ++ i2s_outw(0xF00057F0, data); ++ /* GPIO_DIR4: OUT */ ++ data = i2s_inw(0xF0005030); ++ data |= (0x1<<1); ++ i2s_outw(0xF0005030, data); ++ ++ /* GPIO72 - I2S0_DATA_IN */ ++ data = i2s_inw(0xF0005840); ++ data &= ~(0x7<<6); ++ data |= (0x6<<6); ++ i2s_outw(0xF0005840, data); ++ /* GPIO_DIR5: IN */ ++ data = i2s_inw(0xF0005040); ++ data &= ~(0x1<<8); ++ i2s_outw(0xF0005040, data); ++ ++ return 0; ++} ++ ++int i2s_share_pin_config(i2s_config_type* ptri2s_config) ++{ ++#ifndef CONFIG_ARCH_MT7623 ++ unsigned long data; /*FIXME*/ ++#endif ++ ++ /* set share pins to i2s/gpio mode and i2c mode */ ++#if defined(CONFIG_RALINK_RT6855A) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x860); ++ data |= 0x00008080; ++ i2s_outw(RALINK_SYSCTL_BASE+0x860, data); ++#elif defined(CONFIG_RALINK_MT7621) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x60); ++ data &= 0xFFFFFFE3; ++ data |= 0x00000010; ++ i2s_outw(RALINK_SYSCTL_BASE+0x60, data); ++#elif defined(CONFIG_RALINK_MT7628) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x60); ++ data &= ~(0x3<<6); /* I2S_MODE */ ++ data &= ~(0x3<<20); /* I2C_MODE */ ++ i2s_outw(RALINK_SYSCTL_BASE+0x60, data); ++#elif defined(CONFIG_ARCH_MT7623) ++ i2s_share_pin_mt7623(ptri2s_config); ++#else ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x60); ++ data &= 0xFFFFFFE2; ++ data |= 0x00000018; ++ i2s_outw(RALINK_SYSCTL_BASE+0x60, data); ++#endif ++ return 0; ++} ++ ++int i2s_ws_config(i2s_config_type* ptri2s_config, unsigned long index) ++{ ++ unsigned long data; ++ unsigned long* pTable; ++ ++#if defined(CONFIG_I2S_IN_CLK) ++ /* REFCLK is 15.625Mhz or 40Mhz(fractional division) */ ++#if defined(CONFIG_I2S_FRAC_DIV) ++ MSG("Internal REFCLK with fractional division\n"); ++#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623) ++ if (ptri2s_config->wordlen_24b == 1) ++ { ++ MSG("24 bit int table\n"); ++ pTable = i2s_inclk_int_24bit; ++ } ++ else ++ { ++ MSG("16 bit int table\n"); ++ pTable = i2s_inclk_int_16bit; ++ } ++#else ++ pTable = i2s_inclk_int; ++#endif /* CONFIG_RALINK_MT7628 */ ++ ++ data = (unsigned long)(pTable[index]); ++ i2s_outw(I2S_DIVINT_CFG, data); ++ ++#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623) ++ if (ptri2s_config->wordlen_24b == 1) ++ { ++ MSG("24 bit comp table\n"); ++ pTable = i2s_inclk_comp_24bit; ++ } ++ else ++ { ++ MSG("16 bit comp table\n"); ++ pTable = i2s_inclk_comp_16bit; ++ } ++#else ++ pTable = i2s_inclk_comp; ++#endif /* CONFIG_RALINK_MT7628 */ ++ ++ data = (unsigned long)(pTable[index]); ++ data |= REGBIT(1, I2S_CLKDIV_EN); ++ i2s_outw(I2S_DIVCOMP_CFG, data); ++#else ++ MSG("Internal REFCLK 15.625Mhz \n"); ++ pTable = i2s_inclk_15p625Mhz; ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x30); ++ data &= 0xFFFF00FF; ++ data |= (unsigned long)(pTable[index]); ++ data |= 0x00008000; ++ i2s_outw(RALINK_SYSCTL_BASE+0x30, data); ++#endif /* CONFIG_I2S_FRAC_DIV */ ++#else ++#if defined(CONFIG_I2S_MCLK_12MHZ) ++ /* REFCLK = MCLK = 12Mhz */ ++ MSG("External REFCLK 12Mhz \n"); ++ pTable = i2s_exclk_12Mhz; ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x30); ++ data &= 0xFFFF00FF; ++ data |= (unsigned long)(pTable[index]); ++ data |= 0x0000C000; ++ i2s_outw(RALINK_SYSCTL_BASE+0x30, data); ++#else ++ /* REFCLK = MCLK = 12.288Mhz */ ++ pTable = i2s_exclk_12p288Mhz; ++ MSG("External REFCLK 12.288Mhz \n"); ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x30); ++ data &= 0xFFFF00FF; ++ data |= (unsigned long)(pTable[index]); ++ data |= 0x0000C000; ++ i2s_outw(RALINK_SYSCTL_BASE+0x30, data); ++#endif /* CONFIG_I2S_MCLK_12MHZ */ ++#endif /* Not CONFIG_I2S_IN_CLK */ ++ ++#if defined(CONFIG_I2S_WS_EDGE) ++ data = i2s_inw(I2S_I2SCFG); ++ data |= REGBIT(0x1, I2S_WS_INV); ++ i2s_outw(I2S_I2SCFG, data); ++#endif ++ ++ return 0; ++} ++ ++int i2s_mode_config(u32 slave_en) ++{ ++ unsigned long data; ++ ++ if(slave_en==0) ++ { ++ /* Master mode*/ ++ _printk("This SoC is in Master mode\n"); ++#if defined(CONFIG_RALINK_RT3052) ++ data = i2s_inw(I2S_I2SCFG); ++ data &= ~REGBIT(0x1, I2S_SLAVE_EN); ++ data &= ~REGBIT(0x1, I2S_CLK_OUT_DIS); ++ i2s_outw(I2S_I2SCFG, data); ++#elif defined(CONFIG_RALINK_RT3883)||defined(CONFIG_RALINK_RT3352)||\ ++ defined(CONFIG_RALINK_RT5350)||defined(CONFIG_RALINK_RT6855)||\ ++ defined(CONFIG_RALINK_MT7620)||defined(CONFIG_RALINK_RT6855A)||\ ++ defined(CONFIG_RALINK_MT7621)||defined(CONFIG_RALINK_MT7628)||\ ++ defined(CONFIG_ARCH_MT7623) ++ data = i2s_inw(I2S_I2SCFG); ++ data &= ~REGBIT(0x1, I2S_SLAVE_MODE); ++ i2s_outw(I2S_I2SCFG, data); ++#else ++ #error "a strange clock mode" ++#endif ++ } ++ else ++ { ++ /* Slave mode */ ++ _printk("This SoC is in Slave mode\n"); ++#if defined(CONFIG_RALINK_RT3052) ++ data = i2s_inw(I2S_I2SCFG); ++ data |= REGBIT(0x1, I2S_SLAVE_EN); ++ data |= REGBIT(0x1, I2S_CLK_OUT_DIS); ++ i2s_outw(I2S_I2SCFG, data); ++#elif defined(CONFIG_RALINK_RT3883)||defined(CONFIG_RALINK_RT3352)||\ ++ defined(CONFIG_RALINK_RT5350)||defined(CONFIG_RALINK_RT6855)||\ ++ defined(CONFIG_RALINK_MT7620)||defined(CONFIG_RALINK_RT6855A)||\ ++ defined(CONFIG_RALINK_MT7621)||defined(CONFIG_RALINK_MT7628)||\ ++ defined(CONFIG_ARCH_MT7623) ++ data = i2s_inw(I2S_I2SCFG); ++ data |= REGBIT(0x1, I2S_SLAVE_MODE); ++ i2s_outw(I2S_I2SCFG, data); ++#else ++ #error "a strange clock mode " ++#endif ++ } ++ ++ return 0; ++} ++ ++int i2s_codec_frequency_config(i2s_config_type* ptri2s_config, unsigned long index) ++{ ++#if defined(CONFIG_I2S_WM8960)||defined(CONFIG_I2S_WM8750)||defined(CONFIG_I2S_WM8751) ++ unsigned long data; ++ unsigned long* pTable; ++#endif ++ ++#if defined(CONFIG_I2S_MCLK_12MHZ) ++#if defined(CONFIG_I2S_WM8960)||defined(CONFIG_I2S_WM8750)||defined(CONFIG_I2S_WM8751) ++ pTable = i2s_codec_12Mhz; ++ data = pTable[index]; ++#endif ++#if defined(CONFIG_I2S_WM8960) ++ audiohw_set_frequency(data, ptri2s_config->codec_pll_en); ++#elif defined(CONFIG_I2S_WM8750)||defined(CONFIG_I2S_WM8751) ++ audiohw_set_frequency(data|0x01); ++#endif ++#else ++#if defined(CONFIG_I2S_WM8960)||defined(CONFIG_I2S_WM8750)||defined(CONFIG_I2S_WM8751) ++#if defined(MT7623_FPGA_BOARD) && defined(CONFIG_I2S_WM8750) ++ pTable = i2s_codec_18p432Mhz; ++#else ++ pTable = i2s_codec_12p288Mhz; ++#endif ++ data = pTable[index]; ++#endif ++#if defined(CONFIG_I2S_WM8960) ++ audiohw_set_frequency(data, ptri2s_config->codec_pll_en); ++#elif defined(CONFIG_I2S_WM8750)||defined(CONFIG_I2S_WM8751) ++ audiohw_set_frequency(data); ++#endif ++#endif ++ return 0; ++} ++ ++/* ++ * Ralink Audio System Clock Enable ++ * ++ * I2S_WS : signal direction opposite to/same as I2S_CLK ++ * ++ * I2S_CLK : Integer division or fractional division ++ * REFCLK from Internal or External (external REFCLK not support for fractional division) ++ * Suppose external REFCLK always be the same as external MCLK ++ * ++ * MCLK : External OSC or internal generation ++ * ++ */ ++int i2s_clock_enable(i2s_config_type* ptri2s_config) ++{ ++ unsigned long index; ++ /* audio sampling rate decision */ ++ switch(ptri2s_config->srate) ++ { ++ case 8000: ++ index = 0; ++ break; ++ case 11025: ++ index = 1; ++ break; ++ case 12000: ++ index = 2; ++ break; ++ case 16000: ++ index = 3; ++ break; ++ case 22050: ++ index = 4; ++ break; ++ case 24000: ++ index = 5; ++ break; ++ case 32000: ++ index = 6; ++ break; ++ case 44100: ++ index = 7; ++ break; ++ case 48000: ++ index = 8; ++ break; ++ case 88200: ++ index = 9; ++ break; ++ case 96000: ++ index = 10; ++ break; ++#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623) ++ case 176000: ++ index = 11; ++ break; ++ case 192000: ++ index = 12; ++ break; ++#endif ++ default: ++ index = 7; ++ } ++#ifdef MT7621_ASIC_BOARD ++ /* Set pll config */ ++ i2s_pll_config_mt7621(index); ++#endif ++#ifdef MT7623_ASIC_BOARD ++ /* Set pll config */ ++ i2s_pll_config_mt7623(index); ++#endif ++ ++ /* enable internal MCLK */ ++#if defined(CONFIG_I2S_IN_MCLK) ++#if defined(CONFIG_RALINK_MT7621) ++ i2s_pll_refclk_set(); ++#endif ++#if defined(CONFIG_I2S_MCLK_12MHZ) ++#if defined(MT7628_ASIC_BOARD) || defined(CONFIG_ARCH_MT7623) ++ i2s_driving_strength_adjust(); ++#endif ++ i2s_refclk_12m_enable(); ++#endif /* MCLK_12MHZ */ ++#if defined(CONFIG_I2S_MCLK_12P288MHZ) ++ i2s_refclk_12p288m_enable(); ++#endif /* MCLK_12P288MHZ */ ++#if defined(CONFIG_I2S_MCLK_18P432MHZ) ++ i2s_refclk_18p432m_enable(index); ++#endif ++ i2s_refclk_gpio_out_config(); ++ ++#else ++ MSG("Disable SoC MCLK, use external OSC\n"); ++ i2s_refclk_disable(); ++ i2s_refclk_gpio_in_config(); ++#endif /* CONFIG_I2S_IN_MCLK */ ++ ++ i2s_share_pin_config(ptri2s_config); ++ ++ if(ptri2s_config->slave_en==0) ++ { ++ /* Setup I2S_WS and I2S_CLK */ ++ i2s_ws_config(ptri2s_config, index); ++ } ++ ++ i2s_mode_config(ptri2s_config->slave_en); ++ ++ if(!ptri2s_config->bALSAEnable) ++ { ++#if defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751)|| defined(CONFIG_I2S_WM8960) ++ i2s_codec_enable(ptri2s_config); ++#endif ++ i2s_codec_frequency_config(ptri2s_config,index); ++ } ++ ++ return 0; ++} ++ ++int i2s_clock_disable(i2s_config_type* ptri2s_config) ++{ ++ if(!ptri2s_config->bALSAEnable) ++ { ++#if defined(CONFIG_I2S_WM8960) || defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751) ++ i2s_codec_disable(ptri2s_config); ++#endif ++ } ++ ++ /* disable internal MCLK */ ++#if defined(CONFIG_I2S_IN_MCLK) ++ i2s_refclk_disable(); ++ i2s_refclk_gpio_in_config(); ++#endif ++ return 0; ++} ++ ++ ++int i2s_codec_enable(i2s_config_type* ptri2s_config) ++{ ++ ++ int AIn = 0, AOut = 0; ++#if 1 ++#if defined(CONFIG_I2S_WM8960) || defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751) ++ /* Codec initialization */ ++ audiohw_preinit(); ++#endif ++#endif ++ ++#if defined(CONFIG_I2S_WM8960) ++ if(ptri2s_config->codec_pll_en) ++ { ++ MSG("Codec PLL EN = %d\n", pi2s_config->codec_pll_en); ++ audiohw_set_apll(ptri2s_config->srate); ++ } ++#endif ++ ++#if defined(CONFIG_I2S_TXRX) ++ if((ptri2s_config->bTxDMAEnable) || (ptri2s_config->txrx_coexist)) ++ AOut = 1; ++ if((ptri2s_config->bRxDMAEnable) || (ptri2s_config->txrx_coexist)) ++ AIn = 1; ++#if defined(CONFIG_I2S_WM8960) ++ audiohw_postinit(!(ptri2s_config->slave_en), AIn, AOut, ptri2s_config->codec_pll_en, ptri2s_config->wordlen_24b); ++ audiohw_micboost(ptri2s_config->micboost); ++ audiohw_micin(ptri2s_config->micin); ++#elif defined(CONFIG_I2S_WM8750) ++ audiohw_postinit(!(ptri2s_config->slave_en), AIn, AOut, ptri2s_config->wordlen_24b); ++#endif ++ MSG("AOut=%d, AIn=%d\n", AOut, AIn); ++#else ++#if defined(CONFIG_I2S_WM8750) ++ audiohw_postinit(!(ptri2s_config->slave_en), 0, 1); ++#elif defined(CONFIG_I2S_WM8960) ++ audiohw_postinit(!(ptri2s_config->slave_en), 1, 1, ptri2s_config->codec_pll_en); ++#elif defined(CONFIG_I2S_WM8751) ++ if(ptri2s_config->slave_en==0) ++ audiohw_postinit(1,1); ++ else ++ audiohw_postinit(0,1); ++#endif ++#endif ++ return 0; ++} ++ ++int i2s_codec_disable(i2s_config_type* ptri2s_config) ++{ ++#if defined(CONFIG_I2S_WM8960) || defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751) ++ audiohw_close(); ++#endif ++ return 0; ++} ++ ++int i2s_reset_config(i2s_config_type* ptri2s_config) ++{ ++ unsigned long data; ++ ++ /* RESET bit: write 1 clear */ ++#if defined(CONFIG_RALINK_RT6855A) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x834); ++ data |= (1<<17); ++ i2s_outw(RALINK_SYSCTL_BASE+0x834, data); ++ ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x834); ++ data &= ~(1<<17); ++ i2s_outw(RALINK_SYSCTL_BASE+0x834, data); ++#elif defined(CONFIG_ARCH_MT7623) ++ data = i2s_inw(0xFB000000+0x34); ++ data |= (1<<17); ++ i2s_outw(0xFB000000+0x34, data); ++ ++ data = i2s_inw(0xFB000000+0x34); ++ data &= ~(1<<17); ++ i2s_outw(0xFB000000+0x34, data); ++#else ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x34); ++ data |= (1<<17); ++ i2s_outw(RALINK_SYSCTL_BASE+0x34, data); ++ ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x34); ++ data &= ~(1<<17); ++ i2s_outw(RALINK_SYSCTL_BASE+0x34, data); ++ ++#if 0 /* Reset GDMA */ ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x34); ++ data |= (1<<14); ++ i2s_outw(RALINK_SYSCTL_BASE+0x34, data); ++ ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x34); ++ data &= ~(1<<14); ++ i2s_outw(RALINK_SYSCTL_BASE+0x34, data); ++#endif ++#endif ++ _printk("I2S reset complete!!\n"); ++ return 0; ++} ++ ++int i2s_tx_config(i2s_config_type* ptri2s_config) ++{ ++ unsigned long data; ++ /* set I2S_I2SCFG */ ++ data = i2s_inw(I2S_I2SCFG); ++ data &= 0xFFFFFF81; ++ data |= REGBIT(ptri2s_config->tx_ff_thres, I2S_TX_FF_THRES); ++ data |= REGBIT(ptri2s_config->tx_ch_swap, I2S_TX_CH_SWAP); ++#if defined(CONFIG_RALINK_RT6855A) ++ data |= REGBIT(1, I2S_BYTE_SWAP); ++#endif ++#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623) ++ MSG("TX:wordLen=%d, sysEndian=%d\n", ptri2s_config->wordlen_24b, ptri2s_config->sys_endian); ++ data |= REGBIT(ptri2s_config->wordlen_24b, I2S_DATA_24BIT); ++ data |= REGBIT(ptri2s_config->sys_endian, I2S_SYS_ENDIAN); ++ data |= REGBIT(ptri2s_config->little_edn, I2S_LITTLE_ENDIAN); ++#endif ++ data &= ~REGBIT(1, I2S_TX_CH0_OFF); ++ data &= ~REGBIT(1, I2S_TX_CH1_OFF); ++ i2s_outw(I2S_I2SCFG, data); ++ ++ /* set I2S_I2SCFG1 */ ++ MSG("internal loopback: %d\n", ptri2s_config->lbk); ++ data = i2s_inw(I2S_I2SCFG1); ++ data |= REGBIT(ptri2s_config->lbk, I2S_LBK_EN); ++ data |= REGBIT(ptri2s_config->extlbk, I2S_EXT_LBK_EN); ++ data &= 0xFFFFFFFC; ++#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623) ++ data |= REGBIT(ptri2s_config->fmt, I2S_DATA_FMT); ++#endif ++ i2s_outw(I2S_I2SCFG1, data); ++ ++ return 0; ++} ++ ++int i2s_rx_config(i2s_config_type* ptri2s_config) ++{ ++ unsigned long data; ++ /* set I2S_I2SCFG */ ++ data = i2s_inw(I2S_I2SCFG); ++ data &= 0xFFFF81FF; ++ data |= REGBIT(ptri2s_config->rx_ff_thres, I2S_RX_FF_THRES); ++ data |= REGBIT(ptri2s_config->rx_ch_swap, I2S_RX_CH_SWAP); ++ data &= ~REGBIT(1, I2S_RX_CH0_OFF); ++ data &= ~REGBIT(1, I2S_RX_CH1_OFF); ++#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623) ++ MSG("RX:wordLen=%d, sysEndian=%d\n", ptri2s_config->wordlen_24b, ptri2s_config->sys_endian); ++ data |= REGBIT(ptri2s_config->wordlen_24b, I2S_DATA_24BIT); ++ data |= REGBIT(ptri2s_config->sys_endian, I2S_SYS_ENDIAN); ++ data |= REGBIT(ptri2s_config->little_edn, I2S_LITTLE_ENDIAN); ++#endif ++ i2s_outw(I2S_I2SCFG, data); ++ ++ /* set I2S_I2SCFG1 */ ++ data = i2s_inw(I2S_I2SCFG1); ++ data |= REGBIT(ptri2s_config->lbk, I2S_LBK_EN); ++ data |= REGBIT(ptri2s_config->extlbk, I2S_EXT_LBK_EN); ++#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623) ++ data &= 0xFFFFFFFC; ++ data |= REGBIT(ptri2s_config->fmt, I2S_DATA_FMT); ++#endif ++ i2s_outw(I2S_I2SCFG1, data); ++ ++ return 0; ++} ++ ++/* Turn On Tx DMA and INT */ ++int i2s_tx_enable(i2s_config_type* ptri2s_config) ++{ ++ unsigned long data; ++ ++#if defined(I2S_HW_INTERRUPT_EN) ++ data = i2s_inw(I2S_INT_EN); ++ data |= REGBIT(0x1, I2S_TX_INT3_EN); /* FIFO DMA fault */ ++ data |= REGBIT(0x1, I2S_TX_INT2_EN); /* FIFO overrun */ ++ data |= REGBIT(0x1, I2S_TX_INT1_EN); /* FIFO underrun */ ++ data |= REGBIT(0x1, I2S_TX_INT0_EN); /* FIFO below threshold */ ++ i2s_outw(I2S_INT_EN, data); ++#endif ++ ++ data = i2s_inw(I2S_I2SCFG); ++#if defined(CONFIG_I2S_TXRX) ++ data |= REGBIT(0x1, I2S_TX_EN); ++#endif ++ data |= REGBIT(0x1, I2S_DMA_EN); ++ i2s_outw(I2S_I2SCFG, data); ++ ++ data = i2s_inw(I2S_I2SCFG); ++ data |= REGBIT(0x1, I2S_EN); ++ i2s_outw(I2S_I2SCFG, data); ++ ++ MSG("i2s_tx_enable done\n"); ++ return I2S_OK; ++} ++ ++/* Turn On Rx DMA and INT */ ++int i2s_rx_enable(i2s_config_type* ptri2s_config) ++{ ++ unsigned long data; ++ ++#if defined(I2S_HW_INTERRUPT_EN) ++ data = i2s_inw(I2S_INT_EN); ++ data |= REGBIT(0x1, I2S_RX_INT3_EN); /* FIFO DMA fault */ ++ data |= REGBIT(0x1, I2S_RX_INT2_EN); /* FIFO overrun */ ++ data |= REGBIT(0x1, I2S_RX_INT1_EN); /* FIFO underrun */ ++ data |= REGBIT(0x1, I2S_RX_INT0_EN); /* FIFO below threshold */ ++ i2s_outw(I2S_INT_EN, data); ++#endif ++ ++ data = i2s_inw(I2S_I2SCFG); ++#if defined(CONFIG_I2S_TXRX) ++ data |= REGBIT(0x1, I2S_RX_EN); ++#endif ++ data |= REGBIT(0x1, I2S_DMA_EN); ++ i2s_outw(I2S_I2SCFG, data); ++ ++ data = i2s_inw(I2S_I2SCFG); ++ data |= REGBIT(0x1, I2S_EN); ++ i2s_outw(I2S_I2SCFG, data); ++ ++ MSG("i2s_rx_enable done\n"); ++ return I2S_OK; ++} ++/* Turn Off Tx DMA and INT */ ++int i2s_tx_disable(i2s_config_type* ptri2s_config) ++{ ++ unsigned long data; ++ ++#if defined(I2S_HW_INTERRUPT_EN) ++ data = i2s_inw(I2S_INT_EN); ++ data &= ~REGBIT(0x1, I2S_TX_INT3_EN); ++ data &= ~REGBIT(0x1, I2S_TX_INT2_EN); ++ data &= ~REGBIT(0x1, I2S_TX_INT1_EN); ++ data &= ~REGBIT(0x1, I2S_TX_INT0_EN); ++ i2s_outw(I2S_INT_EN, data); ++#endif ++ ++ data = i2s_inw(I2S_I2SCFG); ++#if defined(CONFIG_I2S_TXRX) ++ data &= ~REGBIT(0x1, I2S_TX_EN); ++#endif ++ if(ptri2s_config->bRxDMAEnable==0) ++ { ++ ptri2s_config->bTxDMAEnable = 0; ++ data &= ~REGBIT(0x1, I2S_DMA_EN); ++ data &= ~REGBIT(0x1, I2S_EN); ++ } ++ i2s_outw(I2S_I2SCFG, data); ++ return I2S_OK; ++} ++/* Turn Off Rx DMA and INT */ ++int i2s_rx_disable(i2s_config_type* ptri2s_config) ++{ ++ unsigned long data; ++ ++#if defined(I2S_HW_INTERRUPT_EN) ++ data = i2s_inw(I2S_INT_EN); ++ data &= ~REGBIT(0x1, I2S_RX_INT3_EN); ++ data &= ~REGBIT(0x1, I2S_RX_INT2_EN); ++ data &= ~REGBIT(0x1, I2S_RX_INT1_EN); ++ data &= ~REGBIT(0x1, I2S_RX_INT0_EN); ++ i2s_outw(I2S_INT_EN, data); ++#endif ++ ++ data = i2s_inw(I2S_I2SCFG); ++#if defined(CONFIG_I2S_TXRX) ++ data &= ~REGBIT(0x1, I2S_RX_EN); ++#endif ++ if(ptri2s_config->bTxDMAEnable==0) ++ { ++ ptri2s_config->bRxDMAEnable = 0; ++ data &= ~REGBIT(0x1, I2S_DMA_EN); ++ data &= ~REGBIT(0x1, I2S_EN); ++ } ++ i2s_outw(I2S_I2SCFG, data); ++ return I2S_OK; ++} ++ ++int i2s_dma_tx_transf_data(i2s_config_type* ptri2s_config, u32 dma_ch) ++{ ++ int tx_r_idx; ++ ++ if ((pi2s_config->bALSAEnable==1) && (pi2s_config->bALSAMMAPEnable==1)) ++ tx_r_idx = (pi2s_config->tx_r_idx + ALSA_MMAP_IDX_SHIFT)%MAX_I2S_PAGE; ++ else ++ tx_r_idx = pi2s_config->tx_r_idx; ++ ++ if(dma_ch==GDMA_I2S_TX0) ++ { ++#if defined(CONFIG_I2S_MMAP) ++ dma_sync_single_for_device(NULL, i2s_mmap_addr[tx_r_idx], I2S_PAGE_SIZE, DMA_TO_DEVICE); ++#if defined(ARM_ARCH) ++ GdmaI2sTx(i2s_mmap_addr[tx_r_idx], I2S_TX_FIFO_WREG_PHY, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler); ++#else ++ GdmaI2sTx((u32)(pi2s_config->pMMAPTxBufPtr[tx_r_idx]), I2S_TX_FIFO_WREG, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler); ++#endif ++#else ++ memcpy(pi2s_config->pPage0TxBuf8ptr, pi2s_config->pMMAPTxBufPtr[tx_r_idx], I2S_PAGE_SIZE); ++#if defined(ARM_ARCH) ++ GdmaI2sTx(i2s_txdma_addr0, I2S_TX_FIFO_WREG_PHY, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler); ++#else ++ GdmaI2sTx((u32)(pi2s_config->pPage0TxBuf8ptr), I2S_TX_FIFO_WREG, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler); ++#endif ++#endif ++ pi2s_config->dmach = GDMA_I2S_TX0; ++ pi2s_config->tx_r_idx = (pi2s_config->tx_r_idx+1)%MAX_I2S_PAGE; ++ } ++ else ++ { ++#if defined(CONFIG_I2S_MMAP) ++ dma_sync_single_for_device(NULL, i2s_mmap_addr[tx_r_idx], I2S_PAGE_SIZE, DMA_TO_DEVICE); ++#if defined(ARM_ARCH) ++ GdmaI2sTx(i2s_mmap_addr[tx_r_idx], I2S_TX_FIFO_WREG_PHY, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler); ++#else ++ GdmaI2sTx((u32)(pi2s_config->pMMAPTxBufPtr[tx_r_idx]), I2S_TX_FIFO_WREG, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler); ++#endif ++#else ++ memcpy(pi2s_config->pPage1TxBuf8ptr, pi2s_config->pMMAPTxBufPtr[tx_r_idx], I2S_PAGE_SIZE); ++#if defined(ARM_ARCH) ++ GdmaI2sTx(i2s_txdma_addr1, I2S_TX_FIFO_WREG_PHY, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler); ++#else ++ GdmaI2sTx((u32)(pi2s_config->pPage1TxBuf8ptr), I2S_TX_FIFO_WREG, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler); ++#endif ++#endif ++ pi2s_config->dmach = GDMA_I2S_TX1; ++ pi2s_config->tx_r_idx = (pi2s_config->tx_r_idx+1)%MAX_I2S_PAGE; ++ } ++#if defined(CONFIG_I2S_WITH_AEC) ++ if(aecFuncP->AECFeEnq){ ++ aecFuncP->AECFeEnq(0,pi2s_config->pMMAPTxBufPtr[pi2s_config->tx_r_idx],I2S_PAGE_SIZE); ++ } ++#endif ++ return 0; ++} ++ ++int i2s_dma_tx_transf_zero(i2s_config_type* ptri2s_config, u32 dma_ch) ++{ ++ if(dma_ch==GDMA_I2S_TX0) ++ { ++ memset(pi2s_config->pPage0TxBuf8ptr, 0, I2S_PAGE_SIZE); ++#if defined(ARM_ARCH) ++ GdmaI2sTx(i2s_txdma_addr0, I2S_TX_FIFO_WREG_PHY, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler); ++#else ++ GdmaI2sTx((u32)pi2s_config->pPage0TxBuf8ptr, I2S_TX_FIFO_WREG, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler); ++#endif ++ } ++ else ++ { ++ memset(pi2s_config->pPage1TxBuf8ptr, 0, I2S_PAGE_SIZE); ++#if defined(ARM_ARCH) ++ GdmaI2sTx(i2s_txdma_addr1, I2S_TX_FIFO_WREG_PHY, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler); ++#else ++ GdmaI2sTx((u32)pi2s_config->pPage1TxBuf8ptr, I2S_TX_FIFO_WREG, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler); ++#endif ++ } ++ return 0; ++} ++ ++int i2s_dma_rx_transf_data(i2s_config_type* ptri2s_config, u32 dma_ch) ++{ ++ int rx_w_idx; ++ ++ pi2s_config->rx_w_idx = (pi2s_config->rx_w_idx+1)%MAX_I2S_PAGE; ++ ++ if ((pi2s_config->bALSAEnable==1) && (pi2s_config->bALSAMMAPEnable==1)) ++ rx_w_idx = (pi2s_config->rx_w_idx+ALSA_MMAP_IDX_SHIFT)%MAX_I2S_PAGE; ++ else ++ rx_w_idx = (pi2s_config->rx_w_idx)%MAX_I2S_PAGE; ++ ++ if(dma_ch==GDMA_I2S_RX0) ++ { ++ ++#ifdef CONFIG_I2S_MMAP ++ dma_sync_single_for_device(NULL, i2s_mmap_addr[rx_w_idx+(pi2s_config->mmap_index-MAX_I2S_PAGE)], I2S_PAGE_SIZE, DMA_FROM_DEVICE); ++#if defined(ARM_ARCH) ++ GdmaI2sRx(I2S_RX_FIFO_RREG_PHY, (u32)i2s_mmap_addr[rx_w_idx+(pi2s_config->mmap_index-MAX_I2S_PAGE)], 0, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler); ++#else ++ GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)(pi2s_config->pMMAPRxBufPtr[rx_w_idx]), 0, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler); ++#endif ++#else ++ memcpy(pi2s_config->pMMAPRxBufPtr[rx_w_idx], pi2s_config->pPage0RxBuf8ptr, I2S_PAGE_SIZE); ++#if defined(ARM_ARCH) ++ GdmaI2sRx(I2S_RX_FIFO_RREG_PHY, i2s_rxdma_addr0, 0, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler); ++#else ++ GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)(pi2s_config->pPage0RxBuf8ptr), 0, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler); ++#endif ++#endif ++ pi2s_config->dmach = GDMA_I2S_RX0; ++ } ++ else ++ { ++ ++#ifdef CONFIG_I2S_MMAP ++ dma_sync_single_for_device(NULL, i2s_mmap_addr[rx_w_idx+(pi2s_config->mmap_index-MAX_I2S_PAGE)], I2S_PAGE_SIZE, DMA_FROM_DEVICE); ++#if defined(ARM_ARCH) ++ GdmaI2sRx(I2S_RX_FIFO_RREG_PHY, (u32)i2s_mmap_addr[rx_w_idx+(pi2s_config->mmap_index-MAX_I2S_PAGE)], 1, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler); ++#else ++ GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)(pi2s_config->pMMAPRxBufPtr[rx_w_idx]), 1, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler); ++#endif ++#else ++ memcpy(pi2s_config->pMMAPRxBufPtr[rx_w_idx], pi2s_config->pPage1RxBuf8ptr, I2S_PAGE_SIZE); ++#if defined(ARM_ARCH) ++ GdmaI2sRx(I2S_RX_FIFO_RREG_PHY, i2s_rxdma_addr1, 1, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler); ++#else ++ GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)(pi2s_config->pPage1RxBuf8ptr), 1, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler); ++#endif ++#endif ++ pi2s_config->dmach = GDMA_I2S_RX1; ++ ++ } ++#if defined(CONFIG_I2S_WITH_AEC) ++ if(aecFuncP->AECNeEnq){ ++ aecFuncP->AECNeEnq(0,pi2s_config->pMMAPRxBufPtr[rx_w_idx],I2S_PAGE_SIZE); ++ } ++#endif ++ return 0; ++} ++ ++int i2s_dma_rx_transf_zero(i2s_config_type* ptri2s_config, u32 dma_ch) ++{ ++ if(dma_ch==GDMA_I2S_RX0) ++ { ++ memset(pi2s_config->pPage0RxBuf8ptr, 0, I2S_PAGE_SIZE); ++#if defined(ARM_ARCH) ++ GdmaI2sRx(I2S_RX_FIFO_RREG_PHY, i2s_rxdma_addr0, 0, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler); ++#else ++ GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)pi2s_config->pPage0RxBuf8ptr, 0, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler); ++#endif ++ } ++ else ++ { ++ memset(pi2s_config->pPage1RxBuf8ptr, 0, I2S_PAGE_SIZE); ++#if defined(ARM_ARCH) ++ GdmaI2sRx(I2S_RX_FIFO_RREG_PHY, i2s_rxdma_addr1, 1, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler); ++#else ++ GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)pi2s_config->pPage1RxBuf8ptr, 1, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler); ++#endif ++ } ++ return 0; ++} ++ ++void i2s_dma_tx_handler(u32 dma_ch) ++{ ++ pi2s_config->enLable = 1; /* TX:enLabel=1; RX:enLabel=2 */ ++ ++ if(pi2s_config->bTxDMAEnable==0) ++ { ++ if(pi2s_config->end_cnt != 0) ++ { ++ i2s_dma_tx_transf_data(pi2s_config, dma_ch); ++ pi2s_config->end_cnt --; ++ MSG("end_cnt = %d, r_idx = %d\n", pi2s_config->end_cnt, pi2s_config->tx_r_idx); ++ } ++ else ++ { ++ pi2s_config->tx_stop_cnt++; ++ i2s_dma_tx_soft_stop(pi2s_config, dma_ch); ++ MSG("tx_stop=%d, ch=%d\n", pi2s_config->tx_stop_cnt, dma_ch); ++ if (pi2s_config->tx_stop_cnt == 3) ++ { ++ wake_up_interruptible(&(pi2s_config->i2s_tx_qh)); ++ _printk("T:wake up!!\n"); ++ } ++ } ++ return; ++ } ++ ++ pi2s_config->tx_isr_cnt++; ++ ++#ifdef I2S_STATISTIC ++ i2s_int_status(dma_ch); ++#endif ++ /* FIXME */ ++ if(pi2s_config->bALSAEnable) ++ { ++ if(pi2s_config->dmaStat[STREAM_PLAYBACK]) ++ { ++ if(!pi2s_config->bTrigger[STREAM_PLAYBACK]){ ++ //_printk("trigger stop: rIdx:%d widx:%d\n", pi2s_config->tx_r_idx,pi2s_config->tx_w_idx); ++ i2s_dma_tx_transf_zero(pi2s_config, dma_ch); ++ if(pi2s_config->bPreTrigger[STREAM_PLAYBACK]){ ++ /* mtk04880 commented: ++ * for corner case, there are cases which ALSA Trigger stop before disabling DMA. ++ * For which case, it needs to keep call snd_pcm_elapased to keep ALSA hw ptr updating. ++ * It is so called post stop handlment. ++ */ ++ //_printk("post-stop\n"); ++ goto EXIT; ++ } ++ else{ ++ //_printk("pre-stop\n"); ++ wake_up_interruptible(&(pi2s_config->i2s_tx_qh)); ++ return; ++ } ++ } ++ else{ ++ if(!pi2s_config->bPreTrigger[STREAM_PLAYBACK]) ++ pi2s_config->bPreTrigger[STREAM_PLAYBACK] = 1; ++ ++ } ++ } ++ } ++ else ++ { ++ if(pi2s_config->tx_r_idx==pi2s_config->tx_w_idx) ++ { ++ /* Buffer Empty */ ++ MSG("TXBE r=%d w=%d[i=%u,c=%u]\n",pi2s_config->tx_r_idx,pi2s_config->tx_w_idx,pi2s_config->tx_isr_cnt,dma_ch); ++#ifdef I2S_STATISTIC ++ pi2s_status->txbuffer_unrun++; ++#endif ++ i2s_dma_tx_transf_zero(pi2s_config, dma_ch); ++ goto EXIT; ++ } ++ } ++ ++ if(pi2s_config->pMMAPTxBufPtr[pi2s_config->tx_r_idx]==NULL) ++ { ++ MSG("mmap buf NULL [%d]\n",pi2s_config->tx_r_idx); ++ i2s_dma_tx_transf_zero(pi2s_config, dma_ch); ++ ++ goto EXIT; ++ } ++ ++ if(pi2s_config->tx_pause_en == 1) ++ { ++ /* Enable PAUSE */ ++ MSG("TX pause now\n"); ++ i2s_dma_tx_transf_zero(pi2s_config, dma_ch); ++ ++ goto EXIT; ++ } ++ ++#ifdef I2S_STATISTIC ++ pi2s_status->txbuffer_len--; ++#endif ++ i2s_dma_tx_transf_data(pi2s_config, dma_ch); ++ ++EXIT: ++#if defined(CONFIG_SND_MT76XX_SOC) ++ if(pi2s_config->bALSAEnable == 1){ ++ if(pi2s_config->pss[STREAM_PLAYBACK]) ++ snd_pcm_period_elapsed(pi2s_config->pss[STREAM_PLAYBACK]); ++ } ++#endif ++ wake_up_interruptible(&(pi2s_config->i2s_tx_qh)); ++ return; ++} ++ ++void i2s_dma_rx_handler(u32 dma_ch) ++{ ++ pi2s_config->enLable = 2; /* TX:enLabel=1; RX:enLabel=2 */ ++#if defined(CONFIG_I2S_TXRX) ++ if(pi2s_config->rx_isr_cnt==0) ++ { ++ pi2s_config->next_p0_idx = 0; ++ pi2s_config->next_p1_idx = 1; ++ } ++ pi2s_config->rx_isr_cnt++; ++ ++#ifdef I2S_STATISTIC ++ i2s_int_status(dma_ch); ++#endif ++ ++ if (pi2s_config->bRxDMAEnable==0) ++ { ++ pi2s_config->rx_stop_cnt++; ++ i2s_dma_rx_soft_stop(pi2s_config, dma_ch); ++ MSG("rx_stop=%d\n", pi2s_config->rx_stop_cnt); ++ ++ if(pi2s_config->rx_stop_cnt == 2) ++ { ++ wake_up_interruptible(&(pi2s_config->i2s_rx_qh)); ++ _printk("R:wake up!!\n"); ++ } ++ return; ++ } ++ ++ if(pi2s_config->bALSAEnable) ++ { ++ if(pi2s_config->dmaStat[STREAM_CAPTURE]){ ++ if(!pi2s_config->bTrigger[STREAM_CAPTURE]){ ++ MSG("trigger stop: rIdx:%d widx:%d\n", pi2s_config->rx_r_idx,pi2s_config->rx_w_idx); ++ i2s_dma_rx_transf_zero(pi2s_config, dma_ch); ++ wake_up_interruptible(&(pi2s_config->i2s_rx_qh)); ++ return; ++ } ++ } ++ } ++ else ++ { ++ if(((pi2s_config->rx_w_idx+1)%MAX_I2S_PAGE)==pi2s_config->rx_r_idx){ ++ /* Buffer Full */ ++ MSG("RXBF r=%d w=%d[i=%u,c=%u]\n",pi2s_config->rx_r_idx,pi2s_config->rx_w_idx,pi2s_config->rx_isr_cnt,dma_ch); ++#ifdef I2S_STATISTIC ++ pi2s_status->rxbuffer_unrun++; ++#endif ++ i2s_dma_rx_transf_zero(pi2s_config, dma_ch); ++ goto EXIT; ++ } ++ } ++ ++ if(pi2s_config->rx_pause_en == 1) ++ { ++ /* Enable PAUSE */ ++ i2s_dma_rx_transf_zero(pi2s_config, dma_ch); ++ ++ goto EXIT; ++ } ++ ++#ifdef I2S_STATISTIC ++ pi2s_status->rxbuffer_len++; ++#endif ++ i2s_dma_rx_transf_data(pi2s_config, dma_ch); ++ ++EXIT: ++#if defined(CONFIG_SND_MT76XX_SOC) ++ if(pi2s_config->bALSAEnable == 1){ ++ if(pi2s_config->pss[STREAM_CAPTURE]) ++ snd_pcm_period_elapsed(pi2s_config->pss[STREAM_CAPTURE]); ++ } ++#endif ++ wake_up_interruptible(&(pi2s_config->i2s_rx_qh)); ++#endif ++ return; ++} ++ ++#ifdef I2S_STATISTIC ++void i2s_int_status(u32 dma_ch) ++{ ++ u32 i2s_status; ++ ++ if((pi2s_config->tx_isr_cnt>0)||(pi2s_config->rx_isr_cnt>0)) ++ { ++ i2s_status = i2s_inw(I2S_INT_STATUS); ++ ++ if(i2s_status®BIT(1, I2S_TX_DMA_FAULT)) ++ { ++ pi2s_status->txdmafault++; ++ } ++ if(i2s_status®BIT(1, I2S_TX_OVRUN)) ++ { ++ pi2s_status->txovrun++; ++ } ++ if(i2s_status®BIT(1, I2S_TX_UNRUN)) ++ { ++ pi2s_status->txunrun++; ++ } ++ if(i2s_status®BIT(1, I2S_TX_THRES)) ++ { ++ pi2s_status->txthres++; ++ } ++ if(i2s_status®BIT(1, I2S_RX_DMA_FAULT)) ++ { ++ pi2s_status->rxdmafault++; ++ } ++ if(i2s_status®BIT(1, I2S_RX_OVRUN)) ++ { ++ pi2s_status->rxovrun++; ++ } ++ if(i2s_status®BIT(1, I2S_RX_UNRUN)) ++ { ++ pi2s_status->rxunrun++; ++ } ++ if(i2s_status®BIT(1, I2S_RX_THRES)) ++ { ++ pi2s_status->rxthres++; ++ } ++ } ++#if 0 ++ if(pi2s_config->enLable == 1) ++ { ++ if((pi2s_config->tx_isr_cnt>0) && (pi2s_config->tx_isr_cnt%40==0)) ++ { ++ MSG("tisr i=%u,ch=%u,o=%u,u=%d,s=%X [r=%d,w=%d]\n",\ ++ pi2s_config->tx_isr_cnt,dma_ch,pi2s_status->txovrun,pi2s_status->txunrun,\ ++ i2s_inw(I2S_INT_STATUS),pi2s_config->tx_r_idx,pi2s_config->tx_w_idx); ++ } ++ } ++ ++ if(pi2s_config->enLable == 2) ++ { ++ if((pi2s_config->rx_isr_cnt>0) && (pi2s_config->rx_isr_cnt%40==0)) ++ { ++ MSG("risr i=%u,ch=%u,o=%u,u=%d,s=%X [r=%d,w=%d]\n",\ ++ pi2s_config->rx_isr_cnt,dma_ch,pi2s_status->rxovrun,pi2s_status->rxunrun,\ ++ i2s_inw(I2S_INT_STATUS),pi2s_config->rx_r_idx,pi2s_config->rx_w_idx); ++ } ++ } ++#endif ++ ++ *(unsigned long*)(I2S_INT_STATUS) = 0xFFFFFFFF; ++} ++#endif ++ ++#if defined(I2S_HW_INTERRUPT_EN)&&(I2S_SW_IRQ_EN) ++irqreturn_t i2s_irq_isr(int irq, void *irqaction) ++{ ++ u32 i2s_status; ++ ++ //MSG("i2s_irq_isr [0x%08X]\n",i2s_inw(I2S_INT_STATUS)); ++ if((pi2s_config->tx_isr_cnt>0)||(pi2s_config->rx_isr_cnt>0)) ++ { ++ i2s_status = i2s_inw(I2S_INT_STATUS); ++ MSG("i2s_irq_isr [0x%08X]\n",i2s_status); ++ } ++ else ++ return IRQ_HANDLED; ++ ++ if(i2s_status®BIT(1, I2S_TX_DMA_FAULT)) ++ { ++#ifdef I2S_STATISTIC ++ pi2s_status->txdmafault++; ++#endif ++ } ++ if(i2s_status®BIT(1, I2S_TX_OVRUN)) ++ { ++#ifdef I2S_STATISTIC ++ pi2s_status->txovrun++; ++#endif ++ } ++ if(i2s_status®BIT(1, I2S_TX_UNRUN)) ++ { ++#ifdef I2S_STATISTIC ++ pi2s_status->txunrun++; ++#endif ++ } ++ if(i2s_status®BIT(1, I2S_TX_THRES)) ++ { ++#ifdef I2S_STATISTIC ++ pi2s_status->txthres++; ++#endif ++ } ++ if(i2s_status®BIT(1, I2S_RX_DMA_FAULT)) ++ { ++#ifdef I2S_STATISTIC ++ pi2s_status->rxdmafault++; ++#endif ++ } ++ if(i2s_status®BIT(1, I2S_RX_OVRUN)) ++ { ++#ifdef I2S_STATISTIC ++ pi2s_status->rxovrun++; ++#endif ++ } ++ if(i2s_status®BIT(1, I2S_RX_UNRUN)) ++ { ++#ifdef I2S_STATISTIC ++ pi2s_status->rxunrun++; ++#endif ++ } ++ if(i2s_status®BIT(1, I2S_RX_THRES)) ++ { ++#ifdef I2S_STATISTIC ++ pi2s_status->rxthres++; ++#endif ++ } ++ i2s_outw(I2S_INT_STATUS, 0xFFFFFFFF); ++ return IRQ_HANDLED; ++} ++#endif ++ ++void i2s_tx_task(unsigned long pData) ++{ ++ unsigned long flags; ++ spin_lock_irqsave(&pi2s_config->lock, flags); ++ //if (pi2s_config->bTxDMAEnable!=0) ++ { ++ if (pi2s_config->tx_unmask_ch!=0) ++ { ++ u32 dmach = pi2s_config->tx_unmask_ch; ++ u32 ch; ++ for (ch = 0; ch < 16; ch++) ++ { ++ if (dmach& (1<<ch)) ++ { ++ MSG("do unmask ch%d tisr=%d in tx_isr\n",ch,pi2s_config->tx_isr_cnt); ++ GdmaUnMaskChannel(ch); ++ } ++ } ++ pi2s_config->tx_unmask_ch = 0; ++ } ++ } ++ spin_unlock_irqrestore(&pi2s_config->lock, flags); ++} ++ ++void i2s_rx_task(unsigned long pData) ++{ ++ unsigned long flags; ++ spin_lock_irqsave(&pi2s_config->lock, flags); ++ //if (pi2s_config->bRxDMAEnable!=0) ++ { ++ if (pi2s_config->rx_unmask_ch!=0) ++ { ++ u32 dmach = pi2s_config->rx_unmask_ch; ++ u32 ch; ++ for (ch = 0; ch < 16; ch++) ++ { ++ if (dmach& (1<<ch)) ++ { ++ MSG("do unmask ch%d risr=%d in rx_isr\n",ch,pi2s_config->rx_isr_cnt); ++ GdmaUnMaskChannel(ch); ++ } ++ } ++ pi2s_config->rx_unmask_ch = 0; ++ ++ } ++ } ++ spin_unlock_irqrestore(&pi2s_config->lock, flags); ++} ++ ++ ++void i2s_dma_unmask_handler(u32 dma_ch) ++{ ++ MSG("i2s_dma_unmask_handler ch=%d\n",dma_ch); ++ ++ GdmaUnMaskChannel(dma_ch); ++ ++ return; ++} ++ ++void i2s_dma_tx_unmask_handler(u32 dma_ch) ++{ ++ MSG("i2s_dma_tx_unmask_handler ch=%d\n",dma_ch); ++ pi2s_config->tx_unmask_ch |= (1<<dma_ch); ++ tasklet_hi_schedule(&i2s_tx_tasklet); ++ return; ++} ++ ++void i2s_dma_rx_unmask_handler(u32 dma_ch) ++{ ++ MSG("i2s_dma_rx_unmask_handler ch=%d\n",dma_ch); ++ pi2s_config->rx_unmask_ch |= (1<<dma_ch); ++ tasklet_hi_schedule(&i2s_rx_tasklet); ++ return; ++} ++ ++void i2s_dma_mask_handler(u32 dma_ch) ++{ ++ MSG("i2s_dma_mask_handler ch=%d\n", dma_ch); ++ GdmaMaskChannel(dma_ch); ++ return; ++} ++ ++void i2s_dma_tx_init(i2s_config_type* ptri2s_config) ++{ ++ memset(pi2s_config->pPage0TxBuf8ptr, 0, I2S_PAGE_SIZE); ++ memset(pi2s_config->pPage1TxBuf8ptr, 0, I2S_PAGE_SIZE); ++#if defined(ARM_ARCH) ++ GdmaI2sTx(i2s_txdma_addr0, I2S_TX_FIFO_WREG_PHY, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler); ++ GdmaI2sTx(i2s_txdma_addr1, I2S_TX_FIFO_WREG_PHY, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler); ++#else ++ GdmaI2sTx((u32)ptri2s_config->pPage0TxBuf8ptr, I2S_FIFO_WREG, 0, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler); ++ GdmaI2sTx((u32)ptri2s_config->pPage1TxBuf8ptr, I2S_FIFO_WREG, 1, I2S_PAGE_SIZE, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler); ++#endif ++ ++ return; ++} ++ ++void i2s_dma_rx_init(i2s_config_type* ptri2s_config) ++{ ++ memset(pi2s_config->pPage0RxBuf8ptr, 0, I2S_PAGE_SIZE); ++ memset(pi2s_config->pPage1RxBuf8ptr, 0, I2S_PAGE_SIZE); ++ ++#if defined(ARM_ARCH) ++ GdmaI2sRx(I2S_RX_FIFO_RREG_PHY, i2s_rxdma_addr0, 0, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler); ++ GdmaI2sRx(I2S_RX_FIFO_RREG_PHY, i2s_rxdma_addr1, 1, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler); ++#else ++ GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)ptri2s_config->pPage0RxBuf8ptr, 0, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler); ++ GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)ptri2s_config->pPage1RxBuf8ptr, 1, I2S_PAGE_SIZE, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler); ++#endif ++ ++ return; ++} ++ ++void i2s_dma_tx_end_handle(i2s_config_type* ptri2s_config) ++{ ++ if (ptri2s_config->tx_w_idx < ptri2s_config->tx_r_idx) ++ { ++ ptri2s_config->end_cnt = (ptri2s_config->tx_w_idx + MAX_I2S_PAGE)-ptri2s_config->tx_r_idx; ++ _printk("case1: w=%d, r=%d, end=%d\n", ptri2s_config->tx_w_idx, ptri2s_config->tx_r_idx, ptri2s_config->end_cnt); ++ } ++ else if (ptri2s_config->tx_w_idx > ptri2s_config->tx_r_idx) ++ { ++ ptri2s_config->end_cnt = ptri2s_config->tx_w_idx-ptri2s_config->tx_r_idx; ++ _printk("case2: w=%d, r=%d, end=%d\n", ptri2s_config->tx_w_idx, ptri2s_config->tx_r_idx, ptri2s_config->end_cnt); ++ } ++ else ++ { ++ _printk("case3: w=%d, r=%d, end=%d\n", ptri2s_config->tx_w_idx, ptri2s_config->tx_r_idx, ptri2s_config->end_cnt); ++ ++ } ++ ++ if (ptri2s_config->end_cnt > 0) ++ { ++ interruptible_sleep_on(&(ptri2s_config->i2s_tx_qh)); ++ } ++ ++ return; ++} ++ ++void i2s_tx_end_sleep_on(i2s_config_type* ptri2s_config) ++{ ++ while(ptri2s_config->tx_stop_cnt<3) ++ interruptible_sleep_on(&(ptri2s_config->i2s_tx_qh)); ++ ++ return; ++} ++ ++void i2s_rx_end_sleep_on(i2s_config_type* ptri2s_config) ++{ ++ while(ptri2s_config->rx_stop_cnt<2) ++ interruptible_sleep_on(&(ptri2s_config->i2s_rx_qh)); ++ return; ++} ++ ++int i2s_dma_tx_soft_stop(i2s_config_type* ptri2s_config, u32 dma_ch) ++{ ++ if(dma_ch==GDMA_I2S_TX0) ++ { ++#if defined(ARM_ARCH) ++ GdmaI2sTx(i2s_txdma_addr0, I2S_TX_FIFO_WREG_PHY, 0, 4, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler); ++#else ++ GdmaI2sTx((u32)pi2s_config->pPage0TxBuf8ptr, I2S_TX_FIFO_WREG, 0, 4, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler); ++#endif ++ } ++ else ++ { ++#if defined(ARM_ARCH) ++ GdmaI2sTx(i2s_txdma_addr1, I2S_TX_FIFO_WREG_PHY, 1, 4, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler); ++#else ++ GdmaI2sTx((u32)pi2s_config->pPage1TxBuf8ptr, I2S_TX_FIFO_WREG, 1, 4, i2s_dma_tx_handler, i2s_dma_tx_unmask_handler); ++#endif ++ } ++ ++ return 0; ++} ++ ++int i2s_dma_rx_soft_stop(i2s_config_type* ptri2s_config, u32 dma_ch) ++{ ++ if(dma_ch==GDMA_I2S_RX0) ++ { ++ memset(pi2s_config->pPage0RxBuf8ptr, 0, I2S_PAGE_SIZE); ++#if defined(ARM_ARCH) ++ GdmaI2sRx(I2S_RX_FIFO_RREG_PHY, i2s_rxdma_addr0, 0, 4, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler); ++#else ++ GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)pi2s_config->pPage0RxBuf8ptr, 0, 4, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler); ++#endif ++ } ++ else ++ { ++ memset(pi2s_config->pPage1RxBuf8ptr, 0, I2S_PAGE_SIZE); ++#if defined(ARM_ARCH) ++ GdmaI2sRx(I2S_RX_FIFO_RREG_PHY, i2s_rxdma_addr1, 1, 4, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler); ++#else ++ GdmaI2sRx(I2S_RX_FIFO_RREG, (u32)pi2s_config->pPage1RxBuf8ptr, 1, 4, i2s_dma_rx_handler, i2s_dma_rx_unmask_handler); ++#endif ++ } ++ ++ return 0; ++} ++ ++void i2s_gen_test_pattern(void) ++{ ++ int i; ++ for (i=0; i<I2S_PAGE_SIZE; i++) ++ { ++ test_buf[i] = 0x5A; ++ test_buf_1[i] = 0x11; ++ test_buf_2[i] = 0x22; ++ ++ } ++} ++ ++int i2s_put_audio(i2s_config_type* ptri2s_config, unsigned long arg) ++{ ++ unsigned long flags; ++ int tx_w_idx; ++ ++ do{ ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ ++ if(((ptri2s_config->tx_w_idx+4)%MAX_I2S_PAGE)!=ptri2s_config->tx_r_idx) ++ { ++ ptri2s_config->tx_w_idx = (ptri2s_config->tx_w_idx+1)%MAX_I2S_PAGE; ++ tx_w_idx = ptri2s_config->tx_w_idx; ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ //_printk("put TB[%d] for user write\n",ptri2s_config->tx_w_idx); ++#if defined(CONFIG_I2S_MMAP) ++ put_user(tx_w_idx, (int*)arg); ++#else ++ copy_from_user(ptri2s_config->pMMAPTxBufPtr[tx_w_idx], (char*)arg, I2S_PAGE_SIZE); ++#endif ++ pi2s_status->txbuffer_len++; ++ //spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ } ++ else ++ { ++ /* Buffer Full */ ++ //_printk("TBF tr=%d, tw=%d\n", ptri2s_config->tx_r_idx, ptri2s_config->tx_w_idx); ++ pi2s_status->txbuffer_ovrun++; ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ interruptible_sleep_on(&(ptri2s_config->i2s_tx_qh)); ++ if (ptri2s_config->bTxDMAEnable==0 && ptri2s_config->end_cnt==0) ++ { ++ _printk("wake up for exit i2s driver\n"); ++ put_user(-1, (int*)arg); ++ break; ++ } ++ } ++ }while(1); ++ ++ return 0; ++} ++ ++int i2s_get_audio(i2s_config_type* ptri2s_config, unsigned long arg) ++{ ++ unsigned long flags; ++ int rx_r_idx; ++ ++ do{ ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ //_printk("GA rr=%d, rw=%d,i=%d\n", ptri2s_config->rx_r_idx, ptri2s_config->rx_w_idx,ptri2s_config->rx_isr_cnt); ++ if(((ptri2s_config->rx_r_idx+2)%MAX_I2S_PAGE)!=ptri2s_config->rx_w_idx) ++ { ++ rx_r_idx = ptri2s_config->rx_r_idx; ++ ptri2s_config->rx_r_idx = (ptri2s_config->rx_r_idx+1)%MAX_I2S_PAGE; ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++#if defined(CONFIG_I2S_MMAP) ++ put_user(rx_r_idx, (int*)arg); ++#else ++ copy_to_user((char*)arg, ptri2s_config->pMMAPRxBufPtr[rx_r_idx], I2S_PAGE_SIZE); ++#endif ++ //_printk("rx_r_idx=%d\n", ptri2s_config->rx_r_idx); ++ //ptri2s_config->rx_r_idx = (ptri2s_config->rx_r_idx+1)%MAX_I2S_PAGE; ++ pi2s_status->rxbuffer_len--; ++ //spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ } ++ else ++ { ++ /* Buffer Full */ ++ //_printk("RBF rr=%d, rw=%d\n", ptri2s_config->rx_r_idx, ptri2s_config->rx_w_idx); ++ pi2s_status->rxbuffer_ovrun++; ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ interruptible_sleep_on(&(ptri2s_config->i2s_rx_qh)); ++ } ++#if defined(CONFIG_I2S_WITH_AEC) ++ if(aecFuncP->AECECDeq){ ++ aecFuncP->AECECDeq(0,pi2s_config->pMMAPRxBufPtr[ptri2s_config->rx_r_idx],I2S_PAGE_SIZE); ++ } ++#endif ++ }while(1); ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++long i2s_ioctl (struct file *filp, unsigned int cmd, unsigned long arg) ++#else ++int i2s_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) ++#endif ++{ ++ int i ; ++ i2s_config_type* ptri2s_config; ++ unsigned long flags; ++ ++ ptri2s_config = filp->private_data; ++ switch (cmd) { ++ case I2S_RESET: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ i2s_reset_config(ptri2s_config); ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ case I2S_SRATE: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++#if defined(CONFIG_I2S_WM8960) ++ if((arg>MAX_SRATE_HZ)||(arg<MIN_SRATE_HZ)) ++ { ++ MSG("Audio sampling rate %u should be %d ~ %d Hz. Set SRate to 48000Hz\n", (u32)arg, MIN_SRATE_HZ, MAX_SRATE_HZ); ++ ptri2s_config->srate = 48000; ++ spin_unlock(&ptri2s_config->lock); ++ break; ++ } ++#elif defined(CONFIG_I2S_WM8750) ++ if((arg>MAX_SRATE_HZ)||(arg<MIN_SRATE_HZ)) ++ { ++ MSG("Audio sampling rate %u should be %d ~ %d Hz. Set SRate to 96000Hz\n", (u32)arg, MIN_SRATE_HZ, MAX_SRATE_HZ); ++ ptri2s_config->srate = 96000; ++ spin_unlock(&ptri2s_config->lock); ++ break; ++ } ++#endif ++ ptri2s_config->srate = arg; ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ MSG("set audio sampling rate to %d Hz\n", ptri2s_config->srate); ++ break; ++ case I2S_TX_VOL: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ ++ if((int)arg > 127) ++ ptri2s_config->txvol = 127; ++ else if((int)arg < 48) ++ ptri2s_config->txvol = 48; ++ else ++ ptri2s_config->txvol = arg; ++ ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++#if (defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751)) ++ audiohw_set_master_vol(arg,arg); ++#elif defined(CONFIG_I2S_WM8960) ++ audiohw_set_lineout_vol(1, ptri2s_config->txvol, ptri2s_config->txvol); ++#endif ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ case I2S_RX_VOL: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ ++ if((int)arg > 63) ++ ptri2s_config->rxvol = 63; ++ else if((int)arg < 0) ++ ptri2s_config->rxvol = 0; ++ else ++ ptri2s_config->rxvol = arg; ++ ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++#if defined (CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623) ++ case I2S_WORD_LEN: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ if((int)arg == 16) ++ { ++ ptri2s_config->wordlen_24b = 0; ++ MSG("Enable 16 bit word length.\n"); ++ } ++ else if ((int)arg == 24) ++ { ++ ptri2s_config->wordlen_24b = 1; ++ MSG("Enable 24 bit word length.\n"); ++ } ++ else ++ { ++ MSG("MT7628 only support 16bit/24bit word length.\n"); ++ spin_unlock(&ptri2s_config->lock); ++ break; ++ } ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ case I2S_ENDIAN_FMT: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ if((int)arg == 1) ++ { ++ ptri2s_config->little_edn = 1; ++ MSG("Little endian format.\n"); ++ } ++ else ++ { ++ ptri2s_config->little_edn = 0; ++ MSG("Big endian format.\n"); ++ } ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++#endif ++ case I2S_INTERNAL_LBK: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ if((int)arg == 1) ++ { ++ ptri2s_config->lbk = 1; ++ MSG("Enable internal loopback.\n"); ++ } ++ else ++ { ++ ptri2s_config->lbk = 0; ++ MSG("Disable internal loopback.\n"); ++ } ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ case I2S_EXTERNAL_LBK: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ if((int)arg == 1) ++ { ++ ptri2s_config->extlbk = 1; ++ MSG("Enable external loopback.\n"); ++ } ++ else ++ { ++ ptri2s_config->extlbk = 0; ++ MSG("Disable external loopback.\n"); ++ } ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ case I2S_TXRX_COEXIST: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ if((int)arg == 1) ++ { ++ ptri2s_config->txrx_coexist = 1; ++ MSG("TX/RX coexist.\n"); ++ } ++ else ++ { ++ ptri2s_config->txrx_coexist = 0; ++ MSG("TX/RX coexist.\n"); ++ } ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ ++ case I2S_TX_ENABLE: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ MSG("I2S_TXENABLE\n"); ++ ++ pi2s_config->tx_unmask_ch = 0; ++ tasklet_init(&i2s_tx_tasklet, i2s_tx_task, (u32)pi2s_config); ++ ++ pi2s_config->dis_match = 0; ++ pi2s_config->start_cnt = 0; ++ i2s_gen_test_pattern(); ++ ++ /* allocate tx buffer */ ++ i2s_txPagebuf_alloc(ptri2s_config); ++ i2s_txbuf_alloc(ptri2s_config); ++ ++ /* Init two dma channels */ ++ i2s_dma_tx_init(ptri2s_config); ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ /* Init & config all tx param */ ++ i2s_reset_tx_param(ptri2s_config); ++ ptri2s_config->bTxDMAEnable = 1; ++ /* Clear all ALSA related config */ ++ ptri2s_config->bALSAEnable = 0; ++ ptri2s_config->bALSAMMAPEnable = 0; ++ ++ i2s_tx_config(ptri2s_config); ++ ++ if(ptri2s_config->bRxDMAEnable==0) ++ i2s_clock_enable(ptri2s_config); ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++#if defined(CONFIG_I2S_WM8960)||defined(CONFIG_I2S_WM8750)||defined(CONFIG_I2S_WM8751) ++ audiohw_set_lineout_vol(1, ptri2s_config->txvol, ptri2s_config->txvol); ++#endif ++ GdmaUnMaskChannel(GDMA_I2S_TX0); ++ ++ i2s_tx_enable(ptri2s_config); ++ ++ /* Kick off dma channel */ ++ //GdmaUnMaskChannel(GDMA_I2S_TX0); ++ ++ MSG("I2S_TXENABLE done\n"); ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ case I2S_TX_DISABLE: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ MSG("I2S_TXDISABLE\n"); ++ ++ //tasklet_kill(&i2s_tx_tasklet); ++ ++ /* Handle tx end data */ ++ ptri2s_config->bTxDMAEnable = 0; ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ ++ i2s_tx_end_sleep_on(ptri2s_config); ++ ++ tasklet_kill(&i2s_tx_tasklet); ++ ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ i2s_reset_tx_param(ptri2s_config); ++ i2s_tx_disable(ptri2s_config); ++ if((ptri2s_config->bRxDMAEnable==0)&&(ptri2s_config->bTxDMAEnable==0)) ++ i2s_clock_disable(ptri2s_config); ++ ++ i2s_txbuf_free(ptri2s_config); ++ if(ptri2s_config->mmap_index <= MAX_I2S_PAGE) ++ ptri2s_config->mmap_index = 0; ++ ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ case I2S_RX_ENABLE: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ MSG("I2S_RXENABLE\n"); ++ pi2s_config->rx_unmask_ch = 0; ++ tasklet_init(&i2s_rx_tasklet, i2s_rx_task, (u32)pi2s_config); ++ ++ /* allocate rx buffer */ ++ i2s_rxPagebuf_alloc(ptri2s_config); ++ i2s_rxbuf_alloc(ptri2s_config); ++ ++ /* Init two dma channels */ ++ i2s_dma_rx_init(ptri2s_config); ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ /* Init & config all rx param */ ++ i2s_reset_rx_param(ptri2s_config); ++ ptri2s_config->bRxDMAEnable = 1; ++ ptri2s_config->bALSAEnable = 0; ++ ptri2s_config->bALSAMMAPEnable = 0; ++ ++ i2s_rx_config(ptri2s_config); ++ ++ if(ptri2s_config->bTxDMAEnable==0) ++ i2s_clock_enable(ptri2s_config); ++ ++#if defined(CONFIG_I2S_TXRX) ++#if defined(CONFIG_I2S_WM8960)||defined(CONFIG_I2S_WM8750)||defined(CONFIG_I2S_WM8751) ++ audiohw_set_linein_vol(ptri2s_config->rxvol, ptri2s_config->rxvol); ++#endif ++#endif ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ /* Kick off dma channel */ ++ GdmaUnMaskChannel(GDMA_I2S_RX0); ++ ++ i2s_rx_enable(ptri2s_config); ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ case I2S_RX_DISABLE: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ MSG("I2S_RXDISABLE\n"); ++ //tasklet_kill(&i2s_rx_tasklet); ++ ++ ptri2s_config->bRxDMAEnable = 0; ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ ++ i2s_rx_end_sleep_on(ptri2s_config); ++ tasklet_kill(&i2s_rx_tasklet); ++ ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ i2s_reset_rx_param(ptri2s_config); ++ i2s_rx_disable(ptri2s_config); ++ if((ptri2s_config->bRxDMAEnable==0)&&(ptri2s_config->bTxDMAEnable==0)) ++ i2s_clock_disable(ptri2s_config); ++ ++ i2s_rxbuf_free(ptri2s_config); ++ if(ptri2s_config->mmap_index <= MAX_I2S_PAGE) ++ ptri2s_config->mmap_index = 0; ++ //i2s_rxPagebuf_free(ptri2s_config); ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ case I2S_PUT_AUDIO: ++ i2s_put_audio(ptri2s_config, arg); ++ break; ++ case I2S_GET_AUDIO: ++ i2s_get_audio(ptri2s_config, arg); ++ break; ++ case I2S_TX_STOP: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ MSG("TxGDMA STOP\n"); ++ ptri2s_config->bTxDMAEnable = 0; ++ ptri2s_config->end_cnt = 0; ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ ++ while(ptri2s_config->tx_stop_cnt<3) ++ interruptible_sleep_on(&(ptri2s_config->i2s_tx_qh)); ++ ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ i2s_reset_tx_param(ptri2s_config); ++ i2s_tx_disable(ptri2s_config); ++ if((ptri2s_config->bRxDMAEnable==0)&&(ptri2s_config->bTxDMAEnable==0)) ++ i2s_clock_disable(ptri2s_config); ++ ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ i2s_txbuf_free(ptri2s_config); ++ if(ptri2s_config->mmap_index <= MAX_I2S_PAGE) ++ ptri2s_config->mmap_index = 0; ++ //i2s_txPagebuf_free(ptri2s_config); ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ case I2S_TX_PAUSE: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ ptri2s_config->tx_pause_en = 1; ++ MSG("* tx_pause_en = 1 *\n"); ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ case I2S_TX_RESUME: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ ptri2s_config->tx_pause_en = 0; ++ MSG("# tx_pause_en = 0 #\n"); ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ case I2S_RX_STOP: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ MSG("I2S_RX_STOP\n"); ++ ptri2s_config->bRxDMAEnable = 0; ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ ++ while(ptri2s_config->rx_stop_cnt<2) ++ interruptible_sleep_on(&(ptri2s_config->i2s_rx_qh)); ++ ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ i2s_reset_rx_param(ptri2s_config); ++ i2s_rx_disable(ptri2s_config); ++ if((ptri2s_config->bRxDMAEnable==0)&&(ptri2s_config->bTxDMAEnable==0)) ++ i2s_clock_disable(ptri2s_config); ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ i2s_rxbuf_free(ptri2s_config); ++ if(ptri2s_config->mmap_index <= MAX_I2S_PAGE) ++ ptri2s_config->mmap_index = 0; ++ //i2s_rxPagebuf_free(ptri2s_config); ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ case I2S_RX_PAUSE: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ ptri2s_config->rx_pause_en = 1; ++ MSG("* rx_pause_en = 1 *\n"); ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ case I2S_RX_RESUME: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ ptri2s_config->rx_pause_en = 0; ++ MSG("# rx_pause_en = 0 #\n"); ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ case I2S_CODEC_MIC_BOOST: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ if((int)arg > 3) ++ ptri2s_config->micboost = 3; ++ else if((int)arg < 0) ++ ptri2s_config->micboost = 0; ++ else ++ ptri2s_config->micboost = arg; ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ case I2S_CODEC_MIC_IN: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ if((int)arg == 1) ++ ptri2s_config->micin = 1; ++ else ++ ptri2s_config->micin = 0; ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ case I2S_CLOCK_ENABLE: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ i2s_clock_disable(ptri2s_config); ++#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623) ++ ptri2s_config->wordlen_24b = 1; ++#endif ++ i2s_tx_config(ptri2s_config); ++ i2s_clock_enable(ptri2s_config); ++ i2s_tx_enable(ptri2s_config); ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++ case I2S_DEBUG_CODEC: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ for (i=0; i<10; i++) ++ { ++ _printk("### i=%d ###\n", i); ++ i2s_clock_enable(ptri2s_config); ++ i2s_clock_disable(ptri2s_config); ++ } ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++#if defined(CONFIG_I2S_MS_CTRL) ++ case I2S_MS_MODE_CTRL: ++ spin_lock_irqsave(&ptri2s_config->lock, flags); ++ if((int)arg == 1) ++ { ++ ptri2s_config->slave_en = 1; ++ _printk("I2S in slave mode.\n"); ++ } ++ else ++ { ++ ptri2s_config->slave_en = 0; ++ _printk("I2S in master mode.\n"); ++ } ++ spin_unlock_irqrestore(&ptri2s_config->lock, flags); ++ break; ++#endif ++ case I2S_DEBUG_CLKGEN: ++ case I2S_DEBUG_INLBK: ++ case I2S_DEBUG_EXLBK: ++ case I2S_DEBUG_CODECBYPASS: ++ case I2S_DEBUG_FMT: ++#if defined(CONFIG_I2S_WM8960) ++ case I2S_DEBUG_CODEC_EXLBK: ++#endif ++ case I2S_DEBUG_RESET: ++ i2s_debug_cmd(cmd, arg); ++ break; ++ default : ++ MSG("i2s_ioctl: command format error\n"); ++ } ++ ++ return 0; ++} ++ ++/************************ ++ * API for ALSA * ++ * * ++ ************************/ ++char* i2s_memPool_Alloc(i2s_config_type* ptri2s_config,int dir) ++{ ++ //_printk("%s\n",__func__); ++ if(!ptri2s_config) ++ return NULL; ++ if(dir == STREAM_PLAYBACK){ ++#if defined(CONFIG_I2S_MMAP) ++ i2s_mmap_alloc(I2S_TOTAL_PAGE_SIZE); ++#endif ++ i2s_txbuf_alloc(ptri2s_config); ++ return ptri2s_config->pMMAPTxBufPtr[0]; ++ }else{ ++#if defined(CONFIG_I2S_MMAP) ++ i2s_mmap_alloc(I2S_TOTAL_PAGE_SIZE); ++#endif ++ i2s_rxbuf_alloc(ptri2s_config); ++ return ptri2s_config->pMMAPRxBufPtr[0]; ++ } ++ return NULL; ++} ++ ++void i2s_memPool_free(i2s_config_type* ptri2s_config,int dir) ++{ ++ if(!ptri2s_config) ++ return; ++ if(dir == STREAM_PLAYBACK){ ++#if defined(CONFIG_I2S_MMAP) ++ i2s_mem_unmap(ptri2s_config); ++#endif ++ i2s_txbuf_free(ptri2s_config); ++ }else{ ++#if defined(CONFIG_I2S_MMAP) ++ i2s_mem_unmap(ptri2s_config); ++#endif ++ i2s_rxbuf_free(ptri2s_config); ++ } ++ ++ return; ++} ++ ++int i2s_page_prepare(i2s_config_type* ptri2s_config,int dir) ++{ ++ if(dir == STREAM_PLAYBACK){ ++ /* allocate tx buffer */ ++ i2s_txPagebuf_alloc(ptri2s_config); ++ i2s_dma_tx_init(ptri2s_config); ++ }else{ ++ /* allocate rx buffer */ ++ i2s_rxPagebuf_alloc(ptri2s_config); ++ i2s_dma_rx_init(ptri2s_config); ++ } ++ return 0; ++} ++ ++int i2s_page_release(i2s_config_type* ptri2s_config,int dir) ++{ ++ if(!ptri2s_config) ++ return (-1); ++ if(dir == STREAM_PLAYBACK) ++ i2s_txPagebuf_free(ptri2s_config); ++ else ++ i2s_rxPagebuf_free(ptri2s_config); ++ ++ return 0; ++} ++ ++int i2s_startup(void) ++{ ++ memset(pi2s_config, 0, sizeof(i2s_config_type)); ++ ++#ifdef I2S_STATISTIC ++ memset(pi2s_status, 0, sizeof(i2s_status_type)); ++#endif ++ ++ i2s_param_init(pi2s_config); ++ pi2s_config->bALSAEnable = 1; ++#if defined(CONFIG_I2S_MMAP) ++ pi2s_config->bALSAMMAPEnable = 1; ++#endif ++ ++#if defined (CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623) ++ pi2s_config->little_edn = 1; ++#endif ++ ++ init_waitqueue_head(&(pi2s_config->i2s_tx_qh)); ++ init_waitqueue_head(&(pi2s_config->i2s_rx_qh)); ++ spin_lock_init(&pi2s_config->lock); ++ ++ return 0; ++} ++ ++int gdma_En_Switch(i2s_config_type* ptri2s_config,int dir,int enabled){ ++ if(!ptri2s_config) ++ return (-1); ++ if(dir == STREAM_PLAYBACK){ ++ ptri2s_config->bTxDMAEnable = enabled; ++ //MSG("%s:%d\n",__func__,ptri2s_config->bTxDMAEnable); ++ }else{ ++ ptri2s_config->bRxDMAEnable = enabled; ++ } ++ return 0; ++} ++ ++int i2s_audio_exchange(i2s_config_type* ptri2s_config,int dir,unsigned long arg) ++{ ++ //MSG("I2S_PUT_AUDIO\n"); ++ if(!ptri2s_config) ++ return (-1); ++ if(dir == STREAM_PLAYBACK){ ++ i2s_put_audio(ptri2s_config, arg); ++ }else{ ++ i2s_get_audio(ptri2s_config, arg); ++ } ++ return 0; ++} ++ ++void gdma_mask_handler(u32 dma_ch) ++{ ++ i2s_dma_mask_handler(dma_ch); ++ return; ++} ++ ++void gdma_unmask_handler(u32 dma_ch) ++{ ++ i2s_dma_unmask_handler(dma_ch); ++ return; ++} ++ ++u32 i2s_mmap_phys_addr(i2s_config_type* ptri2s_config) ++{ ++ if((ptri2s_config->pMMAPBufPtr[0]!=NULL) && (ptri2s_config->mmap_index == MAX_I2S_PAGE)) ++ return (dma_addr_t)i2s_mmap_addr[0]; ++ else if((ptri2s_config->pMMAPBufPtr[MAX_I2S_PAGE]!=NULL) && (ptri2s_config->mmap_index == MAX_I2S_PAGE*2)) ++ return (dma_addr_t)i2s_mmap_addr[MAX_I2S_PAGE]; ++ else ++ return -1; ++} ++ ++EXPORT_SYMBOL(i2s_startup); ++EXPORT_SYMBOL(i2s_mem_unmap); ++EXPORT_SYMBOL(i2s_mmap_alloc); ++EXPORT_SYMBOL(i2s_mmap_remap); ++EXPORT_SYMBOL(i2s_param_init); ++EXPORT_SYMBOL(i2s_txbuf_alloc); ++EXPORT_SYMBOL(i2s_rxbuf_alloc); ++EXPORT_SYMBOL(i2s_txPagebuf_alloc); ++EXPORT_SYMBOL(i2s_rxPagebuf_alloc); ++EXPORT_SYMBOL(i2s_txbuf_free); ++EXPORT_SYMBOL(i2s_rxbuf_free); ++EXPORT_SYMBOL(i2s_txPagebuf_free); ++EXPORT_SYMBOL(i2s_rxPagebuf_free); ++EXPORT_SYMBOL(i2s_rx_disable); ++EXPORT_SYMBOL(i2s_tx_disable); ++EXPORT_SYMBOL(i2s_rx_enable); ++EXPORT_SYMBOL(i2s_tx_enable); ++EXPORT_SYMBOL(i2s_rx_config); ++EXPORT_SYMBOL(i2s_tx_config); ++EXPORT_SYMBOL(i2s_reset_config); ++EXPORT_SYMBOL(i2s_clock_disable); ++EXPORT_SYMBOL(i2s_clock_enable); ++EXPORT_SYMBOL(i2s_reset_rx_param); ++EXPORT_SYMBOL(i2s_reset_tx_param); ++EXPORT_SYMBOL(i2s_dma_rx_handler); ++EXPORT_SYMBOL(i2s_dma_tx_handler); ++EXPORT_SYMBOL(i2s_dma_unmask_handler); ++EXPORT_SYMBOL(i2s_dma_tx_unmask_handler); ++EXPORT_SYMBOL(i2s_dma_rx_unmask_handler); ++EXPORT_SYMBOL(i2s_dma_mask_handler); ++EXPORT_SYMBOL(i2s_dma_tx_init); ++EXPORT_SYMBOL(i2s_dma_rx_init); ++EXPORT_SYMBOL(i2s_tx_end_sleep_on); ++EXPORT_SYMBOL(i2s_rx_end_sleep_on); ++EXPORT_SYMBOL(i2s_mmap_phys_addr); ++EXPORT_SYMBOL(i2s_open); ++EXPORT_SYMBOL(pi2s_config); ++#if defined(CONFIG_I2S_IN_MCLK) ++#if defined(CONFIG_I2S_MCLK_12MHZ) ++EXPORT_SYMBOL(i2s_refclk_12m_enable); ++#endif ++#if defined(CONFIG_I2S_MCLK_12P288MHZ) ++EXPORT_SYMBOL(i2s_refclk_12p288m_enable); ++#endif ++#endif ++#if defined(MT7628_ASIC_BOARD) || defined(CONFIG_ARCH_MT7623) ++EXPORT_SYMBOL(i2s_driving_strength_adjust); ++#endif ++EXPORT_SYMBOL(i2s_refclk_disable); ++EXPORT_SYMBOL(i2s_refclk_gpio_out_config); ++EXPORT_SYMBOL(i2s_refclk_gpio_in_config); ++EXPORT_SYMBOL(i2s_share_pin_config); ++EXPORT_SYMBOL(i2s_share_pin_mt7623); ++EXPORT_SYMBOL(i2s_ws_config); ++EXPORT_SYMBOL(i2s_mode_config); ++EXPORT_SYMBOL(i2s_codec_frequency_config); ++EXPORT_SYMBOL(i2s_dma_tx_transf_data); ++EXPORT_SYMBOL(i2s_dma_tx_transf_zero); ++EXPORT_SYMBOL(i2s_dma_rx_transf_data); ++EXPORT_SYMBOL(i2s_dma_rx_transf_zero); ++EXPORT_SYMBOL(i2s_dma_tx_end_handle); ++EXPORT_SYMBOL(i2s_dma_tx_soft_stop); ++EXPORT_SYMBOL(i2s_dma_rx_soft_stop); ++EXPORT_SYMBOL(i2s_tx_task); ++EXPORT_SYMBOL(i2s_rx_task); ++ ++EXPORT_SYMBOL(i2s_memPool_Alloc); ++EXPORT_SYMBOL(i2s_memPool_free); ++EXPORT_SYMBOL(i2s_page_prepare); ++EXPORT_SYMBOL(i2s_page_release); ++EXPORT_SYMBOL(gdma_En_Switch); ++EXPORT_SYMBOL(i2s_audio_exchange); ++EXPORT_SYMBOL(gdma_mask_handler); ++EXPORT_SYMBOL(gdma_unmask_handler); ++#if defined(CONFIG_I2S_WITH_AEC) ++EXPORT_SYMBOL(aecFuncP); ++#endif ++module_init(i2s_mod_init); ++module_exit(i2s_mod_exit); ++ ++MODULE_DESCRIPTION("Ralink SoC I2S Controller Module"); ++MODULE_AUTHOR("Qwert Chin <qwert.chin@ralinktech.com.tw>"); ++MODULE_SUPPORTED_DEVICE("I2S"); ++MODULE_VERSION(I2S_MOD_VERSION); ++MODULE_LICENSE("GPL"); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,12) ++MODULE_PARM (i2sdrv_major, "i"); ++#else ++module_param (i2sdrv_major, int, 0); ++#endif +--- /dev/null ++++ b/sound/soc/mtk/i2s_ctrl.h +@@ -0,0 +1,523 @@ ++#ifndef __RALINK_I2S_H_ ++#define __RALINK_I2S_H_ ++ ++#ifdef __KERNEL__ ++//#include <asm/rt2880/rt_mmap.h> ++#endif ++ ++#if defined(CONFIG_I2S_WITH_AEC) ++#include "aec/aec_api.h" ++#endif ++ ++#define I2S_MAX_DEV 1 ++#define I2S_MOD_VERSION "0.1" ++#define phys_to_bus(a) (a & 0x1FFFFFFF) ++ ++#ifndef u32 ++#define u32 unsigned int ++#endif ++ ++#ifndef u16 ++#define u16 unsigned short ++#endif ++ ++#ifndef u8 ++#define u8 unsigned char ++#endif ++ ++#ifndef REGBIT ++#define REGBIT(x, n) (x << n) ++#endif ++ ++#define Virtual2Physical(x) (((int)x) & 0x1fffffff) ++#define Physical2Virtual(x) (((int)x) | 0x80000000) ++#define Virtual2NonCache(x) (((int)x) | 0x20000000) ++#define Physical2NonCache(x) (((int)x) | 0xa0000000) ++#define NonCache2Virtual(x) (((int)x) & 0xDFFFFFFF) ++ ++#if defined(CONFIG_I2S_MCLK_12MHZ) ++#define CONFIG_I2S_CODEC_PLL_EN 1 ++#else ++#define CONFIG_I2S_CODEC_PLL_EN 0 ++#endif ++ ++//#define CONFIG_I2S_MS_CTRL ++//#define CONFIG_I2S_MS_MODE ++//#define memory_test ++ ++#if defined (CONFIG_ARCH_MT7623) ++#define MT7623_ASIC_BOARD ++#define ARM_ARCH ++#endif ++ ++#if defined (CONFIG_RALINK_MT7621) ++#define MT7621_ASIC_BOARD ++#endif ++ ++#if defined (CONFIG_RALINK_MT7628) ++#define MT7628_ASIC_BOARD ++#endif ++ ++//#define I2S_DEBUG_PRN ++#ifdef I2S_DEBUG_PRN ++#define MSG(fmt, args...) printk("I2S: " fmt, ## args) ++#else ++#define MSG(fmt, args...) { } ++#endif ++ ++#ifdef I2S_DEBUG_PRN ++#define i2s_outw(address, value) do{printk("0x%08X = 0x%08X\n",(u32)address,(u32)value);*((volatile uint32_t *)(address)) = cpu_to_le32(value);}while(0) ++#else ++#define i2s_outw(address, value) *((volatile uint32_t *)(address)) = cpu_to_le32(value) ++#endif ++#define i2s_inw(address) le32_to_cpu(*(volatile u32 *)(address)) ++ ++/* HW feature definiations */ ++#if defined(CONFIG_RALINK_RT3883) ++#define CONFIG_I2S_TXRX 1 ++#define CONFIG_I2S_IN_MCLK 1 ++//#define CONFIG_I2S_WS_EDGE 1 ++#define CONFIG_I2S_FRAC_DIV 1 ++#define CONFIG_I2S_IN_CLK 1 ++#define CONFIG_I2S_MS_MODE 1 ++#endif ++ ++#if defined(CONFIG_RALINK_RT3352)||defined(CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) \ ++ || defined(CONFIG_RALINK_RT6855A) || defined(CONFIG_RALINK_MT7620) || defined(CONFIG_RALINK_MT7621) \ ++ || defined (CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623) ++#define CONFIG_I2S_TXRX 1 ++//#define CONFIG_I2S_WS_EDGE 1 ++#define CONFIG_I2S_FRAC_DIV 1 ++#define CONFIG_I2S_IN_CLK 1 ++#endif ++ ++#if defined(CONFIG_RALINK_RT3350) ++#define CONFIG_I2S_IN_MCLK 1 ++#endif ++ ++#if defined(CONFIG_RALINK_RT3052) ++#define CONFIG_I2S_MS_MODE 1 ++#endif ++ ++/* This is decided in menuconfig */ ++#define CONFIG_I2S_MMAP 1 ++ ++/* For MT7623 ASIC PLL Setting */ ++#if defined(CONFIG_ARCH_MT7623) ++#define AUD1PLL_CON0 (0xF0209270) ++#define AUD1PLL_CON1 (0xF0209274) ++#define AUD1PLL_CON2 (0xF0209278) ++#define AUD1PLL_PWR_CON0 (0xF020927C) ++#define AUD2PLL_CON0 (0xF02092C0) ++#define AUD2PLL_CON1 (0xF02092C4) ++#define AUD2PLL_CON2 (0xF02092C8) ++#define AUD2PLL_PWR_CON0 (0xF02092CC) ++#endif ++ ++/* Register Map, Ref to RT3052 Data Sheet */ ++ ++/* Register Map Detail */ ++#if defined(CONFIG_ARCH_MT7623) ++#define I2S_I2SCFG (ETHDMASYS_I2S_BASE+0x0000) ++#define I2S_INT_STATUS (ETHDMASYS_I2S_BASE+0x0004) ++#define I2S_INT_EN (ETHDMASYS_I2S_BASE+0x0008) ++#define I2S_FF_STATUS (ETHDMASYS_I2S_BASE+0x000c) ++#define I2S_FIFO_WREG (ETHDMASYS_I2S_BASE+0x0010) ++#define I2S_TX_FIFO_WREG I2S_FIFO_WREG ++#define I2S_RX_FIFO_RREG (ETHDMASYS_I2S_BASE+0x0014) ++#define I2S_I2SCFG1 (ETHDMASYS_I2S_BASE+0x0018) ++#define I2S_DIVINT_CFG (ETHDMASYS_I2S_BASE+0x0024) ++#define I2S_DIVCOMP_CFG (ETHDMASYS_I2S_BASE+0x0020) ++#else ++#define I2S_I2SCFG (RALINK_I2S_BASE+0x0000) ++#define I2S_INT_STATUS (RALINK_I2S_BASE+0x0004) ++#define I2S_INT_EN (RALINK_I2S_BASE+0x0008) ++#define I2S_FF_STATUS (RALINK_I2S_BASE+0x000c) ++#define I2S_FIFO_WREG (RALINK_I2S_BASE+0x0010) ++#define I2S_TX_FIFO_WREG I2S_FIFO_WREG ++#define I2S_RX_FIFO_RREG (RALINK_I2S_BASE+0x0014) ++#define I2S_I2SCFG1 (RALINK_I2S_BASE+0x0018) ++#define I2S_DIVINT_CFG (RALINK_I2S_BASE+0x0024) ++#define I2S_DIVCOMP_CFG (RALINK_I2S_BASE+0x0020) ++#endif ++ ++ ++/* I2SCFG bit field */ ++#define I2S_EN 31 ++#define I2S_DMA_EN 30 ++#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623) ++#define I2S_LITTLE_ENDIAN 29 ++#define I2S_SYS_ENDIAN 28 ++#elif defined(CONFIG_RALINK_RT6855A) ++#define I2S_BYTE_SWAP 28 ++#endif ++#define I2S_TX_EN 24 ++#define I2S_RX_EN 20 ++#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623) ++#define I2S_NORM_24BIT 18 ++#define I2S_DATA_24BIT 17 ++#endif ++#define I2S_SLAVE_MODE 16 ++#define I2S_RX_FF_THRES 12 ++#define I2S_RX_CH_SWAP 11 ++#define I2S_RX_CH1_OFF 10 ++#define I2S_RX_CH0_OFF 9 ++#if defined(CONFIG_RALINK_RT3052) ++#define I2S_CLK_OUT_DIS 8 ++#endif ++#define I2S_TX_FF_THRES 4 ++#define I2S_TX_CH_SWAP 3 ++#define I2S_TX_CH1_OFF 2 ++#define I2S_TX_CH0_OFF 1 ++#if defined(CONFIG_RALINK_RT3052) ++#define I2S_SLAVE_EN 0 ++#else ++#define I2S_WS_INV 0 ++#endif ++/* INT_EN bit field */ ++#define I2S_RX_INT3_EN 7 ++#define I2S_RX_INT2_EN 6 ++#define I2S_RX_INT1_EN 5 ++#define I2S_RX_INT0_EN 4 ++#define I2S_TX_INT3_EN 3 ++#define I2S_TX_INT2_EN 2 ++#define I2S_TX_INT1_EN 1 ++#define I2S_TX_INT0_EN 0 ++ ++/* INT_STATUS bit field */ ++#define I2S_RX_DMA_FAULT 7 ++#define I2S_RX_OVRUN 6 ++#define I2S_RX_UNRUN 5 ++#define I2S_RX_THRES 4 ++#define I2S_TX_DMA_FAULT 3 ++#define I2S_TX_OVRUN 2 ++#define I2S_TX_UNRUN 1 ++#define I2S_TX_THRES 0 ++ ++/* FF_STATUS bit field */ ++#define I2S_RX_EPCNT 4 ++#define I2S_TX_EPCNT 0 ++/* I2S_DIVCOMP_CFG bit field */ ++#define I2S_CLKDIV_EN 31 ++ ++/* I2S_CFG1 bit field */ ++#define I2S_LBK_EN 31 ++#define I2S_EXT_LBK_EN 30 ++#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623) ++#define I2S_DATA_FMT 0 ++#endif ++ ++/* FIFO_WREG bit field */ ++#define I2S_FIFO_WDATA 0 ++ ++/* Constant definition */ ++#define NFF_THRES 4 ++#define I2S_PAGE_SIZE 3072//(3*4096)//(1152*2*2*2) ++#define I2S_MIN_PAGE_SIZE 4096 ++#define MAX_I2S_PAGE 8 ++#define I2S_TOTAL_PAGE_SIZE (I2S_PAGE_SIZE*MAX_I2S_PAGE) ++ ++#if defined(CONFIG_I2S_WM8960) ++#define MAX_SRATE_HZ 48000 ++#define MIN_SRATE_HZ 8000 ++#elif defined(CONFIG_I2S_WM8750) ++#define MAX_SRATE_HZ 96000 ++#define MIN_SRATE_HZ 8000 ++#endif ++ ++#define MAX_VOL_DB +0 ++#define MIN_VOL_DB -127 ++ ++#define ALSA_MMAP_IDX_SHIFT 2 ++#if defined(CONFIG_SND_MT76XX_SOC) ++#define STREAM_PLAYBACK SNDRV_PCM_STREAM_PLAYBACK ++#define STREAM_CAPTURE SNDRV_PCM_STREAM_CAPTURE ++#else ++#define STREAM_PLAYBACK 0 ++#define STREAM_CAPTURE 1 ++#endif ++ ++/* I2S I/O command */ ++#define I2S_SRATE 0 ++#define I2S_VOL 1 ++#define I2S_ENABLE 2 ++#define I2S_DISABLE 3 ++#define I2S_TX_ENABLE 27 ++#define I2S_TX_DISABLE 3 ++#define I2S_GET_WBUF 4 ++#define I2S_PUT_WBUF 5 ++#define I2S_RX_ENABLE 6 ++#define I2S_RX_DISABLE 7 ++#define I2S_PUT_AUDIO 4 ++#define I2S_GET_AUDIO 5 ++#define I2S_TX_VOL 1 ++#define I2S_RX_VOL 8 ++#define I2S_WORD_LEN 9 ++#define I2S_ENDIAN_FMT 10 ++#define I2S_INTERNAL_LBK 11 ++#define I2S_TX_STOP 12 ++#define I2S_DEBUG_CODEC 13 ++#define I2S_MS_MODE_CTRL 14 ++#define I2S_TX_PAUSE 15 ++#define I2S_TX_RESUME 16 ++#define I2S_RESET 17 ++#define I2S_RX_STOP 18 ++#define I2S_EXTERNAL_LBK 19 ++#define I2S_TXRX_COEXIST 20 ++#define I2S_RX_PAUSE 21 ++#define I2S_RX_RESUME 22 ++#define I2S_CODEC_MIC_BOOST 23 ++#define I2S_CODEC_MIC_IN 24 ++#define I2S_CLOCK_ENABLE 25 ++#define I2S_TEST_TEST 26 ++ ++#define I2S_DEBUG 30 ++#define I2S_DEBUG_CLKGEN 30 ++#define I2S_DEBUG_INLBK 31 ++#define I2S_DEBUG_EXLBK 32 ++#define I2S_DEBUG_FMT 33 ++#define I2S_DEBUG_RESET 34 ++#define I2S_DEBUG_CODECBYPASS 35 ++#if defined(CONFIG_I2S_WM8960) ++#define I2S_DEBUG_CODEC_EXLBK 36 ++#endif ++ ++/* configuration */ ++#define CONFIG_I2S_TFF_THRES NFF_THRES ++#define CONFIG_I2S_CH_SWAP 0 ++#if defined(CONFIG_I2S_MS_MODE) ++#define CONFIG_I2S_SLAVE_EN 0 ++#else ++#define CONFIG_I2S_SLAVE_EN 1 ++#endif ++ ++/* driver status definition */ ++#define I2S_OK 0 ++#define I2S_OUTOFMEM 0x01 ++#define I2S_GDMAFAILED 0x02 ++#define I2S_REQUEST_IRQ_FAILED 0x04 ++#define I2S_REG_SETUP_FAILED 0x08 ++ ++#define I2S_STATISTIC ++//#define I2S_HW_INTERRUPT_EN ++//#define I2S_SW_IRQ_EN ++#define I2S_MAJOR 234 ++ ++/* parameter for ALSA */ ++/*GDMA for I2S Status*/ ++#define GDMA_I2S_DIS (0) ++#define GDMA_I2S_EN (1) ++ ++ ++typedef struct i2s_status_t ++{ ++ u32 txdmafault; ++ u32 txovrun; ++ u32 txunrun; ++ u32 txthres; ++ int txbuffer_unrun; ++ int txbuffer_ovrun; ++ int txbuffer_len; ++ ++ u32 rxdmafault; ++ u32 rxovrun; ++ u32 rxunrun; ++ u32 rxthres; ++ int rxbuffer_unrun; ++ int rxbuffer_ovrun; ++ int rxbuffer_len; ++}i2s_status_type; ++ ++ ++typedef struct i2s_config_t ++{ ++ ++ int srate; ++ int txvol; ++ int rxvol; ++ u32 pos; ++ u32 tx_isr_cnt; ++ u32 rx_isr_cnt; ++ int bSleep; ++ int bTxDMAEnable; ++ int bRxDMAEnable; ++ int enLable; ++ int micboost; ++ int micin; ++ ++ /* parameters fo ALSA */ ++ int bALSAEnable; ++ int bALSAMMAPEnable; ++ unsigned char bTrigger[2]; ++ unsigned char bPreTrigger[2]; ++ unsigned char dmaStat[2]; ++ unsigned char i2sStat[2]; ++ unsigned int hw_base_frame[2]; ++ struct snd_pcm_substream *pss[2]; ++ ++#ifdef __KERNEL__ ++ spinlock_t lock; ++ wait_queue_head_t i2s_tx_qh, i2s_rx_qh; ++#endif ++ u32 dmach; ++ u32 tx_unmask_ch; ++ u32 rx_unmask_ch; ++ u32 dma_unmask_status; ++ u32 dma_done_status; ++ u32 tx_ff_thres; ++ u32 tx_ch_swap; ++ u32 rx_ff_thres; ++ u32 rx_ch_swap; ++ u32 slave_en; ++ ++ u32 dis_match; ++ int start_cnt; ++#if defined (CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623) ++ int little_edn; /* test file's fmt: little endian->1; big endian->0 */ ++ int sys_endian; /* kernal' system fmt: little endian->0; big endian->1 */ ++#endif ++ int wordlen_24b; ++ int codec_pll_en; ++ int codec_num; ++ int tx_pause_en; ++ int rx_pause_en; ++ int end_cnt; ++ int txrx_coexist; ++ int tx_stop_cnt; ++ int rx_stop_cnt; ++ /* for I2S_CFG1 */ ++ u32 lbk; ++ u32 extlbk; ++ u32 fmt; ++ ++ int w_idx; ++ int r_idx; ++ ++ int tx_w_idx; ++ int tx_r_idx; ++ int rx_w_idx; ++ int rx_r_idx; ++ int mmap_index; ++ int next_p0_idx; ++ int next_p1_idx; ++ ++ u8* buf8ptr; ++ char* pMMAPBufPtr[MAX_I2S_PAGE*2]; ++ char* pMMAPTxBufPtr[MAX_I2S_PAGE]; ++ char* pMMAPRxBufPtr[MAX_I2S_PAGE]; ++ ++ union { ++ u16* pPage0TxBuf16Ptr; ++ u8* pPage0TxBuf8ptr; ++ }; ++ union { ++ u16* pPage1TxBuf16Ptr; ++ u8* pPage1TxBuf8ptr; ++ }; ++ ++ union { ++ u16* pPage0RxBuf16Ptr; ++ u8* pPage0RxBuf8ptr; ++ }; ++ union { ++ u16* pPage1RxBuf16Ptr; ++ u8* pPage1RxBuf8ptr; ++ }; ++ ++}i2s_config_type; ++ ++ ++void i2s_gen_test_pattern(void); ++int i2s_mem_unmap(i2s_config_type* ptri2s_config); ++int i2s_param_init(i2s_config_type* ptri2s_config); ++int i2s_txbuf_alloc(i2s_config_type* ptri2s_config); ++int i2s_rxbuf_alloc(i2s_config_type* ptri2s_config); ++int i2s_txPagebuf_alloc(i2s_config_type* ptri2s_config); ++int i2s_rxPagebuf_alloc(i2s_config_type* ptri2s_config); ++int i2s_txbuf_free(i2s_config_type* ptri2s_config); ++int i2s_rxbuf_free(i2s_config_type* ptri2s_config); ++int i2s_txPagebuf_free(i2s_config_type* ptri2s_config); ++int i2s_rxPagebuf_free(i2s_config_type* ptri2s_config); ++int i2s_reset_tx_param(i2s_config_type* ptri2s_config); ++int i2s_reset_rx_param(i2s_config_type* ptri2s_config); ++int i2s_tx_config(i2s_config_type* ptri2s_config); ++int i2s_rx_config(i2s_config_type* ptri2s_config); ++int i2s_tx_enable(i2s_config_type* ptri2s_config); ++int i2s_tx_disable(i2s_config_type* ptri2s_config); ++int i2s_rx_enable(i2s_config_type* ptri2s_config); ++int i2s_rx_disable(i2s_config_type* ptri2s_config); ++int i2s_codec_enable(i2s_config_type* ptri2s_config); ++int i2s_codec_disable(i2s_config_type* ptri2s_config); ++int i2s_clock_enable(i2s_config_type* ptri2s_config); ++int i2s_clock_disable(i2s_config_type* ptri2s_config); ++int i2s_reset_config(i2s_config_type* ptri2s_config); ++int i2s_refclk_disable(void); ++int i2s_refclk_gpio_out_config(void); ++int i2s_refclk_gpio_in_config(void); ++int i2s_share_pin_config(i2s_config_type* ptri2s_config); ++int i2s_share_pin_mt7623(i2s_config_type* ptri2s_config); ++int i2s_master_clock_gpio_out_mt7623(void); ++int i2s_slave_clock_gpio_in_mt7623(void); ++int i2s_ws_config(i2s_config_type* ptri2s_config, unsigned long index); ++int i2s_mode_config(u32 slave_en); ++int i2s_codec_frequency_config(i2s_config_type* ptri2s_config, unsigned long index); ++void i2s_tx_end_sleep_on(i2s_config_type* ptri2s_config); ++void i2s_rx_end_sleep_on(i2s_config_type* ptri2s_config); ++ ++#if defined(CONFIG_I2S_MCLK_12MHZ) ++int i2s_refclk_12m_enable(void); ++#endif ++#if defined(CONFIG_I2S_MCLK_12P288MHZ) ++int i2s_refclk_12p288m_enable(void); ++#endif ++ ++#if defined(MT7621_ASIC_BOARD) ++int i2s_pll_config_mt7621(unsigned long index); ++int i2s_pll_refclk_set(void); ++#endif ++#if defined(MT7623_ASIC_BOARD) ++int i2s_pll_config_mt7623(unsigned long index); ++#endif ++#if defined(MT7628_ASIC_BOARD) || defined(CONFIG_ARCH_MT7623) ++int i2s_driving_strength_adjust(void); ++#endif ++#if defined(I2S_STATISTIC) ++void i2s_int_status(u32 dma_ch); ++#endif ++void i2s_dma_tx_handler(u32 dma_ch); ++void i2s_dma_rx_handler(u32 dma_ch); ++void i2s_dma_unmask_handler(u32 dma_ch); ++void i2s_dma_mask_handler(u32 dma_ch); ++void i2s_dma_tx_init(i2s_config_type* ptri2s_config); ++void i2s_dma_rx_init(i2s_config_type* ptri2s_config); ++void i2s_tx_task(unsigned long pData); ++void i2s_rx_task(unsigned long pData); ++void i2s_dma_tx_unmask_handler(u32 dma_ch); ++void i2s_dma_rx_unmask_handler(u32 dma_ch); ++int i2s_dma_tx_transf_data(i2s_config_type* ptri2s_config, u32 dma_ch); ++int i2s_dma_tx_transf_zero(i2s_config_type* ptri2s_config, u32 dma_ch); ++int i2s_dma_rx_transf_data(i2s_config_type* ptri2s_config, u32 dma_ch); ++int i2s_dma_rx_transf_zero(i2s_config_type* ptri2s_config, u32 dma_ch); ++void i2s_dma_tx_end_handle(i2s_config_type* ptri2s_config); ++int i2s_dma_tx_soft_stop(i2s_config_type* ptri2s_config, u32 dma_ch); ++int i2s_dma_rx_soft_stop(i2s_config_type* ptri2s_config, u32 dma_ch); ++ ++int i2s_page_prepare(i2s_config_type* ptri2s_config,int dir); ++int i2s_page_release(i2s_config_type* ptri2s_config,int dir); ++int gdma_En_Switch(i2s_config_type* ptri2s_config,int dir,int enabled); ++int i2s_startup(void); ++int i2s_audio_exchange(i2s_config_type* ptri2s_config,int dir,unsigned long arg); ++void gdma_unmask_handler(u32 dma_ch); ++char* i2s_memPool_Alloc(i2s_config_type* ptri2s_config,int dir); ++void i2s_memPool_free(i2s_config_type* ptri2s_config,int dir); ++u32 i2s_mmap_phys_addr(i2s_config_type* ptri2s_config); ++ ++#if !defined(CONFIG_I2S_TXRX) ++#define GdmaI2sRx //GdmaI2sRx ++#endif ++ ++#define RALINK_I2S_VERSION "1.0" ++#define I2SDRV_DEVNAME "i2s0" ++ ++#endif /* __RALINK_I2S_H_ */ ++ +--- /dev/null ++++ b/sound/soc/mtk/mt76xx_i2s.c +@@ -0,0 +1,304 @@ ++/* ++ * mtk_audio_drv.c ++ * ++ * Created on: 2013/8/20 ++ * Author: MTK04880 ++ */ ++#include <linux/init.h> ++#include <linux/version.h> ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++#include <linux/sched.h> ++#endif ++#include <linux/module.h> ++#include <linux/kernel.h> /* printk() */ ++#include <linux/slab.h> /* kmalloc() */ ++#include <linux/fs.h> /* everything... */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/proc_fs.h> ++#include <linux/fcntl.h> /* O_ACCMODE */ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) ++#include <asm/system.h> /* cli(), *_flags */ ++#endif ++#include <asm/uaccess.h> /* copy_from/to_user */ ++#include <linux/interrupt.h> ++#include <linux/mm.h> ++#include <linux/dma-mapping.h> ++#include <sound/core.h> ++#include <linux/pci.h> ++#include <sound/pcm.h> ++#include <sound/pcm_params.h> ++#include <sound/soc.h> ++#include <sound/soc-dapm.h> ++#include <sound/initval.h> ++#include "ralink_gdma.h" ++#include "mt76xx_i2s.h" ++ ++/****************************/ ++/*GLOBAL VARIABLE DEFINITION*/ ++/****************************/ ++extern i2s_config_type* pi2s_config; ++ ++/****************************/ ++/*FUNCTION DECLRATION */ ++/****************************/ ++static int mt76xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai,\ ++ unsigned int fmt); ++ ++//static int mt76xx_i2s_shutdown(struct snd_pcm_substream *substream, ++// struct snd_soc_dai *dai); ++static int mt76xx_i2s_startup(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai); ++static int mt76xx_i2s_hw_params(struct snd_pcm_substream *substream,\ ++ struct snd_pcm_hw_params *params,\ ++ struct snd_soc_dai *dai); ++static int mt76xx_i2s_play_prepare(struct snd_pcm_substream *substream,struct snd_soc_dai *dai); ++static int mt76xx_i2s_rec_prepare(struct snd_pcm_substream *substream,struct snd_soc_dai *dai); ++static int mt76xx_i2s_hw_free(struct snd_pcm_substream *substream,struct snd_soc_dai *dai); ++static int mt76xx_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai); ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,20) ++static int mt76xx_i2s_drv_probe(struct platform_device *pdev); ++static int mt76xx_i2s_drv_remove(struct platform_device *pdev); ++#endif ++/****************************/ ++/*STRUCTURE DEFINITION */ ++/****************************/ ++ ++ ++static struct snd_soc_dai_ops mt76xx_i2s_dai_ops = { ++ .startup = mt76xx_i2s_startup, ++ .hw_params = mt76xx_i2s_hw_params, ++ .hw_free = mt76xx_i2s_hw_free, ++ //.shutdown = mt76xx_i2s_shutdown, ++ .prepare = mt76xx_i2s_prepare, ++ .set_fmt = mt76xx_i2s_set_fmt, ++ //.set_sysclk = mt76xx_i2s_set_sysclk, ++}; ++ ++const struct snd_soc_component_driver mt76xx_i2s_component = { ++ .name = "mt76xx-i2s", ++}; ++ ++struct snd_soc_dai_driver mt76xx_i2s_dai = { ++ .playback = { ++ .channels_min = 1, ++ .channels_max = 2, ++ .rates = (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_11025|\ ++ SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_22050|SNDRV_PCM_RATE_32000|\ ++ SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000), ++ ++ .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ ++ SNDRV_PCM_FMTBIT_S24_LE), ++ }, ++ .capture = { ++ .channels_min = 1, ++ .channels_max = 2, ++ .rates = (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_11025|\ ++ SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_22050|SNDRV_PCM_RATE_32000|\ ++ SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000), ++ .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ ++ SNDRV_PCM_FMTBIT_S24_LE), ++ }, ++ .ops = &mt76xx_i2s_dai_ops, ++ .symmetric_rates = 1, ++}; ++ ++/****************************/ ++/*FUNCTION BODY */ ++/****************************/ ++ ++static int mt76xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai, ++ unsigned int fmt) ++{//TODO ++ ++ //printk("******* %s *******\n", __func__); ++ return 0; ++} ++ ++static int mt76xx_i2s_play_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) ++{ ++ //printk("******* %s *******\n", __func__); ++ i2s_config_type* rtd = (i2s_config_type*)substream->runtime->private_data; ++ rtd->pss[SNDRV_PCM_STREAM_PLAYBACK] = substream; ++ if(! rtd->i2sStat[SNDRV_PCM_STREAM_PLAYBACK]){ ++ i2s_reset_tx_param( rtd); ++ i2s_tx_config( rtd); ++ gdma_En_Switch(rtd, STREAM_PLAYBACK, GDMA_I2S_EN); ++ ++ if( rtd->bRxDMAEnable==0) ++ i2s_clock_enable( rtd); ++ ++ i2s_tx_enable( rtd); ++ rtd->i2sStat[SNDRV_PCM_STREAM_PLAYBACK] = 1; ++ MSG("I2S_TXENABLE done\n"); ++ } ++ ++ return 0; ++} ++ ++static int mt76xx_i2s_rec_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) ++{ ++ ++ //printk("******* %s *******\n", __func__); ++ i2s_config_type* rtd = (i2s_config_type*)substream->runtime->private_data; ++ rtd->pss[SNDRV_PCM_STREAM_CAPTURE] = substream; ++ if(! rtd->i2sStat[SNDRV_PCM_STREAM_CAPTURE]) { ++ i2s_reset_rx_param(rtd); ++ i2s_rx_config(rtd); ++ gdma_En_Switch(rtd, STREAM_CAPTURE, GDMA_I2S_EN); ++ ++ if(rtd->bTxDMAEnable==0) ++ i2s_clock_enable(rtd); ++ ++ i2s_rx_enable(rtd); ++ rtd->i2sStat[SNDRV_PCM_STREAM_CAPTURE] = 1; ++ } ++ return 0; ++} ++ ++/*static int mt76xx_i2s_shutdown(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ //i2s_config_type* rtd = (i2s_config_type*)substream->runtime->private_data; ++ //printk("******* %s *******\n", __func__); ++ return 0; ++} ++*/ ++static int mt76xx_i2s_startup(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ ++ //printk("******* %s *******\n", __func__); ++ if((!pi2s_config->i2sStat[SNDRV_PCM_STREAM_PLAYBACK]) && (!pi2s_config->i2sStat[SNDRV_PCM_STREAM_CAPTURE])){ ++ i2s_startup(); ++ if(!pi2s_config) ++ return -1; ++ i2s_reset_config(pi2s_config); ++ } ++ substream->runtime->private_data = pi2s_config; ++ return 0; ++} ++ ++static int mt76xx_i2s_hw_params(struct snd_pcm_substream *substream,\ ++ struct snd_pcm_hw_params *params,\ ++ struct snd_soc_dai *dai){ ++ unsigned int srate = 0; ++ //unsigned long data; ++ struct snd_pcm_runtime *runtime = substream->runtime; ++ i2s_config_type* rtd = runtime->private_data; ++ ++ //printk("******* %s *******\n", __func__); ++ switch(params_rate(params)){ ++ case 8000: ++ srate = 8000; ++ break; ++ case 16000: ++ srate = 16000; ++ break; ++ case 32000: ++ srate = 32000; ++ break; ++ case 44100: ++ srate = 44100; ++ break; ++ case 48000: ++ srate = 48000; ++ break; ++ default: ++ srate = 44100; ++ //MSG("audio sampling rate %u should be %d ~ %d Hz\n", (u32)params_rate(params), MIN_SRATE_HZ, MAX_SRATE_HZ); ++ break; ++ } ++ if(srate){ ++ if((rtd->bRxDMAEnable != GDMA_I2S_EN) && (rtd->bTxDMAEnable != GDMA_I2S_EN)){ ++ rtd->srate = srate; ++ MSG("set audio sampling rate to %d Hz\n", rtd->srate); ++ } ++ } ++ ++ return 0; ++} ++static int mt76xx_i2s_hw_free(struct snd_pcm_substream *substream,struct snd_soc_dai *dai){ ++ ++ //printk("******* %s *******\n", __func__); ++ i2s_config_type* rtd = (i2s_config_type*)substream->runtime->private_data; ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){ ++ if(rtd->i2sStat[SNDRV_PCM_STREAM_PLAYBACK]){ ++ MSG("I2S_TXDISABLE\n"); ++ i2s_reset_tx_param(rtd); ++ ++ if((rtd->bRxDMAEnable==0)&&(rtd->bTxDMAEnable==0)){ ++ i2s_clock_disable(rtd); ++ } ++ rtd->i2sStat[SNDRV_PCM_STREAM_PLAYBACK] = 0; ++ } ++ } ++ else{ ++ if(rtd->i2sStat[SNDRV_PCM_STREAM_CAPTURE]){ ++ MSG("I2S_RXDISABLE\n"); ++ i2s_reset_rx_param(rtd); ++ ++ if((rtd->bRxDMAEnable==0)&&(rtd->bTxDMAEnable==0)){ ++ i2s_clock_disable(rtd); ++ } ++ rtd->i2sStat[SNDRV_PCM_STREAM_CAPTURE] = 0; ++ } ++ } ++ return 0; ++} ++static int mt76xx_i2s_prepare(struct snd_pcm_substream *substream,struct snd_soc_dai *dai) ++{ ++ ++ //printk("******* %s *******\n", __func__); ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++ return mt76xx_i2s_play_prepare(substream, dai); ++ else ++ return mt76xx_i2s_rec_prepare(substream, dai); ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,20) ++static int mt76xx_i2s_drv_probe(struct platform_device *pdev) ++{ ++ //printk("****** %s ******\n", __func__); ++ return snd_soc_register_component(&pdev->dev, &mt76xx_i2s_component, ++ &mt76xx_i2s_dai, 1); ++} ++ ++static int mt76xx_i2s_drv_remove(struct platform_device *pdev) ++{ ++ snd_soc_unregister_component(&pdev->dev); ++ return 0; ++} ++ ++static struct platform_driver mt76xx_i2s_driver = { ++ .probe = mt76xx_i2s_drv_probe, ++ .remove = mt76xx_i2s_drv_remove, ++ .driver = { ++ .name = "mt76xx-i2s", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init mt76xx_i2s_init(void) ++{ ++ ++ //printk("****** %s ******\n", __func__); ++ return platform_driver_register(&mt76xx_i2s_driver); ++} ++ ++static void __exit mt76xx_i2s_exit(void) ++{ ++ //printk("****** %s ******\n", __func__); ++ platform_driver_unregister(&mt76xx_i2s_driver); ++} ++ ++module_init(mt76xx_i2s_init); ++module_exit(mt76xx_i2s_exit); ++ ++MODULE_AUTHOR("Dora Chen"); ++MODULE_DESCRIPTION("Stretch MT76xx I2S Interface"); ++MODULE_LICENSE("GPL"); ++#endif +--- /dev/null ++++ b/sound/soc/mtk/mt76xx_i2s.h +@@ -0,0 +1,18 @@ ++/* ++ * mtk_i2s.h ++ * ++ * Created on: 2013/8/20 ++ * Author: MTK04880 ++ */ ++ ++#ifndef MTK_I2S_H_ ++#define MTK_I2S_H_ ++ ++ ++#ifdef __KERNEL__ ++//#include <asm/rt2880/rt_mmap.h> ++#include <linux/fs.h> ++#endif ++ ++#include "i2s_ctrl.h" ++#endif /* MTK_I2S_H_ */ +--- /dev/null ++++ b/sound/soc/mtk/mt76xx_machine.c +@@ -0,0 +1,317 @@ ++/* ++ * mt76xx_machine.c ++ * ++ */ ++#include <linux/init.h> ++#include <linux/version.h> ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++#include <linux/sched.h> ++#endif ++#include <linux/module.h> ++#include <linux/kernel.h> /* printk() */ ++#include <linux/slab.h> /* kmalloc() */ ++#include <linux/fs.h> /* everything... */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/proc_fs.h> ++#include <linux/fcntl.h> /* O_ACCMODE */ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) ++#include <asm/system.h> /* cli(), *_flags */ ++#endif ++#include <asm/uaccess.h> /* copy_from/to_user */ ++#include <linux/interrupt.h> ++#include <linux/mm.h> ++#include <linux/dma-mapping.h> ++#include <sound/core.h> ++#include <linux/pci.h> ++#include <sound/pcm.h> ++#include <sound/pcm_params.h> ++#include <sound/soc.h> ++#include <sound/soc-dapm.h> ++#include <sound/initval.h> ++#include <linux/i2c.h> ++#include <linux/ioport.h> ++#include <linux/delay.h> ++#include "ralink_gdma.h" ++#include "mt76xx_i2s.h" ++#include "mt76xx_machine.h" ++#if defined(CONFIG_SND_SOC_WM8960) ++#include "../codecs/wm8960.h" ++#endif ++ ++#define I2C_AUDIO_DEV_ID (0) ++/****************************/ ++/*FUNCTION DECLRATION */ ++/****************************/ ++extern unsigned long i2s_codec_12p288Mhz[11]; ++extern unsigned long i2s_codec_12Mhz[11]; ++ ++ ++static int mt76xx_codec_clock_hwparams(struct snd_pcm_substream *substream,\ ++ struct snd_pcm_hw_params *params); ++static int mt76xx_codec_startup(struct snd_pcm_substream *substream); ++static int mt76xx_codec_init(struct snd_soc_pcm_runtime *rtd); ++extern struct snd_soc_dai_driver mt76xx_i2s_dai; ++extern struct snd_soc_platform_driver mt76xx_soc_platform; ++struct platform_device *mt76xx_audio_device; ++ ++#if defined(CONFIG_SND_SOC_WM8960) ++extern struct snd_soc_dai wm8960_dai; ++extern struct snd_soc_codec_device soc_codec_dev_wm8960; ++#endif ++ ++static struct snd_soc_ops mtk_audio_ops = { ++ .hw_params = mt76xx_codec_clock_hwparams, ++ .startup = mt76xx_codec_startup, ++}; ++ ++static struct snd_soc_dai_link mtk_audio_dai = { ++ .name = "mtk_dai", ++ .stream_name = "WMserious PCM", ++ .cpu_dai_name = "mt76xx-i2s", ++ .codec_dai_name = "wm8960-hifi", ++ .codec_name = "wm8960.0-001a", ++ .platform_name = "mt76xx-pcm", ++ .ignore_pmdown_time = true, ++ .init = mt76xx_codec_init, ++ .ops = &mtk_audio_ops, ++}; ++ ++static struct snd_soc_card mtk_audio_card = { ++ .name = "MTK APSoC I2S", ++ .owner = THIS_MODULE, ++ .dai_link = &mtk_audio_dai,//I2S/Codec ++ .num_links = 1, ++}; ++ ++static int mt76xx_codec_clock_hwparams(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *p = substream->private_data; ++ struct snd_soc_dai *codec_dai = p->codec_dai; ++ struct snd_pcm_runtime *runtime = substream->runtime; ++ i2s_config_type* rtd = runtime->private_data; ++ unsigned long data,index = 0; ++ unsigned long* pTable; ++ int mclk,ret,targetClk = 0; ++ ++ /*For duplex mode, avoid setting twice.*/ ++ if((rtd->bRxDMAEnable == GDMA_I2S_EN) || (rtd->bTxDMAEnable == GDMA_I2S_EN)) ++ return 0; ++#if defined(CONFIG_I2S_MCLK_12MHZ) ++ mclk = 12000000; ++#elif defined(CONFIG_I2S_MCLK_12P288MHZ) ++ mclk = 12288000; ++#else ++ mclk = 12000000; ++#endif ++ //snd_soc_dai_set_sysclk(codec_dai,0,mclk, SND_SOC_CLOCK_IN); ++ ++ switch(params_rate(params)){ ++ case 8000: ++ index = 0; ++ targetClk = 12288000; ++ break; ++ case 12000: ++ index = 2; ++ targetClk = 12288000; ++ break; ++ case 16000: ++ index = 3; ++ targetClk = 12288000; ++ break; ++ case 24000: ++ index = 5; ++ targetClk = 12288000; ++ break; ++ case 32000: ++ index = 6; ++ targetClk = 12288000; ++ break; ++ case 48000: ++ index = 8; ++ targetClk = 12288000; ++ break; ++ case 11025: ++ index = 1; ++ targetClk = 11289600; ++ break; ++ case 22050: ++ index = 4; ++ targetClk = 11289600; ++ break; ++ case 44100: ++ index = 7; ++ targetClk = 11289600; ++ break; ++ case 88200: ++ index = 9; ++ targetClk = 11289600; ++ break; ++ case 96000: ++ index = 10; ++ targetClk = 11289600; ++ break; ++ default: ++ index = 7; ++ targetClk = 12288000; ++ //MSG("audio sampling rate %u should be %d ~ %d Hz\n", (u32)params_rate(params), MIN_SRATE_HZ, MAX_SRATE_HZ); ++ break; ++ } ++#if defined(CONFIG_SND_SOC_WM8960) ++ /* ++ * There is a fixed divide by 4 in the PLL and a selectable ++ * divide by N after the PLL which should be set to divide by 2 to meet this requirement. ++ * */ ++ ret = snd_soc_dai_set_pll(codec_dai, 0, 0,mclk, targetClk*2); ++ /* From app notes: allow Vref to stabilize to reduce clicks */ ++ if(rtd->slave_en){ ++ //printk("WM8960 is in master mode\n"); ++ ret = snd_soc_dai_set_clkdiv(codec_dai, WM8960_DCLKDIV, 0x1c4); ++ ret = snd_soc_dai_set_clkdiv(codec_dai, WM8960_SYSCLKDIV, 0x5); ++ } ++ ++#endif ++ if(!rtd->slave_en) ++ snd_soc_dai_set_fmt(codec_dai,SND_SOC_DAIFMT_CBS_CFS|SND_SOC_DAIFMT_I2S|SND_SOC_DAIFMT_NB_NF); ++ else{ ++ snd_soc_dai_set_fmt(codec_dai,SND_SOC_DAIFMT_CBM_CFM|SND_SOC_DAIFMT_I2S|SND_SOC_DAIFMT_NB_NF); ++ } ++ mdelay(5); ++ ++#if defined(CONFIG_SND_SOC_WM8960) ++#if defined(CONFIG_I2S_MCLK_12MHZ) ++ pTable = i2s_codec_12Mhz; ++ data = pTable[index]; ++#else ++ pTable = i2s_codec_12p288Mhz; ++ data = pTable[index]; ++#endif ++ if(rtd->codec_pll_en) ++ ret = snd_soc_dai_set_clkdiv(codec_dai, WM8960_DACDIV, (data<<3)|0x5); ++ else ++ ret = snd_soc_dai_set_clkdiv(codec_dai, WM8960_DACDIV, (data<<3|0x4)); ++#endif ++ ++ return 0; ++} ++ ++static int mt76xx_codec_startup(struct snd_pcm_substream *substream) ++{ ++ //printk("******* %s *******\n", __func__); ++ return 0; ++} ++static int mt76xx_codec_init(struct snd_soc_pcm_runtime *rtd) ++{ ++ ++ //printk("******* %s *******\n", __func__); ++ return 0; ++} ++ ++static struct i2c_board_info i2c_board_info[] = { ++ { ++#if defined(CONFIG_SND_SOC_WM8750) ++ I2C_BOARD_INFO("wm8750", (0x36 >> 1)), ++#elif defined(CONFIG_SND_SOC_WM8960) ++ I2C_BOARD_INFO("codec_wm8960", (0x34)), ++ }, { ++ I2C_BOARD_INFO("wm8960", (0x34 >> 1)), ++#endif ++ } ++}; ++ ++static struct platform_device *soc_mtk_i2s_dev; ++static struct platform_device *soc_mtk_pcm_dev; ++ ++static int __init mt76xx_machine_init(void) ++{ ++ //struct snd_soc_device *socdev = &mtk_audio_devdata; ++ //struct i2c_adapter *adapter = NULL; ++ //struct i2c_client *client = NULL; ++ int ret = 0; ++ struct i2c_adapter *adapter = NULL; ++ struct i2c_client *client = NULL; ++ ++ adapter = i2c_get_adapter(I2C_AUDIO_DEV_ID); ++ if (!adapter) ++ return -ENODEV; ++ client = i2c_new_device(adapter, &i2c_board_info[0]); ++ if (!client) ++ return -ENODEV; ++ i2c_get_clientdata(client); ++ ++ client = i2c_new_device(adapter, &i2c_board_info[1]); ++ if (!client) ++ return -ENODEV; ++ i2c_get_clientdata(client); ++ ++ i2c_put_adapter(adapter); ++ ++ soc_mtk_i2s_dev = ++ platform_device_register_simple("mt76xx-i2s", -1, NULL, 0); ++ if (IS_ERR(soc_mtk_i2s_dev)) ++ return PTR_ERR(soc_mtk_i2s_dev); ++ ++ soc_mtk_pcm_dev = ++ platform_device_register_simple("mt76xx-pcm", -1, NULL, 0); ++ if (IS_ERR(soc_mtk_pcm_dev)) ++ return PTR_ERR(soc_mtk_pcm_dev); ++ ++ mt76xx_audio_device = platform_device_alloc("soc-audio",-1); ++ if (mt76xx_audio_device == NULL) { ++ ret = -ENOMEM; ++ goto err_device_alloc; ++ } ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) ++ platform_set_drvdata(mt76xx_audio_device, &mtk_audio_card); ++#else ++ platform_set_drvdata(mt76xx_audio_device, &mtk_audio_devdata); ++ mtk_audio_devdata.dev = &mt76xx_audio_device->dev; ++#endif ++ ++ /*Ralink I2S register process end*/ ++ ret = platform_device_add(mt76xx_audio_device); ++ if (ret) { ++ printk("mtk audio device : platform_device_add failed (%d)\n",ret); ++ goto err_device_add; ++ } ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) ++#else ++ snd_soc_register_dai(&mt76xx_i2s_dai); ++#endif ++ ++ return 0; ++ ++err_device_add: ++ if (mt76xx_audio_device!= NULL) { ++ platform_device_put(mt76xx_audio_device); ++ mt76xx_audio_device = NULL; ++ } ++err_device_alloc: ++ return ret; ++} ++ ++ ++static void __exit mt76xx_machine_exit(void) ++{ ++ ++ platform_device_unregister(mt76xx_audio_device); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,20) ++ /* Do nothing */ ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) ++ snd_soc_unregister_platform(&mt76xx_audio_device->dev); ++#else ++ snd_soc_unregister_platform(&mt76xx_soc_platform); ++#endif ++ platform_device_unregister(soc_mtk_i2s_dev); ++ platform_device_unregister(soc_mtk_pcm_dev); ++ ++ mt76xx_audio_device = NULL; ++} ++ ++//module_init(mt76xx_machine_init); ++late_initcall(mt76xx_machine_init); ++module_exit(mt76xx_machine_exit); ++//EXPORT_SYMBOL_GPL(mt76xx_soc_platform); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/sound/soc/mtk/mt76xx_machine.h +@@ -0,0 +1,21 @@ ++/* ++ * mtk_audio_device.h ++ * ++ * Created on: 2013/10/23 ++ * Author: MTK04880 ++ */ ++ ++#ifndef MT76XX_MACHINE_H_ ++#define MT76XX_MACHINE_H_ ++#include <sound/pcm.h> ++#include <sound/pcm_params.h> ++#include <sound/soc.h> ++#include <sound/soc-dapm.h> ++ ++#if 0 ++#ifdef CONFIG_I2S_MMAP ++#undef CONFIG_I2S_MMAP ++#endif ++#endif ++ ++#endif /* MT76XX_MACHINE_H_ */ +--- /dev/null ++++ b/sound/soc/mtk/mt76xx_pcm.c +@@ -0,0 +1,499 @@ ++/* ++ * mt76xx_pcm.c ++ * ++ * Created on: 2013/9/6 ++ * Author: MTK04880 ++ */ ++ ++#include <linux/init.h> ++#include <linux/version.h> ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++#include <linux/sched.h> ++#endif ++#include <linux/module.h> ++#include <linux/kernel.h> /* printk() */ ++#include <linux/slab.h> /* kmalloc() */ ++#include <linux/fs.h> /* everything... */ ++#include <linux/errno.h> /* error codes */ ++#include <linux/types.h> /* size_t */ ++#include <linux/proc_fs.h> ++#include <linux/fcntl.h> /* O_ACCMODE */ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) ++#include <asm/system.h> /* cli(), *_flags */ ++#endif ++#include <asm/uaccess.h> /* copy_from/to_user */ ++#include <linux/interrupt.h> ++#include <linux/mm.h> ++#include <linux/dma-mapping.h> ++#include <sound/core.h> ++#include <linux/pci.h> ++#include <sound/pcm.h> ++#include <sound/pcm_params.h> ++#include <sound/soc.h> ++#include <sound/soc-dapm.h> ++#include <sound/initval.h> ++#include "ralink_gdma.h" ++#include "mt76xx_i2s.h" ++ ++#define GDMA_PAGE_SIZE I2S_PAGE_SIZE ++#define GDMA_PAGE_NUM MAX_I2S_PAGE ++#define GDMA_TOTAL_PAGE_SIZE I2S_TOTAL_PAGE_SIZE ++ ++dma_addr_t i2s_txdma_addr, i2s_rxdma_addr; ++dma_addr_t i2s_mmap_addr[GDMA_PAGE_NUM*2]; ++ ++extern struct tasklet_struct i2s_tx_tasklet; ++extern struct tasklet_struct i2s_rx_tasklet; ++extern int i2s_mmap_remap(struct vm_area_struct *vma, unsigned long size); ++extern void i2s_tx_end_sleep_on(i2s_config_type* ptri2s_config); ++extern void i2s_rx_end_sleep_on(i2s_config_type* ptri2s_config); ++ ++static int mt76xx_pcm_open(struct snd_pcm_substream *substream); ++static int mt76xx_pcm_new(struct snd_soc_pcm_runtime *rtd); ++static void mt76xx_pcm_free(struct snd_pcm *pcm); ++static int mt76xx_pcm_close(struct snd_pcm_substream *substream); ++static snd_pcm_uframes_t mt76xx_pcm_pointer(struct snd_pcm_substream *substream); ++static int mt76xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd); ++static int mt76xx_pcm_prepare(struct snd_pcm_substream *substream); ++static int mt76xx_pcm_hw_params(struct snd_pcm_substream *substream,\ ++ struct snd_pcm_hw_params *hw_params); ++static int mt76xx_pcm_copy(struct snd_pcm_substream *substream, int channel,\ ++ snd_pcm_uframes_t pos,void __user *buf, snd_pcm_uframes_t count); ++static int mt76xx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma); ++static int mt76xx_pcm_hw_free(struct snd_pcm_substream *substream); ++ ++static int mt76xx_pcm_free_dma_buffer(struct snd_pcm_substream *substream,int stream); ++static int mt76xx_pcm_allocate_dma_buffer(struct snd_pcm_substream *substream,int stream); ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,20) ++static int mt76xx_platform_drv_probe(struct platform_device *pdev); ++static int mt76xx_platform_drv_remove(struct platform_device *pdev); ++#endif ++ ++static const struct snd_pcm_hardware mt76xx_pcm_hwparam = { ++#if defined(CONFIG_I2S_MMAP) ++ .info = (SNDRV_PCM_INFO_INTERLEAVED | ++ SNDRV_PCM_INFO_PAUSE | ++ SNDRV_PCM_INFO_RESUME | ++ SNDRV_PCM_INFO_MMAP | ++ SNDRV_PCM_INFO_MMAP_VALID), ++#else ++ .info = (SNDRV_PCM_INFO_INTERLEAVED | ++ SNDRV_PCM_INFO_PAUSE | ++ SNDRV_PCM_INFO_RESUME), ++#endif ++ .formats = SNDRV_PCM_FMTBIT_S16_LE, ++ .period_bytes_min = GDMA_PAGE_SIZE, ++ .period_bytes_max = GDMA_PAGE_SIZE, ++ .periods_min = 1, ++ .periods_max = GDMA_PAGE_NUM, ++ .buffer_bytes_max = GDMA_TOTAL_PAGE_SIZE, ++}; ++ ++static struct snd_pcm_ops mt76xx_pcm_ops = { ++ ++ .open = mt76xx_pcm_open, ++ .ioctl = snd_pcm_lib_ioctl, ++ .hw_params = mt76xx_pcm_hw_params, ++ .hw_free = mt76xx_pcm_hw_free, ++ .trigger = mt76xx_pcm_trigger, ++ .prepare = mt76xx_pcm_prepare, ++ .pointer = mt76xx_pcm_pointer, ++ .close = mt76xx_pcm_close, ++#if defined(CONFIG_I2S_MMAP) ++ .mmap = mt76xx_pcm_mmap, ++#endif ++ .copy = mt76xx_pcm_copy, ++}; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0) ++struct snd_soc_platform_driver mt76xx_soc_platform = { ++ .ops = &mt76xx_pcm_ops, ++ .pcm_new = mt76xx_pcm_new, ++ .pcm_free = mt76xx_pcm_free, ++}; ++#else ++struct snd_soc_platform mt76xx_soc_platform = { ++ .name = "mtk-dma", ++ .pcm_ops = &mt76xx_pcm_ops, ++ .pcm_new = mt76xx_pcm_new, ++ .pcm_free = mt76xx_pcm_free, ++}; ++#endif ++ ++static int mt76xx_pcm_close(struct snd_pcm_substream *substream){ ++ ++ //printk("******* %s *********\n", __func__); ++ return 0; ++} ++ ++static snd_pcm_uframes_t mt76xx_pcm_pointer(struct snd_pcm_substream *substream) ++{ ++ struct snd_pcm_runtime *runtime = substream->runtime; ++ i2s_config_type* rtd = runtime->private_data; ++ unsigned int offset = 0; ++ //int buff_frame_bond = bytes_to_frames(runtime, GDMA_PAGE_SIZE); ++ //printk("\n******* %s *********\n", __func__); ++ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){ ++ offset = bytes_to_frames(runtime, GDMA_PAGE_SIZE*rtd->tx_r_idx); ++ //printk("r:%d w:%d (%d) \n",rtd->tx_r_idx,rtd->tx_w_idx,(runtime->control->appl_ptr/buff_frame_bond)%GDMA_PAGE_NUM); ++ } ++ else{ ++ offset = bytes_to_frames(runtime, GDMA_PAGE_SIZE*rtd->rx_w_idx); ++ //printk("w:%d r:%d appl_ptr:%x\n",rtd->rx_w_idx,rtd->rx_r_idx,(runtime->control->appl_ptr/buff_frame_bond)%GDMA_PAGE_NUM); ++ } ++ return offset; ++} ++ ++ ++static int mt76xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) ++{ ++ int ret = 0; ++ i2s_config_type* rtd = (i2s_config_type*)substream->runtime->private_data; ++ //struct snd_pcm_runtime *runtime= substream->runtime; ++ ++ //printk("******* %s *********\n", __func__); ++/* printk("trigger cmd:%s\n",(cmd==SNDRV_PCM_TRIGGER_START)?"START":\ ++ (cmd==SNDRV_PCM_TRIGGER_RESUME)?"RESUME":\ ++ (cmd==SNDRV_PCM_TRIGGER_PAUSE_RELEASE)?"PAUSE_RELEASE":\ ++ (cmd==SNDRV_PCM_TRIGGER_STOP)?"STOP":\ ++ (cmd==SNDRV_PCM_TRIGGER_SUSPEND)?"SUSPEND":\ ++ (cmd==SNDRV_PCM_TRIGGER_PAUSE_PUSH)?"PAUSE_PUSH":"default"); ++*/ ++ switch (cmd) { ++ case SNDRV_PCM_TRIGGER_START: ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ rtd->bTrigger[SNDRV_PCM_STREAM_PLAYBACK] = 1; ++ } else { ++ rtd->bTrigger[SNDRV_PCM_STREAM_CAPTURE] = 1; ++ } ++ break; ++ case SNDRV_PCM_TRIGGER_STOP: ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ rtd->bTrigger[SNDRV_PCM_STREAM_PLAYBACK] = 0; ++ } else { ++ rtd->bTrigger[SNDRV_PCM_STREAM_CAPTURE] = 0; ++ } ++ break; ++ case SNDRV_PCM_TRIGGER_RESUME: ++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){ ++ rtd->tx_pause_en = 0; ++ } else { ++ rtd->rx_pause_en = 0; ++ } ++ break; ++ ++ case SNDRV_PCM_TRIGGER_SUSPEND: ++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH: ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){ ++ rtd->tx_pause_en = 1; ++ } else { ++ rtd->rx_pause_en = 1; ++ } ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ return ret; ++} ++ ++static int mt76xx_pcm_copy(struct snd_pcm_substream *substream, int channel,\ ++ snd_pcm_uframes_t pos,void __user *buf, snd_pcm_uframes_t count) ++{ ++ struct snd_pcm_runtime *runtime= substream->runtime; ++ i2s_config_type* rtd = runtime->private_data; ++ int tx_w_idx = 0; ++ int rx_r_idx = 0; ++ char *hwbuf = NULL; ++ ++ //printk("******* %s *********\n", __func__); ++ hwbuf = runtime->dma_area + frames_to_bytes(runtime, pos); ++ //MSG("%s bur:%x\n",__func__,hwbuf); ++ //printk("hw_ptr:%d, buffer_size:%d, appl_prt:%d, boundary:%d\n", ++ // runtime->status->hw_ptr, runtime->buffer_size, runtime->control->appl_ptr, runtime->boundary); ++ ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){ ++ rtd->tx_w_idx = (rtd->tx_w_idx+1)%MAX_I2S_PAGE; ++ tx_w_idx = rtd->tx_w_idx; ++ //printk("put TB[%d - %x] for user write\n",rtd->tx_w_idx,pos); ++ copy_from_user(rtd->pMMAPTxBufPtr[tx_w_idx], (char*)buf, I2S_PAGE_SIZE); ++ } ++ else{ ++ rx_r_idx = rtd->rx_r_idx; ++ rtd->rx_r_idx = (rtd->rx_r_idx+1)%MAX_I2S_PAGE; ++ copy_to_user((char*)buf, rtd->pMMAPRxBufPtr[rx_r_idx], I2S_PAGE_SIZE); ++ } ++ return 0; ++} ++ ++static int mt76xx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma) ++{ ++ int ret; ++ unsigned long size; ++ ++ size = vma->vm_end-vma->vm_start; ++ printk("******* %s: size :%lx end:%lx start:%lx *******\n", __func__,size,vma->vm_end,vma->vm_start); ++ ret = i2s_mmap_remap(vma, size); ++ ++ return ret; ++} ++ ++ ++static int mt76xx_pcm_prepare(struct snd_pcm_substream *substream) ++{ ++ struct snd_pcm_runtime *runtime= substream->runtime; ++ i2s_config_type *rtd = (i2s_config_type*)runtime->private_data; ++ //runtime->buffer_size = GDMA_PAGE_NUM*GDMA_PAGE_SIZE; ++ //runtime->boundary = (GDMA_PAGE_NUM*GDMA_PAGE_SIZE)/4; ++ ++ //printk("******* %s *******\n", __func__); ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){ ++ //printk("===== %s:%s:%d =====\n", __FILE__, __func__, __LINE__); ++ mt76xx_pcm_allocate_dma_buffer(substream,SNDRV_PCM_STREAM_PLAYBACK); ++ ++ if(! rtd->dmaStat[SNDRV_PCM_STREAM_PLAYBACK]){ ++ i2s_page_prepare(rtd,STREAM_PLAYBACK); ++ tasklet_init(&i2s_tx_tasklet, i2s_tx_task, (u32)rtd); ++ rtd->dmaStat[SNDRV_PCM_STREAM_PLAYBACK] = 1; ++ gdma_unmask_handler(GDMA_I2S_TX0); ++ } ++ } else { ++ mt76xx_pcm_allocate_dma_buffer(substream,SNDRV_PCM_STREAM_CAPTURE); ++ ++ if(! rtd->dmaStat[SNDRV_PCM_STREAM_CAPTURE]){ ++ i2s_page_prepare(rtd,STREAM_CAPTURE); /* TX:enLabel=1; RX:enLabel=2 */ ++ tasklet_init(&i2s_rx_tasklet, i2s_rx_task, (u32)rtd); ++ rtd->dmaStat[SNDRV_PCM_STREAM_CAPTURE] = 1; ++ gdma_unmask_handler(GDMA_I2S_RX0); ++ } ++ } ++ ++ return 0; ++} ++ ++ ++static int mt76xx_pcm_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *hw_params) ++{ ++ /*struct snd_pcm_runtime *runtime = substream->runtime; ++ i2s_config_type *rtd = (i2s_config_type*)runtime->private_data; ++ */ ++ int ret,i; ++ ret = i = 0; ++ ++ //printk("******* %s *******\n", __func__); ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){ ++ //i2s_page_prepare(rtd,STREAM_PLAYBACK); ++ } else { ++ //i2s_page_prepare(rtd,STREAM_CAPTURE); ++ } ++ ++ return ret; ++} ++ ++static int mt76xx_pcm_hw_free(struct snd_pcm_substream *substream) ++{ ++ i2s_config_type* rtd = (i2s_config_type*)substream->runtime->private_data; ++ //struct snd_dma_buffer *buf = &substream->dma_buffer; ++ ++ //printk("******* %s *******\n", __func__); ++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){ ++ if(rtd->dmaStat[SNDRV_PCM_STREAM_PLAYBACK]){ ++ ++ gdma_En_Switch(rtd,STREAM_PLAYBACK,GDMA_I2S_DIS); ++ i2s_tx_end_sleep_on(rtd); ++ tasklet_kill(&i2s_tx_tasklet); ++ i2s_tx_disable(rtd); ++ //mt76xx_pcm_free_dma_buffer(substream,substream->stream); ++ i2s_page_release(rtd,STREAM_PLAYBACK); ++ rtd->dmaStat[SNDRV_PCM_STREAM_PLAYBACK] = 0; ++ } ++ mt76xx_pcm_free_dma_buffer(substream,substream->stream); ++ } ++ else{ ++ if(rtd->dmaStat[SNDRV_PCM_STREAM_CAPTURE]){ ++ ++ gdma_En_Switch(rtd,STREAM_CAPTURE,GDMA_I2S_DIS); ++ i2s_tx_end_sleep_on(rtd); ++ tasklet_kill(&i2s_rx_tasklet); ++ i2s_rx_disable(rtd); ++ //mt76xx_pcm_free_dma_buffer(substream,substream->stream); ++ i2s_page_release(rtd,STREAM_CAPTURE); ++ rtd->dmaStat[SNDRV_PCM_STREAM_CAPTURE] = 0; ++ } ++ mt76xx_pcm_free_dma_buffer(substream,substream->stream); ++ } ++ return 0; ++} ++ ++static int mt76xx_pcm_free_dma_buffer(struct snd_pcm_substream *substream, ++ int stream) ++{ ++ ++ //struct snd_pcm_substream *substream = pcm->streams[stream].substream; ++ struct snd_dma_buffer *buf = &substream->dma_buffer; ++ i2s_config_type* rtd = (i2s_config_type*)substream->runtime->private_data; ++ ++ //printk("******* %s *******\n", __func__); ++ if (!buf->area) ++ return 0; ++ if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ++ i2s_memPool_free(rtd,STREAM_PLAYBACK); ++ else ++ i2s_memPool_free(rtd,STREAM_CAPTURE); ++ buf->area = NULL; ++ snd_pcm_set_runtime_buffer(substream, NULL); ++ return 0; ++} ++ ++static int mt76xx_pcm_allocate_dma_buffer(struct snd_pcm_substream *substream, ++ int stream) ++{ ++ //struct snd_pcm_substream *substream = pcm->streams[stream].substream; ++ struct snd_dma_buffer *buf = &substream->dma_buffer; ++ i2s_config_type* rtd = (i2s_config_type*)substream->runtime->private_data; ++ ++ //printk("******* %s *******\n", __func__); ++ if(!buf->area){ ++#if defined(CONFIG_I2S_MMAP) ++ printk("\n############## MMAP ##############\n"); ++ buf->dev.type = SNDRV_DMA_TYPE_DEV; ++#else ++ buf->dev.type = SNDRV_DMA_TYPE_UNKNOWN; ++#endif ++ buf->dev.dev = NULL; ++ buf->private_data = NULL; ++ if(stream == SNDRV_PCM_STREAM_PLAYBACK) ++ buf->area = i2s_memPool_Alloc(rtd,STREAM_PLAYBACK); ++ else ++ buf->area = i2s_memPool_Alloc(rtd,STREAM_CAPTURE); ++ ++ if (!buf->area) ++ return -ENOMEM; ++ buf->bytes = GDMA_TOTAL_PAGE_SIZE; ++#if defined(CONFIG_I2S_MMAP) ++ buf->addr = i2s_mmap_phys_addr(rtd); ++#endif ++ snd_pcm_set_runtime_buffer(substream, buf); ++ } else{ ++ //printk("Buffer have been allocated!\n"); ++ } ++ ++ return 0; ++} ++ ++static int mt76xx_pcm_open(struct snd_pcm_substream *substream) ++{ ++ struct snd_pcm_runtime *runtime= substream->runtime; ++ struct snd_dma_buffer *buf = &substream->dma_buffer; ++ int stream = substream->stream; ++ int ret = 0; ++ ++ //printk("******* %s *******\n", __func__); ++ snd_soc_set_runtime_hwparams(substream, &mt76xx_pcm_hwparam); ++ /* ensure that buffer size is a multiple of period size */ ++ ret = snd_pcm_hw_constraint_integer(runtime, ++ SNDRV_PCM_HW_PARAM_PERIODS); ++ if (ret < 0) ++ goto out; ++ ++#if 1 ++ if(stream == SNDRV_PCM_STREAM_PLAYBACK){ ++ ret = mt76xx_pcm_allocate_dma_buffer(substream, ++ SNDRV_PCM_STREAM_PLAYBACK); ++ } ++ else{ ++ ret = mt76xx_pcm_allocate_dma_buffer(substream, ++ SNDRV_PCM_STREAM_CAPTURE); ++ } ++#endif ++ ++ if (ret) ++ goto out; ++ ++ if(buf) ++ memset(buf->area,0,sizeof(I2S_PAGE_SIZE*MAX_I2S_PAGE)); ++ ++ out: ++ return ret; ++} ++ ++ ++ ++static int mt76xx_pcm_new(struct snd_soc_pcm_runtime *rtd) ++{ ++// int ret = 0; ++ ++ //printk("******* %s *******\n", __func__); ++ return 0; ++} ++ ++static void mt76xx_pcm_free(struct snd_pcm *pcm) ++{ ++ /*struct snd_pcm_substream *substream; ++ struct snd_dma_buffer *buf; ++ i2s_config_type* rtd; ++ int stream; ++*/ ++ //printk("******* %s *******\n", __func__); ++ //return 0; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,20) ++static int mt76xx_platform_drv_probe(struct platform_device *pdev) ++{ ++ //printk("******* %s *******\n", __func__); ++ return snd_soc_register_platform(&pdev->dev, &mt76xx_soc_platform); ++} ++ ++static int mt76xx_platform_drv_remove(struct platform_device *pdev) ++{ ++ //printk("******* %s *******\n", __func__); ++ snd_soc_unregister_platform(&pdev->dev); ++ return 0; ++} ++ ++static struct platform_driver mt76xx_pcm_driver = { ++ .driver = { ++ .name = "mt76xx-pcm", ++ .owner = THIS_MODULE, ++ }, ++ ++ .probe = mt76xx_platform_drv_probe, ++ .remove = mt76xx_platform_drv_remove, ++}; ++ ++static int __init mt76xx_pcm_init(void) ++{ ++ ++ printk("******* %s *******\n", __func__); ++ return platform_driver_register(&mt76xx_pcm_driver); ++} ++ ++static void __exit mt76xx_pcm_exit(void) ++{ ++ platform_driver_unregister(&mt76xx_pcm_driver); ++} ++#else ++static int __init mt76xx_pcm_init(void) ++{ ++ ++ printk("******* %s *******\n", __func__); ++ return snd_soc_register_platform(&mt76xx_soc_platform); ++} ++ ++static void __exit mt76xx_pcm_exit(void) ++{ ++ printk("******* %s *******\n", __func__); ++ snd_soc_unregister_platform(&mt76xx_soc_platform); ++} ++#endif ++module_init(mt76xx_pcm_init); ++module_exit(mt76xx_pcm_exit); ++ ++MODULE_AUTHOR("Dora Chen"); ++MODULE_DESCRIPTION("MTK APSoC I2S DMA driver"); ++MODULE_LICENSE("GPL"); ++ +--- /dev/null ++++ b/sound/soc/mtk/ralink_gdma.c +@@ -0,0 +1,918 @@ ++/* ++ *************************************************************************** ++ * Ralink Tech Inc. ++ * 5F., No.36, Taiyuan St., Jhubei City, ++ * Hsinchu County 302, ++ * Taiwan, R.O.C. ++ * ++ * (c) Copyright, Ralink Technology, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN ++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ *************************************************************************** ++ * ++ Module Name: ++ ralink_gdma.c ++ ++ Abstract: ++ ++ Revision History: ++ Who When What ++ -------- ---------- ---------------------------------------------- ++ Name Date Modification logs ++ Steven Liu 2009-03-24 Support RT3883 ++ * ++ */ ++#include <linux/init.h> ++#include <linux/version.h> ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/interrupt.h> ++#include <linux/fs.h> ++#if defined (CONFIG_MIPS) ++ #include <asm/uaccess.h> ++ #include <asm/addrspace.h> ++#endif ++ ++#include "ralink_gdma.h" ++ ++/* ++ * RT305x: ++ * Ch0 : Pcm0_Rx0 | Pcm0_Rx0 | ALL ++ * Ch1 : Pcm0_Rx1 | Pcm0_Rx1 | ALL ++ * Ch2 : Pcm0_Tx0 | Pcm0_Tx0 | ALL ++ * Ch3 : Pcm0_Tx1 | Pcm0_Tx1 | ALL ++ * Ch4 : Pcm1_Rx0 | I2S_Tx0 | ALL ++ * Ch5 : Pcm1_Rx1 | I2S_Tx1 | ALL ++ * Ch6 : Pcm1_Tx0 | ALL | ALL ++ * Ch7 : Pcm1_Tx1 | ALL | ALL ++ * ++ * RT3883: ++ * Ch0 : Pcm0_Rx0 | Pcm0_Rx0 | ALL ++ * Ch1 : Pcm0_Rx1 | Pcm0_Rx1 | ALL ++ * Ch2 : Pcm0_Tx0 | Pcm0_Tx0 | ALL ++ * Ch3 : Pcm0_Tx1 | Pcm0_Tx1 | ALL ++ * Ch4 : Pcm1_Rx0 | I2S_Tx0 | ALL ++ * Ch5 : Pcm1_Rx1 | I2S_Tx1 | ALL ++ * Ch6 : Pcm1_Tx0 | I2S_Rx0 | ALL ++ * Ch7 : Pcm1_Tx1 | I2S_Rx1 | ALL ++ * Ch8 : ALL | ALL | ALL ++ * Ch9 : ALL | ALL | ALL ++ * Ch10 : ALL | ALL | ALL ++ * Ch11 : ALL | ALL | ALL ++ * Ch12 : ALL | ALL | ALL PCI TX ++ * Ch13 : ALL | ALL | ALL PCI RX ++ * Ch14 : ALL | ALL | ALL ++ * Ch15 : ALL | ALL | ALL ++ * ++ */ ++ ++spinlock_t gdma_lock; ++spinlock_t gdma_lock_mem; ++spinlock_t gdma_int_lock; ++void (*GdmaDoneIntCallback[MAX_GDMA_CHANNEL])(uint32_t); ++void (*GdmaUnMaskIntCallback[MAX_GDMA_CHANNEL])(uint32_t); ++ ++ ++/** ++ * @brief Get free GDMA channel ++ * ++ * @param ChNum GDMA channel number ++ * @retval 1 channel is available ++ * @retval 0 channels are all busy ++ */ ++int _GdmaGetFreeCh(uint32_t *ChNum) ++{ ++ unsigned long flags; ++ uint32_t Data=0; ++ uint32_t Ch=0; ++#if defined (CONFIG_GDMA_DEBUG) ++ static uint32_t Ch_RR=0; ++#endif ++ ++ spin_lock_irqsave(&gdma_lock, flags); ++ ++#if defined (CONFIG_GDMA_PCM_ONLY) ++#if defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623) ++ for(Ch=14; Ch<MAX_GDMA_CHANNEL;Ch++) //channel 14~max_channe, channel 0~13 be usedl ++#else ++ for(Ch=MAX_GDMA_CHANNEL; Ch<MAX_GDMA_CHANNEL;Ch++) //no free channel ++#endif ++#elif defined (CONFIG_GDMA_PCM_I2S_OTHERS) ++#if defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623) ++ for(Ch=14; Ch<MAX_GDMA_CHANNEL;Ch++) //channel 14~max_channe, channel 0~13 be usedl ++#else ++ for(Ch=6; Ch<MAX_GDMA_CHANNEL;Ch++) //channel 6~max_channel ++#endif ++#elif defined (CONFIG_GDMA_EVERYBODY) ++ for(Ch=0; Ch<MAX_GDMA_CHANNEL;Ch++) //all channel ++#elif defined (CONFIG_GDMA_DEBUG) ++ for(Ch=(Ch_RR++)%MAX_GDMA_CHANNEL; Ch<MAX_GDMA_CHANNEL;Ch++) //round robin ++#endif ++ { ++ Data=GDMA_READ_REG(GDMA_CTRL_REG(Ch)); ++ ++ /* hardware will reset this bit if transaction is done. ++ * It means channel is free */ ++ if((Data & (0x01<<CH_EBL_OFFSET))==0) { ++ *ChNum = Ch; ++ spin_unlock_irqrestore(&gdma_lock, flags); ++ return 1; //Channel is free ++ } ++ } ++ ++ spin_unlock_irqrestore(&gdma_lock, flags); ++ return 0; // Channels are all busy ++ ++} ++ ++/** ++ * @brief Set channel is masked ++ * ++ * When channel is masked, the GDMA transaction will stop. ++ * When GDMA controller comes back from another channel (chain feature) ++ * ++ * >> Channel Mask=0: It's strange, and turns on related bit in GDMA interrupt ++ * status register (16:23 Unmasked) ++ * ++ * >> Channel Mask=1: It'll start GDMA transation, and clear this bit. ++ * ++ * @param ChNum GDMA channel number ++ * @retval 1 success ++ * @retval 0 fail ++ */ ++int GdmaMaskChannel(uint32_t ChNum) ++{ ++ uint32_t Data=0; ++ ++ Data=GDMA_READ_REG(GDMA_CTRL_REG1(ChNum)); ++ Data |= ( 0x01 << CH_MASK_OFFSET); ++ GDMA_WRITE_REG(GDMA_CTRL_REG1(ChNum), Data); ++ GDMA_PRINT("%s: Write %0X to %X\n", __FUNCTION__, Data, GDMA_CTRL_REG1(ChNum)); ++ ++ return 1; ++} ++ ++/** ++ * @brief Set channel is unmasked ++ * ++ * You can unmask the channel to start GDMA transaction. ++ * ++ * When GDMA controller comes back from another channel (chain feature) ++ * ++ * >> Channel Mask=0: It's strange, and turns on related bit in GDMA interrupt ++ * status register (16:23 Unmasked) ++ * ++ * >> Channel Mask=1: It'll start GDMA transation, and clear this bit. ++ * ++ * @param ChNum GDMA channel number ++ * @retval 1 success ++ * @retval 0 fail ++ */ ++int GdmaUnMaskChannel(uint32_t ChNum) ++{ ++ uint32_t Data=0; ++ ++ Data=GDMA_READ_REG(GDMA_CTRL_REG1(ChNum)); ++ Data &= ~( 0x01 << CH_MASK_OFFSET); ++ GDMA_WRITE_REG(GDMA_CTRL_REG1(ChNum), Data); ++ GDMA_PRINT("%s: Write %0X to %X\n", __FUNCTION__, Data, GDMA_CTRL_REG1(ChNum)); ++ ++ return 1; ++} ++ ++/** ++ * @brief Insert new GDMA entry to start GDMA transaction ++ * ++ * @param ChNum GDMA channel number ++ * @retval 1 success ++ * @retval 0 fail ++ */ ++int GdmaReqQuickIns(uint32_t ChNum) ++{ ++ uint32_t Data=0; ++ ++ //Mask Channel ++ Data = GDMA_READ_REG(GDMA_CTRL_REG1(ChNum)); ++ Data |= ( 0x1 << CH_MASK_OFFSET); ++ GDMA_WRITE_REG(GDMA_CTRL_REG1(ChNum), Data); ++ ++ //Channel Enable ++ Data = GDMA_READ_REG(GDMA_CTRL_REG(ChNum)); ++ Data |= (0x01<<CH_EBL_OFFSET); ++ GDMA_WRITE_REG(GDMA_CTRL_REG(ChNum), Data); ++ ++ return 1; ++ ++} ++ ++int _GdmaReqEntryIns(GdmaReqEntry *NewEntry) ++{ ++ uint32_t Data=0; ++ ++ GDMA_PRINT("== << GDMA Control Reg (Channel=%d) >> ===\n", NewEntry->ChNum); ++ GDMA_PRINT(" Channel Source Addr = %x \n", NewEntry->Src); ++ GDMA_PRINT(" Channel Dest Addr = %x \n", NewEntry->Dst); ++ GDMA_PRINT(" Transfer Count=%d\n", NewEntry->TransCount); ++ GDMA_PRINT(" Source DMA Req= DMA_REQ%d\n", NewEntry->SrcReqNum); ++ GDMA_PRINT(" Dest DMA Req= DMA_REQ%d\n", NewEntry->DstReqNum); ++ GDMA_PRINT(" Source Burst Mode=%s\n", NewEntry->SrcBurstMode ? "Fix" : "Inc"); ++ GDMA_PRINT(" Dest Burst Mode=%s\n", NewEntry->DstBurstMode ? "Fix" : "Inc"); ++ GDMA_PRINT(" Burst Size=%s\n", NewEntry->BurstSize ==0 ? "1 transfer" : \ ++ NewEntry->BurstSize ==1 ? "2 transfer" :\ ++ NewEntry->BurstSize ==2 ? "4 transfer" :\ ++ NewEntry->BurstSize ==3 ? "8 transfer" :\ ++ NewEntry->BurstSize ==4 ? "16 transfer" :\ ++ "Error"); ++ GDMA_PRINT(" Hardware/Software Mode = %s\n", NewEntry->SoftMode ? ++ "Soft" : "Hw"); ++ GDMA_PRINT("== << GDMA Control Reg1 (Channel=%d) >> =\n", NewEntry->ChNum); ++ GDMA_PRINT("Channel Done Interrput=%s\n", (NewEntry->DoneIntCallback!=NULL) ? ++ "Enable" : "Disable"); ++ GDMA_PRINT("Channel Unmasked Int=%s\n", (NewEntry->UnMaskIntCallback!=NULL) ? ++ "Enable" : "Disable"); ++#if !defined (CONFIG_RALINK_RT3052) && !defined (CONFIG_RALINK_RT3883) ++ GDMA_PRINT("Coherent Interrupt =%s\n", (NewEntry->CoherentIntEbl==1)? ++ "Enable" : "Disable"); ++#endif ++ GDMA_PRINT("Next Unmasked Channel=%d\n", NewEntry->NextUnMaskCh); ++ GDMA_PRINT("Channel Mask=%d\n", NewEntry->ChMask); ++ GDMA_PRINT("========================================\n"); ++ ++ GDMA_WRITE_REG(GDMA_SRC_REG(NewEntry->ChNum), NewEntry->Src); ++ GDMA_PRINT("SrcAddr: Write %0X to %X\n", \ ++ NewEntry->Src, GDMA_SRC_REG(NewEntry->ChNum)); ++ ++ GDMA_WRITE_REG(GDMA_DST_REG(NewEntry->ChNum), NewEntry->Dst); ++ GDMA_PRINT("DstAddr: Write %0X to %X\n", \ ++ NewEntry->Dst, GDMA_DST_REG(NewEntry->ChNum)); ++ ++ Data |= ( (NewEntry->NextUnMaskCh) << NEXT_UNMASK_CH_OFFSET); ++ Data |= ( NewEntry->ChMask << CH_MASK_OFFSET); ++#if !defined (CONFIG_RALINK_RT3052) && !defined (CONFIG_RALINK_RT3883) ++ Data |= ( NewEntry->CoherentIntEbl << COHERENT_INT_EBL_OFFSET); ++#endif ++ ++ if(NewEntry->UnMaskIntCallback!=NULL) { ++ Data |= (0x01<<CH_UNMASKINT_EBL_OFFSET); ++ GdmaUnMaskIntCallback[NewEntry->ChNum] = NewEntry->UnMaskIntCallback; ++ } ++ ++#if defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623) ++ Data |= (NewEntry->SrcReqNum << SRC_DMA_REQ_OFFSET); ++ Data |= (NewEntry->DstReqNum << DST_DMA_REQ_OFFSET); ++#endif ++ ++ GDMA_WRITE_REG(GDMA_CTRL_REG1(NewEntry->ChNum), Data); ++ GDMA_PRINT("CTRL1: Write %08X to %8X\n", Data, GDMA_CTRL_REG1(NewEntry->ChNum)); ++ ++ Data = ((NewEntry->TransCount) << TRANS_CNT_OFFSET); ++#if defined (CONFIG_RALINK_RT3052) ++ Data |= (NewEntry->SrcReqNum << SRC_DMA_REQ_OFFSET); ++ Data |= (NewEntry->DstReqNum << DST_DMA_REQ_OFFSET); ++#endif ++ Data |= (NewEntry->SrcBurstMode << SRC_BRST_MODE_OFFSET); ++ Data |= (NewEntry->DstBurstMode << DST_BRST_MODE_OFFSET); ++ Data |= (NewEntry->BurstSize << BRST_SIZE_OFFSET); ++ ++ if(NewEntry->DoneIntCallback!=NULL) { ++ Data |= (0x01<<CH_DONEINT_EBL_OFFSET); ++ GdmaDoneIntCallback[NewEntry->ChNum] = NewEntry->DoneIntCallback; ++ } ++ ++ if(NewEntry->SoftMode) { ++ Data |= (0x01<<MODE_SEL_OFFSET); ++ } ++ ++ Data |= (0x01<<CH_EBL_OFFSET); ++ GDMA_WRITE_REG(GDMA_CTRL_REG(NewEntry->ChNum), Data); ++ //GDMA_READ_REG(GDMA_CTRL_REG(NewEntry->ChNum)); ++ GDMA_PRINT("CTRL: Write %08X to %8X\n", Data, GDMA_CTRL_REG(NewEntry->ChNum)); ++ //if there is no interrupt handler, this function will ++ //return 1 until GDMA done. ++ if(NewEntry->DoneIntCallback==NULL) { ++ //wait for GDMA processing done ++#if defined (CONFIG_RALINK_RT3052) ++ while((GDMA_READ_REG(RALINK_GDMAISTS) & ++ (0x1<<NewEntry->ChNum))==0); ++ //write 1 clear ++ GDMA_WRITE_REG(RALINK_GDMAISTS, 1<< NewEntry->ChNum); ++#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623) ++ while((GDMA_READ_REG(RALINK_GDMA_DONEINT) & ++ (0x1<<NewEntry->ChNum))==0); ++ //write 1 clear ++ GDMA_WRITE_REG(RALINK_GDMA_DONEINT, 1<< NewEntry->ChNum); ++#endif ++ } ++ ++ return 1; ++ ++} ++ ++#if defined(CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623) ++/** ++ * @brief Start GDMA transaction for sending data to SPI ++ * ++ * @param *Src source address ++ * @param *Dst destination address ++ ++ * @param TransCount data length ++ * @param *DoneIntCallback callback function when transcation is done ++ * @param *UnMaskIntCallback callback func when ch mask field is incorrect ++ * @retval 1 success ++ * @retval 0 fail ++ */ ++int GdmaSpiTx( ++ uint32_t Src, ++ uint32_t Dst, ++ uint16_t TransCount, ++ void (*DoneIntCallback)(uint32_t data), ++ void (*UnMaskIntCallback)(uint32_t data) ++ ) ++{ ++ GdmaReqEntry Entry; ++ ++ #if defined (CONFIG_MIPS) ++ Entry.Src= (Src & 0x1FFFFFFF); ++ Entry.Dst= (Dst & 0x1FFFFFFF); ++ #else ++ Entry.Src= Src; ++ Entry.Dst= Dst; ++ #endif ++ Entry.TransCount = TransCount; ++ Entry.SrcBurstMode=INC_MODE; ++ Entry.DstBurstMode=FIX_MODE; ++ Entry.BurstSize=BUSTER_SIZE_4B; ++ Entry.SrcReqNum=DMA_MEM_REQ; ++ Entry.DstReqNum=DMA_SPI_TX_REQ; ++ Entry.DoneIntCallback=DoneIntCallback; ++ Entry.UnMaskIntCallback=UnMaskIntCallback; ++ Entry.SoftMode=0; ++ Entry.ChMask=0; ++ Entry.CoherentIntEbl=0; ++ ++ //enable chain feature ++ Entry.ChNum = GDMA_SPI_TX; ++ Entry.NextUnMaskCh = GDMA_SPI_TX; ++ ++ return _GdmaReqEntryIns(&Entry); ++} ++ ++int GdmaSpiRx( ++ uint32_t Src, ++ uint32_t Dst, ++ uint16_t TransCount, ++ void (*DoneIntCallback)(uint32_t data), ++ void (*UnMaskIntCallback)(uint32_t data) ++ ) ++{ ++ GdmaReqEntry Entry; ++ ++ #if defined (CONFIG_MIPS) ++ Entry.Src= (Src & 0x1FFFFFFF); ++ Entry.Dst= (Dst & 0x1FFFFFFF); ++ #else ++ Entry.Src= Src; ++ Entry.Dst= Dst; ++ #endif ++ Entry.TransCount = TransCount; ++ Entry.SrcBurstMode=FIX_MODE; ++ Entry.DstBurstMode=INC_MODE; ++ Entry.BurstSize=BUSTER_SIZE_4B; ++ Entry.SrcReqNum=DMA_SPI_RX_REQ; ++ Entry.DstReqNum=DMA_MEM_REQ; ++ Entry.DoneIntCallback=DoneIntCallback; ++ Entry.UnMaskIntCallback=UnMaskIntCallback; ++ Entry.SoftMode=0; ++ Entry.ChMask=0; ++ Entry.CoherentIntEbl=1; ++ ++ ++ //enable chain feature ++ Entry.ChNum=GDMA_SPI_RX; ++ Entry.NextUnMaskCh=GDMA_SPI_RX; ++ ++ ++ return _GdmaReqEntryIns(&Entry); ++ ++} ++#endif ++ ++ ++/** ++ * @brief Start GDMA transaction for sending data to I2S ++ * ++ * @param *Src source address ++ * @param *Dst destination address ++ * @param TxNo I2S Tx number ++ * @param TransCount data length ++ * @param *DoneIntCallback callback function when transcation is done ++ * @param *UnMaskIntCallback callback func when ch mask field is incorrect ++ * @retval 1 success ++ * @retval 0 fail ++ */ ++int GdmaI2sTx( ++ uint32_t Src, ++ uint32_t Dst, ++ uint8_t TxNo, ++ uint16_t TransCount, ++ void (*DoneIntCallback)(uint32_t data), ++ void (*UnMaskIntCallback)(uint32_t data) ++ ) ++{ ++ GdmaReqEntry Entry; ++ ++ #if defined (CONFIG_MIPS) ++ Entry.Src= (Src & 0x1FFFFFFF); ++ Entry.Dst= (Dst & 0x1FFFFFFF); ++ #else ++ Entry.Src= Src; ++ Entry.Dst= Dst; ++ #endif ++ Entry.TransCount = TransCount; ++ Entry.SrcBurstMode=INC_MODE; ++ Entry.DstBurstMode=FIX_MODE; ++ Entry.BurstSize=BUSTER_SIZE_4B; ++ Entry.SrcReqNum=DMA_MEM_REQ; ++ Entry.DstReqNum=DMA_I2S_TX_REQ; ++ Entry.DoneIntCallback=DoneIntCallback; ++ Entry.UnMaskIntCallback=UnMaskIntCallback; ++ Entry.SoftMode=0; ++ Entry.ChMask=1; ++ Entry.CoherentIntEbl=0; ++ ++ if(TxNo==0) { //TX0 ++ //enable chain feature ++ Entry.ChNum=GDMA_I2S_TX0; ++ Entry.NextUnMaskCh= (TransCount==4) ? GDMA_I2S_TX0 : GDMA_I2S_TX1; ++ }else if(TxNo==1) { //TX1 ++ //enable chain feature ++ Entry.ChNum=GDMA_I2S_TX1; ++ Entry.NextUnMaskCh= (TransCount==4) ? GDMA_I2S_TX1 : GDMA_I2S_TX0; ++ }else { ++ GDMA_PRINT("I2S Tx Number %x is invalid\n", TxNo); ++ return 0; ++ } ++ ++ return _GdmaReqEntryIns(&Entry); ++ ++} ++ ++ ++#if defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623) ++/** ++ * @brief Start GDMA transaction for receiving data to I2S ++ * ++ * @param *Src source address ++ * @param *Dst destination address ++ * @param TxNo I2S Tx number ++ * @param TransCount data length ++ * @param *DoneIntCallback callback function when transcation is done ++ * @param *UnMaskIntCallback callback func when ch mask field is incorrect ++ * @retval 1 success ++ * @retval 0 fail ++ */ ++int GdmaI2sRx( ++ uint32_t Src, ++ uint32_t Dst, ++ uint8_t RxNo, ++ uint16_t TransCount, ++ void (*DoneIntCallback)(uint32_t data), ++ void (*UnMaskIntCallback)(uint32_t data) ++ ) ++{ ++ GdmaReqEntry Entry; ++ #if defined (CONFIG_MIPS) ++ Entry.Src= (Src & 0x1FFFFFFF); ++ Entry.Dst= (Dst & 0x1FFFFFFF); ++ #else ++ Entry.Src= Src; ++ Entry.Dst= Dst; ++ #endif ++ Entry.TransCount = TransCount; ++ Entry.SrcBurstMode=FIX_MODE; ++ Entry.DstBurstMode=INC_MODE; ++ Entry.BurstSize=BUSTER_SIZE_4B; ++ Entry.SrcReqNum=DMA_I2S_RX_REQ; ++ Entry.DstReqNum=DMA_MEM_REQ; ++ Entry.DoneIntCallback=DoneIntCallback; ++ Entry.UnMaskIntCallback=UnMaskIntCallback; ++ Entry.SoftMode=0; ++ Entry.ChMask=1; ++ Entry.CoherentIntEbl=1; ++ ++ if(RxNo==0) { //RX0 ++ //enable chain feature ++ Entry.ChNum=GDMA_I2S_RX0; ++ Entry.NextUnMaskCh=(TransCount==4) ? GDMA_I2S_RX0 : GDMA_I2S_RX1; ++ }else if(RxNo==1) { //RX1 ++ //enable chain feature ++ Entry.ChNum=GDMA_I2S_RX1; ++ Entry.NextUnMaskCh=(TransCount==4) ? GDMA_I2S_RX1 : GDMA_I2S_RX0; ++ }else { ++ GDMA_PRINT("I2S Rx Number %x is invalid\n", RxNo); ++ return 0; ++ } ++ ++ return _GdmaReqEntryIns(&Entry); ++ ++} ++ ++#endif ++ ++/** ++ * @brief Start GDMA transaction for receiving data from PCM ++ * ++ * @param *Src source address ++ * @param *Dst destination address ++ * @param TransCount data length ++ * @param PcmNo PCM channel ++ * @param RxNo PCM Rx number ++ * @param *DoneIntCallback callback function when transcation is done ++ * @param *UnMaskIntCallback callback func when ch mask field is incorrect ++ * @retval 1 success ++ * @retval 0 fail ++ */ ++int GdmaPcmRx( ++ uint32_t Src, ++ uint32_t Dst, ++ uint8_t PcmNo, ++ uint8_t RxNo, ++ uint16_t TransCount, ++ void (*DoneIntCallback)(uint32_t data), ++ void (*UnMaskIntCallback)(uint32_t data) ++ ) ++{ ++ GdmaReqEntry Entry; ++ ++ #if defined (CONFIG_MIPS) ++ Entry.Src= (Src & 0x1FFFFFFF); ++ Entry.Dst= (Dst & 0x1FFFFFFF); ++ #else ++ Entry.Src= Src; ++ Entry.Dst= Dst; ++ #endif ++ Entry.TransCount = TransCount; ++ Entry.SrcBurstMode=FIX_MODE; ++ Entry.DstBurstMode=INC_MODE; ++ Entry.BurstSize=BUSTER_SIZE_4B; ++ Entry.DstReqNum=DMA_MEM_REQ; ++ Entry.DoneIntCallback=DoneIntCallback; ++ Entry.UnMaskIntCallback=UnMaskIntCallback; ++ Entry.SoftMode=0; ++ Entry.ChMask=1; ++ Entry.CoherentIntEbl=1; ++ ++ if(RxNo > 2) { ++ GDMA_PRINT("PCM Rx Number %x is invalid\n", RxNo); ++ return 0; ++ } ++ ++ switch(PcmNo) ++ { ++ case 0: ++ Entry.SrcReqNum=DMA_PCM_RX0_REQ; ++ break; ++ case 1: ++ Entry.SrcReqNum=DMA_PCM_RX1_REQ; ++ break; ++#if defined(CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623) ++ case 2: ++ Entry.SrcReqNum=DMA_PCM_RX2_REQ; ++ break; ++ case 3: ++ Entry.SrcReqNum=DMA_PCM_RX3_REQ; ++ break; ++#endif ++ default: ++ GDMA_PRINT("PCM Channel %x is invalid\n", PcmNo); ++ return 0; ++ } ++ Entry.ChNum=GDMA_PCM_RX(PcmNo,RxNo); ++ Entry.NextUnMaskCh=GDMA_PCM_RX(PcmNo,1-RxNo); ++ ++ return _GdmaReqEntryIns(&Entry); ++ ++} ++ ++/** ++ * @brief Start GDMA transaction for sending data to PCM ++ * ++ * @param *Src source address ++ * @param *Dst destination address ++ * @param TransCount data length ++ * @param PcmNo PCM channel ++ * @param TxNo PCM Tx number ++ * @param *DoneIntCallback callback func when transcation is done ++ * @param *UnMaskIntCallback callback func when ch mask field is incorrect ++ * @retval 1 success ++ * @retval 0 fail ++ */ ++int GdmaPcmTx( ++ uint32_t Src, ++ uint32_t Dst, ++ uint8_t PcmNo, ++ uint8_t TxNo, ++ uint16_t TransCount, ++ void (*DoneIntCallback)(uint32_t data), ++ void (*UnMaskIntCallback)(uint32_t data) ++ ) ++{ ++ GdmaReqEntry Entry; ++ ++ #if defined (CONFIG_MIPS) ++ Entry.Src= (Src & 0x1FFFFFFF); ++ Entry.Dst= (Dst & 0x1FFFFFFF); ++ #else ++ Entry.Src= Src; ++ Entry.Dst= Dst; ++ #endif ++ Entry.TransCount = TransCount; ++ Entry.SrcBurstMode=INC_MODE; ++ Entry.DstBurstMode=FIX_MODE; ++ Entry.BurstSize=BUSTER_SIZE_4B; ++ Entry.SrcReqNum=DMA_MEM_REQ; ++ Entry.DoneIntCallback=DoneIntCallback; ++ Entry.UnMaskIntCallback=UnMaskIntCallback; ++ Entry.SoftMode=0; //Hardware Mode ++ Entry.ChMask=1; ++ Entry.CoherentIntEbl=0; ++ ++ if(TxNo > 2) { ++ GDMA_PRINT("PCM Tx Number %x is invalid\n", TxNo); ++ return 0; ++ } ++ switch(PcmNo) ++ { ++ case 0: ++ Entry.DstReqNum=DMA_PCM_TX0_REQ; ++ break; ++ case 1: ++ Entry.DstReqNum=DMA_PCM_TX1_REQ; ++ break; ++#if defined(CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623) ++ case 2: ++ Entry.DstReqNum=DMA_PCM_TX2_REQ; ++ break; ++ case 3: ++ Entry.DstReqNum=DMA_PCM_TX3_REQ; ++ break; ++#endif ++ default: ++ GDMA_PRINT("PCM Channel %x is invalid\n", PcmNo); ++ return 0; ++ } ++ Entry.ChNum=GDMA_PCM_TX(PcmNo,TxNo); ++ Entry.NextUnMaskCh=GDMA_PCM_TX(PcmNo,1-TxNo); ++ ++ return _GdmaReqEntryIns(&Entry); ++ ++} ++ ++ ++/** ++ * @brief Start GDMA transaction for memory to memory copy ++ * ++ * @param *Src source address ++ * @param *Dst destination address ++ * @param TransCount data length ++ * @param *DoneIntCallback callback function when transcation is done ++ * @retval 1 success ++ * @retval 0 fail ++ */ ++int GdmaMem2Mem( ++ uint32_t Src, ++ uint32_t Dst, ++ uint16_t TransCount, ++ void (*DoneIntCallback)(uint32_t data) ++ ) ++ ++{ ++ ++ GdmaReqEntry Entry; ++ #if defined (CONFIG_MIPS) ++ Entry.Src= (Src & 0x1FFFFFFF); ++ Entry.Dst= (Dst & 0x1FFFFFFF); ++ #else ++ Entry.Src= Src; ++ Entry.Dst= Dst; ++ #endif ++ ++ //Entry.Src= virt_to_phys(Src); ++ //Entry.Dst= virt_to_phys(Dst); ++ ++ ++ ++ Entry.TransCount = TransCount; ++ Entry.SrcBurstMode=INC_MODE; ++ Entry.DstBurstMode=INC_MODE; ++ Entry.BurstSize=BUSTER_SIZE_64B; ++ Entry.SrcReqNum=DMA_MEM_REQ; ++ Entry.DstReqNum=DMA_MEM_REQ; ++ Entry.DoneIntCallback=DoneIntCallback; ++ Entry.UnMaskIntCallback=NULL; ++ Entry.SoftMode=1; ++ Entry.ChMask=0; ++ ++ Entry.CoherentIntEbl=1; ++ ++ //No reserved channel for Memory to Memory GDMA, ++ //get free channel on demand ++ if(!_GdmaGetFreeCh(&Entry.ChNum)) { ++ GDMA_PRINT("GDMA Channels are all busy\n"); ++ return 0; ++ } ++ ++ ++ //set next channel to their own channel ++ //to disable chain feature ++ Entry.NextUnMaskCh= Entry.ChNum; ++ //printk ("ChNum = %d\n", Entry.ChNum); ++ //set next channel to another channel ++ //to enable chain feature ++ //Entry.NextUnMaskCh= (Entry.ChNum+1) % MAX_GDMA_CHANNEL; ++ ++ return _GdmaReqEntryIns(&Entry); ++ ++ ++} ++ ++/** ++ * @brief GDMA interrupt handler ++ * ++ * When GDMA transcation is done, call related handler ++ * to do the remain job. ++ * ++ */ ++irqreturn_t GdmaIrqHandler( ++ int irq, ++ void *irqaction ++ ) ++{ ++ ++ u32 Ch=0; ++ unsigned long flags; ++#if defined (CONFIG_RALINK_RT3052) ++ u32 GdmaUnMaskStatus=GDMA_READ_REG(RALINK_GDMAISTS) & 0xFF0000; ++ u32 GdmaDoneStatus=GDMA_READ_REG(RALINK_GDMAISTS) & 0xFF; ++#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623) ++ u32 GdmaUnMaskStatus=GDMA_READ_REG(RALINK_GDMA_UNMASKINT); ++ u32 GdmaDoneStatus=GDMA_READ_REG(RALINK_GDMA_DONEINT); ++#endif ++ //printk("********GDMA Interrupt*******************\n"); ++ ++ //GDMA_PRINT("========================================\n"); ++ //GDMA_PRINT("GdmaUnMask Interrupt=%x\n",GdmaUnMaskStatus); ++ //GDMA_PRINT("GdmaDone Interrupt=%x\n",GdmaDoneStatus); ++ //GDMA_PRINT("========================================\n"); ++ ++ spin_lock_irqsave(&gdma_int_lock, flags); ++ ++ //write 1 clear ++#if defined (CONFIG_RALINK_RT3052) ++ GDMA_WRITE_REG(RALINK_GDMAISTS, GdmaUnMaskStatus); ++#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623) ++ GDMA_WRITE_REG(RALINK_GDMA_UNMASKINT, GdmaUnMaskStatus); ++#endif ++ ++ //UnMask error ++ for(Ch=0;Ch<MAX_GDMA_CHANNEL;Ch++) { ++ ++ if(GdmaUnMaskStatus & (0x1 << (UNMASK_INT_STATUS(Ch))) ) { ++ if(GdmaUnMaskIntCallback[Ch] != NULL) { ++ GdmaUnMaskIntCallback[Ch](Ch); ++ // printk("GdmaUnMaskIntCallback \n"); ++ } ++ } ++ } ++ ++ //write 1 clear ++#if defined (CONFIG_RALINK_RT3052) ++ GDMA_WRITE_REG(RALINK_GDMAISTS, GdmaDoneStatus); ++#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623) ++ GDMA_WRITE_REG(RALINK_GDMA_DONEINT, GdmaDoneStatus); ++#endif ++ ++ //printk("interrupt status = %x \n", GdmaDoneStatus); ++ //processing done ++ for(Ch=0;Ch<MAX_GDMA_CHANNEL;Ch++) { ++ if(GdmaDoneStatus & (0x1<<Ch)) { ++ if(GdmaDoneIntCallback[Ch] != NULL) { ++ //printk("*************Interrupt Ch=%d***********\n", Ch); ++ GdmaDoneIntCallback[Ch](Ch); ++ } ++ } ++ } ++ ++//printk("interrupt status clear = %x \n", GDMA_READ_REG(RALINK_GDMA_DONEINT)); ++ spin_unlock_irqrestore(&gdma_int_lock, flags); ++ ++ return IRQ_HANDLED; ++ ++} ++ ++static int RalinkGdmaInit(void) ++{ ++ ++ uint32_t Ret=0; ++ uint32_t val = 0; ++ printk("Enable Ralink GDMA Controller Module \n"); ++#if defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623) ++ printk("GDMA IP Version=%d\n", GET_GDMA_IP_VER); ++#endif ++spin_lock_init(&gdma_int_lock); ++spin_lock_init(&gdma_lock); ++//spin_lock_init(&gdma_lock_mem); ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) ++ #if defined (CONFIG_MIPS) ++ Ret = request_irq(SURFBOARDINT_DMA, GdmaIrqHandler, \ ++ IRQF_DISABLED, "Ralink_DMA", NULL); ++ #else ++ Ret = request_irq(SURFBOARDINT_DMA, GdmaIrqHandler, \ ++ IRQF_TRIGGER_LOW, "Ralink_DMA", NULL); ++ #endif ++#else ++ Ret = request_irq(SURFBOARDINT_DMA, GdmaIrqHandler, \ ++ SA_INTERRUPT, "Ralink_DMA", NULL); ++#endif ++ ++/* ++ Ret = request_irq(131, GdmaIrqHandler, \ ++ IRQF_TRIGGER_LOW, "Ralink_DMA", NULL); ++ */ ++ if(Ret){ ++ GDMA_PRINT("IRQ %d is not free.\n", SURFBOARDINT_DMA); ++ return 1; ++ } ++ ++#if defined (CONFIG_MIPS) ++ //Enable GDMA interrupt ++ val = le32_to_cpu(*(volatile u32 *)(RALINK_REG_INTENA)); ++ val |= RALINK_INTCTL_DMA; ++ GDMA_WRITE_REG(RALINK_REG_INTENA, val); ++#endif ++ ++ //Channel0~Channel7 are round-robin ++#if defined (CONFIG_RALINK_RT3052) ++ GDMA_WRITE_REG(RALINK_GDMAGCT, 0x01); ++#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623) ++ GDMA_WRITE_REG(RALINK_GDMA_GCT, 0x01); ++#else ++#error Please Choose System Type ++#endif ++ ++ return 0; ++} ++ ++static void __exit RalinkGdmaExit(void) ++{ ++ ++ printk("Disable Ralink GDMA Controller Module\n"); ++#if defined (CONFIG_MIPS) ++ //Disable GDMA interrupt ++ GDMA_WRITE_REG(RALINK_REG_INTDIS, RALINK_INTCTL_DMA); ++#endif ++ free_irq(SURFBOARDINT_DMA, NULL); ++} ++ ++module_init(RalinkGdmaInit); ++module_exit(RalinkGdmaExit); ++ ++EXPORT_SYMBOL(GdmaI2sRx); ++EXPORT_SYMBOL(GdmaI2sTx); ++EXPORT_SYMBOL(GdmaPcmRx); ++EXPORT_SYMBOL(GdmaPcmTx); ++#if defined(CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623) ++EXPORT_SYMBOL(GdmaSpiRx); ++EXPORT_SYMBOL(GdmaSpiTx); ++#endif ++EXPORT_SYMBOL(GdmaMem2Mem); ++EXPORT_SYMBOL(GdmaReqQuickIns); ++EXPORT_SYMBOL(GdmaMaskChannel); ++EXPORT_SYMBOL(GdmaUnMaskChannel); ++ ++ ++MODULE_DESCRIPTION("Ralink SoC GDMA Controller API Module"); ++MODULE_AUTHOR("Steven Liu <steven_liu@ralinktech.com.tw>"); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION(MOD_VERSION); +--- /dev/null ++++ b/sound/soc/mtk/ralink_gdma.h +@@ -0,0 +1,326 @@ ++/* ++ *************************************************************************** ++ * Ralink Tech Inc. ++ * 5F., No.36, Taiyuan St., Jhubei City, ++ * Hsinchu County 302, ++ * Taiwan, R.O.C. ++ * ++ * (c) Copyright, Ralink Technology, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN ++ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ++ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ++ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ *************************************************************************** ++ */ ++ ++#ifndef __RALINK_DMA_CTRL_H__ ++#define __RALINK_DMA_CTRL_H__ ++ ++//#include <asm/rt2880/rt_mmap.h> ++ ++/* ++ * DEFINITIONS AND MACROS ++ */ ++#define MOD_VERSION "0.4" ++ ++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7623) ++#define MAX_GDMA_CHANNEL 16 ++#elif defined (CONFIG_RALINK_RT3052) ++#define MAX_GDMA_CHANNEL 8 ++#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7628) ++#define MAX_GDMA_CHANNEL 16 ++#else ++#error Please Choose System Type ++#endif ++ ++ ++#define RALINK_GDMA_CTRL_BASE (RALINK_GDMA_BASE) ++#if defined (CONFIG_RALINK_RT3052) ++#define RALINK_GDMAISTS (RALINK_GDMA_BASE + 0x80) ++#define RALINK_GDMAGCT (RALINK_GDMA_BASE + 0x88) ++#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623) ++#define RALINK_GDMA_UNMASKINT (RALINK_GDMA_BASE + 0x200) ++#define RALINK_GDMA_DONEINT (RALINK_GDMA_BASE + 0x204) ++#define RALINK_GDMA_GCT (RALINK_GDMA_BASE + 0x220) ++#endif ++ ++#define KSEG1 0xa0000000 ++#define PHYS_TO_VIRT(x) ((void *)((x) | KSEG1)) ++#define VIRT_TO_PHYS(x) ((unsigned long)(x) & ~KSEG1) ++ ++ ++ ++ ++#if defined (CONFIG_ARCH_MT7623) ++#include <mach/sync_write.h> ++#define GDMA_READ_REG(phys) (*(volatile unsigned int *)((phys))) ++#define GDMA_WRITE_REG(phys, val) mt65xx_reg_sync_writel((val), (phys)) ++ ++#else ++#define GDMA_READ_REG(addr) (le32_to_cpu(*(volatile u32 *)(addr))) ++#define GDMA_WRITE_REG(addr, val) *((volatile uint32_t *)(addr)) = cpu_to_le32(val) ++ ++ ++ ++#endif ++ ++ ++#define GET_GDMA_IP_VER (GDMA_READ_REG(RALINK_GDMA_GCT) & 0x6) >> 1 //GDMA_GCT[2:1] ++ ++#define RALINK_IRQ_ADDR RALINK_INTCL_BASE ++#if defined (CONFIG_RALINK_MT7621) || defined (CONFIG_ARCH_MT7628) ++#define RALINK_REG_INTENA (RALINK_IRQ_ADDR + 0x80) ++#define RALINK_REG_INTDIS (RALINK_IRQ_ADDR + 0x78) ++#else ++#define RALINK_REG_INTENA (RALINK_IRQ_ADDR + 0x34) ++#define RALINK_REG_INTDIS (RALINK_IRQ_ADDR + 0x38) ++#endif ++ ++/* ++ * 12bytes=GDMA Channel n Source Address(4) + ++ * GDMA Channel n Destination Address(4) + ++ * GDMA Channel n Control Register(4) ++ * ++ */ ++#define GDMA_SRC_REG(ch) (RALINK_GDMA_BASE + ch*16) ++#define GDMA_DST_REG(ch) (GDMA_SRC_REG(ch) + 4) ++#define GDMA_CTRL_REG(ch) (GDMA_DST_REG(ch) + 4) ++#define GDMA_CTRL_REG1(ch) (GDMA_CTRL_REG(ch) + 4) ++ ++//GDMA Interrupt Status Register ++#if defined (CONFIG_RALINK_RT3052) ++#define UNMASK_INT_STATUS(ch) (ch+16) ++#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623) ++#define UNMASK_INT_STATUS(ch) (ch) ++#endif ++#define TXDONE_INT_STATUS(ch) (ch) ++ ++//Control Reg0 ++#define MODE_SEL_OFFSET 0 ++#define CH_EBL_OFFSET 1 ++#define CH_DONEINT_EBL_OFFSET 2 ++#define BRST_SIZE_OFFSET 3 ++#define DST_BRST_MODE_OFFSET 6 ++#define SRC_BRST_MODE_OFFSET 7 ++#define TRANS_CNT_OFFSET 16 ++ ++//Control Reg1 ++#if defined (CONFIG_RALINK_RT3052) ++#define CH_UNMASKINT_EBL_OFFSET 4 ++#define NEXT_UNMASK_CH_OFFSET 1 ++#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623) ++#define CH_UNMASKINT_EBL_OFFSET 1 ++#define NEXT_UNMASK_CH_OFFSET 3 ++#endif ++#define COHERENT_INT_EBL_OFFSET 2 ++#define CH_MASK_OFFSET 0 ++ ++ ++#if defined (CONFIG_RALINK_RT3052) ++//Control Reg0 ++#define DST_DMA_REQ_OFFSET 8 ++#define SRC_DMA_REQ_OFFSET 12 ++#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) || defined (CONFIG_RALINK_RT6855A) || defined (CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623) ++//Control Reg1 ++#define DST_DMA_REQ_OFFSET 8 ++#define SRC_DMA_REQ_OFFSET 16 ++#endif ++ ++#define GDMA_PCM0_RX0 0 ++#define GDMA_PCM0_RX1 1 ++#define GDMA_PCM0_TX0 2 ++#define GDMA_PCM0_TX1 3 ++ ++#define GDMA_PCM1_RX0 4 ++#define GDMA_PCM1_RX1 5 ++#define GDMA_PCM1_TX0 6 ++#define GDMA_PCM1_TX1 7 ++ ++#define GDMA_PCM_RX(i,j) (0+((i)<<2)+j) ++#define GDMA_PCM_TX(i,j) (2+((i)<<2)+j) ++ ++#define GDMA_I2S_TX0 4 ++#define GDMA_I2S_TX1 5 ++#define GDMA_I2S_RX0 6 ++#define GDMA_I2S_RX1 7 ++ ++#define GDMA_SPI_TX 13 ++#define GDMA_SPI_RX 12 ++ ++ ++//#define GDMA_DEBUG ++#ifdef GDMA_DEBUG ++#define GDMA_PRINT(fmt, args...) printk(KERN_INFO "GDMA: " fmt, ## args) ++#else ++#define GDMA_PRINT(fmt, args...) { } ++#endif ++ ++/* ++ * TYPEDEFS AND STRUCTURES ++ */ ++ ++enum GdmaBusterMode { ++ INC_MODE=0, ++ FIX_MODE=1 ++}; ++ ++enum GdmaBusterSize { ++ BUSTER_SIZE_4B=0, /* 1 transfer */ ++ BUSTER_SIZE_8B=1, /* 2 transfer */ ++ BUSTER_SIZE_16B=2, /* 4 transfer */ ++ BUSTER_SIZE_32B=3, /* 8 transfer */ ++ BUSTER_SIZE_64B=4 /* 16 transfer */ ++}; ++ ++enum GdmaDmaReqNum { ++#if defined (CONFIG_RALINK_RT3052) ++ DMA_REQ0=0, ++ DMA_NAND_REQ=1, ++ DMA_I2S_TX_REQ=2, ++ DMA_PCM_RX0_REQ=3, ++ DMA_PCM_RX1_REQ=4, ++ DMA_PCM_TX0_REQ=5, ++ DMA_PCM_TX1_REQ=6, ++ DMA_REG7=7, ++ DMA_MEM_REQ=8 ++#elif defined (CONFIG_RALINK_RT3883) || defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) ++ DMA_REQ0=0, ++ DMA_NAND_REQ=1, ++ DMA_I2S_TX_REQ=2, ++ DMA_I2S_RX_REQ=3, ++ DMA_PCM_RX0_REQ=4, ++ DMA_PCM_RX1_REQ=5, ++ DMA_PCM_TX0_REQ=6, ++ DMA_PCM_TX1_REQ=7, ++ DMA_CODEC0_REQ8=8, ++ DMA_CODEC1_REQ9=9, ++ DMA_REQ10=10, ++ DMA_REQ11=11, ++ DMA_REQ12=12, ++ DMA_REQ13=13, ++ DMA_REQ14=14, ++ DMA_REQ15=15, ++ ++ #if defined (CONFIG_RALINK_RT3883) ++ DMA_MEM_REQ=16 ++ #elif defined (CONFIG_RALINK_RT3352) || defined (CONFIG_RALINK_RT5350) || defined (CONFIG_RALINK_RT6855) ++ DMA_MEM_REQ=32 ++ #endif ++ ++#elif defined(CONFIG_RALINK_MT7620) || defined (CONFIG_RALINK_MT7621) || defined (CONFIG_RALINK_MT7628) || defined (CONFIG_ARCH_MT7623) ++ DMA_REQ0=0, ++ DMA_NAND_REQ=1, ++ DMA_I2S_TX_REQ=2, ++ DMA_I2S_RX_REQ=3, ++ DMA_PCM_RX0_REQ=4, ++ DMA_PCM_RX1_REQ=5, ++ DMA_PCM_TX0_REQ=6, ++ DMA_PCM_TX1_REQ=7, ++ DMA_PCM_RX2_REQ=8, ++ DMA_PCM_RX3_REQ=9, ++ DMA_PCM_TX2_REQ=10, ++ DMA_PCM_TX3_REQ=11, ++ DMA_SPI_RX_REQ=12, ++ DMA_SPI_TX_REQ=13, ++ DMA_MEM_REQ=32 ++ ++#elif defined (CONFIG_RALINK_RT6855A) ++ DMA_NAND_REQ=0, ++ DMA_I2S_TX_REQ=1, ++ DMA_I2S_RX_REQ=2, ++ DMA_REQ0=3, ++ DMA_PCM_RX0_REQ=4, ++ DMA_PCM_RX1_REQ=5, ++ DMA_PCM_TX0_REQ=6, ++ DMA_PCM_TX1_REQ=7, ++ DMA_CODEC0_REQ8=8, ++ DMA_CODEC1_REQ9=9, ++ DMA_REQ10=10, ++ DMA_REQ11=11, ++ DMA_REQ12=12, ++ DMA_REQ13=13, ++ DMA_REQ14=14, ++ DMA_REQ15=15, ++ DMA_MEM_REQ=32 ++#else ++#error Please Choose System Type ++#endif ++}; ++ ++ ++ ++typedef struct { ++ uint32_t Src; ++ uint32_t Dst; ++ uint16_t TransCount; ++ uint8_t SoftMode; ++ uint8_t NextUnMaskCh; ++ uint8_t ChMask; ++ uint8_t CoherentIntEbl; ++ uint32_t ChNum; ++ enum GdmaDmaReqNum SrcReqNum; ++ enum GdmaDmaReqNum DstReqNum; ++ enum GdmaBusterMode SrcBurstMode; ++ enum GdmaBusterMode DstBurstMode; ++ enum GdmaBusterSize BurstSize; ++ void (*DoneIntCallback)(uint32_t); ++ void (*UnMaskIntCallback)(uint32_t); ++} GdmaReqEntry; ++ ++/* ++ * EXPORT FUNCTION ++ */ ++int GdmaI2sTx(uint32_t Src, uint32_t Dst, uint8_t TxNo, uint16_t TransCount, ++ void (*DoneIntCallback)(uint32_t data), ++ void (*UnMaskIntCallback)(uint32_t data)); ++ ++int GdmaI2sRx(uint32_t Src, uint32_t Dst, uint8_t RxNo, uint16_t TransCount, ++ void (*DoneIntCallback)(uint32_t data), ++ void (*UnMaskIntCallback)(uint32_t data)); ++ ++int GdmaPcmRx(uint32_t Src, uint32_t Dst, uint8_t PcmNo, uint8_t RxNo, uint16_t TransCount, ++ void (*DoneIntCallback)(uint32_t data), ++ void (*UnMaskIntCallback)(uint32_t data)); ++ ++int GdmaPcmTx(uint32_t Src, uint32_t Dst, uint8_t PcmNo, uint8_t TxNo, uint16_t TransCount, ++ void (*DoneIntCallback)(uint32_t data), ++ void (*UnMaskIntCallback)(uint32_t data)); ++ ++int GdmaSpiTx(uint32_t Src, uint32_t Dst, uint16_t TransCount, ++ void (*DoneIntCallback)(uint32_t data), ++ void (*UnMaskIntCallback)(uint32_t data)); ++ ++int GdmaSpiRx(uint32_t Src, uint32_t Dst, uint16_t TransCount, ++ void (*DoneIntCallback)(uint32_t data), ++ void (*UnMaskIntCallback)(uint32_t data)); ++ ++ ++int GdmaMem2Mem(uint32_t Src, uint32_t Dst, uint16_t TransCount, ++ void (*DoneIntCallback)(uint32_t data)); ++ ++int GdmaMaskChannel(uint32_t ChNum); ++ ++int GdmaUnMaskChannel(uint32_t ChNum); ++ ++int GdmaReqQuickIns(uint32_t ChNum); ++ ++ ++#endif +--- a/sound/soc/soc-core.c ++++ b/sound/soc/soc-core.c +@@ -1851,7 +1851,8 @@ static int soc_probe(struct platform_dev + /* Bodge while we unpick instantiation */ + card->dev = &pdev->dev; + +- return snd_soc_register_card(card); ++ snd_soc_register_card(card); ++ return 0; + } + + static int soc_cleanup_card_resources(struct snd_soc_card *card) +--- /dev/null ++++ b/sound/soc/mtk/i2s_debug.c +@@ -0,0 +1,698 @@ ++#include <linux/init.h> ++#include <linux/version.h> ++#include <linux/module.h> ++#include <linux/kernel.h> /* printk() */ ++#include "i2s_ctrl.h" ++#include <linux/delay.h> ++#include <linux/jiffies.h> ++#include <linux/random.h> ++#include <linux/slab.h> ++#include <asm/uaccess.h> /* copy_from/to_user */ ++ ++#if defined(CONFIG_SND_RALINK_SOC) ++#include <sound/soc/mtk/mtk_audio_device.h> ++#endif ++ ++#if defined(CONFIG_I2S_WM8750) ++#include "../codec/i2c_wm8750.h" ++#endif ++#if defined(CONFIG_I2S_WM8751) ++#include "../codec/i2c_wm8751.h" ++#endif ++#if defined(CONFIG_I2S_WM8960) ++#include "i2c_wm8960.h" ++#endif ++ ++ ++//#define INTERNAL_LOOPBACK_DEBUG ++ ++extern unsigned long i2s_codec_12p288Mhz[11]; ++extern unsigned long i2s_codec_12Mhz[11]; ++#if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623) ++extern unsigned long i2s_inclk_int_16bit[13]; ++extern unsigned long i2s_inclk_comp_16bit[13]; ++extern unsigned long i2s_inclk_int_24bit[13]; ++extern unsigned long i2s_inclk_comp_24bit[13]; ++#else ++extern unsigned long i2s_inclk_int[11]; ++extern unsigned long i2s_inclk_comp[11]; ++#endif ++extern int i2s_pll_config_mt7621(unsigned long index); ++extern int i2s_pll_config_mt7623(unsigned long index); ++ ++#if defined(CONFIG_I2S_WM8960) || defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751) ++extern void audiohw_loopback(int fsel); ++extern void audiohw_bypass(void); ++extern int audiohw_set_lineout_vol(int Aout, int vol_l, int vol_r); ++extern int audiohw_set_linein_vol(int vol_l, int vol_r); ++#endif ++ ++#if defined(CONFIG_I2S_WM8960) ++extern void audiohw_codec_exlbk(void); ++#endif ++ ++unsigned long txbuffer[512] = { ++ 0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f10, 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20, ++ 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40, ++ 0x41424344, 0x45464748, 0x494a4b4c, 0x4d4e4f50, 0x51525354, 0x55565758, 0x595a5b5c, 0x5d5e5f60, ++ 0x61626364, 0x65666768, 0x696a6b6c, 0x6d6e6f70, 0x71727374, 0x75767778, 0x797a7b7c, 0x7d7e7f80, ++ 0x81828384, 0x85868788, 0x898a8b8c, 0x8d8e8f90, 0x91929394, 0x95969798, 0x999a9b9c, 0x9d9e9fa0, ++ 0xa1a2a3a4, 0xa5a6a7a8, 0xa9aaabac, 0xadaeafb0, 0xb1b2b3b4, 0xb5b6b7b8, 0xb9babbbc, 0xbdbebfc0, ++ 0xc1c2c3c4, 0xc5c6c7c8, 0xc9cacbcc, 0xcdcecfd0, 0xd1d2d3d4, 0xd5d6d7d8, 0xd9dadbdc, 0xdddedfe0, ++ 0xe1e2e3e4, 0xe5e6e7e8, 0xe9eaebec, 0xedeeeff0, 0xf1f2f3f4, 0xf5f6f7f8, 0xf9fafbfc, 0xfdfeff00, //round 1 ++0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f10, 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20, ++ 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40, ++ 0x41424344, 0x45464748, 0x494a4b4c, 0x4d4e4f50, 0x51525354, 0x55565758, 0x595a5b5c, 0x5d5e5f60, ++ 0x61626364, 0x65666768, 0x696a6b6c, 0x6d6e6f70, 0x71727374, 0x75767778, 0x797a7b7c, 0x7d7e7f80, ++ 0x81828384, 0x85868788, 0x898a8b8c, 0x8d8e8f90, 0x91929394, 0x95969798, 0x999a9b9c, 0x9d9e9fa0, ++ 0xa1a2a3a4, 0xa5a6a7a8, 0xa9aaabac, 0xadaeafb0, 0xb1b2b3b4, 0xb5b6b7b8, 0xb9babbbc, 0xbdbebfc0, ++ 0xc1c2c3c4, 0xc5c6c7c8, 0xc9cacbcc, 0xcdcecfd0, 0xd1d2d3d4, 0xd5d6d7d8, 0xd9dadbdc, 0xdddedfe0, ++ 0xe1e2e3e4, 0xe5e6e7e8, 0xe9eaebec, 0xedeeeff0, 0xf1f2f3f4, 0xf5f6f7f8, 0xf9fafbfc, 0xfdfeff00, //round 2 ++0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f10, 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20, ++ 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40, ++ 0x41424344, 0x45464748, 0x494a4b4c, 0x4d4e4f50, 0x51525354, 0x55565758, 0x595a5b5c, 0x5d5e5f60, ++ 0x61626364, 0x65666768, 0x696a6b6c, 0x6d6e6f70, 0x71727374, 0x75767778, 0x797a7b7c, 0x7d7e7f80, ++ 0x81828384, 0x85868788, 0x898a8b8c, 0x8d8e8f90, 0x91929394, 0x95969798, 0x999a9b9c, 0x9d9e9fa0, ++ 0xa1a2a3a4, 0xa5a6a7a8, 0xa9aaabac, 0xadaeafb0, 0xb1b2b3b4, 0xb5b6b7b8, 0xb9babbbc, 0xbdbebfc0, ++ 0xc1c2c3c4, 0xc5c6c7c8, 0xc9cacbcc, 0xcdcecfd0, 0xd1d2d3d4, 0xd5d6d7d8, 0xd9dadbdc, 0xdddedfe0, ++ 0xe1e2e3e4, 0xe5e6e7e8, 0xe9eaebec, 0xedeeeff0, 0xf1f2f3f4, 0xf5f6f7f8, 0xf9fafbfc, 0xfdfeff00, //round 3 ++0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f10, 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20, ++ 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40, ++ 0x41424344, 0x45464748, 0x494a4b4c, 0x4d4e4f50, 0x51525354, 0x55565758, 0x595a5b5c, 0x5d5e5f60, ++ 0x61626364, 0x65666768, 0x696a6b6c, 0x6d6e6f70, 0x71727374, 0x75767778, 0x797a7b7c, 0x7d7e7f80, ++ 0x81828384, 0x85868788, 0x898a8b8c, 0x8d8e8f90, 0x91929394, 0x95969798, 0x999a9b9c, 0x9d9e9fa0, ++ 0xa1a2a3a4, 0xa5a6a7a8, 0xa9aaabac, 0xadaeafb0, 0xb1b2b3b4, 0xb5b6b7b8, 0xb9babbbc, 0xbdbebfc0, ++ 0xc1c2c3c4, 0xc5c6c7c8, 0xc9cacbcc, 0xcdcecfd0, 0xd1d2d3d4, 0xd5d6d7d8, 0xd9dadbdc, 0xdddedfe0, ++ 0xe1e2e3e4, 0xe5e6e7e8, 0xe9eaebec, 0xedeeeff0, 0xf1f2f3f4, 0xf5f6f7f8, 0xf9fafbfc, 0xfdfeff00, //round 4 ++0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f10, 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20, ++ 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40, ++ 0x41424344, 0x45464748, 0x494a4b4c, 0x4d4e4f50, 0x51525354, 0x55565758, 0x595a5b5c, 0x5d5e5f60, ++ 0x61626364, 0x65666768, 0x696a6b6c, 0x6d6e6f70, 0x71727374, 0x75767778, 0x797a7b7c, 0x7d7e7f80, ++ 0x81828384, 0x85868788, 0x898a8b8c, 0x8d8e8f90, 0x91929394, 0x95969798, 0x999a9b9c, 0x9d9e9fa0, ++ 0xa1a2a3a4, 0xa5a6a7a8, 0xa9aaabac, 0xadaeafb0, 0xb1b2b3b4, 0xb5b6b7b8, 0xb9babbbc, 0xbdbebfc0, ++ 0xc1c2c3c4, 0xc5c6c7c8, 0xc9cacbcc, 0xcdcecfd0, 0xd1d2d3d4, 0xd5d6d7d8, 0xd9dadbdc, 0xdddedfe0, ++ 0xe1e2e3e4, 0xe5e6e7e8, 0xe9eaebec, 0xedeeeff0, 0xf1f2f3f4, 0xf5f6f7f8, 0xf9fafbfc, 0xfdfeff00, //round 5 ++0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f10, 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20, ++ 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40, ++ 0x41424344, 0x45464748, 0x494a4b4c, 0x4d4e4f50, 0x51525354, 0x55565758, 0x595a5b5c, 0x5d5e5f60, ++ 0x61626364, 0x65666768, 0x696a6b6c, 0x6d6e6f70, 0x71727374, 0x75767778, 0x797a7b7c, 0x7d7e7f80, ++ 0x81828384, 0x85868788, 0x898a8b8c, 0x8d8e8f90, 0x91929394, 0x95969798, 0x999a9b9c, 0x9d9e9fa0, ++ 0xa1a2a3a4, 0xa5a6a7a8, 0xa9aaabac, 0xadaeafb0, 0xb1b2b3b4, 0xb5b6b7b8, 0xb9babbbc, 0xbdbebfc0, ++ 0xc1c2c3c4, 0xc5c6c7c8, 0xc9cacbcc, 0xcdcecfd0, 0xd1d2d3d4, 0xd5d6d7d8, 0xd9dadbdc, 0xdddedfe0, ++ 0xe1e2e3e4, 0xe5e6e7e8, 0xe9eaebec, 0xedeeeff0, 0xf1f2f3f4, 0xf5f6f7f8, 0xf9fafbfc, 0xfdfeff00, //round 6 ++0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f10, 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20, ++ 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40, ++ 0x41424344, 0x45464748, 0x494a4b4c, 0x4d4e4f50, 0x51525354, 0x55565758, 0x595a5b5c, 0x5d5e5f60, ++ 0x61626364, 0x65666768, 0x696a6b6c, 0x6d6e6f70, 0x71727374, 0x75767778, 0x797a7b7c, 0x7d7e7f80, ++ 0x81828384, 0x85868788, 0x898a8b8c, 0x8d8e8f90, 0x91929394, 0x95969798, 0x999a9b9c, 0x9d9e9fa0, ++ 0xa1a2a3a4, 0xa5a6a7a8, 0xa9aaabac, 0xadaeafb0, 0xb1b2b3b4, 0xb5b6b7b8, 0xb9babbbc, 0xbdbebfc0, ++ 0xc1c2c3c4, 0xc5c6c7c8, 0xc9cacbcc, 0xcdcecfd0, 0xd1d2d3d4, 0xd5d6d7d8, 0xd9dadbdc, 0xdddedfe0, ++ 0xe1e2e3e4, 0xe5e6e7e8, 0xe9eaebec, 0xedeeeff0, 0xf1f2f3f4, 0xf5f6f7f8, 0xf9fafbfc, 0xfdfeff00, //round 7 ++0x01020304, 0x05060708, 0x090a0b0c, 0x0d0e0f10, 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20, ++ 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40, ++ 0x41424344, 0x45464748, 0x494a4b4c, 0x4d4e4f50, 0x51525354, 0x55565758, 0x595a5b5c, 0x5d5e5f60, ++ 0x61626364, 0x65666768, 0x696a6b6c, 0x6d6e6f70, 0x71727374, 0x75767778, 0x797a7b7c, 0x7d7e7f80, ++ 0x81828384, 0x85868788, 0x898a8b8c, 0x8d8e8f90, 0x91929394, 0x95969798, 0x999a9b9c, 0x9d9e9fa0, ++ 0xa1a2a3a4, 0xa5a6a7a8, 0xa9aaabac, 0xadaeafb0, 0xb1b2b3b4, 0xb5b6b7b8, 0xb9babbbc, 0xbdbebfc0, ++ 0xc1c2c3c4, 0xc5c6c7c8, 0xc9cacbcc, 0xcdcecfd0, 0xd1d2d3d4, 0xd5d6d7d8, 0xd9dadbdc, 0xdddedfe0, ++ 0xe1e2e3e4, 0xe5e6e7e8, 0xe9eaebec, 0xedeeeff0, 0xf1f2f3f4, 0xf5f6f7f8, 0xf9fafbfc, 0xfdfeff00 //round 8 ++ }; ++ ++int i2s_debug_cmd(unsigned int cmd, unsigned long arg) ++{ ++ unsigned long data, index; ++ unsigned long *pTable; ++ int i; ++ ++ switch(cmd) ++ { ++ case I2S_DEBUG_CLKGEN: ++ MSG("I2S_DEBUG_CLKGEN\n"); ++#if defined(CONFIG_RALINK_RT3052) ++ *(volatile unsigned long*)(0xB0000060) = 0x00000016; ++ *(volatile unsigned long*)(0xB0000030) = 0x00009E00; ++ *(volatile unsigned long*)(0xB0000A00) = 0xC0000040; ++#elif defined(CONFIG_RALINK_RT3350) ++ *(volatile unsigned long*)(0xB0000060) = 0x00000018; ++ *(volatile unsigned long*)(0xB000002C) = 0x00000100; ++ *(volatile unsigned long*)(0xB0000030) = 0x00009E00; ++ *(volatile unsigned long*)(0xB0000A00) = 0xC0000040; ++#elif defined(CONFIG_RALINK_RT3883) ++ *(volatile unsigned long*)(0xB0000060) = 0x00000018; ++ *(volatile unsigned long*)(0xB000002C) = 0x00003000; ++ *(volatile unsigned long*)(0xB0000A00) = 0xC1104040; ++ *(volatile unsigned long*)(0xB0000A24) = 0x00000027; ++ *(volatile unsigned long*)(0xB0000A20) = 0x80000020; ++#elif (defined(CONFIG_RALINK_RT3352)||defined(CONFIG_RALINK_RT5350)) || defined (CONFIG_RALINK_RT6855) ++ *(volatile unsigned long*)(0xB0000060) = 0x00000018; ++ *(volatile unsigned long*)(0xB000002C) = 0x00000300; ++ *(volatile unsigned long*)(0xB0000A00) = 0xC1104040; ++ *(volatile unsigned long*)(0xB0000A24) = 0x00000027; ++ *(volatile unsigned long*)(0xB0000A20) = 0x80000020; ++#elif defined(CONFIG_RALINK_RT6855A) ++ *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x860) = 0x00008080; ++ *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x82C) = 0x00000300; ++ *(volatile unsigned long*)(RALINK_I2S_BASE+0x00) = 0xC1104040; ++ *(volatile unsigned long*)(RALINK_I2S_BASE+0x24) = 0x00000027; ++ *(volatile unsigned long*)(RALINK_I2S_BASE+0x20) = 0x80000020; ++#else ++//#error "I2S debug mode not support this Chip" ++#endif ++ break; ++ case I2S_DEBUG_INLBK: ++ MSG("I2S_DEBUG_INLBK\n"); ++#if defined(CONFIG_RALINK_MT7621) ++ switch(96000) ++ { ++ case 8000: ++ index = 0; ++ break; ++ case 11025: ++ index = 1; ++ break; ++ case 12000: ++ index = 2; ++ break; ++ case 16000: ++ index = 3; ++ break; ++ case 22050: ++ index = 4; ++ break; ++ case 24000: ++ index = 5; ++ break; ++ case 32000: ++ index = 6; ++ break; ++ case 44100: ++ index = 7; ++ break; ++ case 48000: ++ index = 8; ++ break; ++ case 88200: ++ index = 9; ++ break; ++ case 96000: ++ index = 10; ++ break; ++ case 192000: ++ index = 11; ++ break; ++ default: ++ index = 7; ++ } ++ i2s_pll_config_mt7621(index); ++#elif defined(CONFIG_ARCH_MT7623) ++ i2s_pll_config_mt7623(11); ++#endif ++ ++ ++#if defined(CONFIG_RALINK_RT3052) ++ break; ++#endif ++#if defined(CONFIG_RALINK_RT6855A) ++ *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x834) |= 0x00020000; ++ *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x834) &= 0xFFFDFFFF; ++ *(volatile unsigned long*)(RALINK_I2S_BASE+0x0) &= 0x7FFFFFFF; //Rest I2S to default vaule ++ *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x860) |= 0x00008080; ++ *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x82C) = 0x00000300; ++#elif defined(CONFIG_RALINK_MT7621) ++ *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x34) |= 0x00020000; ++ *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x34) &= 0xFFFDFFFF; ++ *(volatile unsigned long*)(RALINK_I2S_BASE+0x0) &= 0x7FFFFFFF; //Rest I2S to default vaule ++ *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x60) = 0x00000010; //GPIO purpose selection ++#elif defined(CONFIG_RALINK_MT7628) ++ *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x34) |= 0x00020000; ++ *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x34) &= 0xFFFDFFFF; ++ *(volatile unsigned long*)(RALINK_I2S_BASE+0x0) &= 0x7FFFFFFF; //Rest I2S to default vaule ++ *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x60) &= ~((0x3)<<6); //GPIO purpose selection /*FIXME*/ ++#elif defined(CONFIG_ARCH_MT7623) ++ *(volatile unsigned long*)(0xFB000034) |= 0x00020000; ++ *(volatile unsigned long*)(0xFB000034) &= 0xFFFDFFFF; ++ *(volatile unsigned long*)(ETHDMASYS_I2S_BASE+0x0) &= 0x7FFFFFFF; //Rest I2S to default vaule ++ ++ *(volatile unsigned long*)(0xF0005840) &= ~((0x7)<<12); ++ *(volatile unsigned long*)(0xF0005840) |= ((0x6)<<12); ++ *(volatile unsigned long*)(0xF0005840) &= ~((0x7)<<9); ++ *(volatile unsigned long*)(0xF0005840) |= ((0x6)<<9); ++ *(volatile unsigned long*)(0xF0005040) |= ((0x1)<<10); ++ *(volatile unsigned long*)(0xF0005040) |= ((0x1)<<9); ++ ++ *(volatile unsigned long*)(0xF00057F0) &= ~((0x7)<<12); ++ *(volatile unsigned long*)(0xF00057F0) |= ((0x6)<<12); ++ *(volatile unsigned long*)(0xF0005030) |= ((0x1)<<1); ++ ++ *(volatile unsigned long*)(0xF0005840) &= ~((0x7)<<6); ++ *(volatile unsigned long*)(0xF0005840) |= ((0x6)<<6); ++ *(volatile unsigned long*)(0xF0005040) &= ~((0x1)<<8); ++ ++ *(volatile unsigned long*)(0xF00058F0) &= ~((0x7)<<3); ++ *(volatile unsigned long*)(0xF00058F0) |= ((0x6)<<3); ++ *(volatile unsigned long*)(0xF0005070) |= ((0x1)<<14); ++ ++ ++#else ++ *(volatile unsigned long*)(0xB0000034) |= 0x00020000; ++ *(volatile unsigned long*)(0xB0000034) &= 0xFFFDFFFF; ++ *(volatile unsigned long*)(0xB0000A00) &= 0x7FFFFFFF; //Rest I2S to default vaule ++ *(volatile unsigned long*)(0xB0000060) = 0x00000018; ++ ++#if defined(CONFIG_RALINK_RT3883) ++ *(volatile unsigned long*)(0xB000002C) = 0x00003000; ++#elif defined(CONFIG_ARCH_MT7623) ++ ++#else ++ *(volatile unsigned long*)(0xB000002C) = 0x00000300; ++#endif ++#endif ++#if defined(CONFIG_RALINK_MT7621) ++ *(volatile unsigned long*)(RALINK_I2S_BASE+0x18) = 0x80000000; ++ *(volatile unsigned long*)(RALINK_I2S_BASE+0x00) = 0xc1104040; ++ ++ pTable = i2s_inclk_int; ++ data = pTable[index]; ++ //*(volatile unsigned long*)(RALINK_I2S_BASE+0x24) = data; ++ i2s_outw(RALINK_I2S_BASE+0x24, data); ++ ++ pTable = i2s_inclk_comp; ++ data = pTable[index]; ++ //*(volatile unsigned long*)(RALINK_I2S_BASE+0x20) = data; ++ i2s_outw(RALINK_I2S_BASE+0x20, (data|0x80000000)); ++#elif defined(CONFIG_RALINK_MT7628) ++ index =11; /* SR: 192k */ ++ *(volatile unsigned long*)(RALINK_I2S_BASE+0x18) = 0x80000000; ++ *(volatile unsigned long*)(RALINK_I2S_BASE+0x00) = 0xc1104040; ++ ++ pTable = i2s_inclk_int_16bit; ++ //pTable = i2s_inclk_int_24bit; ++ data = pTable[index]; ++ //*(volatile unsigned long*)(RALINK_I2S_BASE+0x24) = data; ++ i2s_outw(RALINK_I2S_BASE+0x24, data); ++ ++ pTable = i2s_inclk_comp_16bit; ++ //pTable = i2s_inclk_comp_24bit; ++ data = pTable[index]; ++ //*(volatile unsigned long*)(RALINK_I2S_BASE+0x20) = data; ++ i2s_outw(RALINK_I2S_BASE+0x20, (data|0x80000000)); ++ mdelay(5); ++#elif defined(CONFIG_ARCH_MT7623) ++ index = 11; ++ *(volatile unsigned long*)(I2S_I2SCFG1) = 0x80000000; ++ *(volatile unsigned long*)(I2S_I2SCFG) = 0xE1104040; ++ *(volatile unsigned long*)(ETHDMASYS_SYSCTL_BASE+0x30) |= 0x00020000; ++ *(volatile unsigned long*)(ETHDMASYS_SYSCTL_BASE+0x2c) |= 0x00000080; ++ ++ pTable = i2s_inclk_int_16bit; ++ //pTable = i2s_inclk_int_24bit; ++ data = pTable[index]; ++ i2s_outw(I2S_DIVINT_CFG, data); ++ ++ pTable = i2s_inclk_comp_16bit; ++ //pTable = i2s_inclk_comp_24bit; ++ data = pTable[index]; ++ i2s_outw(I2S_DIVCOMP_CFG, (data|0x80000000)); ++ mdelay(5); ++#else ++ *(volatile unsigned long*)(RALINK_I2S_BASE+0x18) = 0x80000000; ++ *(volatile unsigned long*)(RALINK_I2S_BASE+0x00) = 0xC1104040; ++ *(volatile unsigned long*)(RALINK_I2S_BASE+0x24) = 0x00000006; ++ *(volatile unsigned long*)(RALINK_I2S_BASE+0x20) = 0x80000105; ++#endif ++ { ++ int count = 0; ++ int k=0; ++ int enable_cnt=0; ++ unsigned long param[4]; ++ unsigned long data; ++ //unsigned long data_tmp; ++ unsigned long ff_status; ++ //unsigned long* txbuffer; ++#if 0 ++ int j=0; ++ int temp = 0; ++#endif ++#if defined (INTERNAL_LOOPBACK_DEBUG) ++ int count2 = 0; ++#endif ++ memset(param, 0, 4*sizeof(unsigned long) ); ++ copy_from_user(param, (unsigned long*)arg, sizeof(long)*2); ++#if 0 ++ txbuffer = (unsigned long*)kcalloc(param[0], sizeof(unsigned long), GFP_KERNEL); ++ if(txbuffer == NULL) ++ return -1; ++#endif ++ ++ //ff_status = *(volatile unsigned long*)(RALINK_I2S_BASE+0x0C); ++ ff_status = *(volatile unsigned long*)(I2S_FF_STATUS); ++ printk("ff status=[0x%08X]\n",(u32)ff_status); ++ ++#if 0 ++ for(i = 0; i < param[0]; i++) ++ { ++ if (i==0) ++ { ++ txbuffer[i] = 0x555A555A; ++ printk("%d: 0x%8lx\n", i, txbuffer[i]); ++ } ++ else ++ { ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,14) ++ srandom32(jiffies); ++ txbuffer[i] = random32()%(0x555A555A)+1; ++ //printk("%d: 0x%8x\n", i, txbuffer[i]); ++ #else ++ //TODO:do we need to implement random32() ++ txbuffer[i] = 0x01010101; ++ #endif ++ } ++ } ++#endif ++ ++ for( i = 0 ; i < param[0] ; i ++ ) ++ { ++ ff_status = *(volatile unsigned long*)(I2S_FF_STATUS); ++ #if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623) ++ if((ff_status&0xFF) > 0) ++ #else ++ if((ff_status&0x0F) > 0) ++ #endif ++ { ++ *(volatile unsigned long*)(I2S_TX_FIFO_WREG) = txbuffer[i]; ++ mdelay(1); ++ } ++ else ++ { ++ mdelay(1); ++ printk("[%d]NO TX FREE FIFO ST=[0x%08X]\n", i, (u32)ff_status); ++ continue; ++ } ++ ++ //if(i >= 16) ++ { ++ ++ ff_status = *(volatile unsigned long*)(I2S_FF_STATUS); ++ #if defined(CONFIG_RALINK_MT7628) ++ if(((ff_status>>8)&0xFF) > 0) ++ #else ++ if(((ff_status>>4)&0x0F) > 0) ++ #endif ++ { ++ data = *(volatile unsigned long*)(I2S_RX_FIFO_RREG); ++ //data_tmp = *(volatile unsigned long*)(I2S_RX_FIFO_RREG); ++ //MSG("[0x%08X] vs [0x%08X]\n", (u32)data, (u32)data_tmp); ++ } ++ else ++ { ++ printk("*[%d]NO RX FREE FIFO ST=[0x%08X]\n", i, (u32)ff_status); ++ continue; ++ } ++ ++ if (data == txbuffer[0]) ++ { ++ k = i; ++ enable_cnt = 1; ++ } ++ if (enable_cnt==1) ++ { ++ if(data!= txbuffer[i-k]) ++ { ++ MSG("[%d][0x%08X] vs [0x%08X]\n", (i-k), (u32)data, (u32)txbuffer[i-k]); ++ } ++ else ++ { ++ //MSG("**[%d][0x%08X] vs [0x%08X]\n" ,(i-k), (u32)data , (u32)txbuffer[i-k]); ++ count++; ++ data=0; ++ } ++ } ++ ++ } ++ } ++#if 0 ++ temp = i-k; ++ for (j=0; j<k; j++) ++ { ++ ++ //ff_status = *(volatile unsigned long*)(RALINK_I2S_BASE+0x0C); ++ ff_status = *(volatile unsigned long*)(I2S_FF_STATUS); ++ #if defined(CONFIG_RALINK_MT7628) || defined(CONFIG_ARCH_MT7623) ++ if(((ff_status>>8)&0xFF) > 0) ++ #else ++ if(((ff_status>>4)&0x0F) > 0) ++ #endif ++ { ++ //data = *(volatile unsigned long*)(RALINK_I2S_BASE+0x14); ++ data = *(volatile unsigned long*)(I2S_RX_FIFO_RREG); ++ } ++ else ++ { ++ printk("*NO RX FREE FIFO ST=[0x%08X]\n", (u32)ff_status); ++ continue; ++ } ++ ++ if(data!= txbuffer[temp+j]) ++ { ++ MSG("[%d][0x%08X] vs [0x%08X]\n", (temp+j), (u32)data, (u32)txbuffer[temp+j]); ++ } ++ else ++ { ++ //MSG("&&[%d][0x%08X] vs [0x%08X]\n" ,(temp+j), (u32)data , (u32)txbuffer[temp+j]); ++ count++; ++ data=0; ++ } ++ if ((temp+j)==128) ++ { ++ //ff_status = *(volatile unsigned long*)(RALINK_I2S_BASE+0x0C); ++ ff_status = *(volatile unsigned long*)(I2S_FF_STATUS); ++ //printk("[%d]FIFO ST=[0x%08X]\n", (temp+j), (u32)ff_status); ++ } ++ } ++#endif ++ ++#if defined (INTERNAL_LOOPBACK_DEBUG) ++ for( i = 0 ; i < param[0] ; i ++ ) ++ { ++ //ff_status = *(volatile unsigned long*)(RALINK_I2S_BASE+0x0C); ++ ff_status = *(volatile unsigned long*)(I2S_FF_STATUS); ++ #if defined(CONFIG_RALINK_MT7628)|| defined(CONFIG_ARCH_MT7623) ++ if((ff_status&0xFF) > 0) ++ #else ++ if((ff_status&0x0F) > 0) ++ #endif ++ { ++ //*(volatile unsigned long*)(RALINK_I2S_BASE+0x10) = txbuffer[i]; ++ *(volatile unsigned long*)(I2S_TX_FIFO_WREG) = txbuffer[i]; ++ mdelay(1); ++ } ++ else ++ { ++ mdelay(1); ++ printk("[%d]NO TX FREE FIFO ST=[0x%08X]\n", i, (u32)ff_status); ++ continue; ++ } ++ ++ //if(i >= 16) ++ { ++ ++ //ff_status = *(volatile unsigned long*)(RALINK_I2S_BASE+0x0C); ++ ff_status = *(volatile unsigned long*)(I2S_FF_STATUS); ++ #if defined(CONFIG_RALINK_MT7628)|| defined(CONFIG_ARCH_MT7623) ++ if(((ff_status>>8)&0xFF) > 0) ++ #else ++ if(((ff_status>>4)&0x0F) > 0) ++ #endif ++ { ++ //data = *(volatile unsigned long*)(RALINK_I2S_BASE+0x14); ++ data = *(volatile unsigned long*)(I2S_RX_FIFO_RREG); ++ } ++ else ++ { ++ printk("*[%d]NO RX FREE FIFO ST=[0x%08X]\n", i, (u32)ff_status); ++ continue; ++ } ++ ++ { ++ if(data!= txbuffer[i]) ++ { ++ MSG("[%d][0x%08X] vs [0x%08X]\n", (i), (u32)data, (u32)txbuffer[i]); ++ } ++ else ++ { ++ MSG("**[%d][0x%08X] vs [0x%08X]\n" ,(i), (u32)data , (u32)txbuffer[i]); ++ count2++; ++ data=0; ++ } ++ } ++ ++ } ++ } ++ printk("Pattern match done count2=%d.\n", count2); ++#endif ++ printk("Pattern match done count=%d.\n", count); ++ ++ } ++#if defined(CONFIG_ARCH_MT7623) ++ *(volatile unsigned long*)(0xFB000034) |= 0x00020000; ++ *(volatile unsigned long*)(0xFB000034) &= 0xFFFDFFFF; ++ *(volatile unsigned long*)(ETHDMASYS_I2S_BASE+0x0) &= 0x7FFFFFFF; //Rest I2S to default vaule ++#endif ++ ++#if !defined(CONFIG_RALINK_RT3052) ++ break; ++#endif ++ case I2S_DEBUG_EXLBK: ++ MSG("I2S_DEBUG_EXLBK\n"); ++#if !defined(CONFIG_ARCH_MT7623) ++ switch(arg) ++ { ++ case 8000: ++ index = 0; ++ break; ++ case 11025: ++ index = 1; ++ break; ++ case 12000: ++ index = 2; ++ break; ++ case 16000: ++ index = 3; ++ break; ++ case 22050: ++ index = 4; ++ break; ++ case 24000: ++ index = 5; ++ break; ++ case 32000: ++ index = 6; ++ break; ++ case 44100: ++ index = 7; ++ break; ++ case 48000: ++ index = 8; ++ break; ++ case 88200: ++ index = 9; ++ break; ++ case 96000: ++ index = 10; ++ break; ++ default: ++ index = 7; ++ } ++#if defined(CONFIG_RALINK_RT3052) ++ break; ++#endif ++#if defined(CONFIG_RALINK_RT6855A) ++ *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x860) = 0x00008080; ++ //*(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x82C) = 0x00000300; ++#else ++ *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x60) = 0x00000018; ++#if defined(CONFIG_RALINK_RT3883) ++ *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x2C) = 0x00003000; ++#else ++ *(volatile unsigned long*)(RALINK_SYSCTL_BASE+0x2C) = 0x00000300; ++#endif ++#endif ++ ++ *(volatile unsigned long*)(RALINK_I2S_BASE+0x18) = 0x40000000; ++ *(volatile unsigned long*)(RALINK_I2S_BASE+0x00) = 0x81104040; ++#if defined(CONFIG_RALINK_MT7628) ++ pTable = i2s_inclk_int_16bit; ++#else ++ pTable = i2s_inclk_int; ++#endif ++ data = (volatile unsigned long)(pTable[index]); ++ i2s_outw(I2S_DIVINT_CFG, data); ++#if defined(CONFIG_RALINK_MT7628) ++ pTable = i2s_inclk_comp_16bit; ++#else ++ pTable = i2s_inclk_comp; ++#endif ++ data = (volatile unsigned long)(pTable[index]); ++ data |= REGBIT(1, I2S_CLKDIV_EN); ++ i2s_outw(I2S_DIVCOMP_CFG, data); ++ ++ #if defined(CONFIG_I2S_MCLK_12MHZ) ++ pTable = i2s_codec_12Mhz; ++ #if defined(CONFIG_I2S_WM8960) ++ data = pTable[index]; ++ #else ++ data = pTable[index]|0x01; ++ #endif ++ #else ++ pTable = i2s_codec_12p288Mhz; ++ data = pTable[index]; ++ #endif ++ ++ #if defined(CONFIG_I2S_WM8960) || defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751) ++ audiohw_preinit(); ++ #endif ++ ++ ++ #if defined (CONFIG_I2S_WM8960) ++ audiohw_postinit(1, 1, 1, 1, 0); // for codec apll enable, 16 bit word length ++ #elif defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751) ++ audiohw_postinit(1, 1, 1, 0); // for 16 bit word length ++ #endif ++ ++ ++ #if defined (CONFIG_I2S_WM8960) ++ audiohw_set_frequency(data, 1); // for codec apll enable ++ #elif defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751) ++ audiohw_set_frequency(data|0x1); ++ #endif ++ ++ ++ #if defined(CONFIG_I2S_WM8960) || defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751) ++ audiohw_set_lineout_vol(1, 100, 100); ++ audiohw_set_linein_vol(100, 100); ++ #endif ++ ++ ++ #if defined(CONFIG_I2S_TXRX) ++ //audiohw_loopback(data); ++ #endif ++ #if !defined(CONFIG_RALINK_RT3052) ++ break; ++ #endif ++#endif ++ case I2S_DEBUG_CODECBYPASS: ++ #if defined(CONFIG_I2S_TXRX) ++ #if defined(CONFIG_RALINK_MT7628) ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x60); ++ //data &= ~(0x3<<4); ++ data &= ~(0x3<<6); ++ data &= ~(0x3<<16); ++ data &= ~(0x1<<14); ++ i2s_outw(RALINK_SYSCTL_BASE+0x60, data); ++ ++ data = i2s_inw(RALINK_SYSCTL_BASE+0x2c); ++ data &= ~(0x07<<9); ++ i2s_outw(RALINK_SYSCTL_BASE+0x2c, data); ++ #endif ++ ++ #if defined(CONFIG_I2S_WM8960) || defined(CONFIG_I2S_WM8750) || defined(CONFIG_I2S_WM8751) ++ audiohw_bypass(); /* did not work */ ++ #endif ++ #endif ++ break; ++ case I2S_DEBUG_FMT: ++ break; ++ case I2S_DEBUG_RESET: ++ break; ++#if defined(CONFIG_I2S_WM8960) ++ case I2S_DEBUG_CODEC_EXLBK: ++ audiohw_codec_exlbk(); ++ break; ++#endif ++ default: ++ MSG("Not support this debug cmd [%d]\n", cmd); ++ break; ++ } ++ ++ return 0; ++} +--- a/sound/soc/codecs/wm8960.c ++++ b/sound/soc/codecs/wm8960.c +@@ -26,6 +26,7 @@ + #include <sound/wm8960.h> + + #include "wm8960.h" ++#include "../mtk/i2c_wm8960.h" + + /* R25 - Power 1 */ + #define WM8960_VMID_MASK 0x180 +@@ -53,10 +54,10 @@ + * using 2 wire for device control, so we cache them instead. + */ + static const struct reg_default wm8960_reg_defaults[] = { +- { 0x0, 0x00a7 }, +- { 0x1, 0x00a7 }, +- { 0x2, 0x0000 }, +- { 0x3, 0x0000 }, ++ { 0x0, 0x002b }, ++ { 0x1, 0x002b }, ++ { 0x2, 0x00ff }, ++ { 0x3, 0x00ff }, + { 0x4, 0x0000 }, + { 0x5, 0x0008 }, + { 0x6, 0x0000 }, +@@ -88,8 +89,8 @@ static const struct reg_default wm8960_r + { 0x25, 0x0050 }, + { 0x26, 0x0000 }, + { 0x27, 0x0000 }, +- { 0x28, 0x0000 }, +- { 0x29, 0x0000 }, ++ { 0x28, 0x007b }, ++ { 0x29, 0x007b }, + { 0x2a, 0x0040 }, + { 0x2b, 0x0000 }, + { 0x2c, 0x0000 }, +@@ -127,8 +128,15 @@ struct wm8960_priv { + int playback_fs; + }; + ++#if 1 ++#define wm8960_reset(c) do{ \ ++ int i = 0;\ ++ snd_soc_write(c, WM8960_RESET, 0);\ ++ for(i = 0; i < 1000*HZ; i++);\ ++ }while(0) ++#else + #define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0) +- ++#endif + /* enumerated controls */ + static const char *wm8960_polarity[] = {"No Inversion", "Left Inverted", + "Right Inverted", "Stereo Inversion"}; +@@ -181,8 +189,8 @@ static int wm8960_get_deemph(struct snd_ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); + +- ucontrol->value.integer.value[0] = wm8960->deemph; +- return 0; ++ //ucontrol->value.integer.value[0] = wm8960->deemph; ++ return wm8960->deemph; + } + + static int wm8960_put_deemph(struct snd_kcontrol *kcontrol, +@@ -200,6 +208,70 @@ static int wm8960_put_deemph(struct snd_ + return wm8960_set_deemph(codec); + } + ++static int wm8960_preinit(struct snd_soc_codec *codec) ++{ ++ //printk("****** %s ******\n", __func__); ++ snd_soc_write(codec, WM8960_RESET, 0); ++ mdelay(500); ++ ++ return 0; ++} ++ ++static int wm8960_postinit(struct snd_soc_codec *codec) ++{ ++ u32 data; ++ //printk("****** %s ******\n", __func__); ++ // In ++ data = snd_soc_read(codec, WM8960_POWER1); ++ snd_soc_write(codec, WM8960_POWER1, data|WM8960_PWR1_ADCL|WM8960_PWR1_ADCR|WM8960_PWR1_AINL |WM8960_PWR1_AINR|WM8960_PWR1_MICB);//0x19 ++ data = snd_soc_read(codec, WM8960_ADDCTL1); ++ snd_soc_write(codec, WM8960_ADDCTL1, data|ADDITIONAL1_DATSEL(0x01));//0x17 ++ snd_soc_write(codec, WM8960_LADC, LEFTGAIN_LDVU|LEFTGAIN_LDACVOL(0xc3));//0x15 ++ snd_soc_write(codec, WM8960_RADC, LEFTGAIN_LDVU|LEFTGAIN_LDACVOL(0xc3));//0x16 ++ snd_soc_write(codec, WM8960_LINPATH, 0x148);//0x20 ++ snd_soc_write(codec, WM8960_RINPATH, 0x148);//0x21 ++ snd_soc_write(codec, WM8960_POWER3, WM8960_PWR3_LMIC|WM8960_PWR3_RMIC);//0x2f ++ ++ // Out ++ data = snd_soc_read(codec, WM8960_POWER2); ++ snd_soc_write(codec, WM8960_POWER2, data|WM8960_PWR2_DACL|WM8960_PWR2_DACR|WM8960_PWR2_LOUT1|WM8960_PWR2_ROUT1|WM8960_PWR2_SPKL|WM8960_PWR2_SPKR);//0x1a ++ mdelay(10); ++ snd_soc_write(codec, WM8960_IFACE2, 0x40); ++ snd_soc_write(codec, WM8960_LDAC, LEFTGAIN_LDVU|LEFTGAIN_LDACVOL(0xff));//0x0a ++ snd_soc_write(codec, WM8960_RDAC, RIGHTGAIN_RDVU|RIGHTGAIN_RDACVOL(0xff));//0x0b ++ snd_soc_write(codec, WM8960_LOUTMIX, 0x100);//0x22 ++ snd_soc_write(codec, WM8960_ROUTMIX, 0x100);//0x25 ++ ++ data = snd_soc_read(codec, WM8960_POWER3); ++ snd_soc_write(codec, WM8960_POWER3, data|WM8960_PWR3_ROMIX|WM8960_PWR3_LOMIX);//0x2f ++ ++ snd_soc_write(codec, WM8960_CLASSD1, 0xf7);//0x31 ++ snd_soc_write(codec, WM8960_CLASSD3, 0xad);//0x33 ++ snd_soc_write(codec, WM8960_DACCTL1, 0x000);//0x05 ++ ++ data = snd_soc_read(codec, WM8960_POWER1); ++ snd_soc_write(codec, WM8960_POWER1, data|0x1c0);//0x19 ++ ++ ++ snd_soc_write(codec, WM8960_LOUT1, LOUT1_LO1VU|LOUT1_LO1ZC|LOUT1_LOUT1VOL(115));//0x02 ++ snd_soc_write(codec, WM8960_ROUT1, ROUT1_RO1VU|ROUT1_RO1ZC|ROUT1_ROUT1VOL(115));//0x03 ++ ++ snd_soc_write(codec, WM8960_LINVOL, LINV_IPVU|LINV_LINVOL(110)); //LINV(0x00)=>0x12b ++ snd_soc_write(codec, WM8960_RINVOL, RINV_IPVU|RINV_RINVOL(110)); //LINV(0x01)=>0x12b ++ ++ return 0; ++} ++ ++static int wm8960_close(struct snd_soc_codec *codec) ++{ ++ snd_soc_write(codec, WM8960_DACCTL1,0x8); //0x05->0x08 ++ snd_soc_write(codec, WM8960_POWER1, 0x000); //0x19->0x000 ++ mdelay(300); ++ snd_soc_write(codec, WM8960_POWER2, 0x000); //0x1a->0x000 ++ ++ return 0; ++} ++ + static const DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 50, 0); + static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1); + static const DECLARE_TLV_DB_SCALE(bypass_tlv, -2100, 300, 0); +@@ -542,6 +614,7 @@ static int wm8960_set_dai_fmt(struct snd + + /* set iface */ + snd_soc_write(codec, WM8960_IFACE1, iface); ++ wm8960_postinit(codec); + return 0; + } + +@@ -623,11 +696,16 @@ static int wm8960_set_bias_level_out3(st + break; + + case SND_SOC_BIAS_PREPARE: ++#if 0 + /* Set VMID to 2x50k */ + snd_soc_update_bits(codec, WM8960_POWER1, 0x180, 0x80); ++#endif + break; + + case SND_SOC_BIAS_STANDBY: ++#if 1 ++ wm8960_preinit(codec); ++#else + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + regcache_sync(wm8960->regmap); + +@@ -650,9 +728,13 @@ static int wm8960_set_bias_level_out3(st + + /* Set VMID to 2x250k */ + snd_soc_update_bits(codec, WM8960_POWER1, 0x180, 0x100); ++#endif + break; + + case SND_SOC_BIAS_OFF: ++#if 1 ++ wm8960_close(codec); ++#else + /* Enable anti-pop features */ + snd_soc_write(codec, WM8960_APOP1, + WM8960_POBCTRL | WM8960_SOFT_ST | +@@ -661,6 +743,7 @@ static int wm8960_set_bias_level_out3(st + /* Disable VMID and VREF, let them discharge */ + snd_soc_write(codec, WM8960_POWER1, 0); + msleep(600); ++#endif + break; + } + +@@ -853,10 +936,15 @@ static int wm8960_set_dai_pll(struct snd + + if (pll_div.k) { + reg |= 0x20; +- ++#if 1 + snd_soc_write(codec, WM8960_PLL2, (pll_div.k >> 16) & 0xff); + snd_soc_write(codec, WM8960_PLL3, (pll_div.k >> 8) & 0xff); + snd_soc_write(codec, WM8960_PLL4, pll_div.k & 0xff); ++#else ++ snd_soc_write(codec, WM8960_PLL2, (pll_div.k >> 16) & 0xff); ++ snd_soc_write(codec, WM8960_PLL3, (pll_div.k >> 8) & 0xff); ++ snd_soc_write(codec, WM8960_PLL4, pll_div.k & 0xff); ++#endif + } + snd_soc_write(codec, WM8960_PLL1, reg); + +@@ -888,7 +976,11 @@ static int wm8960_set_dai_clkdiv(struct + snd_soc_write(codec, WM8960_PLL1, reg | div); + break; + case WM8960_DCLKDIV: ++#if 1 + reg = snd_soc_read(codec, WM8960_CLOCK2) & 0x03f; ++#else ++ reg = snd_soc_read(codec, WM8960_CLOCK2) & 0x03f; ++#endif + snd_soc_write(codec, WM8960_CLOCK2, reg | div); + break; + case WM8960_TOCLKSEL: +@@ -962,7 +1054,7 @@ static int wm8960_probe(struct snd_soc_c + { + struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); + struct wm8960_data *pdata = dev_get_platdata(codec->dev); +- int ret; ++ int ret = 0; + + wm8960->set_bias_level = wm8960_set_bias_level_out3; + +@@ -973,11 +1065,7 @@ static int wm8960_probe(struct snd_soc_c + wm8960->set_bias_level = wm8960_set_bias_level_capless; + } + +- ret = wm8960_reset(codec); +- if (ret < 0) { +- dev_err(codec->dev, "Failed to issue reset\n"); +- return ret; +- } ++ wm8960_reset(codec); + + wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY); + +--- a/sound/soc/codecs/wm8960.h ++++ b/sound/soc/codecs/wm8960.h +@@ -110,4 +110,68 @@ + #define WM8960_OPCLK_DIV_5_5 (4 << 0) + #define WM8960_OPCLK_DIV_6 (5 << 0) + ++/* ++ * WM8960 Power management ++ */ ++#define WM8960_PWR1_VMIDSEL_DISABLED (0 << 7) ++#define WM8960_PWR1_VMIDSEL_50K (1 << 7) ++#define WM8960_PWR1_VMIDSEL_250K (2 << 7) ++#define WM8960_PWR1_VMIDSEL_5K (3 << 7) ++#define WM8960_PWR1_VREF (1 << 6) ++#define WM8960_PWR1_AINL (1 << 5) ++#define WM8960_PWR1_AINR (1 << 4) ++#define WM8960_PWR1_ADCL (1 << 3) ++#define WM8960_PWR1_ADCR (1 << 2) ++#define WM8960_PWR1_MICB (1 << 1) ++#define WM8960_PWR1_DIGENB (1 << 0) ++ ++#define WM8960_PWR2_DACL (1 << 8) ++#define WM8960_PWR2_DACR (1 << 7) ++//#define WM8960_PWR2_LOUT1 (1 << 6) ++//#define WM8960_PWR2_ROUT1 (1 << 5) ++#define WM8960_PWR2_SPKL (1 << 4) ++#define WM8960_PWR2_SPKR (1 << 3) ++//#define WM8960_PWR2_OUT3 (1 << 1) ++#define WM8960_PWR2_PLL_EN (1 << 0) ++ ++#define WM8960_PWR3_LMIC (1 << 5) ++#define WM8960_PWR3_RMIC (1 << 4) ++#define WM8960_PWR3_LOMIX (1 << 3) ++#define WM8960_PWR3_ROMIX (1 << 2) ++ ++#define LEFTGAIN 0x0a ++#define LEFTGAIN_LDVU (1 << 8) ++#define LEFTGAIN_LDACVOL(x) ((x) & 0xff) ++ ++#define RIGHTGAIN 0x0b ++#define RIGHTGAIN_RDVU (1 << 8) ++#define RIGHTGAIN_RDACVOL(x) ((x) & 0xff) ++ ++#define ADDITIONAL1_DATSEL(x) (((x) & 0x3) << 2) ++ ++#define AINTFCE1_WL_32 (3 << 2) ++#define AINTFCE1_WL_24 (2 << 2) ++#define AINTFCE1_WL_20 (1 << 2) ++#define AINTFCE1_WL_16 (0 << 2) ++#define AINTFCE1_FORMAT_I2S (2 << 0) ++ ++#define LOUT1_LO1VU (1 << 8) ++#define LOUT1_LO1ZC (1 << 7) ++#define LOUT1_LOUT1VOL(x) ((x) & 0x7f) ++ ++#define ROUT1_RO1VU (1 << 8) ++#define ROUT1_RO1ZC (1 << 7) ++#define ROUT1_ROUT1VOL(x) ((x) & 0x7f) ++ ++#define LINV_IPVU (1 << 8) /* FIXME */ ++ ++#define LINV_LINMUTE (1 << 7) ++#define LINV_LIZC (1 << 6) ++#define LINV_LINVOL(x) ((x) & 0x3f) ++ ++#define RINV_IPVU (1 << 8) /* FIXME */ ++#define RINV_RINMUTE (1 << 7) ++#define RINV_RIZC (1 << 6) ++#define RINV_RINVOL(x) ((x) & 0x3f) ++ + #endif diff --git a/target/linux/ramips/patches-3.18/0304-baud_250000.patch b/target/linux/ramips/patches-3.18/0304-baud_250000.patch new file mode 100644 index 0000000..6a364c0 --- /dev/null +++ b/target/linux/ramips/patches-3.18/0304-baud_250000.patch @@ -0,0 +1,12 @@ +--- a/drivers/tty/serial/serial_core.c ++++ b/drivers/tty/serial/serial_core.c +@@ -356,6 +356,9 @@ uart_get_baud_rate(struct uart_port *por + else if (flags == UPF_SPD_WARP) + altbaud = 460800; + ++ if (tty_termios_baud_rate(termios) == 2500000) ++ return 250000; ++ + for (try = 0; try < 2; try++) { + baud = tty_termios_baud_rate(termios); + diff --git a/target/linux/ramips/rt288x/config-3.18 b/target/linux/ramips/rt288x/config-3.18 new file mode 100644 index 0000000..f9eacfb --- /dev/null +++ b/target/linux/ramips/rt288x/config-3.18 @@ -0,0 +1,168 @@ +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_ARCH_DISCARD_MEMBLOCK=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_CEVT_R4K=y +CONFIG_CLKDEV_LOOKUP=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMDLINE="rootfstype=squashfs,jffs2" +CONFIG_CMDLINE_BOOL=y +# CONFIG_CMDLINE_OVERRIDE is not set +CONFIG_CPU_GENERIC_DUMP_TLB=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS32_R1 is not set +CONFIG_CPU_MIPS32_R2=y +CONFIG_CPU_MIPSR2=y +CONFIG_CPU_R4K_CACHE_TLB=y +CONFIG_CPU_R4K_FPU=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_CSRC_R4K=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_DTB_RT2880_EVAL is not set +CONFIG_DTB_RT_NONE=y +CONFIG_DTC=y +CONFIG_EARLY_PRINTK=y +# CONFIG_EARLY_PRINTK_8250 is not set +CONFIG_GENERIC_ATOMIC64=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_IO=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_GPIO_RALINK=y +CONFIG_GPIO_SYSFS=y +CONFIG_HARDWARE_WATCHPOINTS=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_HAVE_CC_STACKPROTECTOR=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_HAVE_DEBUG_KMEMLEAK=y +CONFIG_HAVE_DEBUG_STACKOVERFLOW=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_IDE=y +CONFIG_HAVE_KVM=y +CONFIG_HAVE_MACH_CLKDEV=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MEMBLOCK_NODE_MAP=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_HAVE_NET_DSA=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HW_HAS_PCI=y +CONFIG_HZ_PERIODIC=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IP17XX_PHY=y +CONFIG_IRQCHIP=y +CONFIG_IRQ_CPU=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_INTC=y +CONFIG_IRQ_WORK=y +CONFIG_MDIO_BOARDINFO=y +CONFIG_MIPS=y +# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set +CONFIG_MIPS_L1_CACHE_SHIFT=4 +CONFIG_MIPS_L1_CACHE_SHIFT_4=y +# CONFIG_MIPS_MACHINE is not set +CONFIG_MIPS_MT_DISABLED=y +CONFIG_MODULES_USE_ELF_REL=y +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_M25P80=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_LZMA_FW=y +CONFIG_MTD_SPLIT_UIMAGE_FW=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_PER_CPU_KM=y +CONFIG_NET_RALINK=y +CONFIG_NET_RALINK_MDIO=y +CONFIG_NET_RALINK_MDIO_RT2880=y +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y +CONFIG_OF_NET=y +CONFIG_PAGEFLAGS_EXTENDED=y +# CONFIG_PCI is not set +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PHYLIB=y +# CONFIG_PHY_RALINK_USB is not set +# CONFIG_PINCONF is not set +CONFIG_PINCTRL=y +CONFIG_PINCTRL_RT2880=y +# CONFIG_PINCTRL_SINGLE is not set +# CONFIG_PREEMPT_RCU is not set +CONFIG_RALINK=y +# CONFIG_RALINK_ILL_ACC is not set +# CONFIG_RALINK_USBPHY is not set +CONFIG_RALINK_WDT=y +CONFIG_RA_NAT_NONE=y +# CONFIG_RCU_STALL_COMMON is not set +CONFIG_RESET_CONTROLLER=y +# CONFIG_SCSI_DMA is not set +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RT288X=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SOC_MT7620 is not set +# CONFIG_SOC_MT7621 is not set +CONFIG_SOC_RT288X=y +# CONFIG_SOC_RT305X is not set +# CONFIG_SOC_RT3883 is not set +CONFIG_SPI=y +CONFIG_SPI_MASTER=y +# CONFIG_SPI_MT7621 is not set +CONFIG_SPI_RT2880=y +CONFIG_SWCONFIG=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_SYS_HAS_CPU_MIPS32_R2=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_USB_SUPPORT=y +CONFIG_USE_OF=y +CONFIG_WATCHDOG_CORE=y +# CONFIG_ZBUD is not set +CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/ramips/rt288x/profiles/00-default.mk b/target/linux/ramips/rt288x/profiles/00-default.mk new file mode 100644 index 0000000..583610a --- /dev/null +++ b/target/linux/ramips/rt288x/profiles/00-default.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2010 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 + PACKAGES:=kmod-switch-rtl8366s kmod-swconfig swconfig +endef + +define Profile/Default/Description + Default package set compatible with most boards. +endef +$(eval $(call Profile,Default)) diff --git a/target/linux/ramips/rt288x/profiles/asus.mk b/target/linux/ramips/rt288x/profiles/asus.mk new file mode 100644 index 0000000..aa6fb4d --- /dev/null +++ b/target/linux/ramips/rt288x/profiles/asus.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2011 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/RTN15 + NAME:=Asus RT-N15 + PACKAGES:=kmod-switch-rtl8366s kmod-swconfig swconfig +endef + +define Profile/RTN15/Description + Package set for Asus RT-N15 board +endef +$(eval $(call Profile,RTN15)) diff --git a/target/linux/ramips/rt288x/profiles/belkin.mk b/target/linux/ramips/rt288x/profiles/belkin.mk new file mode 100644 index 0000000..4a0c62d --- /dev/null +++ b/target/linux/ramips/rt288x/profiles/belkin.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2011 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/F5D8235V1 + NAME:=Belkin F5D8235 V1 + PACKAGES:=kmod-switch-rtl8366s kmod-swconfig swconfig +endef + +define Profile/F5D8235V1/Description + Package set for Belkin F5D8235 V1 +endef +$(eval $(call Profile,F5D8235V1)) diff --git a/target/linux/ramips/rt288x/target.mk b/target/linux/ramips/rt288x/target.mk new file mode 100644 index 0000000..1e20e51 --- /dev/null +++ b/target/linux/ramips/rt288x/target.mk @@ -0,0 +1,14 @@ +# +# Copyright (C) 2009 OpenWrt.org +# + +SUBTARGET:=rt288x +BOARDNAME:=RT288x based boards +CPU_TYPE:=mips32r2 + +DEFAULT_PACKAGES += kmod-rt2800-soc + +define Target/Description + Build firmware images for Ralink RT288x based boards. +endef + diff --git a/target/linux/ramips/rt305x/config-3.18 b/target/linux/ramips/rt305x/config-3.18 new file mode 100644 index 0000000..9fb846f --- /dev/null +++ b/target/linux/ramips/rt305x/config-3.18 @@ -0,0 +1,173 @@ +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_ARCH_DISCARD_MEMBLOCK=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +# CONFIG_ARCH_HAS_SG_CHAIN is not set +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_CEVT_R4K=y +CONFIG_CEVT_SYSTICK_QUIRK=y +CONFIG_CLKDEV_LOOKUP=y +CONFIG_CLKEVT_RT3352=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLKSRC_OF=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMDLINE="rootfstype=squashfs,jffs2" +CONFIG_CMDLINE_BOOL=y +# CONFIG_CMDLINE_OVERRIDE is not set +CONFIG_CPU_GENERIC_DUMP_TLB=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS32_R1 is not set +CONFIG_CPU_MIPS32_R2=y +CONFIG_CPU_MIPSR2=y +CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y +CONFIG_CPU_R4K_CACHE_TLB=y +CONFIG_CPU_R4K_FPU=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_CPU_SUPPORTS_MSA=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CSRC_R4K=y +CONFIG_DEBUG_PINCTRL=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_DTB_RT305X_EVAL is not set +CONFIG_DTB_RT_NONE=y +CONFIG_DTC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_ATOMIC64=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_IO=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_GPIO_RALINK=y +CONFIG_GPIO_SYSFS=y +CONFIG_HARDWARE_WATCHPOINTS=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_HAVE_BPF_JIT=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_HAVE_DEBUG_KMEMLEAK=y +CONFIG_HAVE_DEBUG_STACKOVERFLOW=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_IDE=y +CONFIG_HAVE_KVM=y +CONFIG_HAVE_MACH_CLKDEV=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MEMBLOCK_NODE_MAP=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_HAVE_NET_DSA=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HZ_PERIODIC=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQCHIP=y +CONFIG_IRQ_CPU=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_INTC=y +CONFIG_IRQ_WORK=y +CONFIG_LIBFDT=y +CONFIG_MDIO_BOARDINFO=y +CONFIG_MIPS=y +# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_MIPS_MACHINE is not set +CONFIG_MODULES_USE_ELF_REL=y +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_M25P80=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_SEAMA_FW=y +CONFIG_MTD_SPLIT_UIMAGE_FW=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_PER_CPU_KM=y +CONFIG_NET_RALINK=y +CONFIG_NET_RALINK_ESW_RT3052=y +CONFIG_NET_RALINK_RT305X=y +# CONFIG_NO_IOPORT_MAP is not set +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y +CONFIG_OF_NET=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PHYLIB=y +CONFIG_PHY_RALINK_USB=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_RT2880=y +# CONFIG_PINCTRL_SINGLE is not set +# CONFIG_PREEMPT_RCU is not set +CONFIG_RALINK=y +# CONFIG_RALINK_ILL_ACC is not set +CONFIG_RALINK_WDT=y +# CONFIG_RCU_STALL_COMMON is not set +CONFIG_RESET_CONTROLLER=y +# CONFIG_SCSI_DMA is not set +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RT288X=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SOC_MT7620 is not set +# CONFIG_SOC_MT7621 is not set +# CONFIG_SOC_RT288X is not set +CONFIG_SOC_RT305X=y +# CONFIG_SOC_RT3883 is not set +CONFIG_SPI=y +CONFIG_SPI_MASTER=y +# CONFIG_SPI_MT7621 is not set +CONFIG_SPI_RT2880=y +CONFIG_SWCONFIG=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_SYS_HAS_CPU_MIPS32_R2=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_MIPS16=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_USB_SUPPORT=y +CONFIG_USE_OF=y +CONFIG_WATCHDOG_CORE=y +CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/ramips/rt305x/profiles/00-default.mk b/target/linux/ramips/rt305x/profiles/00-default.mk new file mode 100644 index 0000000..a905d1e --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/00-default.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2011 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 + PACKAGES:=\ + kmod-usb-core kmod-usb-dwc2 \ + kmod-ledtrig-usbdev +endef + +define Profile/Default/Description + Default package set compatible with most boards. +endef +$(eval $(call Profile,Default)) diff --git a/target/linux/ramips/rt305x/profiles/allnet.mk b/target/linux/ramips/rt305x/profiles/allnet.mk new file mode 100644 index 0000000..eb175ec --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/allnet.mk @@ -0,0 +1,53 @@ +# +# Copyright (C) 2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/ALL02393G + NAME:=Allnet ALL0239-3G + PACKAGES:=\ + kmod-usb-core kmod-usb-dwc2 \ + kmod-ledtrig-usbdev +endef + +define Profile/ALL02393G/Description + Package set for Allnet ALL0239-3G +endef +$(eval $(call Profile,ALL02393G)) + + +define Profile/ALL0256N + NAME:=Allnet ALL0256N + PACKAGES:=rssileds +endef + +define Profile/ALL0256N/Description + Package set for Allnet ALL0256N +endef +$(eval $(call Profile,ALL0256N)) + + +define Profile/ALL5002 + NAME:=Allnet ALL5002 + PACKAGES:=kmod-usb-core kmod-usb-ohci kmod-usb2 kmod-ledtrig-usbdev \ + kmod-i2c-core kmod-i2c-gpio kmod-hwmon-lm92 kmod-gpio-pcf857x +endef + +define Profile/ALL5002/Description + Package set for Allnet ALL5002 +endef +$(eval $(call Profile,ALL5002)) + + +define Profile/ALL5003 + NAME:=Allnet ALL5003 + PACKAGES:=kmod-usb-core kmod-usb-ohci kmod-usb2 kmod-ledtrig-usbdev \ + kmod-i2c-core kmod-i2c-gpio kmod-hwmon-lm92 kmod-gpio-pcf857x +endef + +define Profile/ALL5003/Description + Package set for Allnet ALL5003 +endef +$(eval $(call Profile,ALL5003)) diff --git a/target/linux/ramips/rt305x/profiles/alpha.mk b/target/linux/ramips/rt305x/profiles/alpha.mk new file mode 100644 index 0000000..4ecbd6a --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/alpha.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/ASL26555 + NAME:=Alpha ASL26555 + PACKAGES:=\ + kmod-usb-core kmod-usb-dwc2 \ + kmod-ledtrig-usbdev +endef + +define Profile/ASL26555/Description + Package set for Alpha ASL26555 +endef +$(eval $(call Profile,ASL26555)) diff --git a/target/linux/ramips/rt305x/profiles/arcwireless.mk b/target/linux/ramips/rt305x/profiles/arcwireless.mk new file mode 100644 index 0000000..8405f2d --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/arcwireless.mk @@ -0,0 +1,17 @@ +# +# Copyright (C) 2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/FREESTATION5 + NAME:=ARC Wireless FreeStation + PACKAGES:=\ + kmod-usb-dwc2 kmod-rt2500-usb kmod-rt2800-usb kmod-rt2x00-usb +endef + +define Profile/FREESTATION5/Description + Package set for ARC Wireless FreeStation, Flex mARC, iFlex, and SplitStation +endef +$(eval $(call Profile,FREESTATION5)) diff --git a/target/linux/ramips/rt305x/profiles/asiarf.mk b/target/linux/ramips/rt305x/profiles/asiarf.mk new file mode 100644 index 0000000..efa01ea --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/asiarf.mk @@ -0,0 +1,39 @@ +# +# Copyright (C) 2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/AWAPN2403 + NAME:=AsiaRF AWAPN2403 +endef + +define Profile/AWAPN2403/Description + Package set for AsiaRF AWAPN2403 Pocket Router +endef +$(eval $(call Profile,AWAPN2403)) + + +define Profile/AWM002EVB + NAME:=AsiaRF AWM002-EVB + PACKAGES:=kmod-usb-core kmod-usb-ohci kmod-usb2 kmod-ledtrig-usbdev \ + kmod-i2c-core kmod-i2c-gpio +endef + +define Profile/AWM002EVB/Description + Package set for AsiaRF AWM002 Evaluation Board +endef +$(eval $(call Profile,AWM002EVB)) + + +define Profile/AWM003EVB + NAME:=AsiaRF AWM003-EVB + PACKAGES:=kmod-usb-core kmod-usb-ohci kmod-usb2 kmod-ledtrig-usbdev \ + kmod-i2c-core kmod-i2c-gpio +endef + +define Profile/AWM003EVB/Description + Package set for AsiaRF AWM003 Evaluation Board +endef +$(eval $(call Profile,AWM003EVB)) diff --git a/target/linux/ramips/rt305x/profiles/asus.mk b/target/linux/ramips/rt305x/profiles/asus.mk new file mode 100644 index 0000000..ddfdc1a --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/asus.mk @@ -0,0 +1,27 @@ +# +# Copyright (C) 2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/RTN10PLUS + NAME:=Asus RT-N10+ + PACKAGES:=kmod-leds-gpio wpad-mini +endef + +define Profile/RTN10PLUS/Description + Package set for Asus RT-N10+. +endef +$(eval $(call Profile,RTN10PLUS)) + + +define Profile/RT-N13U + NAME:=Asus RT-N13U + PACKAGES:=kmod-leds-gpio kmod-rt2800-pci wpad-mini kmod-usb-dwc2 +endef + +define Profile/RT-N13U/Description + Package set for Asus RT-N13U. +endef +$(eval $(call Profile,RT-N13U)) diff --git a/target/linux/ramips/rt305x/profiles/aximcom.mk b/target/linux/ramips/rt305x/profiles/aximcom.mk new file mode 100644 index 0000000..d00e7a9 --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/aximcom.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/MR102N + NAME:=AXIMCom MR-102N + PACKAGES:=kmod-usb-core kmod-usb-dwc2 kmod-ledtrig-usbdev +endef + +define Profile/MR102N/Description + Package set for AXIMCom MR-102N +endef +$(eval $(call Profile,MR102N)) diff --git a/target/linux/ramips/rt305x/profiles/aztech.mk b/target/linux/ramips/rt305x/profiles/aztech.mk new file mode 100644 index 0000000..e869398 --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/aztech.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/HW550-3G + NAME:=Aztech HW550-3G + PACKAGES:=\ + kmod-usb-core kmod-usb-dwc2 \ + kmod-ledtrig-usbdev +endef + +define Profile/HW550-3G/Description + Package set for Aztech HW550-3G +endef +$(eval $(call Profile,HW550-3G)) diff --git a/target/linux/ramips/rt305x/profiles/belkin.mk b/target/linux/ramips/rt305x/profiles/belkin.mk new file mode 100644 index 0000000..27c6bf4 --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/belkin.mk @@ -0,0 +1,32 @@ +# +# Copyright (C) 2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/F5D8235V2 + NAME:=Belkin F5D8235 v2 + PACKAGES:=\ + kmod-switch-rtl8366rb kmod-swconfig swconfig \ + kmod-usb-core kmod-usb-dwc2 \ + kmod-ledtrig-usbdev +endef + +define Profile/F5D8235V2/Description + Package set for Belkin F5D8235 v2 +endef +$(eval $(call Profile,F5D8235V2)) + + +define Profile/F7C027 + NAME:=Belkin F7C027 + PACKAGES:=\ + -kmod-usb-core -kmod-usb-dwc2 \ + -kmod-ledtrig-usbdev +endef + +define Profile/F7C027/Description + Package set for Belkin F7C027 - Plug with soc_ap and a relay +endef +$(eval $(call Profile,F7C027)) diff --git a/target/linux/ramips/rt305x/profiles/broadway.mk b/target/linux/ramips/rt305x/profiles/broadway.mk new file mode 100644 index 0000000..b757387 --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/broadway.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/BROADWAY + NAME:=Hauppauge Broadway + PACKAGES:=\ + kmod-usb-core kmod-usb-dwc2 \ + kmod-ledtrig-usbdev +endef + +define Profile/BROADWAY/Description + Package set for Hauppauge Broadway +endef +$(eval $(call Profile,BROADWAY)) diff --git a/target/linux/ramips/rt305x/profiles/d-link.mk b/target/linux/ramips/rt305x/profiles/d-link.mk new file mode 100644 index 0000000..05d919b --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/d-link.mk @@ -0,0 +1,68 @@ +# +# Copyright (C) 2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/DCS930 + NAME:=D-Link DCS-930 + PACKAGES:=kmod-video-core kmod-video-uvc \ + kmod-sound-core kmod-usb-audio \ + kmod-usb-core kmod-usb-dwc2 +endef + +define Profile/DCS930/Description + Package set for D-Link DCS-930 board +endef +$(eval $(call Profile,DCS930)) + + +define Profile/DCS930LB1 + NAME:=D-Link DCS-930L B1 + PACKAGES:=kmod-video-core kmod-video-uvc \ + kmod-sound-core kmod-usb-audio \ + kmod-usb-core kmod-usb-ohci kmod-usb2 +endef + +define Profile/DCS930LB1/Description + Package set for D-Link DCS-930L B1 board +endef +$(eval $(call Profile,DCS930LB1)) + + +define Profile/DIR610A1 + NAME:=D-Link DIR-610 A1 + PACKAGES:=kmod-ledtrig-netdev kmod-ledtrig-timer +endef + +define Profile/DIR610A1/Description + Package set for D-Link DIR610 A1 board +endef +$(eval $(call Profile,DIR610A1)) + + +define Profile/DIR-615-D + NAME:=D-Link DIR-615 D + PACKAGES:=\ + -kmod-usb-core -kmod-usb-dwc2 \ + -kmod-ledtrig-usbdev +endef + +define Profile/DIR-615-D/Description + Package set for D-Link DIR-615 D board +endef +$(eval $(call Profile,DIR-615-D)) + + +define Profile/DIR615H1 + NAME:=D-Link DIR-615 H1 + PACKAGES:=\ + -kmod-usb-core -kmod-usb-dwc2 \ + -kmod-ledtrig-usbdev +endef + +define Profile/DIR615H1/Description + Package set for D-Link DIR-615 H1 board +endef +$(eval $(call Profile,DIR615H1)) diff --git a/target/linux/ramips/rt305x/profiles/easyacc.mk b/target/linux/ramips/rt305x/profiles/easyacc.mk new file mode 100644 index 0000000..6b31673 --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/easyacc.mk @@ -0,0 +1,20 @@ +# +# Copyright (C) 2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/WIZARD8800 + NAME:=EasyAcc WIZARD 8800 + PACKAGES:=\ + kmod-ledtrig-netdev kmod-ledtrig-timer kmod-leds-gpio \ + kmod-usb-core kmod-usb-ohci kmod-usb2 kmod-usb-net usbutils \ + kmod-scsi-core kmod-scsi-generic kmod-fs-ext4 kmod-fs-msdos \ + kmod-usb-storage kmod-usb-storage-extras block-mount +endef + +define Profile/WIZARD8800/Description + Package set for EasyAcc Wi-Stor Wizard 4in1 wireless storage 8800 +endef +$(eval $(call Profile,WIZARD8800)) diff --git a/target/linux/ramips/rt305x/profiles/engenius.mk b/target/linux/ramips/rt305x/profiles/engenius.mk new file mode 100644 index 0000000..cef275e --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/engenius.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2011 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/ESR-9753 + NAME:=EnGenius ESR-9753 + PACKAGES:= +endef + +define Profile/ESR-9753/Description + EnGenius ESR-9753 profile. +endef +$(eval $(call Profile,ESR-9753)) diff --git a/target/linux/ramips/rt305x/profiles/fon.mk b/target/linux/ramips/rt305x/profiles/fon.mk new file mode 100644 index 0000000..cb95ad9 --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/fon.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/FONERA20N + NAME:=Fonera 2.0N + PACKAGES:=\ + kmod-usb-core kmod-usb-dwc2 \ + kmod-ledtrig-usbdev +endef + +define Profile/FONERA20N/Description + Package set for Fonera 2.0N +endef +$(eval $(call Profile,FONERA20N)) diff --git a/target/linux/ramips/rt305x/profiles/hame.mk b/target/linux/ramips/rt305x/profiles/hame.mk new file mode 100644 index 0000000..2f483a0 --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/hame.mk @@ -0,0 +1,29 @@ +# +# Copyright (C) 2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/MPRA1 + NAME:=HAME MPR-A1 + PACKAGES:=\ + kmod-usb-core kmod-usb-ohci kmod-usb2 kmod-ledtrig-netdev +endef + +define Profile/MPRA1/Description + Package set for HAME MPR-A1 board +endef +$(eval $(call Profile,MPRA1)) + + +define Profile/MPRA2 + NAME:=HAME MPR-A2 + PACKAGES:=\ + kmod-usb-core kmod-usb-ohci kmod-usb2 kmod-ledtrig-netdev +endef + +define Profile/MPRA2/Description + Package set for HAME MPR-A2 board +endef +$(eval $(call Profile,MPRA2)) diff --git a/target/linux/ramips/rt305x/profiles/hilink.mk b/target/linux/ramips/rt305x/profiles/hilink.mk new file mode 100644 index 0000000..fa6833d --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/hilink.mk @@ -0,0 +1,15 @@ +# +# Copyright (C) 2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/HLKRM04 + NAME:=HILINK HLK-RM04 +endef + +define Profile/HLKRM04/Description + Package set for HiLink RM04 Module +endef +$(eval $(call Profile,HLKRM04)) diff --git a/target/linux/ramips/rt305x/profiles/hootoo.mk b/target/linux/ramips/rt305x/profiles/hootoo.mk new file mode 100644 index 0000000..216ccff --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/hootoo.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/HT-TM02 + NAME:=HooToo HT-TM02 + PACKAGES:=kmod-usb-core kmod-usb-ohci kmod-usb2 kmod-ledtrig-usbdev +endef + +define Profile/HT-TM02/Description + Package set optimized for the HooToo HT-TM02. +endef +$(eval $(call Profile,HT-TM02)) diff --git a/target/linux/ramips/rt305x/profiles/huawei.mk b/target/linux/ramips/rt305x/profiles/huawei.mk new file mode 100644 index 0000000..3223e76 --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/huawei.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/HG255D + NAME:=Huawei HG255D + PACKAGES:=kmod-leds-gpio wpad-mini kmod-usb-dwc2 +endef + +define Profile/HG255D/Description + Package set for Huawei HG255D. +endef +$(eval $(call Profile,HG255D)) diff --git a/target/linux/ramips/rt305x/profiles/intenso.mk b/target/linux/ramips/rt305x/profiles/intenso.mk new file mode 100644 index 0000000..89f3094 --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/intenso.mk @@ -0,0 +1,19 @@ +# +# Copyright (C) 2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/M2M + NAME:=Intenso Memory 2 Move + PACKAGES:=\ + kmod-ledtrig-netdev kmod-ledtrig-timer \ + kmod-usb-core kmod-usb2 kmod-usb-storage kmod-scsi-core \ + kmod-fs-ext4 kmod-fs-vfat block-mount +endef + +define Profile/M2M/Description + Package set for Intenso Memory 2 Move USB 3.0 +endef +$(eval $(call Profile,M2M)) diff --git a/target/linux/ramips/rt305x/profiles/misc.mk b/target/linux/ramips/rt305x/profiles/misc.mk new file mode 100644 index 0000000..62a1d94 --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/misc.mk @@ -0,0 +1,17 @@ +# +# Copyright (C) 2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/A5-V11 + NAME:=A5-V11 + PACKAGES:=\ + kmod-usb-core kmod-usb-ohci kmod-usb2 +endef + +define Profile/A5-V11/Description + Package set for A5-V11 +endef +$(eval $(call Profile,A5-V11)) diff --git a/target/linux/ramips/rt305x/profiles/nexx.mk b/target/linux/ramips/rt305x/profiles/nexx.mk new file mode 100644 index 0000000..52f132e --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/nexx.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/WT1520 + NAME:=Nexx WT1520 + PACKAGES:=kmod-usb2 +endef + +define Profile/WT1520/Description + Package set for WT1520 +endef +$(eval $(call Profile,WT1520)) diff --git a/target/linux/ramips/rt305x/profiles/olimex.mk b/target/linux/ramips/rt305x/profiles/olimex.mk new file mode 100644 index 0000000..0c6276a --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/olimex.mk @@ -0,0 +1,33 @@ +# +# Copyright (C) 2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/RT5350F-OLINUXINO + NAME:=RT5350F-OLinuXino + PACKAGES:=\ + kmod-usb-core kmod-usb-ohci kmod-usb2 \ + kmod-i2c-core kmod-i2c-ralink \ + kmod-spi-dev +endef + +define Profile/RT5350F-OLINUXINO/Description + Package set for RT5350F-OLinuXino board +endef +$(eval $(call Profile,RT5350F-OLINUXINO)) + + +define Profile/RT5350F-OLINUXINO-EVB + NAME:=RT5350F-OLinuXino-EVB + PACKAGES:=\ + kmod-usb-core kmod-usb-ohci kmod-usb2 \ + kmod-i2c-core kmod-i2c-ralink \ + kmod-spi-dev +endef + +define Profile/RT5350F-OLINUXINO-EVB/Description + Package set for RT5350F-OLinuXino-EVB board +endef +$(eval $(call Profile,RT5350F-OLINUXINO-EVB)) diff --git a/target/linux/ramips/rt305x/profiles/planex.mk b/target/linux/ramips/rt305x/profiles/planex.mk new file mode 100644 index 0000000..50ce382 --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/planex.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/MZK-DP150N + NAME:=Planex MZK-DP150N + PACKAGES:= kmod-spi-dev +endef + +define Profile/MZK-DP150N/Description + Package set optimized for the Planex MZK-DP150N. +endef +$(eval $(call Profile,MZK-DP150N)) diff --git a/target/linux/ramips/rt305x/profiles/poray.mk b/target/linux/ramips/rt305x/profiles/poray.mk new file mode 100644 index 0000000..7a68a5f --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/poray.mk @@ -0,0 +1,61 @@ +# +# Copyright (C) 2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/IP2202 + NAME:=Poray IP2202 + PACKAGES:=kmod-usb-core kmod-usb2 kmod-usb-dwc2 \ + kmod-ledtrig-netdev kmod-ledtrig-timer +endef + +define Profile/IP2202/Description + Package set for Poray IP2202 board +endef +$(eval $(call Profile,IP2202)) + + +define Profile/M3 + NAME:=Poray M3 + PACKAGES:=kmod-usb-core kmod-usb2 kmod-ledtrig-netdev kmod-ledtrig-timer +endef + +define Profile/M3/Description + Package set for Poray M3 board +endef +$(eval $(call Profile,M3)) + + +define Profile/M4 + NAME:=Poray M4 + PACKAGES:=kmod-usb-core kmod-usb2 kmod-ledtrig-netdev kmod-ledtrig-timer +endef + +define Profile/M4/Description + Package set for Poray M4 board +endef +$(eval $(call Profile,M4)) + + +define Profile/X5 + NAME:=Poray X5/X6 + PACKAGES:=kmod-usb-core kmod-usb2 kmod-ledtrig-netdev kmod-ledtrig-timer +endef + +define Profile/X5/Description + Package set for Poray X5/X6 board +endef +$(eval $(call Profile,X5)) + + +define Profile/X8 + NAME:=Poray X8 + PACKAGES:=kmod-usb-core kmod-usb2 kmod-ledtrig-netdev kmod-ledtrig-timer +endef + +define Profile/X8/Description + Package set for Poray X8 board +endef +$(eval $(call Profile,X8)) diff --git a/target/linux/ramips/rt305x/profiles/sevenlinks.mk b/target/linux/ramips/rt305x/profiles/sevenlinks.mk new file mode 100644 index 0000000..6ddc383 --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/sevenlinks.mk @@ -0,0 +1,18 @@ +# +# Copyright (C) 2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/PX-4885 + NAME:=7Links PX-4885 + PACKAGES:=\ + kmod-usb-core kmod-usb-dwc2 kmod-usb2 kmod-usb-ohci \ + kmod-ledtrig-usbdev kmod-leds-gpio +endef + +define Profile/PX-4885/Description + Package set for 7Links PX-4885 wireless router. +endef +$(eval $(call Profile,PX-4885)) diff --git a/target/linux/ramips/rt305x/profiles/tenda.mk b/target/linux/ramips/rt305x/profiles/tenda.mk new file mode 100644 index 0000000..a3c5d3b --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/tenda.mk @@ -0,0 +1,42 @@ +# +# Copyright (C) 2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/3G150B + NAME:=Tenda 3G150B + PACKAGES:=\ + kmod-usb-core kmod-usb-dwc2 \ + kmod-ledtrig-usbdev +endef + +define Profile/3G150B/Description + Package set for Tenda 3G150B board +endef +$(eval $(call Profile,3G150B)) + + +define Profile/3G300M + NAME:=Tenda 3G300M + PACKAGES:=\ + kmod-usb-core kmod-usb-dwc2 \ + kmod-ledtrig-usbdev +endef + +define Profile/3G300M/Description + Package set for Tenda 3G300M board +endef +$(eval $(call Profile,3G300M)) + + +define Profile/W306R_V20 + NAME:=Tenda W306R V2.0 + PACKAGES:= +endef + +define Profile/W306R_V20/Description + Package set for Tenda W306R V2.0 board +endef +$(eval $(call Profile,W306R_V20)) diff --git a/target/linux/ramips/rt305x/profiles/upvel.mk b/target/linux/ramips/rt305x/profiles/upvel.mk new file mode 100644 index 0000000..c5d60f5 --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/upvel.mk @@ -0,0 +1,31 @@ +# +# Copyright (C) 2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/UR-326N4G + NAME:=UPVEL UR-326N4G + PACKAGES:=\ + kmod-usb-core kmod-usb-dwc2 \ + kmod-ledtrig-usbdev +endef + +define Profile/UR-326N4G/Description + Default package set compatible with URVEL router board. +endef +$(eval $(call Profile,UR-326N4G)) + + +define Profile/UR-336UN + NAME:=UPVEL UR-336UN + PACKAGES:=\ + kmod-usb-core kmod-usb-dwc2 \ + kmod-ledtrig-usbdev +endef + +define Profile/UR-336UN/Description + Default package set compatible with URVEL router board. +endef +$(eval $(call Profile,UR-336UN)) diff --git a/target/linux/ramips/rt305x/profiles/vocore.mk b/target/linux/ramips/rt305x/profiles/vocore.mk new file mode 100644 index 0000000..2ba3499 --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/vocore.mk @@ -0,0 +1,19 @@ +# +# Copyright (C) 2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/VOCORE + NAME:=VoCore + PACKAGES:=\ + kmod-usb-core kmod-usb-ohci kmod-usb2 \ + kmod-i2c-core kmod-i2c-ralink \ + kmod-spi-dev +endef + +define Profile/VOCORE/Description + Package set for VoCore board +endef +$(eval $(call Profile,VOCORE)) diff --git a/target/linux/ramips/rt305x/profiles/wansview.mk b/target/linux/ramips/rt305x/profiles/wansview.mk new file mode 100644 index 0000000..0908a9c --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/wansview.mk @@ -0,0 +1,17 @@ +# +# Copyright (C) 2014 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/NCS601W + NAME:=Wansview NCS601W + PACKAGES:=kmod-video-core kmod-video-uvc \ + kmod-usb-core kmod-usb-ohci +endef + +define Profile/NCS601W/Description + Package set for Wansview NCS601W board +endef +$(eval $(call Profile,NCS601W)) diff --git a/target/linux/ramips/rt305x/profiles/wiznet.mk b/target/linux/ramips/rt305x/profiles/wiznet.mk new file mode 100644 index 0000000..f8e8324 --- /dev/null +++ b/target/linux/ramips/rt305x/profiles/wiznet.mk @@ -0,0 +1,17 @@ +# +# Copyright (C) 2015 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/WIZFI630A + NAME:=WIZnet WizFi630A + PACKAGES:=\ + kmod-usb2 +endef + +define Profile/WIZFI630A/Description + Package set for WIZnet WizFi630A board +endef +$(eval $(call Profile,WIZFI630A)) diff --git a/target/linux/ramips/rt305x/target.mk b/target/linux/ramips/rt305x/target.mk new file mode 100644 index 0000000..b97554f --- /dev/null +++ b/target/linux/ramips/rt305x/target.mk @@ -0,0 +1,17 @@ +# +# Copyright (C) 2009 OpenWrt.org +# + +SUBTARGET:=rt305x +BOARDNAME:=RT3x5x/RT5350 based boards +ARCH_PACKAGES:=ramips_24kec +FEATURES+=usb ramdisk +CPU_TYPE:=24kec +CPU_SUBTYPE:=dsp + +DEFAULT_PACKAGES += kmod-rt2800-soc + +define Target/Description + Build firmware images for Ralink RT3x5x/RT5350 based boards. +endef + diff --git a/target/linux/ramips/rt3883/config-3.18 b/target/linux/ramips/rt3883/config-3.18 new file mode 100644 index 0000000..6dccb46 --- /dev/null +++ b/target/linux/ramips/rt3883/config-3.18 @@ -0,0 +1,182 @@ +CONFIG_AR8216_PHY=y +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_ARCH_DISCARD_MEMBLOCK=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_ARCH_HAS_RESET_CONTROLLER=y +# CONFIG_ARCH_HAS_SG_CHAIN is not set +CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_CEVT_R4K=y +CONFIG_CLKDEV_LOOKUP=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMDLINE="rootfstype=squashfs,jffs2" +CONFIG_CMDLINE_BOOL=y +# CONFIG_CMDLINE_OVERRIDE is not set +CONFIG_CPU_GENERIC_DUMP_TLB=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS32_R1 is not set +CONFIG_CPU_MIPS32_R2=y +CONFIG_CPU_MIPSR2=y +CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y +CONFIG_CPU_R4K_CACHE_TLB=y +CONFIG_CPU_R4K_FPU=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_CPU_SUPPORTS_MSA=y +CONFIG_CSRC_R4K=y +CONFIG_DEBUG_PINCTRL=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_DTB_RT3883_EVAL is not set +CONFIG_DTB_RT_NONE=y +CONFIG_DTC=y +CONFIG_EARLY_PRINTK=y +CONFIG_ETHERNET_PACKET_MANGLE=y +CONFIG_GENERIC_ATOMIC64=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_IO=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_GPIO_RALINK=y +CONFIG_GPIO_SYSFS=y +CONFIG_HARDWARE_WATCHPOINTS=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_HAVE_BPF_JIT=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_HAVE_DEBUG_KMEMLEAK=y +CONFIG_HAVE_DEBUG_STACKOVERFLOW=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_IDE=y +CONFIG_HAVE_KVM=y +CONFIG_HAVE_MACH_CLKDEV=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MEMBLOCK_NODE_MAP=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_HAVE_NET_DSA=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HW_HAS_PCI=y +CONFIG_HZ_PERIODIC=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQCHIP=y +CONFIG_IRQ_CPU=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_INTC=y +CONFIG_IRQ_WORK=y +CONFIG_LIBFDT=y +CONFIG_MDIO_BOARDINFO=y +CONFIG_MIPS=y +# CONFIG_MIPS_HUGE_TLB_SUPPORT is not set +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_MIPS_MACHINE is not set +CONFIG_MODULES_USE_ELF_REL=y +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_M25P80=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_SEAMA_FW=y +CONFIG_MTD_SPLIT_UIMAGE_FW=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_PER_CPU_KM=y +CONFIG_NET_RALINK=y +CONFIG_NET_RALINK_MDIO=y +CONFIG_NET_RALINK_MDIO_RT2880=y +CONFIG_NET_RALINK_RT3883=y +CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y +# CONFIG_NO_IOPORT_MAP is not set +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_ADDRESS_PCI=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_MDIO=y +CONFIG_OF_MTD=y +CONFIG_OF_NET=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PHYLIB=y +CONFIG_PHY_RALINK_USB=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_RT2880=y +# CONFIG_PINCTRL_SINGLE is not set +# CONFIG_PREEMPT_RCU is not set +CONFIG_RALINK=y +# CONFIG_RALINK_ILL_ACC is not set +CONFIG_RALINK_USBPHY=y +CONFIG_RALINK_WDT=y +# CONFIG_RCU_STALL_COMMON is not set +CONFIG_RESET_CONTROLLER=y +CONFIG_RTL8366_SMI=y +CONFIG_RTL8367B_PHY=y +CONFIG_RTL8367_PHY=y +# CONFIG_SCSI_DMA is not set +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RT288X=y +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SOC_MT7620 is not set +# CONFIG_SOC_MT7621 is not set +# CONFIG_SOC_RT288X is not set +# CONFIG_SOC_RT305X is not set +CONFIG_SOC_RT3883=y +CONFIG_SPI=y +CONFIG_SPI_MASTER=y +# CONFIG_SPI_MT7621 is not set +CONFIG_SPI_RT2880=y +CONFIG_SWCONFIG=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_SYS_HAS_CPU_MIPS32_R2=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_MIPS16=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_USB_PHY=y +CONFIG_USB_SUPPORT=y +CONFIG_USE_OF=y +CONFIG_WATCHDOG_CORE=y +CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/ramips/rt3883/profiles/00-default.mk b/target/linux/ramips/rt3883/profiles/00-default.mk new file mode 100644 index 0000000..7007c5d --- /dev/null +++ b/target/linux/ramips/rt3883/profiles/00-default.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2012 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 + PACKAGES:=kmod-usb-core kmod-usb-ohci kmod-usb2 swconfig +endef + +define Profile/Default/Description + Default package set compatible with most boards. +endef +$(eval $(call Profile,Default)) diff --git a/target/linux/ramips/rt3883/profiles/asus.mk b/target/linux/ramips/rt3883/profiles/asus.mk new file mode 100644 index 0000000..4c652df --- /dev/null +++ b/target/linux/ramips/rt3883/profiles/asus.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/RTN56U + NAME:=Asus RT-N56U + PACKAGES:=kmod-usb-core kmod-usb-ohci kmod-usb2 swconfig +endef + +define Profile/RTN56U/Description + Package set compatible with the Asus RT-N56U board. +endef +$(eval $(call Profile,RTN56U)) diff --git a/target/linux/ramips/rt3883/profiles/d-link.mk b/target/linux/ramips/rt3883/profiles/d-link.mk new file mode 100644 index 0000000..6c2636a --- /dev/null +++ b/target/linux/ramips/rt3883/profiles/d-link.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/DIR645 + NAME:=D-Link DIR-645 + PACKAGES:=kmod-usb-core kmod-usb-ohci kmod-usb2 swconfig +endef + +define Profile/DIR645/Description + Package set compatible with the D-Link DIR-645 board. +endef +$(eval $(call Profile,DIR645)) diff --git a/target/linux/ramips/rt3883/profiles/edimax.mk b/target/linux/ramips/rt3883/profiles/edimax.mk new file mode 100644 index 0000000..b807c2c --- /dev/null +++ b/target/linux/ramips/rt3883/profiles/edimax.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/BR6475ND + NAME:=Edimax BR-6475nD + PACKAGES:=swconfig +endef + +define Profile/BR6475ND/Description + Package set compatible with the Edimax BR-6475nD board. +endef +$(eval $(call Profile,BR6475ND)) diff --git a/target/linux/ramips/rt3883/profiles/omnima.mk b/target/linux/ramips/rt3883/profiles/omnima.mk new file mode 100644 index 0000000..ce25999 --- /dev/null +++ b/target/linux/ramips/rt3883/profiles/omnima.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/HPM + NAME:=Omnima HPM + PACKAGES:=kmod-usb-core kmod-usb-ohci kmod-usb2 +endef + +define Profile/HPM/Description + Package set compatible with the Omnima HPM board. +endef +$(eval $(call Profile,HPM)) diff --git a/target/linux/ramips/rt3883/profiles/samsung.mk b/target/linux/ramips/rt3883/profiles/samsung.mk new file mode 100644 index 0000000..18f60d4 --- /dev/null +++ b/target/linux/ramips/rt3883/profiles/samsung.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/CYSWR1100 + NAME:=Samsung CY-SWR1100 + PACKAGES:=kmod-usb-core kmod-usb-ohci kmod-usb2 swconfig +endef + +define Profile/CYSWR1100/Description + Package set compatible with the Samsung CY-SWR1100 board. +endef +$(eval $(call Profile,CYSWR1100)) diff --git a/target/linux/ramips/rt3883/profiles/trendnet.mk b/target/linux/ramips/rt3883/profiles/trendnet.mk new file mode 100644 index 0000000..5a055ae --- /dev/null +++ b/target/linux/ramips/rt3883/profiles/trendnet.mk @@ -0,0 +1,27 @@ +# +# Copyright (C) 2012 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/TEW691GR + NAME:=TRENDnet TEW-691GR + PACKAGES:=swconfig +endef + +define Profile/TEW691GR/Description + Package set compatible with the TRENDnet TEW-691GR board. +endef +$(eval $(call Profile,TEW691GR)) + + +define Profile/TEW692GR + NAME:=TRENDnet TEW-692GR + PACKAGES:=swconfig +endef + +define Profile/TEW692GR/Description + Package set compatible with the TRENDnet TEW-692GR board. +endef +$(eval $(call Profile,TEW692GR)) diff --git a/target/linux/ramips/rt3883/target.mk b/target/linux/ramips/rt3883/target.mk new file mode 100644 index 0000000..96c9e93 --- /dev/null +++ b/target/linux/ramips/rt3883/target.mk @@ -0,0 +1,17 @@ +# +# Copyright (C) 2011 OpenWrt.org +# + +SUBTARGET:=rt3883 +BOARDNAME:=RT3662/RT3883 based boards +ARCH_PACKAGES:=ramips_24kec +FEATURES+=usb pci +CPU_TYPE:=74kc +CPU_SUBTYPE:=dsp2 + +DEFAULT_PACKAGES += kmod-rt2800-pci kmod-rt2800-soc + +define Target/Description + Build firmware images for Ralink RT3662/RT3883 based boards. +endef + |