diff --git a/package/base-files/files/sbin/wifi b/package/base-files/files/sbin/wifi index 75759b94f3..6b9662fe93 100755 --- a/package/base-files/files/sbin/wifi +++ b/package/base-files/files/sbin/wifi @@ -130,10 +130,12 @@ wifi_updown() { ubus_wifi_cmd "$cmd" "$2" scan_wifi cmd=up + ubus call network reload } [ reconf = "$1" ] && { scan_wifi cmd=reconf + ubus call network reload } ubus_wifi_cmd "$cmd" "$2" _wifi_updown "$@" @@ -246,7 +248,7 @@ case "$1" in reload) wifi_reload "$2";; reload_legacy) wifi_reload_legacy "$2";; --help|help) usage;; - reconf) ubus call network reload; wifi_updown "reconf" "$2";; - ''|up) ubus call network reload; wifi_updown "enable" "$2";; + reconf) wifi_updown "reconf" "$2";; + ''|up) wifi_updown "enable" "$2";; *) usage; exit 1;; esac diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh index ced0bf8b60..a27b0e104e 100644 --- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh +++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh @@ -1021,10 +1021,8 @@ drv_mac80211_setup() { return 1 } - [ -z "$(uci -q -P /var/state show wireless._${phy})" ] && { - uci -q -P /var/state set wireless._${phy}=phy - wireless_set_data phy="$phy" - } + wireless_set_data phy="$phy" + [ -z "$(uci -q -P /var/state show wireless._${phy})" ] && uci -q -P /var/state set wireless._${phy}=phy OLDAPLIST=$(uci -q -P /var/state get wireless._${phy}.aplist) OLDSPLIST=$(uci -q -P /var/state get wireless._${phy}.splist) @@ -1117,6 +1115,7 @@ drv_mac80211_setup() { [ -n "$hostapd_ctrl" ] && { local no_reload=1 if [ -n "$(ubus list | grep hostapd.$primary_ap)" ]; then + no_reload=0 [ "${NEW_MD5}" = "${OLD_MD5}" ] || { ubus call hostapd.$primary_ap reload no_reload=$? @@ -1191,6 +1190,10 @@ drv_mac80211_teardown() { json_select data json_get_vars phy json_select .. + [ -n "$phy" ] || { + echo "Bug: PHY is undefined for device '$1'" + return 1 + } mac80211_interface_cleanup "$phy" uci -q -P /var/state revert wireless._${phy} diff --git a/package/kernel/mac80211/patches/subsys/379-mac80211-fix-starting-aggregation-sessions-on-mesh-i.patch b/package/kernel/mac80211/patches/subsys/379-mac80211-fix-starting-aggregation-sessions-on-mesh-i.patch new file mode 100644 index 0000000000..56eafaf847 --- /dev/null +++ b/package/kernel/mac80211/patches/subsys/379-mac80211-fix-starting-aggregation-sessions-on-mesh-i.patch @@ -0,0 +1,112 @@ +From: Felix Fietkau +Date: Tue, 29 Jun 2021 13:25:09 +0200 +Subject: [PATCH] mac80211: fix starting aggregation sessions on mesh + interfaces + +The logic for starting aggregation sessions was recently moved from minstrel_ht +to mac80211, into the subif tx handler just after the sta lookup. +Unfortunately this didn't work for mesh interfaces, since the sta lookup is +deferred until a much later point in time on those. +Fix this by also calling the aggregation check right after the deferred sta +lookup. + +Fixes: 08a46c642001 ("mac80211: move A-MPDU session check from minstrel_ht to mac80211") +Signed-off-by: Felix Fietkau +--- + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1159,6 +1159,29 @@ static bool ieee80211_tx_prep_agg(struct + return queued; + } + ++static void ++ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta, ++ struct sk_buff *skb) ++{ ++ struct rate_control_ref *ref = sdata->local->rate_ctrl; ++ u16 tid; ++ ++ if (!ref || !(ref->ops->capa & RATE_CTRL_CAPA_AMPDU_TRIGGER)) ++ return; ++ ++ if (!sta || !sta->sta.ht_cap.ht_supported || ++ !sta->sta.wme || skb_get_queue_mapping(skb) == IEEE80211_AC_VO || ++ skb->protocol == sdata->control_port_protocol) ++ return; ++ ++ tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; ++ if (likely(sta->ampdu_mlme.tid_tx[tid])) ++ return; ++ ++ ieee80211_start_tx_ba_session(&sta->sta, tid, 0); ++} ++ + /* + * initialises @tx + * pass %NULL for the station if unknown, a valid pointer if known +@@ -1172,6 +1195,7 @@ ieee80211_tx_prepare(struct ieee80211_su + struct ieee80211_local *local = sdata->local; + struct ieee80211_hdr *hdr; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ bool aggr_check = false; + int tid; + + memset(tx, 0, sizeof(*tx)); +@@ -1202,8 +1226,10 @@ ieee80211_tx_prepare(struct ieee80211_su + tx->sdata->control_port_protocol == tx->skb->protocol) { + tx->sta = sta_info_get_bss(sdata, hdr->addr1); + } +- if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) ++ if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) { + tx->sta = sta_info_get(sdata, hdr->addr1); ++ aggr_check = true; ++ } + } + + if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && +@@ -1213,8 +1239,12 @@ ieee80211_tx_prepare(struct ieee80211_su + struct tid_ampdu_tx *tid_tx; + + tid = ieee80211_get_tid(hdr); +- + tid_tx = rcu_dereference(tx->sta->ampdu_mlme.tid_tx[tid]); ++ if (!tid_tx && aggr_check) { ++ ieee80211_aggr_check(sdata, tx->sta, skb); ++ tid_tx = rcu_dereference(tx->sta->ampdu_mlme.tid_tx[tid]); ++ } ++ + if (tid_tx) { + bool queued; + +@@ -3949,29 +3979,6 @@ void ieee80211_txq_schedule_start(struct + } + EXPORT_SYMBOL(ieee80211_txq_schedule_start); + +-static void +-ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata, +- struct sta_info *sta, +- struct sk_buff *skb) +-{ +- struct rate_control_ref *ref = sdata->local->rate_ctrl; +- u16 tid; +- +- if (!ref || !(ref->ops->capa & RATE_CTRL_CAPA_AMPDU_TRIGGER)) +- return; +- +- if (!sta || !sta->sta.ht_cap.ht_supported || +- !sta->sta.wme || skb_get_queue_mapping(skb) == IEEE80211_AC_VO || +- skb->protocol == sdata->control_port_protocol) +- return; +- +- tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; +- if (likely(sta->ampdu_mlme.tid_tx[tid])) +- return; +- +- ieee80211_start_tx_ba_session(&sta->sta, tid, 0); +-} +- + void __ieee80211_subif_start_xmit(struct sk_buff *skb, + struct net_device *dev, + u32 info_flags, diff --git a/package/network/services/dnsmasq/files/dnsmasq.init b/package/network/services/dnsmasq/files/dnsmasq.init index 6a849f2459..aa5a48840b 100644 --- a/package/network/services/dnsmasq/files/dnsmasq.init +++ b/package/network/services/dnsmasq/files/dnsmasq.init @@ -161,7 +161,7 @@ append_server() { } append_rev_server() { - xappend "--rev-server=$1" + xappend "--rev-server=$1" } append_address() { @@ -878,8 +878,16 @@ dnsmasq_start() append_bool "$cfg" noresolv "--no-resolv" append_bool "$cfg" localise_queries "--localise-queries" append_bool "$cfg" readethers "--read-ethers" - append_bool "$cfg" dbus "--enable-dbus" - append_bool "$cfg" ubus "--enable-ubus" 1 + + local instance_name="dnsmasq.$cfg" + if [ "$cfg" = "$DEFAULT_INSTANCE" ]; then + instance_name="dnsmasq" + fi + config_get_bool dbus "$cfg" "dbus" 0 + [ $dbus -gt 0 ] && xappend "--enable-dbus=uk.org.thekelleys.$instance_name" + config_get_bool ubus "$cfg" "ubus" 1 + [ $ubus -gt 0 ] && xappend "--enable-ubus=$instance_name" + append_bool "$cfg" expandhosts "--expand-hosts" config_get tftp_root "$cfg" "tftp_root" [ -n "$tftp_root" ] && mkdir -p "$tftp_root" && append_bool "$cfg" enable_tftp "--enable-tftp" @@ -1178,6 +1186,7 @@ boot() start_service() { local instance="$1" local instance_found=0 + local first_instance="" . /lib/functions/network.sh @@ -1188,10 +1197,27 @@ start_service() { if [ -n "$instance" ] && [ "$instance" = "$name" ]; then instance_found=1 fi + if [ -z "$DEFAULT_INSTANCE" ]; then + local disabled + config_get_bool disabled "$name" disabled 0 + if [ "$disabled" -eq 0 ]; then + # First enabled section will be assigned default instance name. + # Unnamed sections get precedence over named sections. + if expr "$cfg" : 'cfg[0-9a-f]*$' >/dev/null = "9"; then # See uci_fixup_section. + DEFAULT_INSTANCE="$name" # Unnamed config section. + elif [ -z "$first_instance" ]; then + first_instance="$name" + fi + fi + fi fi } + DEFAULT_INSTANCE="" config_load dhcp + if [ -z "$DEFAULT_INSTANCE" ]; then + DEFAULT_INSTANCE="$first_instance" # No unnamed config section was found. + fi if [ -n "$instance" ]; then [ "$instance_found" -gt 0 ] || return diff --git a/package/network/utils/iwinfo/Makefile b/package/network/utils/iwinfo/Makefile index b7c8370bba..9124e5fa07 100644 --- a/package/network/utils/iwinfo/Makefile +++ b/package/network/utils/iwinfo/Makefile @@ -11,9 +11,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/iwinfo.git -PKG_SOURCE_DATE:=2021-06-09 -PKG_SOURCE_VERSION:=c0414642fead263a4a6a686ad3cb7e965ec8a23a -PKG_MIRROR_HASH:=c5686bbae86753c53db03a686b034bbb80d31107cc359ebd8522ea1c82db35ea +PKG_SOURCE_DATE:=2021-06-28 +PKG_SOURCE_VERSION:=c9b1672f5a83c8dcb14fdbaee651f775a7defe52 +PKG_MIRROR_HASH:=f33779035153da6bd0b2f100f402f62f1554ab87ed6fbbd938d41df6b9947a1f PKG_MAINTAINER:=Jo-Philipp Wich PKG_LICENSE:=GPL-2.0 diff --git a/package/system/zram-swap/files/zram.init b/package/system/zram-swap/files/zram.init index 9fce5e4797..1a9cefeff5 100755 --- a/package/system/zram-swap/files/zram.init +++ b/package/system/zram-swap/files/zram.init @@ -2,8 +2,8 @@ START=15 -extra_command "compact" "Trigger compaction for all Z-RAM swap dev's" -extra_command "status" "Print out information & statistics about Z-RAM swap devices" +extra_command "compact" "Trigger compaction for all zram swap devices" +extra_command "status" "Print out information & statistics about zram swap devices" ram_getsize() { @@ -60,15 +60,15 @@ zram_comp_algo() local zram_comp_algo="$( uci -q get system.@system[0].zram_comp_algo )" if [ -z "$zram_comp_algo" ]; then - # lzo-rle fails on small RAM devices, default to lzo, which is always available + # default to lzo, which is always available zram_comp_algo="lzo" fi if [ $(grep -c "$zram_comp_algo" /sys/block/$( basename $dev )/comp_algorithm) -ne 0 ]; then - logger -s -t zram_comp_algo -p daemon.debug "Set compression algorithm '$zram_comp_algo' for zram '$dev'" + logger -s -t zram_comp_algo -p daemon.debug "set compression algorithm '$zram_comp_algo' for zram '$dev'" echo $zram_comp_algo > "/sys/block/$( basename $dev )/comp_algorithm" else - logger -s -t zram_comp_algo -p daemon.debug "Compression algorithm '$zram_comp_algo' is not supported for '$dev'" + logger -s -t zram_comp_algo -p daemon.debug "compression algorithm '$zram_comp_algo' is not supported for '$dev'" fi } @@ -79,7 +79,7 @@ zram_stats() printf "\nGathering stats info for zram device \"$( basename "$1" )\"\n\n" - printf "Z-RAM\n-----\n" + printf "ZRAM\n----\n" printf "%-25s - %s\n" "Block device" $zdev awk '{ printf "%-25s - %d MiB\n", "Device size", $1/1024/1024 }' <$zdev/disksize printf "%-25s - %s\n" "Compression algo" "$(cat $zdev/comp_algorithm)" @@ -131,7 +131,7 @@ start() } if [ $( grep -cs zram /proc/swaps ) -ne 0 ]; then - logger -s -t zram_start -p daemon.notice "[OK] zram swap is already mounted" + logger -s -t zram_start -p daemon.notice "zram swap is already mounted" return 1 fi @@ -144,15 +144,18 @@ start() local zram_size="$( zram_getsize )" local zram_priority="$( uci -q get system.@system[0].zram_priority )" - zram_priority=${zram_priority:+-p $zram_priority} - logger -s -t zram_start -p daemon.debug "activating '$zram_dev' for swapping ($zram_size MegaBytes)" + if [ -z "$zram_priority" ]; then + zram_priority="100" + fi + + logger -s -t zram_start -p daemon.debug "activating '$zram_dev' for swapping ($zram_size MiB)" zram_reset "$zram_dev" "enforcing defaults" zram_comp_algo "$zram_dev" echo $(( $zram_size * 1024 * 1024 )) >"/sys/block/$( basename "$zram_dev" )/disksize" busybox mkswap "$zram_dev" - busybox swapon -d $zram_priority "$zram_dev" + busybox swapon -d -p $zram_priority "$zram_dev" } stop() diff --git a/package/utils/busybox/files/sysntpd b/package/utils/busybox/files/sysntpd index c4c311c242..074f14b8f8 100755 --- a/package/utils/busybox/files/sysntpd +++ b/package/utils/busybox/files/sysntpd @@ -56,7 +56,14 @@ start_ntpd_instance() { procd_set_param command "$PROG" -n -N if [ "$enable_server" = "1" ]; then procd_append_param command -l - [ -n "$interface" ] && procd_append_param command -I $interface + [ -n "$interface" ] && { + local ifname + + network_get_device ifname "$interface" || \ + ifname="$interface" + procd_append_param command -I "$ifname" + procd_append_param netdev "$ifname" + } fi [ -x "$HOTPLUG_SCRIPT" ] && procd_append_param command -S "$HOTPLUG_SCRIPT" for peer in $server; do @@ -79,11 +86,12 @@ start_ntpd_instance() { } start_service() { + . /lib/functions/network.sh validate_ntp_section ntp start_ntpd_instance } service_triggers() { - local script name use_dhcp + local script name use_dhcp enable_server interface script=$(readlink -f "$initscript") name=$(basename ${script:-$initscript}) @@ -106,5 +114,17 @@ service_triggers() { fi } + config_get_bool enable_server ntp enable_server 0 + config_get interface ntp interface + + [ $enable_server -eq 1 ] && [ -n "$interface" ] && { + local ifname + + network_get_device ifname "$interface" || \ + ifname="$interface" + procd_add_interface_trigger "interface.*" "$ifname" \ + /etc/init.d/"$name" reload + } + procd_add_validation validate_ntp_section } diff --git a/target/linux/ath79/image/mikrotik.mk b/target/linux/ath79/image/mikrotik.mk index 96a94793a9..4256f77379 100644 --- a/target/linux/ath79/image/mikrotik.mk +++ b/target/linux/ath79/image/mikrotik.mk @@ -13,7 +13,7 @@ define Device/mikrotik_routerboard-912uag-2hpnd $(Device/mikrotik_nand) SOC := ar9342 DEVICE_MODEL := RouterBOARD 912UAG-2HPnD - DEVICE_PACKAGES += kmod-usb-ehci kmod-usb2 kmod-gpio-beeper + DEVICE_PACKAGES += kmod-usb-ehci kmod-usb2 SUPPORTED_DEVICES += rb-912uag-2hpnd endef TARGET_DEVICES += mikrotik_routerboard-912uag-2hpnd diff --git a/target/linux/ipq40xx/base-files/lib/preinit/05_set_iface_mac_ipq40xx.sh b/target/linux/ipq40xx/base-files/lib/preinit/05_set_iface_mac_ipq40xx.sh index 51ba7071e7..1b8454e4c5 100644 --- a/target/linux/ipq40xx/base-files/lib/preinit/05_set_iface_mac_ipq40xx.sh +++ b/target/linux/ipq40xx/base-files/lib/preinit/05_set_iface_mac_ipq40xx.sh @@ -29,6 +29,7 @@ preinit_set_mac_address() { base_mac=$(cat /sys/class/net/eth0/address) ip link set dev eth0 address $(macaddr_add "$base_mac" 2) ip link set dev eth1 address $(macaddr_add "$base_mac" 3) + ;; esac } diff --git a/target/linux/ipq806x/config-5.4 b/target/linux/ipq806x/config-5.4 index 80549ad304..fd42d371fe 100644 --- a/target/linux/ipq806x/config-5.4 +++ b/target/linux/ipq806x/config-5.4 @@ -4,22 +4,6 @@ CONFIG_ALIGNMENT_TRAP=y CONFIG_AR8216_PHY=y CONFIG_ARCH_32BIT_OFF_T=y CONFIG_ARCH_CLOCKSOURCE_DATA=y -CONFIG_ARCH_HAS_BINFMT_FLAT=y -CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y -CONFIG_ARCH_HAS_ELF_RANDOMIZE=y -CONFIG_ARCH_HAS_FORTIFY_SOURCE=y -CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y -CONFIG_ARCH_HAS_KCOV=y -CONFIG_ARCH_HAS_KEEPINITRD=y -CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y -CONFIG_ARCH_HAS_PHYS_TO_DMA=y -CONFIG_ARCH_HAS_SETUP_DMA_OPS=y -CONFIG_ARCH_HAS_SET_MEMORY=y -CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y -CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y -CONFIG_ARCH_HAS_TEARDOWN_DMA_OPS=y -CONFIG_ARCH_HAS_TICK_BROADCAST=y -CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_ARCH_KEEP_MEMBLOCK=y # CONFIG_ARCH_MDM9615 is not set @@ -34,15 +18,7 @@ CONFIG_ARCH_NR_GPIO=0 CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y CONFIG_ARCH_QCOM=y -CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y -CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y -CONFIG_ARCH_SUPPORTS_UPROBES=y CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_USE_BUILTIN_BSWAP=y -CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y -CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT=y -CONFIG_ARCH_WANT_GENERAL_HUGETLB=y -CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y CONFIG_ARM=y CONFIG_ARM_AMBA=y CONFIG_ARM_APPENDED_DTB=y @@ -75,7 +51,6 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_MQ_PCI=y CONFIG_BOUNCE=y # CONFIG_CACHE_L2X0 is not set -CONFIG_CC_HAS_KASAN_GENERIC=y CONFIG_CLKDEV_LOOKUP=y CONFIG_CLKSRC_QCOM=y CONFIG_CLONE_BACKWARDS=y @@ -196,48 +171,7 @@ CONFIG_HARDIRQS_SW_RESEND=y CONFIG_HAS_DMA=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT_MAP=y -CONFIG_HAVE_ARCH_AUDITSYSCALL=y -CONFIG_HAVE_ARCH_BITREVERSE=y -CONFIG_HAVE_ARCH_JUMP_LABEL=y -CONFIG_HAVE_ARCH_KGDB=y -CONFIG_HAVE_ARCH_PFN_VALID=y -CONFIG_HAVE_ARCH_SECCOMP_FILTER=y -CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y -CONFIG_HAVE_ARCH_TRACEHOOK=y -CONFIG_HAVE_ARM_ARCH_TIMER=y -CONFIG_HAVE_ARM_SMCCC=y -CONFIG_HAVE_CLK=y -CONFIG_HAVE_CLK_PREPARE=y -CONFIG_HAVE_CONTEXT_TRACKING=y -CONFIG_HAVE_COPY_THREAD_TLS=y -CONFIG_HAVE_C_RECORDMCOUNT=y -CONFIG_HAVE_DEBUG_KMEMLEAK=y -CONFIG_HAVE_DMA_CONTIGUOUS=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y -CONFIG_HAVE_EBPF_JIT=y -CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y -CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y -CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_IDE=y -CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y -CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y -CONFIG_HAVE_MOD_ARCH_SPECIFIC=y -CONFIG_HAVE_NET_DSA=y -CONFIG_HAVE_OPROFILE=y -CONFIG_HAVE_OPTPROBES=y -CONFIG_HAVE_PCI=y -CONFIG_HAVE_PERF_EVENTS=y -CONFIG_HAVE_PERF_REGS=y -CONFIG_HAVE_PERF_USER_STACK_DUMP=y -CONFIG_HAVE_PROC_CPU=y -CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y -CONFIG_HAVE_RSEQ=y CONFIG_HAVE_SMP=y -CONFIG_HAVE_SYSCALL_TRACEPOINTS=y -CONFIG_HAVE_UID16=y -CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y CONFIG_HIGHMEM=y # CONFIG_HIGHPTE is not set CONFIG_HWMON=y @@ -340,6 +274,7 @@ CONFIG_NO_HZ_COMMON=y CONFIG_NO_HZ_IDLE=y CONFIG_NR_CPUS=2 CONFIG_NVMEM=y +# CONFIG_NVME_TCP is not set CONFIG_OF=y CONFIG_OF_ADDRESS=y CONFIG_OF_EARLY_FLATTREE=y @@ -372,6 +307,7 @@ CONFIG_PHYLIB=y CONFIG_PHYLINK=y # CONFIG_PHY_QCOM_APQ8064_SATA is not set CONFIG_PHY_QCOM_IPQ806X_SATA=y +# CONFIG_PHY_QCOM_IPQ806X_USB is not set # CONFIG_PHY_QCOM_PCIE2 is not set # CONFIG_PHY_QCOM_QMP is not set # CONFIG_PHY_QCOM_QUSB2 is not set diff --git a/target/linux/ramips/dts/mt7621_tenbay_t-mb5eu-v01.dts b/target/linux/ramips/dts/mt7621_tenbay_t-mb5eu-v01.dts new file mode 100644 index 0000000000..ef0d48b8c4 --- /dev/null +++ b/target/linux/ramips/dts/mt7621_tenbay_t-mb5eu-v01.dts @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "mt7621.dtsi" + +#include +#include + +/ { + compatible = "tenbay,t-mb5eu-v01", "mediatek,mt7621-soc"; + model = "Tenbay T-MB5EU-V01"; + + aliases { + led-boot = &led_green; + led-failsafe = &led_red; + led-running = &led_blue; + led-upgrade = &led_red; + label-mac-device = &wan_port; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + bootargs-override = "console=ttyS0,115200"; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins>; + + led_blue: blue { + label = "blue"; + gpios = <&aw9523 0 GPIO_ACTIVE_LOW>; + }; + + led_red: red { + label = "red"; + gpios = <&aw9523 1 GPIO_ACTIVE_LOW>; + }; + + led_green: green { + label = "green"; + gpios = <&aw9523 11 GPIO_ACTIVE_LOW>; + }; + }; + + keys { + compatible = "gpio-keys-polled"; + poll-interval = <50>; + pinctrl-names = "default"; + pinctrl-0 = <&button_pins>; + + reset { + label = "reset"; + gpios = <&aw9523 9 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&aw9523 8 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + i2c-gpio { + #address-cells = <1>; + #size-cells = <0>; + + compatible = "i2c-gpio"; + gpios = <&gpio 7 GPIO_ACTIVE_HIGH &gpio 8 GPIO_ACTIVE_HIGH>; + i2c-gpio,delay-us = <10>; + + aw9523: gpio-expander@5b { + compatible = "awinic,aw9523-pinctrl"; + reg = <0x5b>; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&aw9523 0 0 16>; + + reset-gpios = <&gpio 6 GPIO_ACTIVE_HIGH>; + + button_pins: button-pins { + pins = "gpio8", "gpio9"; + function = "gpio"; + bias-pull-up; + drive-open-drain; + input-enable; + }; + + led_pins: led-pins { + pins = "gpio0", "gpio1", "gpio11"; + function = "gpio"; + input-disable; + output-low; + }; + }; + }; +}; + +&pcie { + status = "okay"; +}; + +&pcie1 { + wifi@0,0 { + reg = <0x0 0 0 0 0>; + mediatek,mtd-eeprom = <&factory 0x0>; + }; +}; + +&gmac0 { + mtd-mac-address = <&factory 0x4>; +}; + +&switch0 { + ports { + wan_port: port@0 { + status = "okay"; + label = "wan"; + mtd-mac-address = <&factory 0x28>; + }; + + port@1 { + status = "okay"; + label = "lan1"; + }; + + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan3"; + }; + + port@4 { + status = "okay"; + label = "lan4"; + }; + }; +}; + +&state_default { + gpio { + groups = "uart3"; + function = "gpio"; + }; +}; + +&spi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + + partitions { + compatible = "fixed-partitions"; + #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; + }; + + partition@40000 { + label = "product"; + reg = <0x40000 0x10000>; + read-only; + }; + + factory: partition@50000 { + label = "factory"; + reg = <0x50000 0x40000>; + read-only; + }; + + partition@90000 { + compatible = "denx,fit"; + label = "firmware"; + reg = <0x90000 0xf70000>; + }; + }; + }; +}; diff --git a/target/linux/ramips/files/drivers/pinctrl/pinctrl-aw9523.c b/target/linux/ramips/files/drivers/pinctrl/pinctrl-aw9523.c new file mode 100644 index 0000000000..182e11cdc6 --- /dev/null +++ b/target/linux/ramips/files/drivers/pinctrl/pinctrl-aw9523.c @@ -0,0 +1,1135 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Awinic AW9523B i2c pin controller driver + * Copyright (c) 2020, AngeloGioacchino Del Regno + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core.h" +#include "pinconf.h" +#include "pinctrl-utils.h" + +#define AW9523_MAX_FUNCS 2 +#define AW9523_NUM_PORTS 2 +#define AW9523_PINS_PER_PORT 8 + +/* + * HW needs at least 20uS for reset and at least 1-2uS to recover from + * reset, but we have to account for eventual board quirks, if any: + * for this reason, keep reset asserted for 50uS and wait for 20uS + * to recover from the reset. + */ +#define AW9523_HW_RESET_US 50 +#define AW9523_HW_RESET_RECOVERY_US 20 + +/* Port 0: P0_0...P0_7 - Port 1: P1_0...P1_7 */ +#define AW9523_PIN_TO_PORT(pin) (pin >> 3) +#define AW9523_REG_IN_STATE(pin) (0x00 + AW9523_PIN_TO_PORT(pin)) +#define AW9523_REG_OUT_STATE(pin) (0x02 + AW9523_PIN_TO_PORT(pin)) +#define AW9523_REG_CONF_STATE(pin) (0x04 + AW9523_PIN_TO_PORT(pin)) +#define AW9523_REG_INTR_DIS(pin) (0x06 + AW9523_PIN_TO_PORT(pin)) +#define AW9523_REG_CHIPID 0x10 +#define AW9523_VAL_EXPECTED_CHIPID 0x23 + +#define AW9523_REG_GCR 0x11 +#define AW9523_GCR_ISEL_MASK GENMASK(0, 1) +#define AW9523_GCR_GPOMD_MASK BIT(4) + +#define AW9523_REG_PORT_MODE(pin) (0x12 + AW9523_PIN_TO_PORT(pin)) +#define AW9523_REG_SOFT_RESET 0x7f +#define AW9523_VAL_RESET 0x00 + +/* + * struct aw9523_irq - Interrupt controller structure + * @lock: mutex locking for the irq bus + * @irqchip: structure holding irqchip params + * @cached_gpio: stores the previous gpio status for bit comparison + */ +struct aw9523_irq { + struct mutex lock; + struct irq_chip *irqchip; + u16 cached_gpio; +}; + +/* + * struct aw9523_pinmux - Pin mux params + * @name: Name of the mux + * @grps: Groups of the mux + * @num_grps: Number of groups (sizeof array grps) + */ +struct aw9523_pinmux { + const char *name; + const char * const *grps; + const u8 num_grps; +}; + +/* + * struct aw9523 - Main driver structure + * @dev: device handle + * @regmap: regmap handle for current device + * @i2c_lock: Mutex lock for i2c operations + * @reset_gpio: Hardware reset (RSTN) signal GPIO + * @vio_vreg: VCC regulator (Optional) + * @pctl: pinctrl handle for current device + * @gpio: structure holding gpiochip params + * @irq: Interrupt controller structure + */ +struct aw9523 { + struct device *dev; + struct regmap *regmap; + struct mutex i2c_lock; + struct gpio_desc *reset_gpio; + struct regulator *vio_vreg; + struct pinctrl_dev *pctl; + struct gpio_chip gpio; + struct aw9523_irq *irq; +}; + +static const struct pinctrl_pin_desc aw9523_pins[] = { + /* Port 0 */ + PINCTRL_PIN(0, "gpio0"), + PINCTRL_PIN(1, "gpio1"), + PINCTRL_PIN(2, "gpio2"), + PINCTRL_PIN(3, "gpio3"), + PINCTRL_PIN(4, "gpio4"), + PINCTRL_PIN(5, "gpio5"), + PINCTRL_PIN(6, "gpio6"), + PINCTRL_PIN(7, "gpio7"), + + /* Port 1 */ + PINCTRL_PIN(8, "gpio8"), + PINCTRL_PIN(9, "gpio9"), + PINCTRL_PIN(10, "gpio10"), + PINCTRL_PIN(11, "gpio11"), + PINCTRL_PIN(12, "gpio12"), + PINCTRL_PIN(13, "gpio13"), + PINCTRL_PIN(14, "gpio14"), + PINCTRL_PIN(15, "gpio15"), +}; + +static int aw9523_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(aw9523_pins); +} + +static const char *aw9523_pinctrl_get_group_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + return aw9523_pins[selector].name; +} + +static int aw9523_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, + unsigned int selector, + const unsigned int **pins, + unsigned int *num_pins) +{ + *pins = &aw9523_pins[selector].number; + *num_pins = 1; + return 0; +} + +static const struct pinctrl_ops aw9523_pinctrl_ops = { + .get_groups_count = aw9523_pinctrl_get_groups_count, + .get_group_pins = aw9523_pinctrl_get_group_pins, + .get_group_name = aw9523_pinctrl_get_group_name, + .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, + .dt_free_map = pinconf_generic_dt_free_map, +}; + +static const char * const gpio_pwm_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", + "gpio6", "gpio7", "gpio8", "gpio9", "gpio10", "gpio11", + "gpio12", "gpio13", "gpio14", "gpio15" +}; + +/* Warning: Do NOT reorder this array */ +static const struct aw9523_pinmux aw9523_pmx[] = { + { + .name = "pwm", + .grps = gpio_pwm_groups, + .num_grps = ARRAY_SIZE(gpio_pwm_groups), + }, + { + .name = "gpio", + .grps = gpio_pwm_groups, + .num_grps = ARRAY_SIZE(gpio_pwm_groups), + }, +}; + +static int aw9523_pmx_get_funcs_count(struct pinctrl_dev *pctl) +{ + return ARRAY_SIZE(aw9523_pmx); +} + +static const char *aw9523_pmx_get_fname(struct pinctrl_dev *pctl, + unsigned int sel) +{ + return aw9523_pmx[sel].name; +} + +static int aw9523_pmx_get_groups(struct pinctrl_dev *pctl, unsigned int sel, + const char * const **groups, + unsigned int * const num_groups) +{ + *groups = aw9523_pmx[sel].grps; + *num_groups = aw9523_pmx[sel].num_grps; + return 0; +} + +static int aw9523_pmx_set_mux(struct pinctrl_dev *pctl, unsigned int fsel, + unsigned int grp) +{ + struct aw9523 *awi = pinctrl_dev_get_drvdata(pctl); + int ret, pin = aw9523_pins[grp].number % AW9523_PINS_PER_PORT; + + if (fsel >= ARRAY_SIZE(aw9523_pmx)) + return -EINVAL; + + /* + * This maps directly to the aw9523_pmx array: programming a + * high bit means "gpio" and a low bit means "pwm". + */ + mutex_lock(&awi->i2c_lock); + ret = regmap_update_bits(awi->regmap, AW9523_REG_PORT_MODE(pin), + BIT(pin), (fsel ? BIT(pin) : 0)); + mutex_unlock(&awi->i2c_lock); + return ret; +} + +static const struct pinmux_ops aw9523_pinmux_ops = { + .get_functions_count = aw9523_pmx_get_funcs_count, + .get_function_name = aw9523_pmx_get_fname, + .get_function_groups = aw9523_pmx_get_groups, + .set_mux = aw9523_pmx_set_mux, +}; + +static int aw9523_pcfg_param_to_reg(enum pin_config_param pcp, int pin, u8 *r) +{ + u8 reg; + + switch (pcp) { + case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: + case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_PULL_UP: + reg = AW9523_REG_IN_STATE(pin); + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + case PIN_CONFIG_DRIVE_PUSH_PULL: + reg = AW9523_REG_GCR; + break; + case PIN_CONFIG_INPUT_ENABLE: + case PIN_CONFIG_OUTPUT_ENABLE: + reg = AW9523_REG_CONF_STATE(pin); + break; + case PIN_CONFIG_OUTPUT: + reg = AW9523_REG_OUT_STATE(pin); + break; + default: + return -ENOTSUPP; + } + *r = reg; + + return 0; +} + +static int aw9523_pconf_get(struct pinctrl_dev *pctldev, unsigned int pin, + unsigned long *config) +{ + struct aw9523 *awi = pinctrl_dev_get_drvdata(pctldev); + enum pin_config_param param = pinconf_to_config_param(*config); + int regbit = pin % AW9523_PINS_PER_PORT; + unsigned int val; + u8 reg; + int rc; + + rc = aw9523_pcfg_param_to_reg(param, pin, ®); + if (rc) + return rc; + + mutex_lock(&awi->i2c_lock); + rc = regmap_read(awi->regmap, reg, &val); + mutex_unlock(&awi->i2c_lock); + if (rc) + return rc; + + switch (param) { + case PIN_CONFIG_BIAS_PULL_UP: + case PIN_CONFIG_INPUT_ENABLE: + case PIN_CONFIG_OUTPUT: + val &= BIT(regbit); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_OUTPUT_ENABLE: + val &= BIT(regbit); + val = !val; + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + if (pin >= AW9523_PINS_PER_PORT) + val = 0; + else + val = !FIELD_GET(AW9523_GCR_GPOMD_MASK, val); + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (pin >= AW9523_PINS_PER_PORT) + val = 1; + else + val = FIELD_GET(AW9523_GCR_GPOMD_MASK, val); + break; + default: + return -ENOTSUPP; + } + if (val < 1) + return -EINVAL; + + *config = pinconf_to_config_packed(param, !!val); + + return rc; +} + +static int aw9523_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin, + unsigned long *configs, unsigned int num_configs) +{ + struct aw9523 *awi = pinctrl_dev_get_drvdata(pctldev); + enum pin_config_param param; + int regbit = pin % AW9523_PINS_PER_PORT; + u32 arg; + u8 reg; + unsigned int mask, val; + int i, rc; + + mutex_lock(&awi->i2c_lock); + for (i = 0; i < num_configs; i++) { + param = pinconf_to_config_param(configs[i]); + arg = pinconf_to_config_argument(configs[i]); + + rc = aw9523_pcfg_param_to_reg(param, pin, ®); + if (rc) + goto end; + + switch (param) { + case PIN_CONFIG_OUTPUT: + /* First, enable pin output */ + rc = regmap_update_bits(awi->regmap, + AW9523_REG_CONF_STATE(pin), + BIT(regbit), 0); + if (rc) + goto end; + + /* Then, fall through to config output level */ + fallthrough; + case PIN_CONFIG_OUTPUT_ENABLE: + arg = !arg; + fallthrough; + case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: + case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_PULL_UP: + case PIN_CONFIG_INPUT_ENABLE: + mask = BIT(regbit); + val = arg ? BIT(regbit) : 0; + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + /* Open-Drain is supported only on port 0 */ + if (pin >= AW9523_PINS_PER_PORT) { + rc = -ENOTSUPP; + goto end; + } + mask = AW9523_GCR_GPOMD_MASK; + val = 0; + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + /* Port 1 is always Push-Pull */ + if (pin >= AW9523_PINS_PER_PORT) { + mask = 0; + val = 0; + continue; + } + mask = AW9523_GCR_GPOMD_MASK; + val = AW9523_GCR_GPOMD_MASK; + break; + default: + rc = -ENOTSUPP; + goto end; + } + + rc = regmap_update_bits(awi->regmap, reg, mask, val); + if (rc) + goto end; + } +end: + mutex_unlock(&awi->i2c_lock); + return rc; +} + +static const struct pinconf_ops aw9523_pinconf_ops = { + .pin_config_get = aw9523_pconf_get, + .pin_config_set = aw9523_pconf_set, + .is_generic = true, +}; + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 5, 0) +#define GPIO_LINE_DIRECTION_IN 1 +#define GPIO_LINE_DIRECTION_OUT 0 +#endif + +/* + * aw9523_get_pin_direction - Get pin direction + * @regmap: Regmap structure + * @pin: gpiolib pin number + * @n: pin index in port register + * + * Return: Pin direction for success or negative number for error + */ +static int aw9523_get_pin_direction(struct regmap *regmap, u8 pin, u8 n) +{ + int val, ret; + + ret = regmap_read(regmap, AW9523_REG_CONF_STATE(pin), &val); + if (ret < 0) + return ret; + + return (val & BIT(n)) == BIT(n); +} + +/* + * aw9523_get_port_state - Get input or output state for entire port + * @regmap: Regmap structure + * @pin: gpiolib pin number + * @regbit: hw pin index, used to retrieve port number + * @state: returned port state + * + * Return: Zero for success or negative number for error + */ +static int aw9523_get_port_state(struct regmap *regmap, u8 pin, + u8 regbit, unsigned int *state) +{ + u8 reg; + int dir; + + dir = aw9523_get_pin_direction(regmap, pin, regbit); + if (dir < 0) + return dir; + + if (dir == GPIO_LINE_DIRECTION_IN) + reg = AW9523_REG_IN_STATE(pin); + else + reg = AW9523_REG_OUT_STATE(pin); + + return regmap_read(regmap, reg, state); +} + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 5, 0) +#undef GPIO_LINE_DIRECTION_IN +#undef GPIO_LINE_DIRECTION_OUT +#endif + +static int aw9523_gpio_irq_type(struct irq_data *d, unsigned int type) +{ + switch (type) { + case IRQ_TYPE_NONE: + case IRQ_TYPE_EDGE_BOTH: + return 0; + default: + return -EINVAL; + }; +} + +/* + * aw9523_irq_mask - Mask interrupt + * @d: irq data + * + * Sets which interrupt to mask in the bitmap; + * The interrupt will be masked when unlocking the irq bus. + */ +static void aw9523_irq_mask(struct irq_data *d) +{ + struct aw9523 *awi = gpiochip_get_data(irq_data_get_irq_chip_data(d)); + unsigned int n = d->hwirq % AW9523_PINS_PER_PORT; + + regmap_update_bits(awi->regmap, + AW9523_REG_INTR_DIS(d->hwirq), + BIT(n), BIT(n)); +} + +/* + * aw9523_irq_unmask - Unmask interrupt + * @d: irq data + * + * Sets which interrupt to unmask in the bitmap; + * The interrupt will be masked when unlocking the irq bus. + */ +static void aw9523_irq_unmask(struct irq_data *d) +{ + struct aw9523 *awi = gpiochip_get_data(irq_data_get_irq_chip_data(d)); + unsigned int n = d->hwirq % AW9523_PINS_PER_PORT; + + regmap_update_bits(awi->regmap, + AW9523_REG_INTR_DIS(d->hwirq), + BIT(n), 0); +} + +static irqreturn_t aw9523_irq_thread_func(int irq, void *dev_id) +{ + struct aw9523 *awi = (struct aw9523 *)dev_id; + unsigned long n, val = 0; + unsigned long changed_gpio; + unsigned int tmp, port_pin, i, ret; + + for (i = 0; i < AW9523_NUM_PORTS; i++) { + port_pin = i * AW9523_PINS_PER_PORT; + ret = regmap_read(awi->regmap, + AW9523_REG_IN_STATE(port_pin), + &tmp); + if (ret) + return ret; + val |= (u8)tmp << (i * 8); + } + + /* Handle GPIO input release interrupt as well */ + changed_gpio = awi->irq->cached_gpio ^ val; + awi->irq->cached_gpio = val; + + /* + * To avoid up to four *slow* i2c reads from any driver hooked + * up to our interrupts, just check for the irq_find_mapping + * result: if the interrupt is not mapped, then we don't want + * to care about it. + */ + for_each_set_bit(n, &changed_gpio, awi->gpio.ngpio) { + tmp = irq_find_mapping(awi->gpio.irq.domain, n); + if (tmp <= 0) + continue; + handle_nested_irq(tmp); + } + + return IRQ_HANDLED; +} + +/* + * aw9523_irq_bus_lock - Grab lock for interrupt operation + * @d: irq data + */ +static void aw9523_irq_bus_lock(struct irq_data *d) +{ + struct aw9523 *awi = gpiochip_get_data(irq_data_get_irq_chip_data(d)); + + mutex_lock(&awi->irq->lock); + regcache_cache_only(awi->regmap, true); +} + +/* + * aw9523_irq_bus_sync_unlock - Synchronize state and unlock + * @d: irq data + * + * Writes the interrupt mask bits (found in the bit map) to the + * hardware, then unlocks the bus. + */ +static void aw9523_irq_bus_sync_unlock(struct irq_data *d) +{ + struct aw9523 *awi = gpiochip_get_data(irq_data_get_irq_chip_data(d)); + + regcache_cache_only(awi->regmap, false); + regcache_sync(awi->regmap); + mutex_unlock(&awi->irq->lock); +} + +static int aw9523_gpio_get_direction(struct gpio_chip *chip, + unsigned int offset) +{ + struct aw9523 *awi = gpiochip_get_data(chip); + u8 regbit = offset % AW9523_PINS_PER_PORT; + int ret; + + mutex_lock(&awi->i2c_lock); + ret = aw9523_get_pin_direction(awi->regmap, offset, regbit); + mutex_unlock(&awi->i2c_lock); + + return ret; +} + +static int aw9523_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + struct aw9523 *awi = gpiochip_get_data(chip); + u8 regbit = offset % AW9523_PINS_PER_PORT; + unsigned int val; + int ret; + + mutex_lock(&awi->i2c_lock); + ret = aw9523_get_port_state(awi->regmap, offset, regbit, &val); + mutex_unlock(&awi->i2c_lock); + if (ret) + return ret; + + return !!(val & BIT(regbit)); +} + +/** + * _aw9523_gpio_get_multiple - Get I/O state for an entire port + * @regmap: Regmap structure + * @pin: gpiolib pin number + * @regbit: hw pin index, used to retrieve port number + * @state: returned port I/O state + * + * Return: Zero for success or negative number for error + */ +static int _aw9523_gpio_get_multiple(struct aw9523 *awi, u8 regbit, + u8 *state, u8 mask) +{ + u32 dir_in, val; + u8 m; + int ret; + + /* Registers are 8-bits wide */ + ret = regmap_read(awi->regmap, AW9523_REG_CONF_STATE(regbit), &dir_in); + if (ret) + return ret; + *state = 0; + + m = mask & dir_in; + if (m) { + ret = regmap_read(awi->regmap, AW9523_REG_IN_STATE(regbit), + &val); + if (ret) + return ret; + *state |= (u8)val & m; + } + + m = mask & ~dir_in; + if (m) { + ret = regmap_read(awi->regmap, AW9523_REG_OUT_STATE(regbit), + &val); + if (ret) + return ret; + *state |= (u8)val & m; + } + + return 0; +} + +static int aw9523_gpio_get_multiple(struct gpio_chip *chip, + unsigned long *mask, + unsigned long *bits) +{ + struct aw9523 *awi = gpiochip_get_data(chip); + u8 m, state = 0; + int ret; + + mutex_lock(&awi->i2c_lock); + + /* Port 0 (gpio 0-7) */ + m = *mask & U8_MAX; + if (m) { + ret = _aw9523_gpio_get_multiple(awi, 0, &state, m); + if (ret) + goto out; + } + *bits = state; + + /* Port 1 (gpio 8-15) */ + m = (*mask >> 8) & U8_MAX; + if (m) { + ret = _aw9523_gpio_get_multiple(awi, AW9523_PINS_PER_PORT, + &state, m); + if (ret) + goto out; + + *bits |= (state << 8); + } +out: + mutex_unlock(&awi->i2c_lock); + return ret; +} + +static void aw9523_gpio_set_multiple(struct gpio_chip *chip, + unsigned long *mask, + unsigned long *bits) +{ + struct aw9523 *awi = gpiochip_get_data(chip); + u8 mask_lo, mask_hi, bits_lo, bits_hi; + unsigned int reg; + int ret = 0; + + mask_lo = *mask & U8_MAX; + mask_hi = (*mask >> 8) & U8_MAX; + mutex_lock(&awi->i2c_lock); + if (mask_hi) { + reg = AW9523_REG_OUT_STATE(AW9523_PINS_PER_PORT); + bits_hi = (*bits >> 8) & U8_MAX; + + ret = regmap_write_bits(awi->regmap, reg, mask_hi, bits_hi); + if (ret) { + dev_warn(awi->dev, "Cannot write port1 out level\n"); + goto out; + } + } + if (mask_lo) { + reg = AW9523_REG_OUT_STATE(0); + bits_lo = *bits & U8_MAX; + ret = regmap_write_bits(awi->regmap, reg, mask_lo, bits_lo); + if (ret) + dev_warn(awi->dev, "Cannot write port0 out level\n"); + } +out: + mutex_unlock(&awi->i2c_lock); +} + +static void aw9523_gpio_set(struct gpio_chip *chip, + unsigned int offset, int value) +{ + struct aw9523 *awi = gpiochip_get_data(chip); + u8 regbit = offset % AW9523_PINS_PER_PORT; + + mutex_lock(&awi->i2c_lock); + regmap_update_bits(awi->regmap, AW9523_REG_OUT_STATE(offset), + BIT(regbit), value ? BIT(regbit) : 0); + mutex_unlock(&awi->i2c_lock); +} + + +static int aw9523_direction_input(struct gpio_chip *chip, unsigned int offset) +{ + struct aw9523 *awi = gpiochip_get_data(chip); + u8 regbit = offset % AW9523_PINS_PER_PORT; + int ret; + + mutex_lock(&awi->i2c_lock); + ret = regmap_update_bits(awi->regmap, AW9523_REG_CONF_STATE(offset), + BIT(regbit), BIT(regbit)); + mutex_unlock(&awi->i2c_lock); + + return ret; +} + +static int aw9523_direction_output(struct gpio_chip *chip, + unsigned int offset, int value) +{ + struct aw9523 *awi = gpiochip_get_data(chip); + u8 regbit = offset % AW9523_PINS_PER_PORT; + int ret; + + mutex_lock(&awi->i2c_lock); + ret = regmap_update_bits(awi->regmap, AW9523_REG_OUT_STATE(offset), + BIT(regbit), value ? BIT(regbit) : 0); + if (ret) + goto end; + + ret = regmap_update_bits(awi->regmap, AW9523_REG_CONF_STATE(offset), + BIT(regbit), 0); +end: + mutex_unlock(&awi->i2c_lock); + return ret; +} + +static int aw9523_drive_reset_gpio(struct aw9523 *awi) +{ + unsigned int chip_id; + int ret; + + /* + * If the chip is already configured for any reason, then we + * will probably succeed in sending the soft reset signal to + * the hardware through I2C: this operation takes less time + * compared to a full HW reset and it gives the same results. + */ + ret = regmap_write(awi->regmap, AW9523_REG_SOFT_RESET, 0); + if (ret == 0) + goto done; + + dev_dbg(awi->dev, "Cannot execute soft reset: trying hard reset\n"); + ret = gpiod_direction_output(awi->reset_gpio, 0); + if (ret) + return ret; + + /* The reset pulse has to be longer than 20uS due to deglitch */ + usleep_range(AW9523_HW_RESET_US, AW9523_HW_RESET_US + 1); + + ret = gpiod_direction_output(awi->reset_gpio, 1); + if (ret) + return ret; +done: + /* The HW needs at least 1uS to reliably recover after reset */ + usleep_range(AW9523_HW_RESET_RECOVERY_US, + AW9523_HW_RESET_RECOVERY_US + 1); + + /* Check the ChipID */ + ret = regmap_read(awi->regmap, AW9523_REG_CHIPID, &chip_id); + if (ret) { + dev_err(awi->dev, "Cannot read Chip ID: %d\n", ret); + return ret; + } + if (chip_id != AW9523_VAL_EXPECTED_CHIPID) { + dev_err(awi->dev, "Bad ChipID; read 0x%x, expected 0x%x\n", + chip_id, AW9523_VAL_EXPECTED_CHIPID); + return -EINVAL; + } + + return 0; +} + +static int aw9523_hw_reset(struct aw9523 *awi) +{ + int ret, max_retries = 2; + + /* Sometimes the chip needs more than one reset cycle */ + do { + ret = aw9523_drive_reset_gpio(awi); + if (ret == 0) + break; + max_retries--; + } while (max_retries); + + return ret; +} + +static int aw9523_init_gpiochip(struct aw9523 *awi, unsigned int npins) +{ + struct device *dev = awi->dev; + struct gpio_chip *gpiochip = &awi->gpio; + + gpiochip->label = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL); + if (!gpiochip->label) + return -ENOMEM; + + gpiochip->base = -1; + gpiochip->ngpio = npins; + gpiochip->get_direction = aw9523_gpio_get_direction; + gpiochip->direction_input = aw9523_direction_input; + gpiochip->direction_output = aw9523_direction_output; + gpiochip->get = aw9523_gpio_get; + gpiochip->get_multiple = aw9523_gpio_get_multiple; + gpiochip->set = aw9523_gpio_set; + gpiochip->set_multiple = aw9523_gpio_set_multiple; + gpiochip->set_config = gpiochip_generic_config; + gpiochip->parent = dev; + gpiochip->of_node = dev->of_node; + gpiochip->owner = THIS_MODULE; + gpiochip->can_sleep = false; + + return 0; +} + +static int aw9523_init_irq(struct aw9523 *awi, int irq) +{ + struct device *dev = awi->dev; + struct gpio_irq_chip *gpioirq; + struct irq_chip *irqchip; + int ret; + + if (!device_property_read_bool(dev, "interrupt-controller")) + return 0; + + irqchip = devm_kzalloc(dev, sizeof(*irqchip), GFP_KERNEL); + if (!irqchip) + return -ENOMEM; + + awi->irq = devm_kzalloc(dev, sizeof(*awi->irq), GFP_KERNEL); + if (!awi->irq) + return -ENOMEM; + + irqchip->name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL); + if (!irqchip->name) + return -ENOMEM; + + irqchip->irq_mask = aw9523_irq_mask; + irqchip->irq_unmask = aw9523_irq_unmask; + irqchip->irq_bus_lock = aw9523_irq_bus_lock; + irqchip->irq_bus_sync_unlock = aw9523_irq_bus_sync_unlock; + irqchip->irq_set_type = aw9523_gpio_irq_type; + awi->irq->irqchip = irqchip; + mutex_init(&awi->irq->lock); + + ret = devm_request_threaded_irq(dev, irq, NULL, aw9523_irq_thread_func, + IRQF_ONESHOT, dev_name(dev), awi); + if (ret) { + dev_err(dev, "Failed to request irq %d\n", irq); + return ret; + } + + gpioirq = &awi->gpio.irq; + gpioirq->chip = irqchip; + gpioirq->parent_handler = NULL; + gpioirq->num_parents = 0; + gpioirq->parents = NULL; + gpioirq->default_type = IRQ_TYPE_LEVEL_MASK; + gpioirq->handler = handle_simple_irq; + gpioirq->threaded = true; + gpioirq->first = 0; + + return 0; +} + +static bool aw9523_is_reg_hole(unsigned int reg) +{ + return (reg > AW9523_REG_PORT_MODE(AW9523_PINS_PER_PORT) && + reg < AW9523_REG_SOFT_RESET) || + (reg > AW9523_REG_INTR_DIS(AW9523_PINS_PER_PORT) && + reg < AW9523_REG_CHIPID); +} + +static bool aw9523_readable_reg(struct device *dev, unsigned int reg) +{ + /* All available registers (minus holes) can be read */ + return !aw9523_is_reg_hole(reg); +} + +static bool aw9523_volatile_reg(struct device *dev, unsigned int reg) +{ + return aw9523_is_reg_hole(reg) || + reg == AW9523_REG_IN_STATE(0) || + reg == AW9523_REG_IN_STATE(AW9523_PINS_PER_PORT) || + reg == AW9523_REG_CHIPID || + reg == AW9523_REG_SOFT_RESET; +} + +static bool aw9523_writeable_reg(struct device *dev, unsigned int reg) +{ + return !aw9523_is_reg_hole(reg) && reg != AW9523_REG_CHIPID; +} + +static bool aw9523_precious_reg(struct device *dev, unsigned int reg) +{ + /* Reading AW9523_REG_IN_STATE clears interrupt status */ + return aw9523_is_reg_hole(reg) || + reg == AW9523_REG_IN_STATE(0) || + reg == AW9523_REG_IN_STATE(AW9523_PINS_PER_PORT); +} + +static const struct regmap_config aw9523_regmap = { + .reg_bits = 8, + .val_bits = 8, + .reg_stride = 1, + + .precious_reg = aw9523_precious_reg, + .readable_reg = aw9523_readable_reg, + .volatile_reg = aw9523_volatile_reg, + .writeable_reg = aw9523_writeable_reg, + + .cache_type = REGCACHE_FLAT, + .disable_locking = true, + + .num_reg_defaults_raw = AW9523_REG_SOFT_RESET, +}; + +static int aw9523_hw_init(struct aw9523 *awi) +{ + u8 p1_pin = AW9523_PINS_PER_PORT; + unsigned int val; + int ret; + + /* No register caching during initialization */ + regcache_cache_bypass(awi->regmap, true); + + /* Bring up the chip */ + ret = aw9523_hw_reset(awi); + if (ret) { + dev_err(awi->dev, "HW Reset failed: %d\n", ret); + return ret; + } + + /* + * This is the expected chip and it is running: it's time to + * set a safe default configuration in case the user doesn't + * configure (all of the available) pins in this chip. + * P.S.: The writes order doesn't matter. + */ + + /* Set all pins as GPIO */ + ret = regmap_write(awi->regmap, AW9523_REG_PORT_MODE(0), U8_MAX); + if (ret) + return ret; + ret = regmap_write(awi->regmap, AW9523_REG_PORT_MODE(p1_pin), U8_MAX); + if (ret) + return ret; + + /* Set Open-Drain mode on Port 0 (Port 1 is always P-P) */ + ret = regmap_write(awi->regmap, AW9523_REG_GCR, 0); + if (ret) + return ret; + + /* Set all pins as inputs */ + ret = regmap_write(awi->regmap, AW9523_REG_CONF_STATE(0), U8_MAX); + if (ret) + return ret; + ret = regmap_write(awi->regmap, AW9523_REG_CONF_STATE(p1_pin), U8_MAX); + if (ret) + return ret; + + /* Disable all interrupts to avoid unreasoned wakeups */ + ret = regmap_write(awi->regmap, AW9523_REG_INTR_DIS(0), U8_MAX); + if (ret) + return ret; + ret = regmap_write(awi->regmap, AW9523_REG_INTR_DIS(p1_pin), U8_MAX); + if (ret) + return ret; + + /* Clear setup-generated interrupts by performing a port state read */ + ret = aw9523_get_port_state(awi->regmap, 0, 0, &val); + if (ret) + return ret; + ret = aw9523_get_port_state(awi->regmap, p1_pin, 0, &val); + if (ret) + return ret; + + /* Everything went fine: activate and reinitialize register cache */ + regcache_cache_bypass(awi->regmap, false); + return regmap_reinit_cache(awi->regmap, &aw9523_regmap); +} + +static int aw9523_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct pinctrl_desc *pdesc; + struct aw9523 *awi; + int ret; + + awi = devm_kzalloc(dev, sizeof(*awi), GFP_KERNEL); + if (!awi) + return -ENOMEM; + + i2c_set_clientdata(client, awi); + + awi->dev = dev; + awi->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(awi->reset_gpio)) + return PTR_ERR(awi->reset_gpio); + gpiod_set_consumer_name(awi->reset_gpio, "aw9523 reset"); + + awi->regmap = devm_regmap_init_i2c(client, &aw9523_regmap); + if (IS_ERR(awi->regmap)) + return PTR_ERR(awi->regmap); + + awi->vio_vreg = devm_regulator_get_optional(dev, "vio"); + if (IS_ERR(awi->vio_vreg)) { + if (PTR_ERR(awi->vio_vreg) == -EPROBE_DEFER) + return -EPROBE_DEFER; + awi->vio_vreg = NULL; + } else { + ret = regulator_enable(awi->vio_vreg); + if (ret) + return ret; + } + + mutex_init(&awi->i2c_lock); + lockdep_set_subclass(&awi->i2c_lock, + i2c_adapter_depth(client->adapter)); + + pdesc = devm_kzalloc(dev, sizeof(*pdesc), GFP_KERNEL); + if (!pdesc) + return -ENOMEM; + + ret = aw9523_hw_init(awi); + if (ret) + goto err_disable_vregs; + + pdesc->name = dev_name(dev); + pdesc->owner = THIS_MODULE; + pdesc->pctlops = &aw9523_pinctrl_ops; + pdesc->pmxops = &aw9523_pinmux_ops; + pdesc->confops = &aw9523_pinconf_ops; + pdesc->pins = aw9523_pins; + pdesc->npins = ARRAY_SIZE(aw9523_pins); + + ret = aw9523_init_gpiochip(awi, pdesc->npins); + if (ret) + goto err_disable_vregs; + + if (client->irq) { + ret = aw9523_init_irq(awi, client->irq); + if (ret) + goto err_disable_vregs; + } + + awi->pctl = devm_pinctrl_register(dev, pdesc, awi); + if (IS_ERR(awi->pctl)) { + ret = PTR_ERR(awi->pctl); + dev_err(dev, "Cannot register pinctrl: %d", ret); + goto err_disable_vregs; + } + + ret = devm_gpiochip_add_data(dev, &awi->gpio, awi); + if (ret) + goto err_disable_vregs; + + return ret; + +err_disable_vregs: + if (awi->vio_vreg) + regulator_disable(awi->vio_vreg); + mutex_destroy(&awi->i2c_lock); + return ret; +} + +static int aw9523_remove(struct i2c_client *client) +{ + struct aw9523 *awi = i2c_get_clientdata(client); + int ret; + + if (!awi) + return 0; + + /* + * If the chip VIO is connected to a regulator that we can turn + * off, life is easy... otherwise, reinitialize the chip and + * set the pins to hardware defaults before removing the driver + * to leave it in a clean, safe and predictable state. + */ + if (awi->vio_vreg) { + regulator_disable(awi->vio_vreg); + } else { + mutex_lock(&awi->i2c_lock); + ret = aw9523_hw_init(awi); + mutex_unlock(&awi->i2c_lock); + if (ret) + return ret; + } + + mutex_destroy(&awi->i2c_lock); + return 0; +} + +static const struct i2c_device_id aw9523_i2c_id_table[] = { + { "aw9523_i2c", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, aw9523_i2c_id_table); + +static const struct of_device_id of_aw9523_i2c_match[] = { + { .compatible = "awinic,aw9523-pinctrl", }, +}; +MODULE_DEVICE_TABLE(of, of_aw9523_i2c_match); + +static struct i2c_driver aw9523_driver = { + .driver = { + .name = "aw9523-pinctrl", + .of_match_table = of_aw9523_i2c_match, + }, + .probe = aw9523_probe, + .remove = aw9523_remove, + .id_table = aw9523_i2c_id_table, +}; +module_i2c_driver(aw9523_driver); + +MODULE_DESCRIPTION("Awinic AW9523 I2C GPIO Expander driver"); +MODULE_AUTHOR("AngeloGioacchino Del Regno "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:aw9523"); diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk index 1b04d771df..5b24c771b9 100644 --- a/target/linux/ramips/image/mt7621.mk +++ b/target/linux/ramips/image/mt7621.mk @@ -1200,6 +1200,18 @@ define Device/telco-electronics_x1 endef TARGET_DEVICES += telco-electronics_x1 +define Device/tenbay_t-mb5eu-v01 + $(Device/dsa-migration) + DEVICE_VENDOR := Tenbay + DEVICE_MODEL := T-MB5EU-V01 + DEVICE_DTS_CONFIG := config@1 + DEVICE_PACKAGES += kmod-mt7915e kmod-usb3 + KERNEL := kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb + IMAGE_SIZE := 15808k + SUPPORTED_DEVICES += mt7621-dm2-t-mb5eu-v01-nor +endef +TARGET_DEVICES += tenbay_t-mb5eu-v01 + define Device/thunder_timecloud $(Device/dsa-migration) $(Device/uimage-lzma-loader) diff --git a/target/linux/ramips/mt7620/config-5.10 b/target/linux/ramips/mt7620/config-5.10 index b6a8b03d25..391449cc51 100644 --- a/target/linux/ramips/mt7620/config-5.10 +++ b/target/linux/ramips/mt7620/config-5.10 @@ -148,6 +148,7 @@ CONFIG_PGTABLE_LEVELS=2 CONFIG_PHYLIB=y CONFIG_PHY_RALINK_USB=y CONFIG_PINCTRL=y +# CONFIG_PINCTRL_AW9523 is not set CONFIG_PINCTRL_RT2880=y # CONFIG_PINCTRL_SINGLE is not set CONFIG_RALINK=y diff --git a/target/linux/ramips/mt7620/config-5.4 b/target/linux/ramips/mt7620/config-5.4 index 4bafded763..ca96f09c5b 100644 --- a/target/linux/ramips/mt7620/config-5.4 +++ b/target/linux/ramips/mt7620/config-5.4 @@ -150,6 +150,7 @@ CONFIG_PGTABLE_LEVELS=2 CONFIG_PHYLIB=y CONFIG_PHY_RALINK_USB=y CONFIG_PINCTRL=y +# CONFIG_PINCTRL_AW9523 is not set CONFIG_PINCTRL_RT2880=y # CONFIG_PINCTRL_SINGLE is not set CONFIG_RALINK=y diff --git a/target/linux/ramips/mt7621/config-5.10 b/target/linux/ramips/mt7621/config-5.10 index 5e1a5cd30a..92165590f6 100644 --- a/target/linux/ramips/mt7621/config-5.10 +++ b/target/linux/ramips/mt7621/config-5.10 @@ -102,6 +102,7 @@ CONFIG_HAS_IOPORT_MAP=y CONFIG_HIGHMEM=y CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_GPIO=y CONFIG_I2C_MT7621=y CONFIG_INITRAMFS_SOURCE="" CONFIG_IRQCHIP=y @@ -212,6 +213,7 @@ CONFIG_PHYLIB=y CONFIG_PHYLINK=y # CONFIG_PHY_RALINK_USB is not set CONFIG_PINCTRL=y +CONFIG_PINCTRL_AW9523=y CONFIG_PINCTRL_RT2880=y # CONFIG_PINCTRL_SINGLE is not set CONFIG_PINCTRL_SX150X=y diff --git a/target/linux/ramips/mt7621/config-5.4 b/target/linux/ramips/mt7621/config-5.4 index 7a3adae555..0ce300c138 100644 --- a/target/linux/ramips/mt7621/config-5.4 +++ b/target/linux/ramips/mt7621/config-5.4 @@ -100,6 +100,7 @@ CONFIG_HIGHMEM=y CONFIG_HZ_PERIODIC=y CONFIG_I2C=y CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_GPIO=y CONFIG_I2C_MT7621=y CONFIG_INITRAMFS_SOURCE="" CONFIG_IRQCHIP=y @@ -202,6 +203,7 @@ CONFIG_PHYLIB=y CONFIG_PHYLINK=y # CONFIG_PHY_RALINK_USB is not set CONFIG_PINCTRL=y +CONFIG_PINCTRL_AW9523=y CONFIG_PINCTRL_RT2880=y # CONFIG_PINCTRL_SINGLE is not set CONFIG_PINCTRL_SX150X=y diff --git a/target/linux/ramips/mt76x8/config-5.10 b/target/linux/ramips/mt76x8/config-5.10 index 8c612a643f..3a42a5770f 100644 --- a/target/linux/ramips/mt76x8/config-5.10 +++ b/target/linux/ramips/mt76x8/config-5.10 @@ -143,6 +143,7 @@ CONFIG_PGTABLE_LEVELS=2 CONFIG_PHYLIB=y CONFIG_PHY_RALINK_USB=y CONFIG_PINCTRL=y +# CONFIG_PINCTRL_AW9523 is not set CONFIG_PINCTRL_RT2880=y # CONFIG_PINCTRL_SINGLE is not set CONFIG_RALINK=y diff --git a/target/linux/ramips/mt76x8/config-5.4 b/target/linux/ramips/mt76x8/config-5.4 index 302a39adc9..c69f120899 100644 --- a/target/linux/ramips/mt76x8/config-5.4 +++ b/target/linux/ramips/mt76x8/config-5.4 @@ -143,6 +143,7 @@ CONFIG_PGTABLE_LEVELS=2 CONFIG_PHYLIB=y CONFIG_PHY_RALINK_USB=y CONFIG_PINCTRL=y +# CONFIG_PINCTRL_AW9523 is not set CONFIG_PINCTRL_RT2880=y # CONFIG_PINCTRL_SINGLE is not set CONFIG_RALINK=y diff --git a/target/linux/ramips/patches-5.10/405-mtd-spi-nor-Add-support-for-BoHong-bh25q128as.patch b/target/linux/ramips/patches-5.10/405-mtd-spi-nor-Add-support-for-BoHong-bh25q128as.patch new file mode 100644 index 0000000000..4c762925fb --- /dev/null +++ b/target/linux/ramips/patches-5.10/405-mtd-spi-nor-Add-support-for-BoHong-bh25q128as.patch @@ -0,0 +1,75 @@ +From 52d14545d2fc276b1bf9ccf48d4612fab6edfb6a Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Thu, 6 May 2021 17:49:55 +0200 +Subject: [PATCH] mtd: spi-nor: Add support for BoHong bh25q128as + +Add MTD support for the BoHong bh25q128as SPI NOR chip. +The chip has 16MB of total capacity, divided into a total of 256 +sectors, each 64KB sized. The chip also supports 4KB sectors. +Additionally, it supports dual and quad read modes. + +Functionality was verified on an Tenbay WR1800K / MTK MT7621 board. + +Signed-off-by: David Bauer +--- + drivers/mtd/spi-nor/Makefile | 1 + + drivers/mtd/spi-nor/bohong.c | 21 +++++++++++++++++++++ + drivers/mtd/spi-nor/core.c | 1 + + drivers/mtd/spi-nor/core.h | 1 + + 4 files changed, 24 insertions(+) + create mode 100644 drivers/mtd/spi-nor/bohong.c + +--- a/drivers/mtd/spi-nor/Makefile ++++ b/drivers/mtd/spi-nor/Makefile +@@ -2,6 +2,7 @@ + + spi-nor-objs := core.o sfdp.o + spi-nor-objs += atmel.o ++spi-nor-objs += bohong.o + spi-nor-objs += catalyst.o + spi-nor-objs += eon.o + spi-nor-objs += esmt.o +--- /dev/null ++++ b/drivers/mtd/spi-nor/bohong.c +@@ -0,0 +1,21 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2005, Intec Automation Inc. ++ * Copyright (C) 2014, Freescale Semiconductor, Inc. ++ */ ++ ++#include ++ ++#include "core.h" ++ ++static const struct flash_info bohong_parts[] = { ++ /* BoHong Microelectronics */ ++ { "bh25q128as", INFO(0x684018, 0, 64 * 1024, 256, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++}; ++ ++const struct spi_nor_manufacturer spi_nor_bohong = { ++ .name = "bohong", ++ .parts = bohong_parts, ++ .nparts = ARRAY_SIZE(bohong_parts), ++}; +--- a/drivers/mtd/spi-nor/core.c ++++ b/drivers/mtd/spi-nor/core.c +@@ -2038,6 +2038,7 @@ int spi_nor_sr2_bit7_quad_enable(struct + + static const struct spi_nor_manufacturer *manufacturers[] = { + &spi_nor_atmel, ++ &spi_nor_bohong, + &spi_nor_catalyst, + &spi_nor_eon, + &spi_nor_esmt, +--- a/drivers/mtd/spi-nor/core.h ++++ b/drivers/mtd/spi-nor/core.h +@@ -382,6 +382,7 @@ struct spi_nor_manufacturer { + + /* Manufacturer drivers. */ + extern const struct spi_nor_manufacturer spi_nor_atmel; ++extern const struct spi_nor_manufacturer spi_nor_bohong; + extern const struct spi_nor_manufacturer spi_nor_catalyst; + extern const struct spi_nor_manufacturer spi_nor_eon; + extern const struct spi_nor_manufacturer spi_nor_esmt; diff --git a/target/linux/ramips/patches-5.10/805-pinctrl-AW9523.patch b/target/linux/ramips/patches-5.10/805-pinctrl-AW9523.patch new file mode 100644 index 0000000000..e80d0c9967 --- /dev/null +++ b/target/linux/ramips/patches-5.10/805-pinctrl-AW9523.patch @@ -0,0 +1,72 @@ +From: AngeloGioacchino Del Regno + +To: linus.walleij@linaro.org +Cc: linux-kernel@vger.kernel.org, konrad.dybcio@somainline.org, + marijn.suijten@somainline.org, martin.botka@somainline.org, + phone-devel@vger.kernel.org, linux-gpio@vger.kernel.org, + devicetree@vger.kernel.org, robh+dt@kernel.org, + AngeloGioacchino Del Regno + +Subject: [PATCH v5 1/2] pinctrl: Add driver for Awinic AW9523/B I2C GPIO + Expander +Date: Mon, 25 Jan 2021 19:22:18 +0100 + +The Awinic AW9523(B) is a multi-function I2C gpio expander in a +TQFN-24L package, featuring PWM (max 37mA per pin, or total max +power 3.2Watts) for LED driving capability. + +It has two ports with 8 pins per port (for a total of 16 pins), +configurable as either PWM with 1/256 stepping or GPIO input/output, +1.8V logic input; each GPIO can be configured as input or output +independently from each other. + +This IC also has an internal interrupt controller, which is capable +of generating an interrupt for each GPIO, depending on the +configuration, and will raise an interrupt on the INTN pin to +advertise this to an external interrupt controller. + +Signed-off-by: AngeloGioacchino Del Regno +--- + drivers/pinctrl/Kconfig | 17 + + drivers/pinctrl/Makefile | 1 + + drivers/pinctrl/pinctrl-aw9523.c | 1122 ++++++++++++++++++++++++++++++ + 3 files changed, 1140 insertions(+) + create mode 100644 drivers/pinctrl/pinctrl-aw9523.c + +--- a/drivers/pinctrl/Kconfig ++++ b/drivers/pinctrl/Kconfig +@@ -110,6 +110,24 @@ config PINCTRL_AMD + Requires ACPI/FDT device enumeration code to set up a platform + device. + ++config PINCTRL_AW9523 ++ bool "Awinic AW9523/AW9523B I2C GPIO expander pinctrl driver" ++ depends on OF && I2C ++ select PINMUX ++ select PINCONF ++ select GENERIC_PINCONF ++ select GPIOLIB ++ select GPIOLIB_IRQCHIP ++ select REGMAP ++ select REGMAP_I2C ++ help ++ The Awinic AW9523/AW9523B is a multi-function I2C GPIO ++ expander with PWM functionality. This driver bundles a ++ pinctrl driver to select the function muxing and a GPIO ++ driver to handle GPIO, when the GPIO function is selected. ++ ++ Say yes to enable pinctrl and GPIO support for the AW9523(B). ++ + config PINCTRL_BM1880 + bool "Bitmain BM1880 Pinctrl driver" + depends on OF && (ARCH_BITMAIN || COMPILE_TEST) +--- a/drivers/pinctrl/Makefile ++++ b/drivers/pinctrl/Makefile +@@ -14,6 +14,7 @@ obj-$(CONFIG_PINCTRL_AXP209) += pinctrl- + obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o + obj-$(CONFIG_PINCTRL_AT91PIO4) += pinctrl-at91-pio4.o + obj-$(CONFIG_PINCTRL_AMD) += pinctrl-amd.o ++obj-$(CONFIG_PINCTRL_AW9523) += pinctrl-aw9523.o + obj-$(CONFIG_PINCTRL_BM1880) += pinctrl-bm1880.o + obj-$(CONFIG_PINCTRL_DA850_PUPD) += pinctrl-da850-pupd.o + obj-$(CONFIG_PINCTRL_DA9062) += pinctrl-da9062.o diff --git a/target/linux/ramips/patches-5.4/405-mtd-spi-nor-Add-support-for-BoHong-bh25q128as.patch b/target/linux/ramips/patches-5.4/405-mtd-spi-nor-Add-support-for-BoHong-bh25q128as.patch new file mode 100644 index 0000000000..728876322c --- /dev/null +++ b/target/linux/ramips/patches-5.4/405-mtd-spi-nor-Add-support-for-BoHong-bh25q128as.patch @@ -0,0 +1,34 @@ +From 52d14545d2fc276b1bf9ccf48d4612fab6edfb6a Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Thu, 6 May 2021 17:49:55 +0200 +Subject: [PATCH] mtd: spi-nor: Add support for BoHong bh25q128as + +Add MTD support for the BoHong bh25q128as SPI NOR chip. +The chip has 16MB of total capacity, divided into a total of 256 +sectors, each 64KB sized. The chip also supports 4KB sectors. +Additionally, it supports dual and quad read modes. + +Functionality was verified on an Tenbay WR1800K / MTK MT7621 board. + +Signed-off-by: David Bauer +--- + drivers/mtd/spi-nor/Makefile | 1 + + drivers/mtd/spi-nor/bohong.c | 21 +++++++++++++++++++++ + drivers/mtd/spi-nor/core.c | 1 + + drivers/mtd/spi-nor/core.h | 1 + + 4 files changed, 24 insertions(+) + create mode 100644 drivers/mtd/spi-nor/bohong.c + +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c +@@ -2233,6 +2233,10 @@ static const struct flash_info spi_nor_i + + { "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) }, + ++ /* BoHong Microelectronics */ ++ { "bh25q128as", INFO(0x684018, 0, 64 * 1024, 256, ++ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, ++ + /* EON -- en25xxx */ + { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) }, + { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) }, diff --git a/target/linux/ramips/patches-5.4/805-pinctrl-AW9523.patch b/target/linux/ramips/patches-5.4/805-pinctrl-AW9523.patch new file mode 100644 index 0000000000..d8e17a671a --- /dev/null +++ b/target/linux/ramips/patches-5.4/805-pinctrl-AW9523.patch @@ -0,0 +1,72 @@ +From: AngeloGioacchino Del Regno + +To: linus.walleij@linaro.org +Cc: linux-kernel@vger.kernel.org, konrad.dybcio@somainline.org, + marijn.suijten@somainline.org, martin.botka@somainline.org, + phone-devel@vger.kernel.org, linux-gpio@vger.kernel.org, + devicetree@vger.kernel.org, robh+dt@kernel.org, + AngeloGioacchino Del Regno + +Subject: [PATCH v5 1/2] pinctrl: Add driver for Awinic AW9523/B I2C GPIO + Expander +Date: Mon, 25 Jan 2021 19:22:18 +0100 + +The Awinic AW9523(B) is a multi-function I2C gpio expander in a +TQFN-24L package, featuring PWM (max 37mA per pin, or total max +power 3.2Watts) for LED driving capability. + +It has two ports with 8 pins per port (for a total of 16 pins), +configurable as either PWM with 1/256 stepping or GPIO input/output, +1.8V logic input; each GPIO can be configured as input or output +independently from each other. + +This IC also has an internal interrupt controller, which is capable +of generating an interrupt for each GPIO, depending on the +configuration, and will raise an interrupt on the INTN pin to +advertise this to an external interrupt controller. + +Signed-off-by: AngeloGioacchino Del Regno +--- + drivers/pinctrl/Kconfig | 17 + + drivers/pinctrl/Makefile | 1 + + drivers/pinctrl/pinctrl-aw9523.c | 1122 ++++++++++++++++++++++++++++++ + 3 files changed, 1140 insertions(+) + create mode 100644 drivers/pinctrl/pinctrl-aw9523.c + +--- a/drivers/pinctrl/Kconfig ++++ b/drivers/pinctrl/Kconfig +@@ -109,6 +109,24 @@ config PINCTRL_AMD + Requires ACPI/FDT device enumeration code to set up a platform + device. + ++config PINCTRL_AW9523 ++ bool "Awinic AW9523/AW9523B I2C GPIO expander pinctrl driver" ++ depends on OF && I2C ++ select PINMUX ++ select PINCONF ++ select GENERIC_PINCONF ++ select GPIOLIB ++ select GPIOLIB_IRQCHIP ++ select REGMAP ++ select REGMAP_I2C ++ help ++ The Awinic AW9523/AW9523B is a multi-function I2C GPIO ++ expander with PWM functionality. This driver bundles a ++ pinctrl driver to select the function muxing and a GPIO ++ driver to handle GPIO, when the GPIO function is selected. ++ ++ Say yes to enable pinctrl and GPIO support for the AW9523(B). ++ + config PINCTRL_BM1880 + bool "Bitmain BM1880 Pinctrl driver" + depends on OF && (ARCH_BITMAIN || COMPILE_TEST) +--- a/drivers/pinctrl/Makefile ++++ b/drivers/pinctrl/Makefile +@@ -14,6 +14,7 @@ obj-$(CONFIG_PINCTRL_AXP209) += pinctrl- + obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o + obj-$(CONFIG_PINCTRL_AT91PIO4) += pinctrl-at91-pio4.o + obj-$(CONFIG_PINCTRL_AMD) += pinctrl-amd.o ++obj-$(CONFIG_PINCTRL_AW9523) += pinctrl-aw9523.o + obj-$(CONFIG_PINCTRL_BM1880) += pinctrl-bm1880.o + obj-$(CONFIG_PINCTRL_DA850_PUPD) += pinctrl-da850-pupd.o + obj-$(CONFIG_PINCTRL_DIGICOLOR) += pinctrl-digicolor.o diff --git a/target/linux/ramips/rt288x/config-5.10 b/target/linux/ramips/rt288x/config-5.10 index 095c16c43b..88d06266b9 100644 --- a/target/linux/ramips/rt288x/config-5.10 +++ b/target/linux/ramips/rt288x/config-5.10 @@ -131,6 +131,7 @@ CONFIG_PGTABLE_LEVELS=2 CONFIG_PHYLIB=y # CONFIG_PHY_RALINK_USB is not set CONFIG_PINCTRL=y +# CONFIG_PINCTRL_AW9523 is not set CONFIG_PINCTRL_RT2880=y # CONFIG_PINCTRL_SINGLE is not set CONFIG_RALINK=y diff --git a/target/linux/ramips/rt288x/config-5.4 b/target/linux/ramips/rt288x/config-5.4 index ad269ff5be..d0de43e29c 100644 --- a/target/linux/ramips/rt288x/config-5.4 +++ b/target/linux/ramips/rt288x/config-5.4 @@ -131,6 +131,7 @@ CONFIG_PGTABLE_LEVELS=2 CONFIG_PHYLIB=y # CONFIG_PHY_RALINK_USB is not set CONFIG_PINCTRL=y +# CONFIG_PINCTRL_AW9523 is not set CONFIG_PINCTRL_RT2880=y # CONFIG_PINCTRL_SINGLE is not set CONFIG_RALINK=y diff --git a/target/linux/ramips/rt305x/config-5.10 b/target/linux/ramips/rt305x/config-5.10 index fbc2edc840..1704accf95 100644 --- a/target/linux/ramips/rt305x/config-5.10 +++ b/target/linux/ramips/rt305x/config-5.10 @@ -131,6 +131,7 @@ CONFIG_PGTABLE_LEVELS=2 CONFIG_PHYLIB=y CONFIG_PHY_RALINK_USB=y CONFIG_PINCTRL=y +# CONFIG_PINCTRL_AW9523 is not set CONFIG_PINCTRL_RT2880=y # CONFIG_PINCTRL_SINGLE is not set CONFIG_RALINK=y diff --git a/target/linux/ramips/rt305x/config-5.4 b/target/linux/ramips/rt305x/config-5.4 index 6ab68f9d56..b4ee93c05b 100644 --- a/target/linux/ramips/rt305x/config-5.4 +++ b/target/linux/ramips/rt305x/config-5.4 @@ -131,6 +131,7 @@ CONFIG_PGTABLE_LEVELS=2 CONFIG_PHYLIB=y CONFIG_PHY_RALINK_USB=y CONFIG_PINCTRL=y +# CONFIG_PINCTRL_AW9523 is not set CONFIG_PINCTRL_RT2880=y # CONFIG_PINCTRL_SINGLE is not set CONFIG_RALINK=y diff --git a/target/linux/ramips/rt3883/config-5.10 b/target/linux/ramips/rt3883/config-5.10 index 5bb641cbdc..16d6fc32f8 100644 --- a/target/linux/ramips/rt3883/config-5.10 +++ b/target/linux/ramips/rt3883/config-5.10 @@ -132,6 +132,7 @@ CONFIG_PGTABLE_LEVELS=2 CONFIG_PHYLIB=y CONFIG_PHY_RALINK_USB=y CONFIG_PINCTRL=y +# CONFIG_PINCTRL_AW9523 is not set CONFIG_PINCTRL_RT2880=y # CONFIG_PINCTRL_SINGLE is not set CONFIG_RALINK=y diff --git a/target/linux/ramips/rt3883/config-5.4 b/target/linux/ramips/rt3883/config-5.4 index 577743e798..f7d6a2cc2b 100644 --- a/target/linux/ramips/rt3883/config-5.4 +++ b/target/linux/ramips/rt3883/config-5.4 @@ -133,6 +133,7 @@ CONFIG_PGTABLE_LEVELS=2 CONFIG_PHYLIB=y CONFIG_PHY_RALINK_USB=y CONFIG_PINCTRL=y +# CONFIG_PINCTRL_AW9523 is not set CONFIG_PINCTRL_RT2880=y # CONFIG_PINCTRL_SINGLE is not set CONFIG_RALINK=y