feeds: resolve conflict

This commit is contained in:
hayzamjs 2023-05-26 12:13:27 +05:30
commit 390085a386
146 changed files with 17399 additions and 1735 deletions

View file

@ -0,0 +1,8 @@
ARG OWNER_LC
ARG CONTAINER_TAG
FROM ghcr.io/$OWNER_LC/tools:$CONTAINER_TAG
ARG TOOLCHAIN_NAME
ADD $TOOLCHAIN_NAME /external-toolchain/

View file

@ -5,6 +5,9 @@ on:
secrets:
coverity_api_token:
inputs:
container_name:
type: string
default: tools
target:
required: true
type: string
@ -47,6 +50,10 @@ on:
mbedtls
wolfssl
openssl
build_external_toolchain:
type: boolean
upload_external_toolchain:
type: boolean
permissions:
contents: read
@ -59,6 +66,7 @@ jobs:
owner_lc: ${{ steps.lower_owner.outputs.owner_lc }}
ccache_hash: ${{ steps.ccache_hash.outputs.ccache_hash }}
container_tag: ${{ steps.determine_tools_container.outputs.container_tag }}
container_name: ${{ steps.determine_tools_container.outputs.container_name }}
steps:
- name: Checkout
@ -92,6 +100,7 @@ jobs:
- name: Determine tools container tag
id: determine_tools_container
run: |
CONTAINER_NAME=${{ inputs.container_name }}
CONTAINER_TAG=latest
if [ -n "${{ github.base_ref }}" ]; then
if echo "${{ github.base_ref }}" | grep -q -E '^openwrt-[0-9][0-9]\.[0-9][0-9]$'; then
@ -108,15 +117,29 @@ jobs:
CONTAINER_TAG=openwrt-"$(echo ${{ github.ref_name }} | sed 's/^v\([0-9][0-9]\.[0-9][0-9]\)\..\+/\1/')"
fi
fi
echo "Tools container to use tools:$CONTAINER_TAG"
if [ "$CONTAINER_NAME" = "toolchain" ]; then
GHCR_TOKEN=$(echo ${{ secrets.GITHUB_TOKEN }} | base64)
GHCR_HEADER="Authorization: Bearer ${GHCR_TOKEN}"
GHCR_MANIFEST_LINK=https://ghcr.io/v2/${{ steps.lower_owner.outputs.owner_lc }}/${{ inputs.container_name }}/manifests/${{ inputs.target }}-${{ inputs.subtarget }}-"$CONTAINER_TAG"
# Check if container exist
if [ $(curl -s -o /dev/null -w "%{http_code}" -H "$GHCR_HEADER" -I "$GHCR_MANIFEST_LINK") = 200 ]; then
CONTAINER_TAG=${{ inputs.target }}-${{ inputs.subtarget }}-"$CONTAINER_TAG"
else
CONTAINER_NAME=tools
fi
fi
echo "Tools container to use $CONTAINER_NAME:$CONTAINER_TAG"
echo "container_tag=$CONTAINER_TAG" >> $GITHUB_OUTPUT
echo "container_name=$CONTAINER_NAME" >> $GITHUB_OUTPUT
build:
name: Build ${{ inputs.target }}/${{ inputs.subtarget }}
needs: setup_build
runs-on: ubuntu-latest
container: ghcr.io/${{ needs.setup_build.outputs.owner_lc }}/tools:${{ needs.setup_build.outputs.container_tag }}
container: ghcr.io/${{ needs.setup_build.outputs.owner_lc }}/${{ needs.setup_build.outputs.container_name }}:${{ needs.setup_build.outputs.container_tag }}
permissions:
contents: read
@ -156,33 +179,16 @@ jobs:
repository: openwrt/telephony
path: openwrt/feeds/telephony
- name: Fix permission
run: |
chown -R buildbot:buildbot openwrt
- name: Prepare prebuilt tools
shell: su buildbot -c "sh -e {0}"
working-directory: openwrt
run: |
mkdir -p staging_dir build_dir
ln -s /prebuilt_tools/staging_dir/host staging_dir/host
ln -s /prebuilt_tools/build_dir/host build_dir/host
./scripts/ext-tools.sh --refresh
- name: Update & Install feeds
if: inputs.include_feeds == true
shell: su buildbot -c "sh -e {0}"
working-directory: openwrt
run: |
./scripts/feeds update -a
./scripts/feeds install -a
- name: Parse toolchain file
if: inputs.build_toolchain == false
id: parse-toolchain
working-directory: openwrt
run: |
if [ -d /external-toolchain/ ]; then
echo "toolchain-type=external_container" >> $GITHUB_OUTPUT
exit 0
fi
TOOLCHAIN_PATH=snapshots
if [ -n "${{ github.base_ref }}" ]; then
@ -227,6 +233,28 @@ jobs:
echo "TOOLCHAIN_FILE=$TOOLCHAIN_FILE" >> "$GITHUB_ENV"
echo "TOOLCHAIN_PATH=$TOOLCHAIN_PATH" >> "$GITHUB_ENV"
- name: Fix permission
run: |
chown -R buildbot:buildbot openwrt
- name: Prepare prebuilt tools
shell: su buildbot -c "sh -e {0}"
working-directory: openwrt
run: |
mkdir -p staging_dir build_dir
ln -s /prebuilt_tools/staging_dir/host staging_dir/host
ln -s /prebuilt_tools/build_dir/host build_dir/host
./scripts/ext-tools.sh --refresh
- name: Update & Install feeds
if: inputs.include_feeds == true
shell: su buildbot -c "sh -e {0}"
working-directory: openwrt
run: |
./scripts/feeds update -a
./scripts/feeds install -a
- name: Cache ccache
uses: actions/cache@v3
with:
@ -236,7 +264,7 @@ jobs:
ccache-kernel-${{ inputs.target }}/${{ inputs.subtarget }}-
- name: Download external toolchain/sdk
if: inputs.build_toolchain == false && steps.parse-toolchain.outputs.toolchain-type != 'internal'
if: inputs.build_toolchain == false && steps.parse-toolchain.outputs.toolchain-type != 'internal' && steps.parse-toolchain.outputs.toolchain-type != 'external_container'
shell: su buildbot -c "sh -e {0}"
working-directory: openwrt
run: |
@ -273,6 +301,20 @@ jobs:
echo CONFIG_TARGET_PER_DEVICE_ROOTFS=y >> .config
echo CONFIG_TARGET_ALL_PROFILES=y >> .config
- name: Configure external toolchain in container
if: inputs.build_toolchain == false && steps.parse-toolchain.outputs.toolchain-type == 'external_container'
shell: su buildbot -c "sh -e {0}"
working-directory: openwrt
run: |
echo CONFIG_DEVEL=y >> .config
echo CONFIG_AUTOREMOVE=y >> .config
echo CONFIG_CCACHE=y >> .config
./scripts/ext-toolchain.sh \
--toolchain /external-toolchain/$(ls /external-toolchain/ | grep openwrt-toolchain)/toolchain-* \
--overwrite-config \
--config ${{ inputs.target }}/${{ inputs.subtarget }}
- name: Configure external toolchain
if: inputs.build_toolchain == false && steps.parse-toolchain.outputs.toolchain-type == 'external_toolchain'
shell: su buildbot -c "sh -e {0}"
@ -376,6 +418,12 @@ jobs:
working-directory: openwrt
run: make -j$(nproc) BUILD_LOG=1 || ret=$? .github/workflows/scripts/show_build_failures.sh
- name: Build external toolchain
if: inputs.build_external_toolchain == true
shell: su buildbot -c "sh -e {0}"
working-directory: openwrt
run: make target/toolchain/compile -j$(nproc) BUILD_LOG=1 || ret=$? .github/workflows/scripts/show_build_failures.sh
- name: Coverity prepare toolchain
if: inputs.coverity_check_packages != ''
shell: su buildbot -c "sh -e {0}"
@ -433,3 +481,19 @@ jobs:
with:
name: ${{ inputs.target }}-${{ inputs.subtarget }}-logs
path: "openwrt/logs"
- name: Find external toolchain name
id: get-toolchain-name
if: inputs.upload_external_toolchain == true
working-directory: openwrt
run: |
TOOLCHAIN_NAME=$(ls bin/targets/${{inputs.target }}/${{ inputs.subtarget }} | grep toolchain)
echo "toolchain-name=$TOOLCHAIN_NAME" >> $GITHUB_OUTPUT
- name: Upload prebuilt toolchain
if: inputs.upload_external_toolchain == true
uses: actions/upload-artifact@v3
with:
name: ${{ inputs.target }}-${{ inputs.subtarget }}-external-toolchain
path: openwrt/bin/targets/${{ inputs.target }}/${{ inputs.subtarget }}/${{ steps.get-toolchain-name.outputs.toolchain-name }}
retention-days: 1

View file

@ -17,6 +17,7 @@ jobs:
packages: read
uses: ./.github/workflows/build.yml
with:
container_name: toolchain
target: x86
subtarget: 64
build_full: true

View file

@ -17,6 +17,8 @@ on:
- 'include/kernel*'
- 'package/kernel/**'
- 'target/linux/**'
branches-ignore:
- master
permissions:
contents: read
@ -109,6 +111,7 @@ jobs:
include: ${{fromJson(needs.determine_targets.outputs.targets_subtargets)}}
uses: ./.github/workflows/build.yml
with:
container_name: toolchain
target: ${{ matrix.target }}
subtarget: ${{ matrix.subtarget }}
build_kernel: true

View file

@ -13,6 +13,7 @@ jobs:
runs-on: ubuntu-latest
outputs:
target: ${{ steps.set_target.outputs.target }}
subtarget: ${{ steps.set_target.outputs.subtarget }}
steps:
- name: Set target
@ -20,7 +21,8 @@ jobs:
env:
CI_EVENT_LABEL_NAME: ${{ github.event.label.name }}
run: |
echo "$CI_EVENT_LABEL_NAME" | sed -n 's/.*:\(.*\):\(.*\)$/target="\1\/\2"/p' | tee --append $GITHUB_OUTPUT
echo "$CI_EVENT_LABEL_NAME" | sed -n 's/.*:\(.*\):\(.*\)$/target="\1"/p' | tee --append $GITHUB_OUTPUT
echo "$CI_EVENT_LABEL_NAME" | sed -n 's/.*:\(.*\):\(.*\)$/subtarget="\2"/p' | tee --append $GITHUB_OUTPUT
build_kernel:
name: Build Kernel with external toolchain
@ -31,6 +33,7 @@ jobs:
uses: ./.github/workflows/build.yml
with:
target: ${{ needs.set_target.outputs.target }}
subtarget: ${{ needs.set_target.outputs.subtarget }}
build_kernel: true
build_all_kmods: true
@ -43,3 +46,4 @@ jobs:
uses: ./.github/workflows/check-kernel-patches.yml
with:
target: ${{ needs.set_target.outputs.target }}
subtarget: ${{ needs.set_target.outputs.subtarget }}

View file

@ -13,6 +13,7 @@ jobs:
runs-on: ubuntu-latest
outputs:
target: ${{ steps.set_target.outputs.target }}
subtarget: ${{ steps.set_target.outputs.subtarget }}
steps:
- name: Set target
@ -20,7 +21,8 @@ jobs:
env:
CI_EVENT_LABEL_NAME: ${{ github.event.label.name }}
run: |
echo "$CI_EVENT_LABEL_NAME" | sed -n 's/.*:\(.*\):\(.*\)$/target="\1\/\2"/p' | tee --append $GITHUB_OUTPUT
echo "$CI_EVENT_LABEL_NAME" | sed -n 's/.*:\(.*\):\(.*\)$/target="\1"/p' | tee --append $GITHUB_OUTPUT
echo "$CI_EVENT_LABEL_NAME" | sed -n 's/.*:\(.*\):\(.*\)$/subtarget="\2"/p' | tee --append $GITHUB_OUTPUT
build_target:
name: Build target
@ -31,6 +33,7 @@ jobs:
uses: ./.github/workflows/build.yml
with:
target: ${{ needs.set_target.outputs.target }}
subtarget: ${{ needs.set_target.outputs.subtarget }}
build_full: true
build_all_kmods: true
build_all_boards: true

View file

@ -19,6 +19,8 @@ on:
- 'package/**'
- 'target/linux/generic/**'
- 'toolchain/**'
branches-ignore:
- master
permissions:
contents: read
@ -43,6 +45,7 @@ jobs:
subtarget: 64
uses: ./.github/workflows/build.yml
with:
container_name: toolchain
target: ${{ matrix.target }}
subtarget: ${{ matrix.subtarget }}
build_kernel: true

View file

@ -3,10 +3,17 @@ name: Build and Push prebuilt tools container
on:
push:
paths:
- 'include/version.mk'
- 'tools/**'
- '.github/workflows/build-tools.yml'
- '.github/workflows/push-containers.yml'
- '.github/workflows/Dockerfile.tools'
- 'toolchain/**'
- '.github/workflows/build.yml'
- '.github/workflows/toolchain.yml'
- '.github/workflows/Dockerfile.toolchain'
branches-ignore:
- master
permissions:
contents: read
@ -16,29 +23,21 @@ concurrency:
cancel-in-progress: true
jobs:
build-linux-buildbot:
name: Build tools with buildbot container
if: ${{ github.repository_owner == 'openwrt' }}
uses: ./.github/workflows/build-tools.yml
with:
generate_prebuilt_artifacts: true
push-tools-container:
needs: build-linux-buildbot
name: Push prebuilt tools container
determine-container-info:
name: Determine needed info to push containers
if: ${{ github.repository_owner == 'openwrt' }}
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
outputs:
owner-lc: ${{ steps.generate-owner-lc.outputs.owner-lc }}
container-tag: ${{ steps.determine-container-tag.outputs.container-tag }}
steps:
- name: Set lower case owner name
id: generate-owner-lc
env:
OWNER: ${{ github.repository_owner }}
run: |
echo "OWNER_LC=${OWNER,,}" >> "$GITHUB_ENV"
echo "owner-lc=${OWNER,,}" >> "$GITHUB_OUTPUT"
# Per branch tools container tag
# By default stick to latest
@ -49,6 +48,7 @@ jobs:
# (example branch openwrt-22.03 -> tools:openwrt-22.03)
# (example branch openwrt-22.03-test -> tools:openwrt-22.03)
- name: Determine tools container tag
id: determine-container-tag
run: |
CONTAINER_TAG=latest
@ -62,9 +62,27 @@ jobs:
fi
fi
echo "Tools container to push tools:$CONTAINER_TAG"
echo "CONTAINER_TAG=$CONTAINER_TAG" >> "$GITHUB_ENV"
echo "Container tag to push for tools and toolchain is $CONTAINER_TAG"
echo "container-tag=$CONTAINER_TAG" >> "$GITHUB_OUTPUT"
build-linux-buildbot:
name: Build tools with buildbot container
if: ${{ github.repository_owner == 'openwrt' }}
uses: ./.github/workflows/build-tools.yml
with:
generate_prebuilt_artifacts: true
push-tools-container:
needs: [ determine-container-info, build-linux-buildbot ]
if: ${{ github.repository_owner == 'openwrt' }}
name: Push prebuilt tools container
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v3
with:
@ -92,5 +110,110 @@ jobs:
with:
context: openwrt
push: true
tags: ghcr.io/${{ env.OWNER_LC }}/tools:${{ env.CONTAINER_TAG }}
tags: ghcr.io/${{ needs.determine-container-info.outputs.owner-lc }}/tools:${{ needs.determine-container-info.outputs.container-tag }}
file: openwrt/.github/workflows/Dockerfile.tools
determine-targets:
name: Set targets
if: ${{ github.repository_owner == 'openwrt' }}
runs-on: ubuntu-latest
outputs:
target: ${{ steps.find_targets.outputs.target }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set targets
id: find_targets
run: |
export TARGETS="$(perl ./scripts/dump-target-info.pl targets 2>/dev/null \
| awk '{ print $1 }')"
JSON='['
FIRST=1
for TARGET in $TARGETS; do
TUPLE='{"target":"'"$(echo $TARGET | cut -d "/" -f 1)"'","subtarget":"'"$(echo $TARGET | cut -d "/" -f 2)"'"}'
[[ $FIRST -ne 1 ]] && JSON="$JSON"','
JSON="$JSON""$TUPLE"
FIRST=0
done
JSON="$JSON"']'
echo -e "\n---- targets ----\n"
echo "$JSON"
echo -e "\n---- targets ----\n"
echo "target=$JSON" >> $GITHUB_OUTPUT
build:
name: Build Target Toolchain
if: ${{ github.repository_owner == 'openwrt' }}
needs: [ determine-targets, push-tools-container ]
permissions:
contents: read
packages: read
strategy:
fail-fast: False
matrix:
include: ${{fromJson(needs.determine-targets.outputs.target)}}
uses: ./.github/workflows/build.yml
with:
target: ${{ matrix.target }}
subtarget: ${{ matrix.subtarget }}
build_toolchain: true
build_external_toolchain: true
upload_external_toolchain: true
push-toolchain-container:
name: Push Target Toolchain container
if: ${{ github.repository_owner == 'openwrt' }}
needs: [ determine-container-info, determine-targets, build ]
runs-on: ubuntu-latest
strategy:
fail-fast: False
matrix:
include: ${{fromJson(needs.determine-targets.outputs.target)}}
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v3
with:
path: 'openwrt'
- name: Download external toolchain from build job
uses: actions/download-artifact@v3
with:
name: ${{ matrix.target }}-${{ matrix.subtarget }}-external-toolchain
path: openwrt
- name: Find external toolchain name
id: get-toolchain-name
working-directory: openwrt
run: |
TOOLCHAIN_NAME=$(ls | grep toolchain-${{ matrix.target }}-${{ matrix.subtarget }})
echo "toolchain-name=$TOOLCHAIN_NAME" >> $GITHUB_OUTPUT
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v3
with:
context: openwrt
push: true
tags: ghcr.io/${{ needs.determine-container-info.outputs.owner-lc }}/toolchain:${{ matrix.target }}-${{ matrix.subtarget }}-${{ needs.determine-container-info.outputs.container-tag }}
file: openwrt/.github/workflows/Dockerfile.toolchain
build-args: |
OWNER_LC=${{ needs.determine-container-info.outputs.owner-lc }}
CONTAINER_TAG=${{ needs.determine-container-info.outputs.container-tag }}
TOOLCHAIN_NAME=${{ steps.get-toolchain-name.outputs.toolchain-name }}

View file

@ -11,6 +11,8 @@ on:
- '.github/workflows/build.yml'
- '.github/workflows/toolchain.yml'
- 'toolchain/**'
branches-ignore:
- master
permissions:
contents: read

View file

@ -3,14 +3,18 @@ name: Build host tools
on:
pull_request:
paths:
- 'include/**'
- 'tools/**'
- '.github/workflows/build-tools.yml'
- '.github/workflows/tools.yml'
push:
paths:
- 'include/**'
- 'tools/**'
- '.github/workflows/build-tools.yml'
- '.github/workflows/tools.yml'
branches-ignore:
- master
permissions:
contents: read

View file

@ -113,7 +113,7 @@ define SetupHostCommand
;; \
esac; \
ln -sf "$$$$$$$$bin" "$(STAGING_DIR_HOST)/bin/$(strip $(1))"; \
exit 1; \
exit 0; \
fi; \
fi; \
done; \

View file

@ -11,7 +11,7 @@ include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=mac80211
PKG_VERSION:=6.1.24
PKG_RELEASE:=3
PKG_RELEASE:=4
# PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.15.58/
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources/
PKG_HASH:=5d39aca7e34c33cb9b3e366117b2e86841b7bdd37933679d6b1e61be6b150648

View file

@ -1,5 +1,6 @@
From 986e43b19ae9176093da35e0a844e65c8bf9ede7 Mon Sep 17 00:00:00 2001
From: Felix Fietkau <nbd@nbd.name>
Date: Tue, 6 Dec 2022 11:15:02 +0100
Date: Mon, 13 Feb 2023 11:08:54 +0100
Subject: [PATCH] wifi: mac80211: fix receiving A-MSDU frames on mesh
interfaces
@ -33,7 +34,15 @@ For locally received packets, the Mesh Control header is stripped away.
For forwarded packets, a new 802.11 header gets added.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Link: https://lore.kernel.org/r/20230213100855.34315-4-nbd@nbd.name
[fix fortify build error]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
.../wireless/marvell/mwifiex/11n_rxreorder.c | 2 +-
include/net/cfg80211.h | 27 +-
net/mac80211/rx.c | 350 ++++++++++--------
net/wireless/util.c | 120 +++---
4 files changed, 297 insertions(+), 202 deletions(-)
--- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
@ -557,7 +566,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ memcpy(&payload.eth.h_source, mesh_addr, ETH_ALEN);
+ break;
+ case MESH_FLAGS_AE_A5_A6:
+ memcpy(&payload.eth.h_dest, mesh_addr, 2 * ETH_ALEN);
+ memcpy(&payload.eth, mesh_addr, 2 * ETH_ALEN);
+ break;
+ default:
+ break;

View file

@ -1,7 +1,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=qca-ssdk
PKG_RELEASE:=1
PKG_RELEASE:=2
PKG_SOURCE_URL:=https://git.codelinaro.org/clo/qsdk/oss/lklm/qca-ssdk.git
PKG_SOURCE_PROTO:=git
@ -37,6 +37,8 @@ else
TOOLCHAIN_BIN_PATH=$(TOOLCHAIN_DIR)/bin
endif
LNX_CONFIG_OPTS = LNX_MAKEOPTS='$(KERNEL_MAKEOPTS)' MODULE_TYPE=KSLIB modules
MAKE_FLAGS+= \
TARGET_NAME=$(CONFIG_TARGET_NAME) \
TOOL_PATH=$(TOOLCHAIN_BIN_PATH) \
@ -47,7 +49,7 @@ MAKE_FLAGS+= \
TARGET_SUFFIX=$(CONFIG_TARGET_SUFFIX) \
GCC_VERSION=$(GCC_VERSION) \
EXTRA_CFLAGS=-fno-stack-protector -I$(STAGING_DIR)/usr/include \
$(KERNEL_MAKE_FLAGS)
$(LNX_CONFIG_OPTS)
ifeq ($(CONFIG_TARGET_BOARD), "ipq807x")
MAKE_FLAGS+= CHIP_TYPE=HPPE PTP_FEATURE=disable SWCONFIG_FEATURE=disable

View file

@ -0,0 +1,286 @@
From edd3d4347cc73a99c7cf59aceeb1e8ad4d4dd303 Mon Sep 17 00:00:00 2001
From: crao <quic_crao@quicinc.com>
Date: Tue, 15 Nov 2022 18:50:01 +0800
Subject: [PATCH] [qca-ssdk]: Support Linux-Style Makefile for SSDK
Change-Id: I8c4399433b6422ef6192f70bf08b0d3023cc94b6
Signed-off-by: crao <quic_crao@quicinc.com>
---
Makefile | 15 +++++++++++++
Makefile.modules | 16 ++++++++++++++
make/defs.mk | 1 +
make/linux_opt.mk | 54 ++++++++++++++++++++++++++++-------------------
make/target.mk | 12 +++++++++++
src/api/Makefile | 2 +-
6 files changed, 77 insertions(+), 23 deletions(-)
mode change 100755 => 100644 Makefile
create mode 100644 Makefile.modules
mode change 100755 => 100644 make/defs.mk
mode change 100755 => 100644 make/linux_opt.mk
mode change 100755 => 100644 make/target.mk
mode change 100755 => 100644 src/api/Makefile
--- a/Makefile
+++ b/Makefile
@@ -12,6 +12,9 @@ include ./make/$(OS)_opt.mk
SUB_DIR=$(patsubst %/, %, $(dir $(wildcard src/*/Makefile)))
SUB_LIB=$(subst src/, , $(SUB_DIR))
+####################################################################
+# SSDK-Style Makefile
+####################################################################
all: $(BIN_DIR) kslib
mkdir -p ./temp/;cd ./temp;cp ../build/bin/ssdk_ks_km.a ./;ar -x ssdk_ks_km.a; cp ../ko_Makefile ./Makefile;
make -C $(SYS_PATH) M=$(PRJ_PATH)/temp/ CROSS_COMPILE=$(TOOLPREFIX) modules
@@ -20,6 +23,18 @@ all: $(BIN_DIR) kslib
rm -Rf ./temp/*.o ./temp/*.ko ./temp/*.a
@echo "---Build [SSDK-$(VERSION)] at $(BUILD_DATE) finished."
+####################################################################
+# LNX Modules-Style Makefile
+####################################################################
+modules: $(BIN_DIR) kslib_c
+ cp Makefile.modules ./Makefile;
+ make -C $(SYS_PATH) M=$(PRJ_PATH)/ $(LNX_MAKEOPTS) modules
+ cp *.ko build/bin;
+ @echo "---Build [SSDK-$(VERSION)] at $(BUILD_DATE) finished."
+
+kslib_c:
+ $(foreach i, $(SUB_LIB), $(MAKE) MODULE_TYPE=KSLIB -C src/$i src_list_loop || exit 1;)
+
kslib:kslib_o
$(AR) -r $(BIN_DIR)/$(KS_MOD)_$(RUNMODE).a $(wildcard $(BLD_DIR)/KSLIB/*.o)
--- /dev/null
+++ b/Makefile.modules
@@ -0,0 +1,16 @@
+####################################################################
+# Add All Local Flags
+####################################################################
+ccflags-y += $(LNX_LOCAL_CFLAGS) -Wno-error
+
+####################################################################
+# Build Object List
+####################################################################
+SRC_LIST := $(shell cat $(PRJ_PATH)/src_list.dep)
+OBJ_LIST := $(patsubst %.c,%.o,$(SRC_LIST))
+
+####################################################################
+# Linux Kernel Module
+####################################################################
+obj-m := qca-ssdk.o
+qca-ssdk-objs := $(OBJ_LIST)
--- a/make/defs.mk
+++ b/make/defs.mk
@@ -7,6 +7,7 @@ ifeq (,$(findstring $(LIB), $(COMPONENTS
endif
SRC_FILE=$(addprefix $(PRJ_PATH)/$(LOC_DIR)/, $(SRC_LIST))
+LOC_SRC_FILE=$(addprefix $(LOC_DIR)/, $(SRC_LIST))
OBJ_LIST=$(SRC_LIST:.c=.o)
OBJ_FILE=$(addprefix $(DST_DIR)/, $(OBJ_LIST))
--- a/make/linux_opt.mk
+++ b/make/linux_opt.mk
@@ -295,7 +295,7 @@ ifeq (TRUE, $(DEBUG_ON))
MODULE_CFLAG += -g
endif
-MODULE_CFLAG += $(OPT_FLAG) -Wall -DVERSION=\"$(VERSION)\" -DBUILD_DATE=\"$(BUILD_DATE)\" -DOS=\"$(OS)\" -D"KBUILD_STR(s)=\#s" -D"KBUILD_MODNAME=KBUILD_STR(qca-ssdk)"
+MODULE_CFLAG += $(OPT_FLAG) -Wall -DVERSION=\"$(VERSION)\" -DBUILD_DATE=\"$(BUILD_DATE)\" -DOS=\"$(OS)\" -D"KBUILD_STR(s)=\#s"
MODULE_INC += -I$(PRJ_PATH)/include \
-I$(PRJ_PATH)/include/common \
@@ -450,7 +450,7 @@ ifeq (KSLIB, $(MODULE_TYPE))
MODULE_CFLAG += -DKVER34
MODULE_CFLAG += -DKVER32
MODULE_CFLAG += -DLNX26_22
- MODULE_INC += -I$(SYS_PATH) \
+ SYS_INC += -I$(SYS_PATH) \
-I$(TOOL_PATH)/../lib/gcc/$(TARGET_NAME)/$(GCC_VERSION)/include/ \
-I$(SYS_PATH)/include \
-I$(SYS_PATH)/source/include \
@@ -473,7 +473,7 @@ ifeq (KSLIB, $(MODULE_TYPE))
MODULE_CFLAG += -DKVER32
MODULE_CFLAG += -DLNX26_22
ifeq ($(ARCH), arm64)
- MODULE_INC += -I$(SYS_PATH) \
+ SYS_INC += -I$(SYS_PATH) \
-I$(TOOL_PATH)/../lib/gcc/$(TARGET_NAME)/$(GCC_VERSION)/include/ \
-I$(SYS_PATH)/include \
-I$(SYS_PATH)/source \
@@ -492,13 +492,13 @@ ifeq (KSLIB, $(MODULE_TYPE))
-I$(SYS_PATH)/source/include/uapi
ifneq ($(wildcard $(SYS_PATH)/include/linux/kconfig.h),)
- MODULE_INC += -include $(SYS_PATH)/include/linux/kconfig.h
+ SYS_INC += -include $(SYS_PATH)/include/linux/kconfig.h
else
- MODULE_INC += -include $(KERNEL_SRC)/include/linux/kconfig.h
+ SYS_INC += -include $(KERNEL_SRC)/include/linux/kconfig.h
endif
else ifeq ($(ARCH), arm)
- MODULE_INC += -I$(SYS_PATH) \
+ SYS_INC += -I$(SYS_PATH) \
-I$(TOOL_PATH)/../lib/gcc/$(TARGET_NAME)/$(GCC_VERSION)/include/ \
-I$(TOOL_PATH)/../lib/gcc/$(TARGET_NAME)/7.5.0/include/ \
-I$(TOOL_PATH)/../../lib/armv7a-vfp-neon-rdk-linux-gnueabi/gcc/arm-rdk-linux-gnueabi/4.8.4/include/ \
@@ -522,13 +522,13 @@ ifeq (KSLIB, $(MODULE_TYPE))
-I$(TOOL_PATH)/../../lib/arm-rdk-linux-gnueabi/gcc/arm-rdk-linux-gnueabi/9.3.0/include/
ifneq ($(wildcard $(SYS_PATH)/include/linux/kconfig.h),)
- MODULE_INC += -include $(SYS_PATH)/include/linux/kconfig.h
+ SYS_INC += -include $(SYS_PATH)/include/linux/kconfig.h
else
- MODULE_INC += -include $(KERNEL_SRC)/include/linux/kconfig.h
+ SYS_INC += -include $(KERNEL_SRC)/include/linux/kconfig.h
endif
else
- MODULE_INC += -I$(SYS_PATH) \
+ SYS_INC += -I$(SYS_PATH) \
-I$(TOOL_PATH)/../lib/gcc/$(TARGET_NAME)/$(GCC_VERSION)/include/ \
-I$(SYS_PATH)/include \
-I$(SYS_PATH)/source \
@@ -564,7 +564,7 @@ ifeq (KSLIB, $(MODULE_TYPE))
MODULE_CFLAG += -DLNX26_22
ifeq ($(ARCH), arm64)
KCONF_FILE = $(SYS_PATH)/source/include/linux/kconfig.h
- MODULE_INC += -I$(SYS_PATH) \
+ SYS_INC += -I$(SYS_PATH) \
-I$(TOOL_PATH)/../lib/gcc/$(TARGET_NAME)/$(GCC_VERSION)/include/ \
-I$(SYS_PATH)/include \
-I$(SYS_PATH)/source/include \
@@ -581,7 +581,7 @@ ifeq (KSLIB, $(MODULE_TYPE))
-I$(SYS_PATH)/source/arch/arm64/include/asm/mach \
-include $(KCONF_FILE)
else ifeq ($(ARCH), arm)
- MODULE_INC += -I$(SYS_PATH) \
+ SYS_INC += -I$(SYS_PATH) \
-I$(TOOL_PATH)/../lib/gcc/$(TARGET_NAME)/$(GCC_VERSION)/include/ \
-I$(TOOL_PATH)/../../lib/armv7a-vfp-neon-rdk-linux-gnueabi/gcc/arm-rdk-linux-gnueabi/4.8.4/include/ \
-I$(SYS_PATH)/include \
@@ -604,7 +604,7 @@ ifeq (KSLIB, $(MODULE_TYPE))
MODULE_CFLAG += -DKVER34
MODULE_CFLAG += -DKVER32
MODULE_CFLAG += -DLNX26_22
- MODULE_INC += -I$(SYS_PATH) \
+ SYS_INC += -I$(SYS_PATH) \
-I$(TOOL_PATH)/../lib/gcc/$(TARGET_NAME)/$(GCC_VERSION)/include/ \
-I$(TOOL_PATH)/../../lib/arm-poky-linux-gnueabi/gcc/arm-poky-linux-gnueabi/5.3.0/include/ \
-I$(TOOL_PATH)/../../lib/armv7a-vfp-neon-rdk-linux-gnueabi/gcc/arm-rdk-linux-gnueabi/4.8.4/include/ \
@@ -627,10 +627,10 @@ ifeq (KSLIB, $(MODULE_TYPE))
-I$(EXT_PATH) \
-I$(SYS_PATH)/source/arch/arm/include/asm/mach
ifneq ($(wildcard $(SYS_PATH)/include/linux/kconfig.h),)
- MODULE_INC += \
+ SYS_INC += \
-include $(SYS_PATH)/include/linux/kconfig.h
else
- MODULE_INC += \
+ SYS_INC += \
-include $(SYS_PATH)/source/include/linux/kconfig.h
endif
@@ -641,7 +641,7 @@ ifeq (KSLIB, $(MODULE_TYPE))
MODULE_CFLAG += -DKVER32
MODULE_CFLAG += -DLNX26_22
MODULE_CFLAG += -Werror
- MODULE_INC += -I$(SYS_PATH) \
+ SYS_INC += -I$(SYS_PATH) \
-I$(SYS_PATH)/include \
-I$(SYS_PATH)/source/include \
-I$(SYS_PATH)/source/arch/arm/mach-msm/include \
@@ -657,7 +657,7 @@ ifeq (KSLIB, $(MODULE_TYPE))
MODULE_CFLAG += -DKVER32
MODULE_CFLAG += -DLNX26_22
ifeq (mips, $(CPU))
- MODULE_INC += -I$(SYS_PATH) \
+ SYS_INC += -I$(SYS_PATH) \
-I$(SYS_PATH)/include \
-I$(SYS_PATH)/arch/mips/include \
-I$(SYS_PATH)/arch/mips/include/asm/mach-ar7240 \
@@ -678,7 +678,7 @@ ifeq (KSLIB, $(MODULE_TYPE))
-O2 -fno-pic -pipe -mabi=32 -march=mips32r2 -DMODULE -mlong-calls -DEXPORT_SYMTAB
endif
else
- MODULE_INC += -I$(SYS_PATH) \
+ SYS_INC += -I$(SYS_PATH) \
-I$(SYS_PATH)/include \
-I$(SYS_PATH)/arch/arm/include \
-I$(SYS_PATH)/arch/arm/include/asm \
@@ -695,7 +695,7 @@ ifeq (KSLIB, $(MODULE_TYPE))
MODULE_CFLAG += -DKVER26
MODULE_CFLAG += -DLNX26_22
ifeq (mips, $(CPU))
- MODULE_INC += -I$(SYS_PATH) \
+ SYS_INC += -I$(SYS_PATH) \
-I$(SYS_PATH)/include \
-I$(SYS_PATH)/arch/mips/include \
-I$(SYS_PATH)/arch/mips/include/asm/mach-ar7240 \
@@ -708,7 +708,7 @@ ifeq (KSLIB, $(MODULE_TYPE))
-O2 -fno-pic -pipe -mabi=32 -march=mips32r2 -DMODULE -mlong-calls -DEXPORT_SYMTAB
endif
else
- MODULE_INC += -I$(SYS_PATH) \
+ SYS_INC += -I$(SYS_PATH) \
-I$(SYS_PATH)/include \
-I$(SYS_PATH)/arch/arm/include \
-I$(SYS_PATH)/arch/arm/include/asm \
@@ -721,8 +721,7 @@ ifeq (KSLIB, $(MODULE_TYPE))
endif
- MODULE_CFLAG += -D__KERNEL__ -DKERNEL_MODULE $(CPU_CFLAG)
-
+ MODULE_CFLAG += -D__KERNEL__ -DKERNEL_MODULE
endif
@@ -748,4 +747,15 @@ ifneq (TRUE, $(KERNEL_MODE))
endif
endif
-LOCAL_CFLAGS += $(MODULE_INC) $(MODULE_CFLAG) $(EXTRA_CFLAGS)
+LOCAL_CFLAGS += $(MODULE_INC) $(SYS_INC) $(MODULE_CFLAG) $(EXTRA_CFLAGS)
+
+####################################################################
+# cflags for SSDK-Style Makefile
+####################################################################
+LOCAL_CFLAGS += $(CPU_CFLAG) -D"KBUILD_MODNAME=KBUILD_STR(qca-ssdk)"
+
+####################################################################
+# cflags for LNX Modules-Style Makefile
+####################################################################
+LNX_LOCAL_CFLAGS += $(MODULE_INC) $(MODULE_CFLAG) ${EXTRA_INC}
+export LNX_LOCAL_CFLAGS
--- a/make/target.mk
+++ b/make/target.mk
@@ -3,6 +3,18 @@ include $(PRJ_PATH)/make/$(OS)_opt.mk
include $(PRJ_PATH)/make/tools.mk
+####################################################################
+# LNX Modules-Style Makefile
+####################################################################
+src_list_loop: src_list
+ $(foreach i, $(SUB_DIR), $(MAKE) -C $(i) src_list_loop || exit 1;)
+
+src_list:
+ echo -n "$(LOC_SRC_FILE) " >> $(PRJ_PATH)/src_list.dep
+
+####################################################################
+# SSDK-Style Makefile
+####################################################################
obj: $(OBJ_LIST)
$(OBJ_LOOP)
--- a/src/api/Makefile
+++ b/src/api/Makefile
@@ -1,4 +1,4 @@
-LOC_DIR=src/sal
+LOC_DIR=src/api
LIB=API
include $(PRJ_PATH)/make/config.mk

View file

@ -0,0 +1,27 @@
From 3026f89b06049df01d5fe19c5fccc972637aa344 Mon Sep 17 00:00:00 2001
From: crao <quic_crao@quicinc.com>
Date: Tue, 7 Mar 2023 17:15:07 +0800
Subject: [PATCH] [qca-ssdk]: fix compilation issue in Linux-Style Makefile
Change-Id: If38251fc0a2bf4abc666d30f4812c0d9507310dc
Signed-off-by: crao <quic_crao@quicinc.com>
---
Makefile | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
mode change 100644 => 100755 Makefile
--- a/Makefile
+++ b/Makefile
@@ -27,9 +27,9 @@ all: $(BIN_DIR) kslib
# LNX Modules-Style Makefile
####################################################################
modules: $(BIN_DIR) kslib_c
- cp Makefile.modules ./Makefile;
- make -C $(SYS_PATH) M=$(PRJ_PATH)/ $(LNX_MAKEOPTS) modules
- cp *.ko build/bin;
+ mkdir -p ./temp/;cp * ./temp -a;cd ./temp;cp ../Makefile.modules ./Makefile;
+ make -C $(SYS_PATH) M=$(PRJ_PATH)/temp $(LNX_MAKEOPTS) modules
+ cp temp/*.ko build/bin;
@echo "---Build [SSDK-$(VERSION)] at $(BUILD_DATE) finished."
kslib_c:

View file

@ -0,0 +1,23 @@
From 6e4efd68e6e560a1994bc273fe6f7a72139f3957 Mon Sep 17 00:00:00 2001
From: crao <quic_crao@quicinc.com>
Date: Wed, 15 Mar 2023 11:19:39 +0800
Subject: [PATCH] [qca-ssdk]: fix compilation issue in Miami yocto
Change-Id: I8526b9e43667d72ae9afa4ef8a13167088d194ba
Signed-off-by: crao <quic_crao@quicinc.com>
---
Makefile | 2 ++
1 file changed, 2 insertions(+)
--- a/Makefile
+++ b/Makefile
@@ -29,7 +29,9 @@ all: $(BIN_DIR) kslib
modules: $(BIN_DIR) kslib_c
mkdir -p ./temp/;cp * ./temp -a;cd ./temp;cp ../Makefile.modules ./Makefile;
make -C $(SYS_PATH) M=$(PRJ_PATH)/temp $(LNX_MAKEOPTS) modules
+ cp $(PRJ_PATH)/temp/Module.symvers $(PRJ_PATH)/Module.symvers;
cp temp/*.ko build/bin;
+ rm -Rf ./temp/*.o ./temp/*.ko ./temp/*.a
@echo "---Build [SSDK-$(VERSION)] at $(BUILD_DATE) finished."
kslib_c:

View file

@ -20,7 +20,7 @@ define KernelPackage/leds-ubnt-ledbar
FILES:= \
$(PKG_BUILD_DIR)/leds-ubnt-ledbar.ko
AUTOLOAD:=$(call AutoProbe,leds-ubnt-ledbar,1)
DEPENDS:=+kmod-i2c-core
DEPENDS:=@TARGET_mediatek_mt7622||TARGET_ramips_mt7621 +kmod-i2c-core
endef
define KernelPackage/leds-ubnt-ledbar/description

View file

@ -9,6 +9,7 @@
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/version.h>
/**
* Driver for the Ubiquiti RGB LED controller (LEDBAR).
@ -218,13 +219,19 @@ static int ubnt_ledbar_probe(struct i2c_client *client,
return ubnt_ledbar_apply_state(ledbar);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)
static int ubnt_ledbar_remove(struct i2c_client *client)
#else
static void ubnt_ledbar_remove(struct i2c_client *client)
#endif
{
struct ubnt_ledbar *ledbar = i2c_get_clientdata(client);
mutex_destroy(&ledbar->lock);
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)
return 0;
#endif
}
static const struct i2c_device_id ubnt_ledbar_id[] = {

View file

@ -0,0 +1,75 @@
#
# Copyright (C) 2020-2023 Tony Ambardar <itugrok@yahoo.com>
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=libbpf
PKG_VERSION:=1.2.0
PKG_RELEASE:=1
PKG_SOURCE_URL:=https://github.com/libbpf/libbpf
PKG_SOURCE_PROTO:=git
PKG_SOURCE_VERSION:=fbd60dbff51c870f5e80a17c4f2fd639eb80af90
PKG_MIRROR_HASH:=80a80dfba71576e017b596fb28068e2a92de629e426f063e4b37314c8d576336
PKG_ABI_VERSION:=$(firstword $(subst .,$(space),$(PKG_VERSION)))
PKG_MAINTAINER:=Tony Ambardar <itugrok@yahoo.com>
PKG_BUILD_FLAGS:=no-mips16
PKG_BUILD_PARALLEL:=1
PKG_INSTALL:=1
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/nls.mk
define Package/libbpf
SECTION:=libs
CATEGORY:=Libraries
TITLE:=libbpf - eBPF helper library
LICENSE:=LGPL-2.1 OR BSD-2-Clause
ABI_VERSION:=$(PKG_ABI_VERSION)
URL:=http://www.kernel.org
DEPENDS:=+libelf
endef
define Package/libbpf/description
libbpf is a library for loading eBPF programs and reading and manipulating eBPF objects from user-space.
endef
MAKE_VARS = \
EXTRA_CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \
LDFLAGS="$(TARGET_LDFLAGS)"
MAKE_FLAGS += \
$(if $(findstring c,$(OPENWRT_VERBOSE)),V=1,V='') \
LIBSUBDIR=lib
MAKE_PATH = src
define Build/InstallDev/libbpf
$(INSTALL_DIR) $(1)/usr/include/bpf
$(CP) $(PKG_INSTALL_DIR)/usr/include/bpf/*.h $(1)/usr/include/bpf/
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libbpf.{a,so*} \
$(1)/usr/lib/
$(INSTALL_DIR) $(1)/usr/lib/pkgconfig
$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libbpf.pc \
$(1)/usr/lib/pkgconfig/
$(SED) 's,/usr/include,$$$${prefix}/include,g' \
$(1)/usr/lib/pkgconfig/libbpf.pc
$(SED) 's,/usr/lib,$$$${exec_prefix}/lib,g' \
$(1)/usr/lib/pkgconfig/libbpf.pc
endef
Build/InstallDev=$(Build/InstallDev/libbpf)
define Package/libbpf/install
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libbpf.so.* $(1)/usr/lib/
endef
$(eval $(call BuildPackage,libbpf))

View file

@ -0,0 +1,10 @@
--- a/src/Makefile
+++ b/src/Makefile
@@ -34,6 +34,7 @@ ALL_CFLAGS := $(INCLUDES)
SHARED_CFLAGS += -fPIC -fvisibility=hidden -DSHARED
+CFLAGS = $(EXTRA_CFLAGS)
CFLAGS ?= -g -O2 -Werror -Wall -std=gnu89
ALL_CFLAGS += $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 $(EXTRA_CFLAGS)
ALL_LDFLAGS += $(LDFLAGS) $(EXTRA_LDFLAGS)

View file

@ -1,5 +1,5 @@
#
# Copyright (C) 2020 Tony Ambardar <itugrok@yahoo.com>
# Copyright (C) 2020-2023 Tony Ambardar <itugrok@yahoo.com>
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
@ -8,14 +8,13 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=bpftools
PKG_VERSION:=7.2.0
PKG_RELEASE:=1
PKG_SOURCE_URL:=https://github.com/libbpf/bpftool
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=7.1.0
PKG_SOURCE_VERSION:=b01941c8f7890489f09713348a7d89567538504b
PKG_MIRROR_HASH:=641fb337342e25ae784a3efe72c71d8c88600a326300d8d5834e26be21547015
PKG_ABI_VERSION:=$(call abi_version_str,$(PKG_SOURCE_DATE))
PKG_SOURCE_VERSION:=19ff0564980a7429e730f6987a0b0bf418b3c676
PKG_MIRROR_HASH:=f9b9871f64986dd2e5dab7060bb919398256ba93964da49c62efaf0e6bc9bbc4
PKG_MAINTAINER:=Tony Ambardar <itugrok@yahoo.com>
@ -63,27 +62,8 @@ define Package/bpftool-full/description
eBPF programs and jited code.
endef
define Package/libbpf
SECTION:=libs
CATEGORY:=Libraries
TITLE:=libbpf - eBPF helper library
VARIANT:=lib
LICENSE:=LGPL-2.1 OR BSD-2-Clause
ABI_VERSION:=$(PKG_ABI_VERSION)
URL:=http://www.kernel.org
DEPENDS:=+libelf
endef
define Package/libbpf/description
libbpf is a library for loading eBPF programs and reading and manipulating eBPF objects from user-space.
endef
# LTO not compatible with DSO using PIC
ifneq ($(BUILD_VARIANT),lib)
TARGET_CFLAGS += -ffunction-sections -fdata-sections -flto
TARGET_LDFLAGS += -Wl,--gc-sections -flto
endif
TARGET_CFLAGS += -ffunction-sections -fdata-sections -flto
TARGET_LDFLAGS += -Wl,--gc-sections -flto
ifeq ($(BUILD_VARIANT),full)
full:=1
@ -99,7 +79,6 @@ MAKE_FLAGS += \
OUTPUT="$(PKG_BUILD_DIR)/" \
prefix="/usr" \
$(if $(findstring c,$(OPENWRT_VERBOSE)),V=1,V='') \
LIBSUBDIR=lib \
check_feat=0 \
feature-clang-bpf-co-re=0 \
feature-libbfd=$(full) \
@ -108,30 +87,7 @@ MAKE_FLAGS += \
feature-disassembler-four-args=1 \
feature-disassembler-init-styled=1
ifeq ($(BUILD_VARIANT),lib)
MAKE_PATH = libbpf/src
else
MAKE_PATH = src
endif
define Build/InstallDev/libbpf
$(INSTALL_DIR) $(1)/usr/include/bpf
$(CP) $(PKG_INSTALL_DIR)/usr/include/bpf/*.h $(1)/usr/include/bpf/
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libbpf.{a,so*} \
$(1)/usr/lib/
$(INSTALL_DIR) $(1)/usr/lib/pkgconfig
$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libbpf.pc \
$(1)/usr/lib/pkgconfig/
$(SED) 's,/usr/include,$$$${prefix}/include,g' \
$(1)/usr/lib/pkgconfig/libbpf.pc
$(SED) 's,/usr/lib,$$$${exec_prefix}/lib,g' \
$(1)/usr/lib/pkgconfig/libbpf.pc
endef
ifeq ($(BUILD_VARIANT),lib)
Build/InstallDev=$(Build/InstallDev/libbpf)
endif
MAKE_PATH = src
define Package/bpftool-$(BUILD_VARIANT)/install
$(INSTALL_DIR) $(1)/usr/libexec
@ -139,11 +95,5 @@ define Package/bpftool-$(BUILD_VARIANT)/install
$(1)/usr/libexec/bpftool-$(BUILD_VARIANT)
endef
define Package/libbpf/install
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libbpf.so.* $(1)/usr/lib/
endef
$(eval $(call BuildPackage,libbpf))
$(eval $(call BuildPackage,bpftool-full))
$(eval $(call BuildPackage,bpftool-minimal))

View file

@ -23,7 +23,6 @@ CONFIG_ARM64_ERRATUM_832075=y
CONFIG_ARM64_ERRATUM_843419=y
CONFIG_ARM64_HW_AFDBM=y
CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y
CONFIG_ARM64_MODULE_PLTS=y
CONFIG_ARM64_PAGE_SHIFT=12
CONFIG_ARM64_PAN=y
CONFIG_ARM64_PA_BITS=48

View file

@ -27,7 +27,6 @@ CONFIG_ARM64_ERRATUM_832075=y
CONFIG_ARM64_ERRATUM_843419=y
CONFIG_ARM64_HW_AFDBM=y
CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y
CONFIG_ARM64_MODULE_PLTS=y
CONFIG_ARM64_PAGE_SHIFT=12
CONFIG_ARM64_PAN=y
CONFIG_ARM64_PA_BITS=48

View file

@ -27,7 +27,6 @@ CONFIG_ARM64_ERRATUM_832075=y
CONFIG_ARM64_ERRATUM_843419=y
CONFIG_ARM64_HW_AFDBM=y
CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y
CONFIG_ARM64_MODULE_PLTS=y
CONFIG_ARM64_PAGE_SHIFT=12
CONFIG_ARM64_PAN=y
CONFIG_ARM64_PA_BITS=48

View file

@ -25,7 +25,7 @@ Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17538,6 +17538,14 @@ T: git git://linuxtv.org/media_tree.git
@@ -17541,6 +17541,14 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
F: drivers/media/i2c/imx412.c

View file

@ -132,7 +132,7 @@ Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
+...
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17552,6 +17552,7 @@ M: Raspberry Pi Kernel Maintenance <kern
@@ -17555,6 +17555,7 @@ M: Raspberry Pi Kernel Maintenance <kern
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git

View file

@ -132,7 +132,7 @@ Signed-off-by: Lee Jackson <info@arducam.com>
+...
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17556,6 +17556,14 @@ F: Documentation/devicetree/bindings/med
@@ -17559,6 +17559,14 @@ F: Documentation/devicetree/bindings/med
F: Documentation/devicetree/bindings/media/i2c/imx477.yaml
F: drivers/media/i2c/imx477.c

View file

@ -0,0 +1,266 @@
From 087ed25eaf5a78a678508e893f80addab9b1c103 Mon Sep 17 00:00:00 2001
From: Kalesh Singh <kaleshsingh@google.com>
Date: Thu, 13 Apr 2023 14:43:26 -0700
Subject: [PATCH] mm: Multi-gen LRU: remove wait_event_killable()
Android 14 and later default to MGLRU [1] and field telemetry showed
occasional long tail latency (>100ms) in the reclaim path.
Tracing revealed priority inversion in the reclaim path. In
try_to_inc_max_seq(), when high priority tasks were blocked on
wait_event_killable(), the preemption of the low priority task to call
wake_up_all() caused those high priority tasks to wait longer than
necessary. In general, this problem is not different from others of its
kind, e.g., one caused by mutex_lock(). However, it is specific to MGLRU
because it introduced the new wait queue lruvec->mm_state.wait.
The purpose of this new wait queue is to avoid the thundering herd
problem. If many direct reclaimers rush into try_to_inc_max_seq(), only
one can succeed, i.e., the one to wake up the rest, and the rest who
failed might cause premature OOM kills if they do not wait. So far there
is no evidence supporting this scenario, based on how often the wait has
been hit. And this begs the question how useful the wait queue is in
practice.
Based on Minchan's recommendation, which is in line with his commit
6d4675e60135 ("mm: don't be stuck to rmap lock on reclaim path") and the
rest of the MGLRU code which also uses trylock when possible, remove the
wait queue.
[1] https://android-review.googlesource.com/q/I7ed7fbfd6ef9ce10053347528125dd98c39e50bf
Link: https://lkml.kernel.org/r/20230413214326.2147568-1-kaleshsingh@google.com
Fixes: bd74fdaea146 ("mm: multi-gen LRU: support page table walks")
Change-Id: I911f3968fd1adb25171279cc5b6f48ccb7efc8de
Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Suggested-by: Minchan Kim <minchan@kernel.org>
Reported-by: Wei Wang <wvw@google.com>
Acked-by: Yu Zhao <yuzhao@google.com>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Jan Alexander Steffens (heftig) <heftig@archlinux.org>
Cc: Oleksandr Natalenko <oleksandr@natalenko.name>
Cc: Suleiman Souhlal <suleiman@google.com>
Cc: Suren Baghdasaryan <surenb@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
include/linux/mmzone.h | 8 +--
mm/vmscan.c | 111 +++++++++++++++--------------------------
2 files changed, 42 insertions(+), 77 deletions(-)
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -452,18 +452,14 @@ enum {
struct lru_gen_mm_state {
/* set to max_seq after each iteration */
unsigned long seq;
- /* where the current iteration continues (inclusive) */
+ /* where the current iteration continues after */
struct list_head *head;
- /* where the last iteration ended (exclusive) */
+ /* where the last iteration ended before */
struct list_head *tail;
- /* to wait for the last page table walker to finish */
- struct wait_queue_head wait;
/* Bloom filters flip after each iteration */
unsigned long *filters[NR_BLOOM_FILTERS];
/* the mm stats for debugging */
unsigned long stats[NR_HIST_GENS][NR_MM_STATS];
- /* the number of concurrent page table walkers */
- int nr_walkers;
};
struct lru_gen_mm_walk {
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2999,18 +2999,13 @@ void lru_gen_del_mm(struct mm_struct *mm
if (!lruvec)
continue;
- /* where the last iteration ended (exclusive) */
+ /* where the current iteration continues after */
+ if (lruvec->mm_state.head == &mm->lru_gen.list)
+ lruvec->mm_state.head = lruvec->mm_state.head->prev;
+
+ /* where the last iteration ended before */
if (lruvec->mm_state.tail == &mm->lru_gen.list)
lruvec->mm_state.tail = lruvec->mm_state.tail->next;
-
- /* where the current iteration continues (inclusive) */
- if (lruvec->mm_state.head != &mm->lru_gen.list)
- continue;
-
- lruvec->mm_state.head = lruvec->mm_state.head->next;
- /* the deletion ends the current iteration */
- if (lruvec->mm_state.head == &mm_list->fifo)
- WRITE_ONCE(lruvec->mm_state.seq, lruvec->mm_state.seq + 1);
}
list_del_init(&mm->lru_gen.list);
@@ -3194,68 +3189,54 @@ static bool iterate_mm_list(struct lruve
struct mm_struct **iter)
{
bool first = false;
- bool last = true;
+ bool last = false;
struct mm_struct *mm = NULL;
struct mem_cgroup *memcg = lruvec_memcg(lruvec);
struct lru_gen_mm_list *mm_list = get_mm_list(memcg);
struct lru_gen_mm_state *mm_state = &lruvec->mm_state;
/*
- * There are four interesting cases for this page table walker:
- * 1. It tries to start a new iteration of mm_list with a stale max_seq;
- * there is nothing left to do.
- * 2. It's the first of the current generation, and it needs to reset
- * the Bloom filter for the next generation.
- * 3. It reaches the end of mm_list, and it needs to increment
- * mm_state->seq; the iteration is done.
- * 4. It's the last of the current generation, and it needs to reset the
- * mm stats counters for the next generation.
+ * mm_state->seq is incremented after each iteration of mm_list. There
+ * are three interesting cases for this page table walker:
+ * 1. It tries to start a new iteration with a stale max_seq: there is
+ * nothing left to do.
+ * 2. It started the next iteration: it needs to reset the Bloom filter
+ * so that a fresh set of PTE tables can be recorded.
+ * 3. It ended the current iteration: it needs to reset the mm stats
+ * counters and tell its caller to increment max_seq.
*/
spin_lock(&mm_list->lock);
VM_WARN_ON_ONCE(mm_state->seq + 1 < walk->max_seq);
- VM_WARN_ON_ONCE(*iter && mm_state->seq > walk->max_seq);
- VM_WARN_ON_ONCE(*iter && !mm_state->nr_walkers);
- if (walk->max_seq <= mm_state->seq) {
- if (!*iter)
- last = false;
+ if (walk->max_seq <= mm_state->seq)
goto done;
- }
- if (!mm_state->nr_walkers) {
- VM_WARN_ON_ONCE(mm_state->head && mm_state->head != &mm_list->fifo);
+ if (!mm_state->head)
+ mm_state->head = &mm_list->fifo;
- mm_state->head = mm_list->fifo.next;
+ if (mm_state->head == &mm_list->fifo)
first = true;
- }
-
- while (!mm && mm_state->head != &mm_list->fifo) {
- mm = list_entry(mm_state->head, struct mm_struct, lru_gen.list);
+ do {
mm_state->head = mm_state->head->next;
+ if (mm_state->head == &mm_list->fifo) {
+ WRITE_ONCE(mm_state->seq, mm_state->seq + 1);
+ last = true;
+ break;
+ }
/* force scan for those added after the last iteration */
- if (!mm_state->tail || mm_state->tail == &mm->lru_gen.list) {
- mm_state->tail = mm_state->head;
+ if (!mm_state->tail || mm_state->tail == mm_state->head) {
+ mm_state->tail = mm_state->head->next;
walk->force_scan = true;
}
+ mm = list_entry(mm_state->head, struct mm_struct, lru_gen.list);
if (should_skip_mm(mm, walk))
mm = NULL;
- }
-
- if (mm_state->head == &mm_list->fifo)
- WRITE_ONCE(mm_state->seq, mm_state->seq + 1);
+ } while (!mm);
done:
- if (*iter && !mm)
- mm_state->nr_walkers--;
- if (!*iter && mm)
- mm_state->nr_walkers++;
-
- if (mm_state->nr_walkers)
- last = false;
-
if (*iter || last)
reset_mm_stats(lruvec, walk, last);
@@ -3283,9 +3264,9 @@ static bool iterate_mm_list_nowalk(struc
VM_WARN_ON_ONCE(mm_state->seq + 1 < max_seq);
- if (max_seq > mm_state->seq && !mm_state->nr_walkers) {
- VM_WARN_ON_ONCE(mm_state->head && mm_state->head != &mm_list->fifo);
-
+ if (max_seq > mm_state->seq) {
+ mm_state->head = NULL;
+ mm_state->tail = NULL;
WRITE_ONCE(mm_state->seq, mm_state->seq + 1);
reset_mm_stats(lruvec, NULL, true);
success = true;
@@ -3894,10 +3875,6 @@ restart:
walk_pmd_range(&val, addr, next, args);
- /* a racy check to curtail the waiting time */
- if (wq_has_sleeper(&walk->lruvec->mm_state.wait))
- return 1;
-
if (need_resched() || walk->batched >= MAX_LRU_BATCH) {
end = (addr | ~PUD_MASK) + 1;
goto done;
@@ -3930,8 +3907,14 @@ static void walk_mm(struct lruvec *lruve
walk->next_addr = FIRST_USER_ADDRESS;
do {
+ DEFINE_MAX_SEQ(lruvec);
+
err = -EBUSY;
+ /* another thread might have called inc_max_seq() */
+ if (walk->max_seq != max_seq)
+ break;
+
/* page_update_gen() requires stable page_memcg() */
if (!mem_cgroup_trylock_pages(memcg))
break;
@@ -4164,25 +4147,12 @@ static bool try_to_inc_max_seq(struct lr
success = iterate_mm_list(lruvec, walk, &mm);
if (mm)
walk_mm(lruvec, mm, walk);
-
- cond_resched();
} while (mm);
done:
- if (!success) {
- if (sc->priority <= DEF_PRIORITY - 2)
- wait_event_killable(lruvec->mm_state.wait,
- max_seq < READ_ONCE(lrugen->max_seq));
- return false;
- }
+ if (success)
+ inc_max_seq(lruvec, can_swap, force_scan);
- VM_WARN_ON_ONCE(max_seq != READ_ONCE(lrugen->max_seq));
-
- inc_max_seq(lruvec, can_swap, force_scan);
- /* either this sees any waiters or they will see updated max_seq */
- if (wq_has_sleeper(&lruvec->mm_state.wait))
- wake_up_all(&lruvec->mm_state.wait);
-
- return true;
+ return success;
}
static bool lruvec_is_sizable(struct lruvec *lruvec, struct scan_control *sc)
@@ -5746,7 +5716,6 @@ void lru_gen_init_lruvec(struct lruvec *
INIT_LIST_HEAD(&lrugen->pages[gen][type][zone]);
lruvec->mm_state.seq = MIN_NR_GENS;
- init_waitqueue_head(&lruvec->mm_state.wait);
}
#ifdef CONFIG_MEMCG

View file

@ -0,0 +1,32 @@
From b6f56cddb5f57a0b8da0ce582232a2f1933558c6 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Mon, 3 Apr 2023 02:17:19 +0100
Subject: [PATCH 04/16] net: dsa: mt7530: make some noise if register read
fails
Simply returning the negative error value instead of the read value
doesn't seem like a good idea. Return 0 instead and add WARN_ON_ONCE(1)
so this kind of error will not go unnoticed.
Suggested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/mt7530.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -224,9 +224,10 @@ mt7530_mii_read(struct mt7530_priv *priv
/* MT7530 uses 31 as the pseudo port */
ret = bus->write(bus, 0x1f, 0x1f, page);
if (ret < 0) {
+ WARN_ON_ONCE(1);
dev_err(&bus->dev,
"failed to read mt7530 register\n");
- return ret;
+ return 0;
}
lo = bus->read(bus, 0x1f, r);

View file

@ -0,0 +1,111 @@
From 9ecc00164dc2300dfcd40afe549a8ee951dfea9f Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Mon, 3 Apr 2023 02:17:30 +0100
Subject: [PATCH 05/16] net: dsa: mt7530: refactor SGMII PCS creation
Instead of macro templates use a dedidated function and allocated
regmap_config when creating the regmaps for the pcs-mtk-lynxi
instances.
This is in preparation to switching to use unlocked regmap accessors
and have regmap's locking API handle locking for us.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/mt7530.c | 74 +++++++++++++++++++++++++++-------------
1 file changed, 50 insertions(+), 24 deletions(-)
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -2926,26 +2926,56 @@ static const struct regmap_bus mt7531_re
.reg_update_bits = mt7530_regmap_update_bits,
};
-#define MT7531_PCS_REGMAP_CONFIG(_name, _reg_base) \
- { \
- .name = _name, \
- .reg_bits = 16, \
- .val_bits = 32, \
- .reg_stride = 4, \
- .reg_base = _reg_base, \
- .max_register = 0x17c, \
+static int
+mt7531_create_sgmii(struct mt7530_priv *priv)
+{
+ struct regmap_config *mt7531_pcs_config[2];
+ struct phylink_pcs *pcs;
+ struct regmap *regmap;
+ int i, ret = 0;
+
+ for (i = 0; i < 2; i++) {
+ mt7531_pcs_config[i] = devm_kzalloc(priv->dev,
+ sizeof(struct regmap_config),
+ GFP_KERNEL);
+ if (!mt7531_pcs_config[i]) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ mt7531_pcs_config[i]->name = i ? "port6" : "port5";
+ mt7531_pcs_config[i]->reg_bits = 16;
+ mt7531_pcs_config[i]->val_bits = 32;
+ mt7531_pcs_config[i]->reg_stride = 4;
+ mt7531_pcs_config[i]->reg_base = MT7531_SGMII_REG_BASE(5 + i);
+ mt7531_pcs_config[i]->max_register = 0x17c;
+
+ regmap = devm_regmap_init(priv->dev,
+ &mt7531_regmap_bus, priv,
+ mt7531_pcs_config[i]);
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ break;
+ }
+ pcs = mtk_pcs_lynxi_create(priv->dev, regmap,
+ MT7531_PHYA_CTRL_SIGNAL3, 0);
+ if (!pcs) {
+ ret = -ENXIO;
+ break;
+ }
+ priv->ports[5 + i].sgmii_pcs = pcs;
}
-static const struct regmap_config mt7531_pcs_config[] = {
- MT7531_PCS_REGMAP_CONFIG("port5", MT7531_SGMII_REG_BASE(5)),
- MT7531_PCS_REGMAP_CONFIG("port6", MT7531_SGMII_REG_BASE(6)),
-};
+ if (ret && i)
+ mtk_pcs_lynxi_destroy(priv->ports[5].sgmii_pcs);
+
+ return ret;
+}
static int
mt753x_setup(struct dsa_switch *ds)
{
struct mt7530_priv *priv = ds->priv;
- struct regmap *regmap;
int i, ret;
/* Initialise the PCS devices */
@@ -2967,15 +2997,11 @@ mt753x_setup(struct dsa_switch *ds)
if (ret && priv->irq)
mt7530_free_irq_common(priv);
- if (priv->id == ID_MT7531)
- for (i = 0; i < 2; i++) {
- regmap = devm_regmap_init(ds->dev,
- &mt7531_regmap_bus, priv,
- &mt7531_pcs_config[i]);
- priv->ports[5 + i].sgmii_pcs =
- mtk_pcs_lynxi_create(ds->dev, regmap,
- MT7531_PHYA_CTRL_SIGNAL3, 0);
- }
+ if (priv->id == ID_MT7531) {
+ ret = mt7531_create_sgmii(priv);
+ if (ret && priv->irq)
+ mt7530_free_irq_common(priv);
+ }
return ret;
}

View file

@ -0,0 +1,74 @@
From 1bd099c49f65ed923b9f19b8c4b3cd1ff0024091 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Mon, 3 Apr 2023 02:17:40 +0100
Subject: [PATCH 06/16] net: dsa: mt7530: use unlocked regmap accessors
Instead of wrapping the locked register accessor functions, use the
unlocked variants and add locking wrapper functions to let regmap
handle the locking.
This is a preparation towards being able to always use regmap to
access switch registers instead of open-coded accessor functions.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/mt7530.c | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -2899,7 +2899,7 @@ static int mt7530_regmap_read(void *cont
{
struct mt7530_priv *priv = context;
- *val = mt7530_read(priv, reg);
+ *val = mt7530_mii_read(priv, reg);
return 0;
};
@@ -2907,23 +2907,25 @@ static int mt7530_regmap_write(void *con
{
struct mt7530_priv *priv = context;
- mt7530_write(priv, reg, val);
+ mt7530_mii_write(priv, reg, val);
return 0;
};
-static int mt7530_regmap_update_bits(void *context, unsigned int reg,
- unsigned int mask, unsigned int val)
+static void
+mt7530_mdio_regmap_lock(void *mdio_lock)
{
- struct mt7530_priv *priv = context;
+ mutex_lock_nested(mdio_lock, MDIO_MUTEX_NESTED);
+}
- mt7530_rmw(priv, reg, mask, val);
- return 0;
-};
+static void
+mt7530_mdio_regmap_unlock(void *mdio_lock)
+{
+ mutex_unlock(mdio_lock);
+}
static const struct regmap_bus mt7531_regmap_bus = {
.reg_write = mt7530_regmap_write,
.reg_read = mt7530_regmap_read,
- .reg_update_bits = mt7530_regmap_update_bits,
};
static int
@@ -2949,6 +2951,9 @@ mt7531_create_sgmii(struct mt7530_priv *
mt7531_pcs_config[i]->reg_stride = 4;
mt7531_pcs_config[i]->reg_base = MT7531_SGMII_REG_BASE(5 + i);
mt7531_pcs_config[i]->max_register = 0x17c;
+ mt7531_pcs_config[i]->lock = mt7530_mdio_regmap_lock;
+ mt7531_pcs_config[i]->unlock = mt7530_mdio_regmap_unlock;
+ mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock;
regmap = devm_regmap_init(priv->dev,
&mt7531_regmap_bus, priv,

View file

@ -0,0 +1,224 @@
From a08c045580e060a6886bbb656c50ae20b0c780b5 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Mon, 3 Apr 2023 02:17:52 +0100
Subject: [PATCH 07/16] net: dsa: mt7530: use regmap to access switch register
space
Use regmap API to access the switch register space.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/mt7530.c | 99 ++++++++++++++++++++++++----------------
drivers/net/dsa/mt7530.h | 2 +
2 files changed, 62 insertions(+), 39 deletions(-)
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -183,9 +183,9 @@ core_clear(struct mt7530_priv *priv, u32
}
static int
-mt7530_mii_write(struct mt7530_priv *priv, u32 reg, u32 val)
+mt7530_regmap_write(void *context, unsigned int reg, unsigned int val)
{
- struct mii_bus *bus = priv->bus;
+ struct mii_bus *bus = context;
u16 page, r, lo, hi;
int ret;
@@ -197,24 +197,34 @@ mt7530_mii_write(struct mt7530_priv *pri
/* MT7530 uses 31 as the pseudo port */
ret = bus->write(bus, 0x1f, 0x1f, page);
if (ret < 0)
- goto err;
+ return ret;
ret = bus->write(bus, 0x1f, r, lo);
if (ret < 0)
- goto err;
+ return ret;
ret = bus->write(bus, 0x1f, 0x10, hi);
-err:
+ return ret;
+}
+
+static int
+mt7530_mii_write(struct mt7530_priv *priv, u32 reg, u32 val)
+{
+ int ret;
+
+ ret = regmap_write(priv->regmap, reg, val);
+
if (ret < 0)
- dev_err(&bus->dev,
+ dev_err(priv->dev,
"failed to write mt7530 register\n");
+
return ret;
}
-static u32
-mt7530_mii_read(struct mt7530_priv *priv, u32 reg)
+static int
+mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val)
{
- struct mii_bus *bus = priv->bus;
+ struct mii_bus *bus = context;
u16 page, r, lo, hi;
int ret;
@@ -223,17 +233,32 @@ mt7530_mii_read(struct mt7530_priv *priv
/* MT7530 uses 31 as the pseudo port */
ret = bus->write(bus, 0x1f, 0x1f, page);
- if (ret < 0) {
+ if (ret < 0)
+ return ret;
+
+ lo = bus->read(bus, 0x1f, r);
+ hi = bus->read(bus, 0x1f, 0x10);
+
+ *val = (hi << 16) | (lo & 0xffff);
+
+ return 0;
+}
+
+static u32
+mt7530_mii_read(struct mt7530_priv *priv, u32 reg)
+{
+ int ret;
+ u32 val;
+
+ ret = regmap_read(priv->regmap, reg, &val);
+ if (ret) {
WARN_ON_ONCE(1);
- dev_err(&bus->dev,
+ dev_err(priv->dev,
"failed to read mt7530 register\n");
return 0;
}
- lo = bus->read(bus, 0x1f, r);
- hi = bus->read(bus, 0x1f, 0x10);
-
- return (hi << 16) | (lo & 0xffff);
+ return val;
}
static void
@@ -283,14 +308,10 @@ mt7530_rmw(struct mt7530_priv *priv, u32
u32 mask, u32 set)
{
struct mii_bus *bus = priv->bus;
- u32 val;
mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
- val = mt7530_mii_read(priv, reg);
- val &= ~mask;
- val |= set;
- mt7530_mii_write(priv, reg, val);
+ regmap_update_bits(priv->regmap, reg, mask, set);
mutex_unlock(&bus->mdio_lock);
}
@@ -298,7 +319,7 @@ mt7530_rmw(struct mt7530_priv *priv, u32
static void
mt7530_set(struct mt7530_priv *priv, u32 reg, u32 val)
{
- mt7530_rmw(priv, reg, 0, val);
+ mt7530_rmw(priv, reg, val, val);
}
static void
@@ -2895,22 +2916,6 @@ static const struct phylink_pcs_ops mt75
.pcs_an_restart = mt7530_pcs_an_restart,
};
-static int mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val)
-{
- struct mt7530_priv *priv = context;
-
- *val = mt7530_mii_read(priv, reg);
- return 0;
-};
-
-static int mt7530_regmap_write(void *context, unsigned int reg, unsigned int val)
-{
- struct mt7530_priv *priv = context;
-
- mt7530_mii_write(priv, reg, val);
- return 0;
-};
-
static void
mt7530_mdio_regmap_lock(void *mdio_lock)
{
@@ -2923,7 +2928,7 @@ mt7530_mdio_regmap_unlock(void *mdio_loc
mutex_unlock(mdio_lock);
}
-static const struct regmap_bus mt7531_regmap_bus = {
+static const struct regmap_bus mt7530_regmap_bus = {
.reg_write = mt7530_regmap_write,
.reg_read = mt7530_regmap_read,
};
@@ -2956,7 +2961,7 @@ mt7531_create_sgmii(struct mt7530_priv *
mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock;
regmap = devm_regmap_init(priv->dev,
- &mt7531_regmap_bus, priv,
+ &mt7530_regmap_bus, priv->bus,
mt7531_pcs_config[i]);
if (IS_ERR(regmap)) {
ret = PTR_ERR(regmap);
@@ -3121,6 +3126,7 @@ MODULE_DEVICE_TABLE(of, mt7530_of_match)
static int
mt7530_probe(struct mdio_device *mdiodev)
{
+ static struct regmap_config *regmap_config;
struct mt7530_priv *priv;
struct device_node *dn;
@@ -3200,6 +3206,21 @@ mt7530_probe(struct mdio_device *mdiodev
mutex_init(&priv->reg_mutex);
dev_set_drvdata(&mdiodev->dev, priv);
+ regmap_config = devm_kzalloc(&mdiodev->dev, sizeof(*regmap_config),
+ GFP_KERNEL);
+ if (!regmap_config)
+ return -ENOMEM;
+
+ regmap_config->reg_bits = 16;
+ regmap_config->val_bits = 32;
+ regmap_config->reg_stride = 4;
+ regmap_config->max_register = MT7530_CREV;
+ regmap_config->disable_locking = true;
+ priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus,
+ priv->bus, regmap_config);
+ if (IS_ERR(priv->regmap))
+ return PTR_ERR(priv->regmap);
+
return dsa_register_switch(priv->ds);
}
--- a/drivers/net/dsa/mt7530.h
+++ b/drivers/net/dsa/mt7530.h
@@ -747,6 +747,7 @@ struct mt753x_info {
* @dev: The device pointer
* @ds: The pointer to the dsa core structure
* @bus: The bus used for the device and built-in PHY
+ * @regmap: The regmap instance representing all switch registers
* @rstc: The pointer to reset control used by MCM
* @core_pwr: The power supplied into the core
* @io_pwr: The power supplied into the I/O
@@ -767,6 +768,7 @@ struct mt7530_priv {
struct device *dev;
struct dsa_switch *ds;
struct mii_bus *bus;
+ struct regmap *regmap;
struct reset_control *rstc;
struct regulator *core_pwr;
struct regulator *io_pwr;

View file

@ -0,0 +1,54 @@
From 6de2852297737171ba96b91e89bf302ca1fda869 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Mon, 3 Apr 2023 02:18:04 +0100
Subject: [PATCH 08/16] net: dsa: mt7530: move SGMII PCS creation to
mt7530_probe function
Move creating the SGMII PCS from mt753x_setup() to the more appropriate
mt7530_probe() function.
This is done also in preparation of moving all functions related to
MDIO-connected MT753x switches to a separate module.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/mt7530.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -3007,12 +3007,6 @@ mt753x_setup(struct dsa_switch *ds)
if (ret && priv->irq)
mt7530_free_irq_common(priv);
- if (priv->id == ID_MT7531) {
- ret = mt7531_create_sgmii(priv);
- if (ret && priv->irq)
- mt7530_free_irq_common(priv);
- }
-
return ret;
}
@@ -3129,6 +3123,7 @@ mt7530_probe(struct mdio_device *mdiodev
static struct regmap_config *regmap_config;
struct mt7530_priv *priv;
struct device_node *dn;
+ int ret;
dn = mdiodev->dev.of_node;
@@ -3221,6 +3216,12 @@ mt7530_probe(struct mdio_device *mdiodev
if (IS_ERR(priv->regmap))
return PTR_ERR(priv->regmap);
+ if (priv->id == ID_MT7531) {
+ ret = mt7531_create_sgmii(priv);
+ if (ret)
+ return ret;
+ }
+
return dsa_register_switch(priv->ds);
}

View file

@ -0,0 +1,273 @@
From 1557c679f71c82a994eae0baadbaeb62b71e15bf Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Mon, 3 Apr 2023 02:18:16 +0100
Subject: [PATCH 09/16] net: dsa: mt7530: introduce mutex helpers
As the MDIO bus lock only needs to be involved if actually operating
on an MDIO-connected switch we will need to skip locking for built-in
switches which are accessed via MMIO.
Create helper functions which simplify that upcoming change.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/mt7530.c | 73 ++++++++++++++++++++--------------------
1 file changed, 36 insertions(+), 37 deletions(-)
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -143,31 +143,40 @@ err:
}
static void
-core_write(struct mt7530_priv *priv, u32 reg, u32 val)
+mt7530_mutex_lock(struct mt7530_priv *priv)
{
- struct mii_bus *bus = priv->bus;
+ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
+}
- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+static void
+mt7530_mutex_unlock(struct mt7530_priv *priv)
+{
+ mutex_unlock(&priv->bus->mdio_lock);
+}
+
+static void
+core_write(struct mt7530_priv *priv, u32 reg, u32 val)
+{
+ mt7530_mutex_lock(priv);
core_write_mmd_indirect(priv, reg, MDIO_MMD_VEND2, val);
- mutex_unlock(&bus->mdio_lock);
+ mt7530_mutex_unlock(priv);
}
static void
core_rmw(struct mt7530_priv *priv, u32 reg, u32 mask, u32 set)
{
- struct mii_bus *bus = priv->bus;
u32 val;
- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+ mt7530_mutex_lock(priv);
val = core_read_mmd_indirect(priv, reg, MDIO_MMD_VEND2);
val &= ~mask;
val |= set;
core_write_mmd_indirect(priv, reg, MDIO_MMD_VEND2, val);
- mutex_unlock(&bus->mdio_lock);
+ mt7530_mutex_unlock(priv);
}
static void
@@ -264,13 +273,11 @@ mt7530_mii_read(struct mt7530_priv *priv
static void
mt7530_write(struct mt7530_priv *priv, u32 reg, u32 val)
{
- struct mii_bus *bus = priv->bus;
-
- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+ mt7530_mutex_lock(priv);
mt7530_mii_write(priv, reg, val);
- mutex_unlock(&bus->mdio_lock);
+ mt7530_mutex_unlock(priv);
}
static u32
@@ -282,14 +289,13 @@ _mt7530_unlocked_read(struct mt7530_dumm
static u32
_mt7530_read(struct mt7530_dummy_poll *p)
{
- struct mii_bus *bus = p->priv->bus;
u32 val;
- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+ mt7530_mutex_lock(p->priv);
val = mt7530_mii_read(p->priv, p->reg);
- mutex_unlock(&bus->mdio_lock);
+ mt7530_mutex_unlock(p->priv);
return val;
}
@@ -307,13 +313,11 @@ static void
mt7530_rmw(struct mt7530_priv *priv, u32 reg,
u32 mask, u32 set)
{
- struct mii_bus *bus = priv->bus;
-
- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+ mt7530_mutex_lock(priv);
regmap_update_bits(priv->regmap, reg, mask, set);
- mutex_unlock(&bus->mdio_lock);
+ mt7530_mutex_unlock(priv);
}
static void
@@ -645,14 +649,13 @@ static int
mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad,
int regnum)
{
- struct mii_bus *bus = priv->bus;
struct mt7530_dummy_poll p;
u32 reg, val;
int ret;
INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);
- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+ mt7530_mutex_lock(priv);
ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
!(val & MT7531_PHY_ACS_ST), 20, 100000);
@@ -685,7 +688,7 @@ mt7531_ind_c45_phy_read(struct mt7530_pr
ret = val & MT7531_MDIO_RW_DATA_MASK;
out:
- mutex_unlock(&bus->mdio_lock);
+ mt7530_mutex_unlock(priv);
return ret;
}
@@ -694,14 +697,13 @@ static int
mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad,
int regnum, u32 data)
{
- struct mii_bus *bus = priv->bus;
struct mt7530_dummy_poll p;
u32 val, reg;
int ret;
INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);
- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+ mt7530_mutex_lock(priv);
ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
!(val & MT7531_PHY_ACS_ST), 20, 100000);
@@ -733,7 +735,7 @@ mt7531_ind_c45_phy_write(struct mt7530_p
}
out:
- mutex_unlock(&bus->mdio_lock);
+ mt7530_mutex_unlock(priv);
return ret;
}
@@ -741,14 +743,13 @@ out:
static int
mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum)
{
- struct mii_bus *bus = priv->bus;
struct mt7530_dummy_poll p;
int ret;
u32 val;
INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);
- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+ mt7530_mutex_lock(priv);
ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val,
!(val & MT7531_PHY_ACS_ST), 20, 100000);
@@ -771,7 +772,7 @@ mt7531_ind_c22_phy_read(struct mt7530_pr
ret = val & MT7531_MDIO_RW_DATA_MASK;
out:
- mutex_unlock(&bus->mdio_lock);
+ mt7530_mutex_unlock(priv);
return ret;
}
@@ -780,14 +781,13 @@ static int
mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum,
u16 data)
{
- struct mii_bus *bus = priv->bus;
struct mt7530_dummy_poll p;
int ret;
u32 reg;
INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC);
- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+ mt7530_mutex_lock(priv);
ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg,
!(reg & MT7531_PHY_ACS_ST), 20, 100000);
@@ -809,7 +809,7 @@ mt7531_ind_c22_phy_write(struct mt7530_p
}
out:
- mutex_unlock(&bus->mdio_lock);
+ mt7530_mutex_unlock(priv);
return ret;
}
@@ -1109,7 +1109,6 @@ static int
mt7530_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
{
struct mt7530_priv *priv = ds->priv;
- struct mii_bus *bus = priv->bus;
int length;
u32 val;
@@ -1120,7 +1119,7 @@ mt7530_port_change_mtu(struct dsa_switch
if (!dsa_is_cpu_port(ds, port))
return 0;
- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
+ mt7530_mutex_lock(priv);
val = mt7530_mii_read(priv, MT7530_GMACCR);
val &= ~MAX_RX_PKT_LEN_MASK;
@@ -1141,7 +1140,7 @@ mt7530_port_change_mtu(struct dsa_switch
mt7530_mii_write(priv, MT7530_GMACCR, val);
- mutex_unlock(&bus->mdio_lock);
+ mt7530_mutex_unlock(priv);
return 0;
}
@@ -1937,10 +1936,10 @@ mt7530_irq_thread_fn(int irq, void *dev_
u32 val;
int p;
- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
+ mt7530_mutex_lock(priv);
val = mt7530_mii_read(priv, MT7530_SYS_INT_STS);
mt7530_mii_write(priv, MT7530_SYS_INT_STS, val);
- mutex_unlock(&priv->bus->mdio_lock);
+ mt7530_mutex_unlock(priv);
for (p = 0; p < MT7530_NUM_PHYS; p++) {
if (BIT(p) & val) {
@@ -1976,7 +1975,7 @@ mt7530_irq_bus_lock(struct irq_data *d)
{
struct mt7530_priv *priv = irq_data_get_irq_chip_data(d);
- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
+ mt7530_mutex_lock(priv);
}
static void
@@ -1985,7 +1984,7 @@ mt7530_irq_bus_sync_unlock(struct irq_da
struct mt7530_priv *priv = irq_data_get_irq_chip_data(d);
mt7530_mii_write(priv, MT7530_SYS_INT_EN, priv->irq_enable);
- mutex_unlock(&priv->bus->mdio_lock);
+ mt7530_mutex_unlock(priv);
}
static struct irq_chip mt7530_irq_chip = {

View file

@ -0,0 +1,75 @@
From 25d15dee34a1a40d5fd71636a205e3211f09fd1d Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Mon, 3 Apr 2023 02:18:28 +0100
Subject: [PATCH 10/16] net: dsa: mt7530: move p5_intf_modes() function to
mt7530.c
In preparation of splitting mt7530.c into a driver for MDIO-connected
as well as MDIO-accessed built-in switches on one hand and MMIO-accessed
built-in switches move the p5_inft_modes() function from mt7530.h to
mt7530.c. The function is only needed there and will trigger a compiler
warning about a defined but unused function otherwise when including
mt7530.h in the to-be-introduced bus-specific drivers.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/mt7530.c | 18 ++++++++++++++++++
drivers/net/dsa/mt7530.h | 18 ------------------
2 files changed, 18 insertions(+), 18 deletions(-)
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -950,6 +950,24 @@ mt7530_set_ageing_time(struct dsa_switch
return 0;
}
+static const char *p5_intf_modes(unsigned int p5_interface)
+{
+ switch (p5_interface) {
+ case P5_DISABLED:
+ return "DISABLED";
+ case P5_INTF_SEL_PHY_P0:
+ return "PHY P0";
+ case P5_INTF_SEL_PHY_P4:
+ return "PHY P4";
+ case P5_INTF_SEL_GMAC5:
+ return "GMAC5";
+ case P5_INTF_SEL_GMAC5_SGMII:
+ return "GMAC5_SGMII";
+ default:
+ return "unknown";
+ }
+}
+
static void mt7530_setup_port5(struct dsa_switch *ds, phy_interface_t interface)
{
struct mt7530_priv *priv = ds->priv;
--- a/drivers/net/dsa/mt7530.h
+++ b/drivers/net/dsa/mt7530.h
@@ -682,24 +682,6 @@ enum p5_interface_select {
P5_INTF_SEL_GMAC5_SGMII,
};
-static const char *p5_intf_modes(unsigned int p5_interface)
-{
- switch (p5_interface) {
- case P5_DISABLED:
- return "DISABLED";
- case P5_INTF_SEL_PHY_P0:
- return "PHY P0";
- case P5_INTF_SEL_PHY_P4:
- return "PHY P4";
- case P5_INTF_SEL_GMAC5:
- return "GMAC5";
- case P5_INTF_SEL_GMAC5_SGMII:
- return "GMAC5_SGMII";
- default:
- return "unknown";
- }
-}
-
struct mt7530_priv;
struct mt753x_pcs {

View file

@ -0,0 +1,155 @@
From 37c9c0d8d0b2e24f8c9af72ecd4edd31537284d3 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Mon, 3 Apr 2023 02:18:39 +0100
Subject: [PATCH 11/16] net: dsa: mt7530: introduce mt7530_probe_common helper
function
Move commonly used parts from mt7530_probe into new mt7530_probe_common
helper function which will be used by both, mt7530_probe and the
to-be-introduced mt7988_probe.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/mt7530.c | 98 ++++++++++++++++++++++------------------
1 file changed, 54 insertions(+), 44 deletions(-)
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -3135,44 +3135,21 @@ static const struct of_device_id mt7530_
MODULE_DEVICE_TABLE(of, mt7530_of_match);
static int
-mt7530_probe(struct mdio_device *mdiodev)
+mt7530_probe_common(struct mt7530_priv *priv)
{
- static struct regmap_config *regmap_config;
- struct mt7530_priv *priv;
- struct device_node *dn;
- int ret;
+ struct device *dev = priv->dev;
- dn = mdiodev->dev.of_node;
-
- priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- priv->ds = devm_kzalloc(&mdiodev->dev, sizeof(*priv->ds), GFP_KERNEL);
+ priv->ds = devm_kzalloc(dev, sizeof(*priv->ds), GFP_KERNEL);
if (!priv->ds)
return -ENOMEM;
- priv->ds->dev = &mdiodev->dev;
+ priv->ds->dev = dev;
priv->ds->num_ports = MT7530_NUM_PORTS;
- /* Use medatek,mcm property to distinguish hardware type that would
- * casues a little bit differences on power-on sequence.
- */
- priv->mcm = of_property_read_bool(dn, "mediatek,mcm");
- if (priv->mcm) {
- dev_info(&mdiodev->dev, "MT7530 adapts as multi-chip module\n");
-
- priv->rstc = devm_reset_control_get(&mdiodev->dev, "mcm");
- if (IS_ERR(priv->rstc)) {
- dev_err(&mdiodev->dev, "Couldn't get our reset line\n");
- return PTR_ERR(priv->rstc);
- }
- }
-
/* Get the hardware identifier from the devicetree node.
* We will need it for some of the clock and regulator setup.
*/
- priv->info = of_device_get_match_data(&mdiodev->dev);
+ priv->info = of_device_get_match_data(dev);
if (!priv->info)
return -EINVAL;
@@ -3186,23 +3163,53 @@ mt7530_probe(struct mdio_device *mdiodev
return -EINVAL;
priv->id = priv->info->id;
+ priv->dev = dev;
+ priv->ds->priv = priv;
+ priv->ds->ops = &mt7530_switch_ops;
+ mutex_init(&priv->reg_mutex);
+ dev_set_drvdata(dev, priv);
- if (priv->id == ID_MT7530) {
- priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core");
- if (IS_ERR(priv->core_pwr))
- return PTR_ERR(priv->core_pwr);
+ return 0;
+}
- priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io");
- if (IS_ERR(priv->io_pwr))
- return PTR_ERR(priv->io_pwr);
- }
+static int
+mt7530_probe(struct mdio_device *mdiodev)
+{
+ static struct regmap_config *regmap_config;
+ struct mt7530_priv *priv;
+ struct device_node *dn;
+ int ret;
+
+ dn = mdiodev->dev.of_node;
+
+ priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
- /* Not MCM that indicates switch works as the remote standalone
+ priv->bus = mdiodev->bus;
+ priv->dev = &mdiodev->dev;
+
+ ret = mt7530_probe_common(priv);
+ if (ret)
+ return ret;
+
+ /* Use medatek,mcm property to distinguish hardware type that would
+ * cause a little bit differences on power-on sequence.
+ * Not MCM that indicates switch works as the remote standalone
* integrated circuit so the GPIO pin would be used to complete
* the reset, otherwise memory-mapped register accessing used
* through syscon provides in the case of MCM.
*/
- if (!priv->mcm) {
+ priv->mcm = of_property_read_bool(dn, "mediatek,mcm");
+ if (priv->mcm) {
+ dev_info(&mdiodev->dev, "MT7530 adapts as multi-chip module\n");
+
+ priv->rstc = devm_reset_control_get(&mdiodev->dev, "mcm");
+ if (IS_ERR(priv->rstc)) {
+ dev_err(&mdiodev->dev, "Couldn't get our reset line\n");
+ return PTR_ERR(priv->rstc);
+ }
+ } else {
priv->reset = devm_gpiod_get_optional(&mdiodev->dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(priv->reset)) {
@@ -3211,12 +3218,15 @@ mt7530_probe(struct mdio_device *mdiodev
}
}
- priv->bus = mdiodev->bus;
- priv->dev = &mdiodev->dev;
- priv->ds->priv = priv;
- priv->ds->ops = &mt7530_switch_ops;
- mutex_init(&priv->reg_mutex);
- dev_set_drvdata(&mdiodev->dev, priv);
+ if (priv->id == ID_MT7530) {
+ priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core");
+ if (IS_ERR(priv->core_pwr))
+ return PTR_ERR(priv->core_pwr);
+
+ priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io");
+ if (IS_ERR(priv->io_pwr))
+ return PTR_ERR(priv->io_pwr);
+ }
regmap_config = devm_kzalloc(&mdiodev->dev, sizeof(*regmap_config),
GFP_KERNEL);

View file

@ -0,0 +1,55 @@
From 720d736351761574af02ed093658ab60de60576c Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Mon, 3 Apr 2023 02:18:50 +0100
Subject: [PATCH 12/16] net: dsa: mt7530: introduce mt7530_remove_common helper
function
Move commonly used parts from mt7530_remove into new
mt7530_remove_common helper function which will be used by both,
mt7530_remove and the to-be-introduced mt7988_remove.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/mt7530.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -3253,6 +3253,17 @@ mt7530_probe(struct mdio_device *mdiodev
}
static void
+mt7530_remove_common(struct mt7530_priv *priv)
+{
+ if (priv->irq)
+ mt7530_free_irq(priv);
+
+ dsa_unregister_switch(priv->ds);
+
+ mutex_destroy(&priv->reg_mutex);
+}
+
+static void
mt7530_remove(struct mdio_device *mdiodev)
{
struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev);
@@ -3271,16 +3282,11 @@ mt7530_remove(struct mdio_device *mdiode
dev_err(priv->dev, "Failed to disable io pwr: %d\n",
ret);
- if (priv->irq)
- mt7530_free_irq(priv);
-
- dsa_unregister_switch(priv->ds);
+ mt7530_remove_common(priv);
for (i = 0; i < 2; ++i)
mtk_pcs_lynxi_destroy(priv->ports[5 + i].sgmii_pcs);
- mutex_destroy(&priv->reg_mutex);
-
dev_set_drvdata(&mdiodev->dev, NULL);
}

View file

@ -0,0 +1,143 @@
From 7f54cc9772ced2d76ac11832f0ada43798443ac9 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Mon, 3 Apr 2023 02:19:02 +0100
Subject: [PATCH 13/16] net: dsa: mt7530: split-off common parts from
mt7531_setup
MT7988 shares a significant part of the setup function with MT7531.
Split-off those parts into a shared function which is going to be used
also by mt7988_setup.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/mt7530.c | 99 ++++++++++++++++++++++------------------
1 file changed, 55 insertions(+), 44 deletions(-)
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -2348,11 +2348,64 @@ mt7530_setup(struct dsa_switch *ds)
}
static int
+mt7531_setup_common(struct dsa_switch *ds)
+{
+ struct mt7530_priv *priv = ds->priv;
+ struct dsa_port *cpu_dp;
+ int ret, i;
+
+ /* BPDU to CPU port */
+ dsa_switch_for_each_cpu_port(cpu_dp, ds) {
+ mt7530_rmw(priv, MT7531_CFC, MT7531_CPU_PMAP_MASK,
+ BIT(cpu_dp->index));
+ break;
+ }
+ mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK,
+ MT753X_BPDU_CPU_ONLY);
+
+ /* Enable and reset MIB counters */
+ mt7530_mib_reset(ds);
+
+ for (i = 0; i < MT7530_NUM_PORTS; i++) {
+ /* Disable forwarding by default on all ports */
+ mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK,
+ PCR_MATRIX_CLR);
+
+ /* Disable learning by default on all ports */
+ mt7530_set(priv, MT7530_PSC_P(i), SA_DIS);
+
+ mt7530_set(priv, MT7531_DBG_CNT(i), MT7531_DIS_CLR);
+
+ if (dsa_is_cpu_port(ds, i)) {
+ ret = mt753x_cpu_port_enable(ds, i);
+ if (ret)
+ return ret;
+ } else {
+ mt7530_port_disable(ds, i);
+
+ /* Set default PVID to 0 on all user ports */
+ mt7530_rmw(priv, MT7530_PPBV1_P(i), G0_PORT_VID_MASK,
+ G0_PORT_VID_DEF);
+ }
+
+ /* Enable consistent egress tag */
+ mt7530_rmw(priv, MT7530_PVC_P(i), PVC_EG_TAG_MASK,
+ PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
+ }
+
+ /* Flush the FDB table */
+ ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int
mt7531_setup(struct dsa_switch *ds)
{
struct mt7530_priv *priv = ds->priv;
struct mt7530_dummy_poll p;
- struct dsa_port *cpu_dp;
u32 val, id;
int ret, i;
@@ -2426,44 +2479,7 @@ mt7531_setup(struct dsa_switch *ds)
mt7531_ind_c45_phy_write(priv, MT753X_CTRL_PHY_ADDR, MDIO_MMD_VEND2,
CORE_PLL_GROUP4, val);
- /* BPDU to CPU port */
- dsa_switch_for_each_cpu_port(cpu_dp, ds) {
- mt7530_rmw(priv, MT7531_CFC, MT7531_CPU_PMAP_MASK,
- BIT(cpu_dp->index));
- break;
- }
- mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK,
- MT753X_BPDU_CPU_ONLY);
-
- /* Enable and reset MIB counters */
- mt7530_mib_reset(ds);
-
- for (i = 0; i < MT7530_NUM_PORTS; i++) {
- /* Disable forwarding by default on all ports */
- mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK,
- PCR_MATRIX_CLR);
-
- /* Disable learning by default on all ports */
- mt7530_set(priv, MT7530_PSC_P(i), SA_DIS);
-
- mt7530_set(priv, MT7531_DBG_CNT(i), MT7531_DIS_CLR);
-
- if (dsa_is_cpu_port(ds, i)) {
- ret = mt753x_cpu_port_enable(ds, i);
- if (ret)
- return ret;
- } else {
- mt7530_port_disable(ds, i);
-
- /* Set default PVID to 0 on all user ports */
- mt7530_rmw(priv, MT7530_PPBV1_P(i), G0_PORT_VID_MASK,
- G0_PORT_VID_DEF);
- }
-
- /* Enable consistent egress tag */
- mt7530_rmw(priv, MT7530_PVC_P(i), PVC_EG_TAG_MASK,
- PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
- }
+ mt7531_setup_common(ds);
/* Setup VLAN ID 0 for VLAN-unaware bridges */
ret = mt7530_setup_vlan0(priv);
@@ -2473,11 +2489,6 @@ mt7531_setup(struct dsa_switch *ds)
ds->assisted_learning_on_cpu_port = true;
ds->mtu_enforcement_ingress = true;
- /* Flush the FDB table */
- ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL);
- if (ret < 0)
- return ret;
-
return 0;
}

View file

@ -0,0 +1,692 @@
From cb675afcddbbeb2bfa6596e3bc236bc026cd425f Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Mon, 3 Apr 2023 02:19:13 +0100
Subject: [PATCH 14/16] net: dsa: mt7530: introduce separate MDIO driver
Split MT7530 switch driver into a common part and a part specific
for MDIO connected switches and multi-chip modules.
Move MDIO-specific functions to newly introduced mt7530-mdio.c while
keeping the common parts in mt7530.c.
Introduce new Kconfig symbol CONFIG_NET_DSA_MT7530_MDIO which is
implied by CONFIG_NET_DSA_MT7530.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
MAINTAINERS | 1 +
drivers/net/dsa/Kconfig | 15 +-
drivers/net/dsa/Makefile | 1 +
drivers/net/dsa/mt7530-mdio.c | 271 ++++++++++++++++++++++++++++++++++
drivers/net/dsa/mt7530.c | 264 +--------------------------------
drivers/net/dsa/mt7530.h | 6 +
6 files changed, 300 insertions(+), 258 deletions(-)
create mode 100644 drivers/net/dsa/mt7530-mdio.c
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11901,6 +11901,7 @@ M: Landen Chao <Landen.Chao@mediatek.com
M: DENG Qingfang <dqfext@gmail.com>
L: netdev@vger.kernel.org
S: Maintained
+F: drivers/net/dsa/mt7530-mdio.c
F: drivers/net/dsa/mt7530.*
F: net/dsa/tag_mtk.c
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -37,10 +37,22 @@ config NET_DSA_MT7530
tristate "MediaTek MT753x and MT7621 Ethernet switch support"
select NET_DSA_TAG_MTK
select MEDIATEK_GE_PHY
+ imply NET_DSA_MT7530_MDIO
+ help
+ This enables support for the MediaTek MT7530 and MT7531 Ethernet
+ switch chips. Multi-chip module MT7530 in MT7621AT, MT7621DAT,
+ MT7621ST and MT7623AI SoCs, and built-in switch in MT7988 SoC are
+ supported as well.
+
+config NET_DSA_MT7530_MDIO
+ tristate "MediaTek MT7530 MDIO interface driver"
+ depends on NET_DSA_MT7530
select PCS_MTK_LYNXI
help
- This enables support for the MediaTek MT7530, MT7531, and MT7621
- Ethernet switch chips.
+ This enables support for the MediaTek MT7530 and MT7531 switch
+ chips which are connected via MDIO, as well as multi-chip
+ module MT7530 which can be found in the MT7621AT, MT7621DAT,
+ MT7621ST and MT7623AI SoCs.
config NET_DSA_MV88E6060
tristate "Marvell 88E6060 ethernet switch chip support"
--- a/drivers/net/dsa/Makefile
+++ b/drivers/net/dsa/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_FIXED_PHY) += dsa_loop_bdi
endif
obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o
obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o
+obj-$(CONFIG_NET_DSA_MT7530_MDIO) += mt7530-mdio.o
obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
realtek-smi-objs := realtek-smi-core.o rtl8366.o rtl8366rb.o
--- /dev/null
+++ b/drivers/net/dsa/mt7530-mdio.c
@@ -0,0 +1,271 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/gpio/consumer.h>
+#include <linux/mdio.h>
+#include <linux/module.h>
+#include <linux/pcs/pcs-mtk-lynxi.h>
+#include <linux/of_irq.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/regulator/consumer.h>
+#include <net/dsa.h>
+
+#include "mt7530.h"
+
+static int
+mt7530_regmap_write(void *context, unsigned int reg, unsigned int val)
+{
+ struct mii_bus *bus = context;
+ u16 page, r, lo, hi;
+ int ret;
+
+ page = (reg >> 6) & 0x3ff;
+ r = (reg >> 2) & 0xf;
+ lo = val & 0xffff;
+ hi = val >> 16;
+
+ /* MT7530 uses 31 as the pseudo port */
+ ret = bus->write(bus, 0x1f, 0x1f, page);
+ if (ret < 0)
+ return ret;
+
+ ret = bus->write(bus, 0x1f, r, lo);
+ if (ret < 0)
+ return ret;
+
+ ret = bus->write(bus, 0x1f, 0x10, hi);
+ return ret;
+}
+
+static int
+mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val)
+{
+ struct mii_bus *bus = context;
+ u16 page, r, lo, hi;
+ int ret;
+
+ page = (reg >> 6) & 0x3ff;
+ r = (reg >> 2) & 0xf;
+
+ /* MT7530 uses 31 as the pseudo port */
+ ret = bus->write(bus, 0x1f, 0x1f, page);
+ if (ret < 0)
+ return ret;
+
+ lo = bus->read(bus, 0x1f, r);
+ hi = bus->read(bus, 0x1f, 0x10);
+
+ *val = (hi << 16) | (lo & 0xffff);
+
+ return 0;
+}
+
+static void
+mt7530_mdio_regmap_lock(void *mdio_lock)
+{
+ mutex_lock_nested(mdio_lock, MDIO_MUTEX_NESTED);
+}
+
+static void
+mt7530_mdio_regmap_unlock(void *mdio_lock)
+{
+ mutex_unlock(mdio_lock);
+}
+
+static const struct regmap_bus mt7530_regmap_bus = {
+ .reg_write = mt7530_regmap_write,
+ .reg_read = mt7530_regmap_read,
+};
+
+static int
+mt7531_create_sgmii(struct mt7530_priv *priv)
+{
+ struct regmap_config *mt7531_pcs_config[2];
+ struct phylink_pcs *pcs;
+ struct regmap *regmap;
+ int i, ret = 0;
+
+ for (i = 0; i < 2; i++) {
+ mt7531_pcs_config[i] = devm_kzalloc(priv->dev,
+ sizeof(struct regmap_config),
+ GFP_KERNEL);
+ if (!mt7531_pcs_config[i]) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ mt7531_pcs_config[i]->name = i ? "port6" : "port5";
+ mt7531_pcs_config[i]->reg_bits = 16;
+ mt7531_pcs_config[i]->val_bits = 32;
+ mt7531_pcs_config[i]->reg_stride = 4;
+ mt7531_pcs_config[i]->reg_base = MT7531_SGMII_REG_BASE(5 + i);
+ mt7531_pcs_config[i]->max_register = 0x17c;
+ mt7531_pcs_config[i]->lock = mt7530_mdio_regmap_lock;
+ mt7531_pcs_config[i]->unlock = mt7530_mdio_regmap_unlock;
+ mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock;
+
+ regmap = devm_regmap_init(priv->dev,
+ &mt7530_regmap_bus, priv->bus,
+ mt7531_pcs_config[i]);
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ break;
+ }
+ pcs = mtk_pcs_lynxi_create(priv->dev, regmap,
+ MT7531_PHYA_CTRL_SIGNAL3, 0);
+ if (!pcs) {
+ ret = -ENXIO;
+ break;
+ }
+ priv->ports[5 + i].sgmii_pcs = pcs;
+ }
+
+ if (ret && i)
+ mtk_pcs_lynxi_destroy(priv->ports[5].sgmii_pcs);
+
+ return ret;
+}
+
+static const struct of_device_id mt7530_of_match[] = {
+ { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], },
+ { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], },
+ { .compatible = "mediatek,mt7531", .data = &mt753x_table[ID_MT7531], },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mt7530_of_match);
+
+static int
+mt7530_probe(struct mdio_device *mdiodev)
+{
+ static struct regmap_config *regmap_config;
+ struct mt7530_priv *priv;
+ struct device_node *dn;
+ int ret;
+
+ dn = mdiodev->dev.of_node;
+
+ priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->bus = mdiodev->bus;
+ priv->dev = &mdiodev->dev;
+
+ ret = mt7530_probe_common(priv);
+ if (ret)
+ return ret;
+
+ /* Use medatek,mcm property to distinguish hardware type that would
+ * cause a little bit differences on power-on sequence.
+ * Not MCM that indicates switch works as the remote standalone
+ * integrated circuit so the GPIO pin would be used to complete
+ * the reset, otherwise memory-mapped register accessing used
+ * through syscon provides in the case of MCM.
+ */
+ priv->mcm = of_property_read_bool(dn, "mediatek,mcm");
+ if (priv->mcm) {
+ dev_info(&mdiodev->dev, "MT7530 adapts as multi-chip module\n");
+
+ priv->rstc = devm_reset_control_get(&mdiodev->dev, "mcm");
+ if (IS_ERR(priv->rstc)) {
+ dev_err(&mdiodev->dev, "Couldn't get our reset line\n");
+ return PTR_ERR(priv->rstc);
+ }
+ } else {
+ priv->reset = devm_gpiod_get_optional(&mdiodev->dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(priv->reset)) {
+ dev_err(&mdiodev->dev, "Couldn't get our reset line\n");
+ return PTR_ERR(priv->reset);
+ }
+ }
+
+ if (priv->id == ID_MT7530) {
+ priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core");
+ if (IS_ERR(priv->core_pwr))
+ return PTR_ERR(priv->core_pwr);
+
+ priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io");
+ if (IS_ERR(priv->io_pwr))
+ return PTR_ERR(priv->io_pwr);
+ }
+
+ regmap_config = devm_kzalloc(&mdiodev->dev, sizeof(*regmap_config),
+ GFP_KERNEL);
+ if (!regmap_config)
+ return -ENOMEM;
+
+ regmap_config->reg_bits = 16;
+ regmap_config->val_bits = 32;
+ regmap_config->reg_stride = 4;
+ regmap_config->max_register = MT7530_CREV;
+ regmap_config->disable_locking = true;
+ priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus,
+ priv->bus, regmap_config);
+ if (IS_ERR(priv->regmap))
+ return PTR_ERR(priv->regmap);
+
+ if (priv->id == ID_MT7531) {
+ ret = mt7531_create_sgmii(priv);
+ if (ret)
+ return ret;
+ }
+
+ return dsa_register_switch(priv->ds);
+}
+
+static void
+mt7530_remove(struct mdio_device *mdiodev)
+{
+ struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev);
+ int ret = 0, i;
+
+ if (!priv)
+ return;
+
+ ret = regulator_disable(priv->core_pwr);
+ if (ret < 0)
+ dev_err(priv->dev,
+ "Failed to disable core power: %d\n", ret);
+
+ ret = regulator_disable(priv->io_pwr);
+ if (ret < 0)
+ dev_err(priv->dev, "Failed to disable io pwr: %d\n",
+ ret);
+
+ mt7530_remove_common(priv);
+
+ for (i = 0; i < 2; ++i)
+ mtk_pcs_lynxi_destroy(priv->ports[5 + i].sgmii_pcs);
+}
+
+static void mt7530_shutdown(struct mdio_device *mdiodev)
+{
+ struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev);
+
+ if (!priv)
+ return;
+
+ dsa_switch_shutdown(priv->ds);
+
+ dev_set_drvdata(&mdiodev->dev, NULL);
+}
+
+static struct mdio_driver mt7530_mdio_driver = {
+ .probe = mt7530_probe,
+ .remove = mt7530_remove,
+ .shutdown = mt7530_shutdown,
+ .mdiodrv.driver = {
+ .name = "mt7530-mdio",
+ .of_match_table = mt7530_of_match,
+ },
+};
+
+mdio_module_driver(mt7530_mdio_driver);
+
+MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
+MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch (MDIO)");
+MODULE_LICENSE("GPL");
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -14,7 +14,6 @@
#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/of_platform.h>
-#include <linux/pcs/pcs-mtk-lynxi.h>
#include <linux/phylink.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@@ -192,31 +191,6 @@ core_clear(struct mt7530_priv *priv, u32
}
static int
-mt7530_regmap_write(void *context, unsigned int reg, unsigned int val)
-{
- struct mii_bus *bus = context;
- u16 page, r, lo, hi;
- int ret;
-
- page = (reg >> 6) & 0x3ff;
- r = (reg >> 2) & 0xf;
- lo = val & 0xffff;
- hi = val >> 16;
-
- /* MT7530 uses 31 as the pseudo port */
- ret = bus->write(bus, 0x1f, 0x1f, page);
- if (ret < 0)
- return ret;
-
- ret = bus->write(bus, 0x1f, r, lo);
- if (ret < 0)
- return ret;
-
- ret = bus->write(bus, 0x1f, 0x10, hi);
- return ret;
-}
-
-static int
mt7530_mii_write(struct mt7530_priv *priv, u32 reg, u32 val)
{
int ret;
@@ -230,29 +204,6 @@ mt7530_mii_write(struct mt7530_priv *pri
return ret;
}
-static int
-mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val)
-{
- struct mii_bus *bus = context;
- u16 page, r, lo, hi;
- int ret;
-
- page = (reg >> 6) & 0x3ff;
- r = (reg >> 2) & 0xf;
-
- /* MT7530 uses 31 as the pseudo port */
- ret = bus->write(bus, 0x1f, 0x1f, page);
- if (ret < 0)
- return ret;
-
- lo = bus->read(bus, 0x1f, r);
- hi = bus->read(bus, 0x1f, 0x10);
-
- *val = (hi << 16) | (lo & 0xffff);
-
- return 0;
-}
-
static u32
mt7530_mii_read(struct mt7530_priv *priv, u32 reg)
{
@@ -2944,72 +2895,6 @@ static const struct phylink_pcs_ops mt75
.pcs_an_restart = mt7530_pcs_an_restart,
};
-static void
-mt7530_mdio_regmap_lock(void *mdio_lock)
-{
- mutex_lock_nested(mdio_lock, MDIO_MUTEX_NESTED);
-}
-
-static void
-mt7530_mdio_regmap_unlock(void *mdio_lock)
-{
- mutex_unlock(mdio_lock);
-}
-
-static const struct regmap_bus mt7530_regmap_bus = {
- .reg_write = mt7530_regmap_write,
- .reg_read = mt7530_regmap_read,
-};
-
-static int
-mt7531_create_sgmii(struct mt7530_priv *priv)
-{
- struct regmap_config *mt7531_pcs_config[2];
- struct phylink_pcs *pcs;
- struct regmap *regmap;
- int i, ret = 0;
-
- for (i = 0; i < 2; i++) {
- mt7531_pcs_config[i] = devm_kzalloc(priv->dev,
- sizeof(struct regmap_config),
- GFP_KERNEL);
- if (!mt7531_pcs_config[i]) {
- ret = -ENOMEM;
- break;
- }
-
- mt7531_pcs_config[i]->name = i ? "port6" : "port5";
- mt7531_pcs_config[i]->reg_bits = 16;
- mt7531_pcs_config[i]->val_bits = 32;
- mt7531_pcs_config[i]->reg_stride = 4;
- mt7531_pcs_config[i]->reg_base = MT7531_SGMII_REG_BASE(5 + i);
- mt7531_pcs_config[i]->max_register = 0x17c;
- mt7531_pcs_config[i]->lock = mt7530_mdio_regmap_lock;
- mt7531_pcs_config[i]->unlock = mt7530_mdio_regmap_unlock;
- mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock;
-
- regmap = devm_regmap_init(priv->dev,
- &mt7530_regmap_bus, priv->bus,
- mt7531_pcs_config[i]);
- if (IS_ERR(regmap)) {
- ret = PTR_ERR(regmap);
- break;
- }
- pcs = mtk_pcs_lynxi_create(priv->dev, regmap,
- MT7531_PHYA_CTRL_SIGNAL3, 0);
- if (!pcs) {
- ret = -ENXIO;
- break;
- }
- priv->ports[5 + i].sgmii_pcs = pcs;
- }
-
- if (ret && i)
- mtk_pcs_lynxi_destroy(priv->ports[5].sgmii_pcs);
-
- return ret;
-}
-
static int
mt753x_setup(struct dsa_switch *ds)
{
@@ -3068,7 +2953,7 @@ static int mt753x_set_mac_eee(struct dsa
return 0;
}
-static const struct dsa_switch_ops mt7530_switch_ops = {
+const struct dsa_switch_ops mt7530_switch_ops = {
.get_tag_protocol = mtk_get_tag_protocol,
.setup = mt753x_setup,
.get_strings = mt7530_get_strings,
@@ -3102,8 +2987,9 @@ static const struct dsa_switch_ops mt753
.get_mac_eee = mt753x_get_mac_eee,
.set_mac_eee = mt753x_set_mac_eee,
};
+EXPORT_SYMBOL_GPL(mt7530_switch_ops);
-static const struct mt753x_info mt753x_table[] = {
+const struct mt753x_info mt753x_table[] = {
[ID_MT7621] = {
.id = ID_MT7621,
.pcs_ops = &mt7530_pcs_ops,
@@ -3136,16 +3022,9 @@ static const struct mt753x_info mt753x_t
.mac_port_config = mt7531_mac_config,
},
};
+EXPORT_SYMBOL_GPL(mt753x_table);
-static const struct of_device_id mt7530_of_match[] = {
- { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], },
- { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], },
- { .compatible = "mediatek,mt7531", .data = &mt753x_table[ID_MT7531], },
- { /* sentinel */ },
-};
-MODULE_DEVICE_TABLE(of, mt7530_of_match);
-
-static int
+int
mt7530_probe_common(struct mt7530_priv *priv)
{
struct device *dev = priv->dev;
@@ -3182,88 +3061,9 @@ mt7530_probe_common(struct mt7530_priv *
return 0;
}
+EXPORT_SYMBOL_GPL(mt7530_probe_common);
-static int
-mt7530_probe(struct mdio_device *mdiodev)
-{
- static struct regmap_config *regmap_config;
- struct mt7530_priv *priv;
- struct device_node *dn;
- int ret;
-
- dn = mdiodev->dev.of_node;
-
- priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- priv->bus = mdiodev->bus;
- priv->dev = &mdiodev->dev;
-
- ret = mt7530_probe_common(priv);
- if (ret)
- return ret;
-
- /* Use medatek,mcm property to distinguish hardware type that would
- * cause a little bit differences on power-on sequence.
- * Not MCM that indicates switch works as the remote standalone
- * integrated circuit so the GPIO pin would be used to complete
- * the reset, otherwise memory-mapped register accessing used
- * through syscon provides in the case of MCM.
- */
- priv->mcm = of_property_read_bool(dn, "mediatek,mcm");
- if (priv->mcm) {
- dev_info(&mdiodev->dev, "MT7530 adapts as multi-chip module\n");
-
- priv->rstc = devm_reset_control_get(&mdiodev->dev, "mcm");
- if (IS_ERR(priv->rstc)) {
- dev_err(&mdiodev->dev, "Couldn't get our reset line\n");
- return PTR_ERR(priv->rstc);
- }
- } else {
- priv->reset = devm_gpiod_get_optional(&mdiodev->dev, "reset",
- GPIOD_OUT_LOW);
- if (IS_ERR(priv->reset)) {
- dev_err(&mdiodev->dev, "Couldn't get our reset line\n");
- return PTR_ERR(priv->reset);
- }
- }
-
- if (priv->id == ID_MT7530) {
- priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core");
- if (IS_ERR(priv->core_pwr))
- return PTR_ERR(priv->core_pwr);
-
- priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io");
- if (IS_ERR(priv->io_pwr))
- return PTR_ERR(priv->io_pwr);
- }
-
- regmap_config = devm_kzalloc(&mdiodev->dev, sizeof(*regmap_config),
- GFP_KERNEL);
- if (!regmap_config)
- return -ENOMEM;
-
- regmap_config->reg_bits = 16;
- regmap_config->val_bits = 32;
- regmap_config->reg_stride = 4;
- regmap_config->max_register = MT7530_CREV;
- regmap_config->disable_locking = true;
- priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus,
- priv->bus, regmap_config);
- if (IS_ERR(priv->regmap))
- return PTR_ERR(priv->regmap);
-
- if (priv->id == ID_MT7531) {
- ret = mt7531_create_sgmii(priv);
- if (ret)
- return ret;
- }
-
- return dsa_register_switch(priv->ds);
-}
-
-static void
+void
mt7530_remove_common(struct mt7530_priv *priv)
{
if (priv->irq)
@@ -3274,57 +3074,6 @@ mt7530_remove_common(struct mt7530_priv
mutex_destroy(&priv->reg_mutex);
}
-static void
-mt7530_remove(struct mdio_device *mdiodev)
-{
- struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev);
- int ret = 0, i;
-
- if (!priv)
- return;
-
- ret = regulator_disable(priv->core_pwr);
- if (ret < 0)
- dev_err(priv->dev,
- "Failed to disable core power: %d\n", ret);
-
- ret = regulator_disable(priv->io_pwr);
- if (ret < 0)
- dev_err(priv->dev, "Failed to disable io pwr: %d\n",
- ret);
-
- mt7530_remove_common(priv);
-
- for (i = 0; i < 2; ++i)
- mtk_pcs_lynxi_destroy(priv->ports[5 + i].sgmii_pcs);
-
- dev_set_drvdata(&mdiodev->dev, NULL);
-}
-
-static void mt7530_shutdown(struct mdio_device *mdiodev)
-{
- struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev);
-
- if (!priv)
- return;
-
- dsa_switch_shutdown(priv->ds);
-
- dev_set_drvdata(&mdiodev->dev, NULL);
-}
-
-static struct mdio_driver mt7530_mdio_driver = {
- .probe = mt7530_probe,
- .remove = mt7530_remove,
- .shutdown = mt7530_shutdown,
- .mdiodrv.driver = {
- .name = "mt7530",
- .of_match_table = mt7530_of_match,
- },
-};
-
-mdio_module_driver(mt7530_mdio_driver);
-
MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch");
MODULE_LICENSE("GPL");
--- a/drivers/net/dsa/mt7530.h
+++ b/drivers/net/dsa/mt7530.h
@@ -807,4 +807,10 @@ static inline void INIT_MT7530_DUMMY_POL
p->reg = reg;
}
+int mt7530_probe_common(struct mt7530_priv *priv);
+void mt7530_remove_common(struct mt7530_priv *priv);
+
+extern const struct dsa_switch_ops mt7530_switch_ops;
+extern const struct mt753x_info mt753x_table[];
+
#endif /* __MT7530_H */

View file

@ -0,0 +1,47 @@
From 54d4147a121cec5004a673a58572da346e4458f8 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Mon, 3 Apr 2023 02:19:28 +0100
Subject: [PATCH 15/16] net: dsa: mt7530: skip locking if MDIO bus isn't
present
As MT7530 and MT7531 internally use 32-bit wide registers, each access
to any register of the switch requires several operations on the MDIO
bus. Hence if there is congruent access, e.g. due to PCS or PHY
polling, this can mess up and interfere with another ongoing register
access sequence.
However, the MDIO bus mutex is only relevant for MDIO-connected
switches. Prepare switches which have there registers directly mapped
into the SoCs register space via MMIO which do not require such
locking. There we can simply use regmap's default locking mechanism.
Hence guard mutex operations to only be performed in case of MDIO
connected switches.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
drivers/net/dsa/mt7530.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -144,13 +144,15 @@ err:
static void
mt7530_mutex_lock(struct mt7530_priv *priv)
{
- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
+ if (priv->bus)
+ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED);
}
static void
mt7530_mutex_unlock(struct mt7530_priv *priv)
{
- mutex_unlock(&priv->bus->mdio_lock);
+ if (priv->bus)
+ mutex_unlock(&priv->bus->mdio_lock);
}
static void

View file

@ -0,0 +1,421 @@
From 110c18bfed41421edd677935dd33be5e6507ba92 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Mon, 3 Apr 2023 02:19:40 +0100
Subject: [PATCH 16/16] net: dsa: mt7530: introduce driver for MT7988 built-in
switch
Add driver for the built-in Gigabit Ethernet switch which can be found
in the MediaTek MT7988 SoC.
The switch shares most of its design with MT7530 and MT7531, but has
it's registers mapped into the SoCs register space rather than being
connected externally or internally via MDIO.
Introduce a new platform driver to support that.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
MAINTAINERS | 2 +
drivers/net/dsa/Kconfig | 12 +++
drivers/net/dsa/Makefile | 1 +
drivers/net/dsa/mt7530-mmio.c | 101 +++++++++++++++++++++++++
drivers/net/dsa/mt7530.c | 137 +++++++++++++++++++++++++++++++++-
drivers/net/dsa/mt7530.h | 12 +--
6 files changed, 255 insertions(+), 10 deletions(-)
create mode 100644 drivers/net/dsa/mt7530-mmio.c
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11899,9 +11899,11 @@ MEDIATEK SWITCH DRIVER
M: Sean Wang <sean.wang@mediatek.com>
M: Landen Chao <Landen.Chao@mediatek.com>
M: DENG Qingfang <dqfext@gmail.com>
+M: Daniel Golle <daniel@makrotopia.org>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/dsa/mt7530-mdio.c
+F: drivers/net/dsa/mt7530-mmio.c
F: drivers/net/dsa/mt7530.*
F: net/dsa/tag_mtk.c
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -38,6 +38,7 @@ config NET_DSA_MT7530
select NET_DSA_TAG_MTK
select MEDIATEK_GE_PHY
imply NET_DSA_MT7530_MDIO
+ imply NET_DSA_MT7530_MMIO
help
This enables support for the MediaTek MT7530 and MT7531 Ethernet
switch chips. Multi-chip module MT7530 in MT7621AT, MT7621DAT,
@@ -54,6 +55,17 @@ config NET_DSA_MT7530_MDIO
module MT7530 which can be found in the MT7621AT, MT7621DAT,
MT7621ST and MT7623AI SoCs.
+config NET_DSA_MT7530_MMIO
+ tristate "MediaTek MT7530 MMIO interface driver"
+ depends on NET_DSA_MT7530
+ depends on HAS_IOMEM
+ help
+ This enables support for the built-in Ethernet switch found
+ in the MediaTek MT7988 SoC.
+ The switch is a similar design as MT7531, but the switch registers
+ are directly mapped into the SoCs register space rather than being
+ accessible via MDIO.
+
config NET_DSA_MV88E6060
tristate "Marvell 88E6060 ethernet switch chip support"
select NET_DSA_TAG_TRAILER
--- a/drivers/net/dsa/Makefile
+++ b/drivers/net/dsa/Makefile
@@ -8,6 +8,7 @@ endif
obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o
obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o
obj-$(CONFIG_NET_DSA_MT7530_MDIO) += mt7530-mdio.o
+obj-$(CONFIG_NET_DSA_MT7530_MMIO) += mt7530-mmio.o
obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o
realtek-smi-objs := realtek-smi-core.o rtl8366.o rtl8366rb.o
--- /dev/null
+++ b/drivers/net/dsa/mt7530-mmio.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <net/dsa.h>
+
+#include "mt7530.h"
+
+static const struct of_device_id mt7988_of_match[] = {
+ { .compatible = "mediatek,mt7988-switch", .data = &mt753x_table[ID_MT7988], },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mt7988_of_match);
+
+static int
+mt7988_probe(struct platform_device *pdev)
+{
+ static struct regmap_config *sw_regmap_config;
+ struct mt7530_priv *priv;
+ void __iomem *base_addr;
+ int ret;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->bus = NULL;
+ priv->dev = &pdev->dev;
+
+ ret = mt7530_probe_common(priv);
+ if (ret)
+ return ret;
+
+ priv->rstc = devm_reset_control_get(&pdev->dev, NULL);
+ if (IS_ERR(priv->rstc)) {
+ dev_err(&pdev->dev, "Couldn't get our reset line\n");
+ return PTR_ERR(priv->rstc);
+ }
+
+ base_addr = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base_addr)) {
+ dev_err(&pdev->dev, "cannot request I/O memory space\n");
+ return -ENXIO;
+ }
+
+ sw_regmap_config = devm_kzalloc(&pdev->dev, sizeof(*sw_regmap_config), GFP_KERNEL);
+ if (!sw_regmap_config)
+ return -ENOMEM;
+
+ sw_regmap_config->name = "switch";
+ sw_regmap_config->reg_bits = 16;
+ sw_regmap_config->val_bits = 32;
+ sw_regmap_config->reg_stride = 4;
+ sw_regmap_config->max_register = MT7530_CREV;
+ priv->regmap = devm_regmap_init_mmio(&pdev->dev, base_addr, sw_regmap_config);
+ if (IS_ERR(priv->regmap))
+ return PTR_ERR(priv->regmap);
+
+ return dsa_register_switch(priv->ds);
+}
+
+static int
+mt7988_remove(struct platform_device *pdev)
+{
+ struct mt7530_priv *priv = platform_get_drvdata(pdev);
+
+ if (priv)
+ mt7530_remove_common(priv);
+
+ return 0;
+}
+
+static void mt7988_shutdown(struct platform_device *pdev)
+{
+ struct mt7530_priv *priv = platform_get_drvdata(pdev);
+
+ if (!priv)
+ return;
+
+ dsa_switch_shutdown(priv->ds);
+
+ dev_set_drvdata(&pdev->dev, NULL);
+}
+
+static struct platform_driver mt7988_platform_driver = {
+ .probe = mt7988_probe,
+ .remove = mt7988_remove,
+ .shutdown = mt7988_shutdown,
+ .driver = {
+ .name = "mt7530-mmio",
+ .of_match_table = mt7988_of_match,
+ },
+};
+module_platform_driver(mt7988_platform_driver);
+
+MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
+MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch (MMIO)");
+MODULE_LICENSE("GPL");
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -1984,6 +1984,47 @@ static const struct irq_domain_ops mt753
};
static void
+mt7988_irq_mask(struct irq_data *d)
+{
+ struct mt7530_priv *priv = irq_data_get_irq_chip_data(d);
+
+ priv->irq_enable &= ~BIT(d->hwirq);
+ mt7530_mii_write(priv, MT7530_SYS_INT_EN, priv->irq_enable);
+}
+
+static void
+mt7988_irq_unmask(struct irq_data *d)
+{
+ struct mt7530_priv *priv = irq_data_get_irq_chip_data(d);
+
+ priv->irq_enable |= BIT(d->hwirq);
+ mt7530_mii_write(priv, MT7530_SYS_INT_EN, priv->irq_enable);
+}
+
+static struct irq_chip mt7988_irq_chip = {
+ .name = KBUILD_MODNAME,
+ .irq_mask = mt7988_irq_mask,
+ .irq_unmask = mt7988_irq_unmask,
+};
+
+static int
+mt7988_irq_map(struct irq_domain *domain, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ irq_set_chip_data(irq, domain->host_data);
+ irq_set_chip_and_handler(irq, &mt7988_irq_chip, handle_simple_irq);
+ irq_set_nested_thread(irq, true);
+ irq_set_noprobe(irq);
+
+ return 0;
+}
+
+static const struct irq_domain_ops mt7988_irq_domain_ops = {
+ .map = mt7988_irq_map,
+ .xlate = irq_domain_xlate_onecell,
+};
+
+static void
mt7530_setup_mdio_irq(struct mt7530_priv *priv)
{
struct dsa_switch *ds = priv->ds;
@@ -2017,8 +2058,15 @@ mt7530_setup_irq(struct mt7530_priv *pri
return priv->irq ? : -EINVAL;
}
- priv->irq_domain = irq_domain_add_linear(np, MT7530_NUM_PHYS,
- &mt7530_irq_domain_ops, priv);
+ if (priv->id == ID_MT7988)
+ priv->irq_domain = irq_domain_add_linear(np, MT7530_NUM_PHYS,
+ &mt7988_irq_domain_ops,
+ priv);
+ else
+ priv->irq_domain = irq_domain_add_linear(np, MT7530_NUM_PHYS,
+ &mt7530_irq_domain_ops,
+ priv);
+
if (!priv->irq_domain) {
dev_err(dev, "failed to create IRQ domain\n");
return -ENOMEM;
@@ -2507,6 +2555,25 @@ static void mt7531_mac_port_get_caps(str
}
}
+static void mt7988_mac_port_get_caps(struct dsa_switch *ds, int port,
+ struct phylink_config *config)
+{
+ phy_interface_zero(config->supported_interfaces);
+
+ switch (port) {
+ case 0 ... 4: /* Internal phy */
+ __set_bit(PHY_INTERFACE_MODE_INTERNAL,
+ config->supported_interfaces);
+ break;
+
+ case 6:
+ __set_bit(PHY_INTERFACE_MODE_INTERNAL,
+ config->supported_interfaces);
+ config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+ MAC_10000FD;
+ }
+}
+
static int
mt753x_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state)
{
@@ -2583,6 +2650,17 @@ static bool mt753x_is_mac_port(u32 port)
}
static int
+mt7988_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
+ phy_interface_t interface)
+{
+ if (dsa_is_cpu_port(ds, port) &&
+ interface == PHY_INTERFACE_MODE_INTERNAL)
+ return 0;
+
+ return -EINVAL;
+}
+
+static int
mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
phy_interface_t interface)
{
@@ -2652,7 +2730,8 @@ mt753x_phylink_mac_config(struct dsa_swi
switch (port) {
case 0 ... 4: /* Internal phy */
- if (state->interface != PHY_INTERFACE_MODE_GMII)
+ if (state->interface != PHY_INTERFACE_MODE_GMII &&
+ state->interface != PHY_INTERFACE_MODE_INTERNAL)
goto unsupported;
break;
case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */
@@ -2730,7 +2809,8 @@ static void mt753x_phylink_mac_link_up(s
/* MT753x MAC works in 1G full duplex mode for all up-clocked
* variants.
*/
- if (interface == PHY_INTERFACE_MODE_TRGMII ||
+ if (interface == PHY_INTERFACE_MODE_INTERNAL ||
+ interface == PHY_INTERFACE_MODE_TRGMII ||
(phy_interface_mode_is_8023z(interface))) {
speed = SPEED_1000;
duplex = DUPLEX_FULL;
@@ -2810,6 +2890,21 @@ mt7531_cpu_port_config(struct dsa_switch
return 0;
}
+static int
+mt7988_cpu_port_config(struct dsa_switch *ds, int port)
+{
+ struct mt7530_priv *priv = ds->priv;
+
+ mt7530_write(priv, MT7530_PMCR_P(port),
+ PMCR_CPU_PORT_SETTING(priv->id));
+
+ mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED,
+ PHY_INTERFACE_MODE_INTERNAL, NULL,
+ SPEED_10000, DUPLEX_FULL, true, true);
+
+ return 0;
+}
+
static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port,
struct phylink_config *config)
{
@@ -2955,6 +3050,27 @@ static int mt753x_set_mac_eee(struct dsa
return 0;
}
+static int mt7988_pad_setup(struct dsa_switch *ds, phy_interface_t interface)
+{
+ return 0;
+}
+
+static int mt7988_setup(struct dsa_switch *ds)
+{
+ struct mt7530_priv *priv = ds->priv;
+
+ /* Reset the switch */
+ reset_control_assert(priv->rstc);
+ usleep_range(20, 50);
+ reset_control_deassert(priv->rstc);
+ usleep_range(20, 50);
+
+ /* Reset the switch PHYs */
+ mt7530_write(priv, MT7530_SYS_CTRL, SYS_CTRL_PHY_RST);
+
+ return mt7531_setup_common(ds);
+}
+
const struct dsa_switch_ops mt7530_switch_ops = {
.get_tag_protocol = mtk_get_tag_protocol,
.setup = mt753x_setup,
@@ -3023,6 +3139,17 @@ const struct mt753x_info mt753x_table[]
.mac_port_get_caps = mt7531_mac_port_get_caps,
.mac_port_config = mt7531_mac_config,
},
+ [ID_MT7988] = {
+ .id = ID_MT7988,
+ .pcs_ops = &mt7530_pcs_ops,
+ .sw_setup = mt7988_setup,
+ .phy_read = mt7531_ind_phy_read,
+ .phy_write = mt7531_ind_phy_write,
+ .pad_setup = mt7988_pad_setup,
+ .cpu_port_config = mt7988_cpu_port_config,
+ .mac_port_get_caps = mt7988_mac_port_get_caps,
+ .mac_port_config = mt7988_mac_config,
+ },
};
EXPORT_SYMBOL_GPL(mt753x_table);
--- a/drivers/net/dsa/mt7530.h
+++ b/drivers/net/dsa/mt7530.h
@@ -18,6 +18,7 @@ enum mt753x_id {
ID_MT7530 = 0,
ID_MT7621 = 1,
ID_MT7531 = 2,
+ ID_MT7988 = 3,
};
#define NUM_TRGMII_CTRL 5
@@ -54,11 +55,11 @@ enum mt753x_id {
#define MT7531_MIRROR_PORT_SET(x) (((x) & MIRROR_MASK) << 16)
#define MT7531_CPU_PMAP_MASK GENMASK(7, 0)
-#define MT753X_MIRROR_REG(id) (((id) == ID_MT7531) ? \
+#define MT753X_MIRROR_REG(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
MT7531_CFC : MT7530_MFC)
-#define MT753X_MIRROR_EN(id) (((id) == ID_MT7531) ? \
+#define MT753X_MIRROR_EN(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
MT7531_MIRROR_EN : MIRROR_EN)
-#define MT753X_MIRROR_MASK(id) (((id) == ID_MT7531) ? \
+#define MT753X_MIRROR_MASK(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
MT7531_MIRROR_MASK : MIRROR_MASK)
/* Registers for BPDU and PAE frame control*/
@@ -295,9 +296,8 @@ enum mt7530_vlan_port_acc_frm {
MT7531_FORCE_DPX | \
MT7531_FORCE_RX_FC | \
MT7531_FORCE_TX_FC)
-#define PMCR_FORCE_MODE_ID(id) (((id) == ID_MT7531) ? \
- MT7531_FORCE_MODE : \
- PMCR_FORCE_MODE)
+#define PMCR_FORCE_MODE_ID(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
+ MT7531_FORCE_MODE : PMCR_FORCE_MODE)
#define PMCR_LINK_SETTINGS_MASK (PMCR_TX_EN | PMCR_FORCE_SPEED_1000 | \
PMCR_RX_EN | PMCR_FORCE_SPEED_100 | \
PMCR_TX_FC_EN | PMCR_RX_FC_EN | \

View file

@ -0,0 +1,118 @@
From 91daa4f62ce878b6e1ac5908aceb83550332447f Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Sun, 16 Apr 2023 13:08:14 +0100
Subject: [PATCH] net: dsa: mt7530: fix support for MT7531BE
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
There are two variants of the MT7531 switch IC which got different
features (and pins) regarding port 5:
* MT7531AE: SGMII/1000Base-X/2500Base-X SerDes PCS
* MT7531BE: RGMII
Moving the creation of the SerDes PCS from mt753x_setup to mt7530_probe
with commit 6de285229773 ("net: dsa: mt7530: move SGMII PCS creation
to mt7530_probe function") works fine for MT7531AE which got two
instances of mtk-pcs-lynxi, however, MT7531BE requires mt7531_pll_setup
to setup clocks before the single PCS on port 6 (usually used as CPU
port) starts to work and hence the PCS creation failed on MT7531BE.
Fix this by introducing a pointer to mt7531_create_sgmii function in
struct mt7530_priv and call it again at the end of mt753x_setup like it
was before commit 6de285229773 ("net: dsa: mt7530: move SGMII PCS
creation to mt7530_probe function").
Fixes: 6de285229773 ("net: dsa: mt7530: move SGMII PCS creation to mt7530_probe function")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Acked-by: Arınç ÜNAL <arinc.unal@arinc9.com>
Link: https://lore.kernel.org/r/ZDvlLhhqheobUvOK@makrotopia.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/dsa/mt7530-mdio.c | 16 ++++++++--------
drivers/net/dsa/mt7530.c | 6 ++++++
drivers/net/dsa/mt7530.h | 4 ++--
3 files changed, 16 insertions(+), 10 deletions(-)
--- a/drivers/net/dsa/mt7530-mdio.c
+++ b/drivers/net/dsa/mt7530-mdio.c
@@ -81,14 +81,17 @@ static const struct regmap_bus mt7530_re
};
static int
-mt7531_create_sgmii(struct mt7530_priv *priv)
+mt7531_create_sgmii(struct mt7530_priv *priv, bool dual_sgmii)
{
- struct regmap_config *mt7531_pcs_config[2];
+ struct regmap_config *mt7531_pcs_config[2] = {};
struct phylink_pcs *pcs;
struct regmap *regmap;
int i, ret = 0;
- for (i = 0; i < 2; i++) {
+ /* MT7531AE has two SGMII units for port 5 and port 6
+ * MT7531BE has only one SGMII unit for port 6
+ */
+ for (i = dual_sgmii ? 0 : 1; i < 2; i++) {
mt7531_pcs_config[i] = devm_kzalloc(priv->dev,
sizeof(struct regmap_config),
GFP_KERNEL);
@@ -208,11 +211,8 @@ mt7530_probe(struct mdio_device *mdiodev
if (IS_ERR(priv->regmap))
return PTR_ERR(priv->regmap);
- if (priv->id == ID_MT7531) {
- ret = mt7531_create_sgmii(priv);
- if (ret)
- return ret;
- }
+ if (priv->id == ID_MT7531)
+ priv->create_sgmii = mt7531_create_sgmii;
return dsa_register_switch(priv->ds);
}
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -3017,6 +3017,12 @@ mt753x_setup(struct dsa_switch *ds)
if (ret && priv->irq)
mt7530_free_irq_common(priv);
+ if (priv->create_sgmii) {
+ ret = priv->create_sgmii(priv, mt7531_dual_sgmii_supported(priv));
+ if (ret && priv->irq)
+ mt7530_free_irq(priv);
+ }
+
return ret;
}
--- a/drivers/net/dsa/mt7530.h
+++ b/drivers/net/dsa/mt7530.h
@@ -741,10 +741,10 @@ struct mt753x_info {
* registers
* @p6_interface Holding the current port 6 interface
* @p5_intf_sel: Holding the current port 5 interface select
- *
* @irq: IRQ number of the switch
* @irq_domain: IRQ domain of the switch irq_chip
* @irq_enable: IRQ enable bits, synced to SYS_INT_EN
+ * @create_sgmii: Pointer to function creating SGMII PCS instance(s)
*/
struct mt7530_priv {
struct device *dev;
@@ -763,7 +763,6 @@ struct mt7530_priv {
unsigned int p5_intf_sel;
u8 mirror_rx;
u8 mirror_tx;
-
struct mt7530_port ports[MT7530_NUM_PORTS];
struct mt753x_pcs pcs[MT7530_NUM_PORTS];
/* protect among processes for registers access*/
@@ -771,6 +770,7 @@ struct mt7530_priv {
int irq;
struct irq_domain *irq_domain;
u32 irq_enable;
+ int (*create_sgmii)(struct mt7530_priv *priv, bool dual_sgmii);
};
struct mt7530_hw_vlan_entry {

View file

@ -21,7 +21,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12697,6 +12697,7 @@ F: include/uapi/linux/meye.h
@@ -12700,6 +12700,7 @@ F: include/uapi/linux/meye.h
MOTORCOMM PHY DRIVER
M: Peter Geis <pgwipeout@gmail.com>

View file

@ -19,7 +19,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17962,6 +17962,11 @@ L: netdev@vger.kernel.org
@@ -17965,6 +17965,11 @@ L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/ethernet/dlink/sundance.c

View file

@ -57,7 +57,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12361,6 +12361,14 @@ S: Supported
@@ -12364,6 +12364,14 @@ S: Supported
F: Documentation/devicetree/bindings/mtd/atmel-nand.txt
F: drivers/mtd/nand/raw/atmel/*

View file

@ -1,7 +1,7 @@
From 348fdbada9fb3f0bf1a53651be46319105af187f Mon Sep 17 00:00:00 2001
From 8c20e2eb5f2a0175b774134685e4d7bd93e85ff8 Mon Sep 17 00:00:00 2001
From: Yu Zhao <yuzhao@google.com>
Date: Wed, 21 Dec 2022 21:18:59 -0700
Subject: [PATCH 21/29] mm: multi-gen LRU: rename lru_gen_struct to
Subject: [PATCH 01/19] UPSTREAM: mm: multi-gen LRU: rename lru_gen_struct to
lru_gen_folio
Patch series "mm: multi-gen LRU: memcg LRU", v3.
@ -115,6 +115,10 @@ Cc: Mike Rapoport <rppt@kernel.org>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Suren Baghdasaryan <surenb@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Bug: 274865848
(cherry picked from commit 391655fe08d1f942359a11148aa9aaf3f99d6d6f)
Change-Id: I7df67e0e2435ba28f10eaa57d28d98b61a9210a6
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
include/linux/mm_inline.h | 4 ++--
include/linux/mmzone.h | 6 +++---
@ -122,9 +126,11 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/workingset.c | 4 ++--
4 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h
index e8ed225d8f7ca..f63968bd7de59 100644
--- a/include/linux/mm_inline.h
+++ b/include/linux/mm_inline.h
@@ -178,7 +178,7 @@ static inline void lru_gen_update_size(s
@@ -178,7 +178,7 @@ static inline void lru_gen_update_size(struct lruvec *lruvec, struct folio *foli
int zone = folio_zonenum(folio);
int delta = folio_nr_pages(folio);
enum lru_list lru = type * LRU_INACTIVE_FILE;
@ -133,7 +139,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
VM_WARN_ON_ONCE(old_gen != -1 && old_gen >= MAX_NR_GENS);
VM_WARN_ON_ONCE(new_gen != -1 && new_gen >= MAX_NR_GENS);
@@ -224,7 +224,7 @@ static inline bool lru_gen_add_folio(str
@@ -224,7 +224,7 @@ static inline bool lru_gen_add_folio(struct lruvec *lruvec, struct folio *folio,
int gen = folio_lru_gen(folio);
int type = folio_is_file_lru(folio);
int zone = folio_zonenum(folio);
@ -142,6 +148,8 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
VM_WARN_ON_ONCE_FOLIO(gen != -1, folio);
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 5f74891556f33..bd3e4689f72dc 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -404,7 +404,7 @@ enum {
@ -171,9 +179,11 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
/* to concurrently iterate lru_gen_mm_list */
struct lru_gen_mm_state mm_state;
#endif
diff --git a/mm/vmscan.c b/mm/vmscan.c
index d18296109aa7e..27142caf284c1 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -3190,7 +3190,7 @@ static int get_nr_gens(struct lruvec *lr
@@ -3190,7 +3190,7 @@ static int get_nr_gens(struct lruvec *lruvec, int type)
static bool __maybe_unused seq_is_valid(struct lruvec *lruvec)
{
@ -191,7 +201,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
int hist = lru_hist_from_seq(lrugen->min_seq[type]);
pos->refaulted = lrugen->avg_refaulted[type][tier] +
@@ -3611,7 +3611,7 @@ static void read_ctrl_pos(struct lruvec
@@ -3611,7 +3611,7 @@ static void read_ctrl_pos(struct lruvec *lruvec, int type, int tier, int gain,
static void reset_ctrl_pos(struct lruvec *lruvec, int type, bool carryover)
{
int hist, tier;
@ -200,7 +210,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
bool clear = carryover ? NR_HIST_GENS == 1 : NR_HIST_GENS > 1;
unsigned long seq = carryover ? lrugen->min_seq[type] : lrugen->max_seq + 1;
@@ -3688,7 +3688,7 @@ static int folio_update_gen(struct folio
@@ -3688,7 +3688,7 @@ static int folio_update_gen(struct folio *folio, int gen)
static int folio_inc_gen(struct lruvec *lruvec, struct folio *folio, bool reclaiming)
{
int type = folio_is_file_lru(folio);
@ -209,7 +219,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
int new_gen, old_gen = lru_gen_from_seq(lrugen->min_seq[type]);
unsigned long new_flags, old_flags = READ_ONCE(folio->flags);
@@ -3733,7 +3733,7 @@ static void update_batch_size(struct lru
@@ -3733,7 +3733,7 @@ static void update_batch_size(struct lru_gen_mm_walk *walk, struct folio *folio,
static void reset_batch_size(struct lruvec *lruvec, struct lru_gen_mm_walk *walk)
{
int gen, type, zone;
@ -218,7 +228,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
walk->batched = 0;
@@ -4253,7 +4253,7 @@ static bool inc_min_seq(struct lruvec *l
@@ -4250,7 +4250,7 @@ static bool inc_min_seq(struct lruvec *lruvec, int type, bool can_swap)
{
int zone;
int remaining = MAX_LRU_BATCH;
@ -227,7 +237,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
int new_gen, old_gen = lru_gen_from_seq(lrugen->min_seq[type]);
if (type == LRU_GEN_ANON && !can_swap)
@@ -4289,7 +4289,7 @@ static bool try_to_inc_min_seq(struct lr
@@ -4286,7 +4286,7 @@ static bool try_to_inc_min_seq(struct lruvec *lruvec, bool can_swap)
{
int gen, type, zone;
bool success = false;
@ -236,7 +246,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
DEFINE_MIN_SEQ(lruvec);
VM_WARN_ON_ONCE(!seq_is_valid(lruvec));
@@ -4310,7 +4310,7 @@ next:
@@ -4307,7 +4307,7 @@ static bool try_to_inc_min_seq(struct lruvec *lruvec, bool can_swap)
;
}
@ -245,7 +255,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
if (can_swap) {
min_seq[LRU_GEN_ANON] = min(min_seq[LRU_GEN_ANON], min_seq[LRU_GEN_FILE]);
min_seq[LRU_GEN_FILE] = max(min_seq[LRU_GEN_ANON], lrugen->min_seq[LRU_GEN_FILE]);
@@ -4332,7 +4332,7 @@ static void inc_max_seq(struct lruvec *l
@@ -4329,7 +4329,7 @@ static void inc_max_seq(struct lruvec *lruvec, bool can_swap, bool force_scan)
{
int prev, next;
int type, zone;
@ -254,7 +264,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
spin_lock_irq(&lruvec->lru_lock);
@@ -4390,7 +4390,7 @@ static bool try_to_inc_max_seq(struct lr
@@ -4387,7 +4387,7 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq,
bool success;
struct lru_gen_mm_walk *walk;
struct mm_struct *mm = NULL;
@ -263,7 +273,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
VM_WARN_ON_ONCE(max_seq > READ_ONCE(lrugen->max_seq));
@@ -4455,7 +4455,7 @@ static bool should_run_aging(struct lruv
@@ -4452,7 +4452,7 @@ static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, unsig
unsigned long old = 0;
unsigned long young = 0;
unsigned long total = 0;
@ -272,7 +282,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
struct mem_cgroup *memcg = lruvec_memcg(lruvec);
for (type = !can_swap; type < ANON_AND_FILE; type++) {
@@ -4740,7 +4740,7 @@ static bool sort_folio(struct lruvec *lr
@@ -4737,7 +4737,7 @@ static bool sort_folio(struct lruvec *lruvec, struct folio *folio, int tier_idx)
int delta = folio_nr_pages(folio);
int refs = folio_lru_refs(folio);
int tier = lru_tier_from_refs(refs);
@ -281,7 +291,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
VM_WARN_ON_ONCE_FOLIO(gen >= MAX_NR_GENS, folio);
@@ -4840,7 +4840,7 @@ static int scan_folios(struct lruvec *lr
@@ -4837,7 +4837,7 @@ static int scan_folios(struct lruvec *lruvec, struct scan_control *sc,
int scanned = 0;
int isolated = 0;
int remaining = MAX_LRU_BATCH;
@ -290,7 +300,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
struct mem_cgroup *memcg = lruvec_memcg(lruvec);
VM_WARN_ON_ONCE(!list_empty(list));
@@ -5240,7 +5240,7 @@ done:
@@ -5237,7 +5237,7 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc
static bool __maybe_unused state_is_valid(struct lruvec *lruvec)
{
@ -299,7 +309,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
if (lrugen->enabled) {
enum lru_list lru;
@@ -5522,7 +5522,7 @@ static void lru_gen_seq_show_full(struct
@@ -5519,7 +5519,7 @@ static void lru_gen_seq_show_full(struct seq_file *m, struct lruvec *lruvec,
int i;
int type, tier;
int hist = lru_hist_from_seq(seq);
@ -308,7 +318,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
for (tier = 0; tier < MAX_NR_TIERS; tier++) {
seq_printf(m, " %10d", tier);
@@ -5572,7 +5572,7 @@ static int lru_gen_seq_show(struct seq_f
@@ -5569,7 +5569,7 @@ static int lru_gen_seq_show(struct seq_file *m, void *v)
unsigned long seq;
bool full = !debugfs_real_fops(m->file)->write;
struct lruvec *lruvec = v;
@ -317,7 +327,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
int nid = lruvec_pgdat(lruvec)->node_id;
struct mem_cgroup *memcg = lruvec_memcg(lruvec);
DEFINE_MAX_SEQ(lruvec);
@@ -5826,7 +5826,7 @@ void lru_gen_init_lruvec(struct lruvec *
@@ -5823,7 +5823,7 @@ void lru_gen_init_lruvec(struct lruvec *lruvec)
{
int i;
int gen, type, zone;
@ -326,9 +336,11 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
lrugen->max_seq = MIN_NR_GENS + 1;
lrugen->enabled = lru_gen_enabled();
diff --git a/mm/workingset.c b/mm/workingset.c
index ae7e984b23c6b..688aaa73f64e8 100644
--- a/mm/workingset.c
+++ b/mm/workingset.c
@@ -223,7 +223,7 @@ static void *lru_gen_eviction(struct fol
@@ -223,7 +223,7 @@ static void *lru_gen_eviction(struct folio *folio)
unsigned long token;
unsigned long min_seq;
struct lruvec *lruvec;
@ -337,7 +349,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
int type = folio_is_file_lru(folio);
int delta = folio_nr_pages(folio);
int refs = folio_lru_refs(folio);
@@ -252,7 +252,7 @@ static void lru_gen_refault(struct folio
@@ -252,7 +252,7 @@ static void lru_gen_refault(struct folio *folio, void *shadow)
unsigned long token;
unsigned long min_seq;
struct lruvec *lruvec;
@ -346,3 +358,6 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
struct mem_cgroup *memcg;
struct pglist_data *pgdat;
int type = folio_is_file_lru(folio);
--
2.40.1

View file

@ -1,7 +1,7 @@
From afd37e73db04c7e6b47411120ac5f6a7eca51fec Mon Sep 17 00:00:00 2001
From 656287d55d9cfc72a4bcd4d9bd098570f12ce409 Mon Sep 17 00:00:00 2001
From: Yu Zhao <yuzhao@google.com>
Date: Wed, 21 Dec 2022 21:19:00 -0700
Subject: [PATCH 22/29] mm: multi-gen LRU: rename lrugen->lists[] to
Subject: [PATCH 02/19] UPSTREAM: mm: multi-gen LRU: rename lrugen->lists[] to
lrugen->folios[]
lru_gen_folio will be chained into per-node lists by the coming
@ -17,15 +17,54 @@ Cc: Mike Rapoport <rppt@kernel.org>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Suren Baghdasaryan <surenb@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Bug: 274865848
(cherry picked from commit 6df1b2212950aae2b2188c6645ea18e2a9e3fdd5)
Change-Id: I09f53e0fb2cd6b8b3adbb8a80b15dc5efbeae857
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
include/linux/mm_inline.h | 4 ++--
include/linux/mmzone.h | 8 ++++----
mm/vmscan.c | 20 ++++++++++----------
3 files changed, 16 insertions(+), 16 deletions(-)
Documentation/mm/multigen_lru.rst | 8 ++++----
include/linux/mm_inline.h | 4 ++--
include/linux/mmzone.h | 8 ++++----
mm/vmscan.c | 20 ++++++++++----------
4 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/Documentation/mm/multigen_lru.rst b/Documentation/mm/multigen_lru.rst
index d7062c6a89464..d8f721f98868a 100644
--- a/Documentation/mm/multigen_lru.rst
+++ b/Documentation/mm/multigen_lru.rst
@@ -89,15 +89,15 @@ variables are monotonically increasing.
Generation numbers are truncated into ``order_base_2(MAX_NR_GENS+1)``
bits in order to fit into the gen counter in ``folio->flags``. Each
-truncated generation number is an index to ``lrugen->lists[]``. The
+truncated generation number is an index to ``lrugen->folios[]``. The
sliding window technique is used to track at least ``MIN_NR_GENS`` and
at most ``MAX_NR_GENS`` generations. The gen counter stores a value
within ``[1, MAX_NR_GENS]`` while a page is on one of
-``lrugen->lists[]``; otherwise it stores zero.
+``lrugen->folios[]``; otherwise it stores zero.
Each generation is divided into multiple tiers. A page accessed ``N``
times through file descriptors is in tier ``order_base_2(N)``. Unlike
-generations, tiers do not have dedicated ``lrugen->lists[]``. In
+generations, tiers do not have dedicated ``lrugen->folios[]``. In
contrast to moving across generations, which requires the LRU lock,
moving across tiers only involves atomic operations on
``folio->flags`` and therefore has a negligible cost. A feedback loop
@@ -127,7 +127,7 @@ page mapped by this PTE to ``(max_seq%MAX_NR_GENS)+1``.
Eviction
--------
The eviction consumes old generations. Given an ``lruvec``, it
-increments ``min_seq`` when ``lrugen->lists[]`` indexed by
+increments ``min_seq`` when ``lrugen->folios[]`` indexed by
``min_seq%MAX_NR_GENS`` becomes empty. To select a type and a tier to
evict from, it first compares ``min_seq[]`` to select the older type.
If both types are equally old, it selects the one whose first tier has
diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h
index f63968bd7de59..da38e3d962e2f 100644
--- a/include/linux/mm_inline.h
+++ b/include/linux/mm_inline.h
@@ -256,9 +256,9 @@ static inline bool lru_gen_add_folio(str
@@ -256,9 +256,9 @@ static inline bool lru_gen_add_folio(struct lruvec *lruvec, struct folio *folio,
lru_gen_update_size(lruvec, folio, -1, gen);
/* for folio_rotate_reclaimable() */
if (reclaiming)
@ -37,6 +76,8 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
return true;
}
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index bd3e4689f72dc..02e4323744715 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -312,7 +312,7 @@ enum lruvec_flags {
@ -68,9 +109,11 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
/* the multi-gen LRU sizes, eventually consistent */
long nr_pages[MAX_NR_GENS][ANON_AND_FILE][MAX_NR_ZONES];
/* the exponential moving average of refaulted */
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 27142caf284c1..b02fed912f742 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -4261,7 +4261,7 @@ static bool inc_min_seq(struct lruvec *l
@@ -4258,7 +4258,7 @@ static bool inc_min_seq(struct lruvec *lruvec, int type, bool can_swap)
/* prevent cold/hot inversion if force_scan is true */
for (zone = 0; zone < MAX_NR_ZONES; zone++) {
@ -79,7 +122,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
while (!list_empty(head)) {
struct folio *folio = lru_to_folio(head);
@@ -4272,7 +4272,7 @@ static bool inc_min_seq(struct lruvec *l
@@ -4269,7 +4269,7 @@ static bool inc_min_seq(struct lruvec *lruvec, int type, bool can_swap)
VM_WARN_ON_ONCE_FOLIO(folio_zonenum(folio) != zone, folio);
new_gen = folio_inc_gen(lruvec, folio, false);
@ -88,7 +131,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
if (!--remaining)
return false;
@@ -4300,7 +4300,7 @@ static bool try_to_inc_min_seq(struct lr
@@ -4297,7 +4297,7 @@ static bool try_to_inc_min_seq(struct lruvec *lruvec, bool can_swap)
gen = lru_gen_from_seq(min_seq[type]);
for (zone = 0; zone < MAX_NR_ZONES; zone++) {
@ -97,7 +140,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
goto next;
}
@@ -4765,7 +4765,7 @@ static bool sort_folio(struct lruvec *lr
@@ -4762,7 +4762,7 @@ static bool sort_folio(struct lruvec *lruvec, struct folio *folio, int tier_idx)
/* promoted */
if (gen != lru_gen_from_seq(lrugen->min_seq[type])) {
@ -106,7 +149,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
return true;
}
@@ -4774,7 +4774,7 @@ static bool sort_folio(struct lruvec *lr
@@ -4771,7 +4771,7 @@ static bool sort_folio(struct lruvec *lruvec, struct folio *folio, int tier_idx)
int hist = lru_hist_from_seq(lrugen->min_seq[type]);
gen = folio_inc_gen(lruvec, folio, false);
@ -115,7 +158,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
WRITE_ONCE(lrugen->protected[hist][type][tier - 1],
lrugen->protected[hist][type][tier - 1] + delta);
@@ -4786,7 +4786,7 @@ static bool sort_folio(struct lruvec *lr
@@ -4783,7 +4783,7 @@ static bool sort_folio(struct lruvec *lruvec, struct folio *folio, int tier_idx)
if (folio_test_locked(folio) || folio_test_writeback(folio) ||
(type == LRU_GEN_FILE && folio_test_dirty(folio))) {
gen = folio_inc_gen(lruvec, folio, true);
@ -124,7 +167,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
return true;
}
@@ -4853,7 +4853,7 @@ static int scan_folios(struct lruvec *lr
@@ -4850,7 +4850,7 @@ static int scan_folios(struct lruvec *lruvec, struct scan_control *sc,
for (zone = sc->reclaim_idx; zone >= 0; zone--) {
LIST_HEAD(moved);
int skipped = 0;
@ -133,7 +176,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
while (!list_empty(head)) {
struct folio *folio = lru_to_folio(head);
@@ -5253,7 +5253,7 @@ static bool __maybe_unused state_is_vali
@@ -5250,7 +5250,7 @@ static bool __maybe_unused state_is_valid(struct lruvec *lruvec)
int gen, type, zone;
for_each_gen_type_zone(gen, type, zone) {
@ -142,7 +185,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
return false;
}
}
@@ -5298,7 +5298,7 @@ static bool drain_evictable(struct lruve
@@ -5295,7 +5295,7 @@ static bool drain_evictable(struct lruvec *lruvec)
int remaining = MAX_LRU_BATCH;
for_each_gen_type_zone(gen, type, zone) {
@ -151,7 +194,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
while (!list_empty(head)) {
bool success;
@@ -5835,7 +5835,7 @@ void lru_gen_init_lruvec(struct lruvec *
@@ -5832,7 +5832,7 @@ void lru_gen_init_lruvec(struct lruvec *lruvec)
lrugen->timestamps[i] = jiffies;
for_each_gen_type_zone(gen, type, zone)
@ -160,3 +203,6 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
lruvec->mm_state.seq = MIN_NR_GENS;
init_waitqueue_head(&lruvec->mm_state.wait);
--
2.40.1

View file

@ -1,7 +1,8 @@
From ce45f1c4b32cf69b166f56ef5bc6c761e06ed4e5 Mon Sep 17 00:00:00 2001
From 14f9a7a15f3d1af351f30e0438fd747b7ac253b0 Mon Sep 17 00:00:00 2001
From: Yu Zhao <yuzhao@google.com>
Date: Wed, 21 Dec 2022 21:19:01 -0700
Subject: [PATCH 23/29] mm: multi-gen LRU: remove eviction fairness safeguard
Subject: [PATCH 03/19] UPSTREAM: mm: multi-gen LRU: remove eviction fairness
safeguard
Recall that the eviction consumes the oldest generation: first it
bucket-sorts folios whose gen counters were updated by the aging and
@ -31,13 +32,19 @@ Cc: Mike Rapoport <rppt@kernel.org>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Suren Baghdasaryan <surenb@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Bug: 274865848
(cherry picked from commit a579086c99ed70cc4bfc104348dbe3dd8f2787e6)
Change-Id: I08ac1b3c90e29cafd0566785aaa4bcdb5db7d22c
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
mm/vmscan.c | 82 +++++++++++++++--------------------------------------
1 file changed, 23 insertions(+), 59 deletions(-)
mm/vmscan.c | 81 +++++++++++++++--------------------------------------
1 file changed, 23 insertions(+), 58 deletions(-)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index b02fed912f742..991961180b320 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -448,6 +448,11 @@ static bool cgroup_reclaim(struct scan_c
@@ -448,6 +448,11 @@ static bool cgroup_reclaim(struct scan_control *sc)
return sc->target_mem_cgroup;
}
@ -49,7 +56,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
/**
* writeback_throttling_sane - is the usual dirty throttling mechanism available?
* @sc: scan_control in question
@@ -498,6 +503,11 @@ static bool cgroup_reclaim(struct scan_c
@@ -498,6 +503,11 @@ static bool cgroup_reclaim(struct scan_control *sc)
return false;
}
@ -61,7 +68,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
static bool writeback_throttling_sane(struct scan_control *sc)
{
return true;
@@ -4996,8 +5006,7 @@ static int isolate_folios(struct lruvec
@@ -4993,8 +5003,7 @@ static int isolate_folios(struct lruvec *lruvec, struct scan_control *sc, int sw
return scanned;
}
@ -71,7 +78,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
{
int type;
int scanned;
@@ -5086,9 +5095,6 @@ retry:
@@ -5083,9 +5092,6 @@ static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, int swap
goto retry;
}
@ -81,7 +88,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
return scanned;
}
@@ -5127,67 +5133,26 @@ done:
@@ -5124,67 +5130,26 @@ static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *
return min_seq[!can_swap] + MIN_NR_GENS <= max_seq ? nr_to_scan : 0;
}
@ -158,7 +165,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
lru_add_drain();
@@ -5211,7 +5176,7 @@ static void lru_gen_shrink_lruvec(struct
@@ -5208,7 +5173,7 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc
if (!nr_to_scan)
goto done;
@ -167,7 +174,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
if (!delta)
goto done;
@@ -5219,7 +5184,7 @@ static void lru_gen_shrink_lruvec(struct
@@ -5216,7 +5181,7 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc
if (scanned >= nr_to_scan)
break;
@ -176,7 +183,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
break;
cond_resched();
@@ -5669,7 +5634,7 @@ static int run_eviction(struct lruvec *l
@@ -5666,7 +5631,7 @@ static int run_eviction(struct lruvec *lruvec, unsigned long seq, struct scan_co
if (sc->nr_reclaimed >= nr_to_reclaim)
return 0;
@ -185,3 +192,6 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
return 0;
cond_resched();
--
2.40.1

View file

@ -1,7 +1,8 @@
From e20b7386fccc18c791796eb1dc1a91eee3ccf801 Mon Sep 17 00:00:00 2001
From f3c93d2e37a3c56593d7ccf4f4bcf1b58426fdd8 Mon Sep 17 00:00:00 2001
From: Yu Zhao <yuzhao@google.com>
Date: Wed, 21 Dec 2022 21:19:02 -0700
Subject: [PATCH 24/29] mm: multi-gen LRU: remove aging fairness safeguard
Subject: [PATCH 04/19] BACKPORT: mm: multi-gen LRU: remove aging fairness
safeguard
Recall that the aging produces the youngest generation: first it scans
for accessed folios and updates their gen counters; then it increments
@ -31,10 +32,18 @@ Cc: Mike Rapoport <rppt@kernel.org>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Suren Baghdasaryan <surenb@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Bug: 274865848
(cherry picked from commit 7348cc91821b0cb24dfb00e578047f68299a50ab)
[TJ: Resolved conflicts with older function signatures for
min_cgroup_below_min / min_cgroup_below_low]
Change-Id: I6e36ecfbaaefbc0a56d9a9d5d7cbe404ed7f57a5
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
mm/vmscan.c | 126 ++++++++++++++++++++++++----------------------------
1 file changed, 59 insertions(+), 67 deletions(-)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 991961180b320..5a2e83e673232 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -136,7 +136,6 @@ struct scan_control {
@ -45,7 +54,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
unsigned long last_reclaimed;
#endif
@@ -4458,7 +4457,7 @@ done:
@@ -4455,7 +4454,7 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq,
return true;
}
@ -54,7 +63,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
struct scan_control *sc, bool can_swap, unsigned long *nr_to_scan)
{
int gen, type, zone;
@@ -4467,6 +4466,13 @@ static bool should_run_aging(struct lruv
@@ -4464,6 +4463,13 @@ static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, unsig
unsigned long total = 0;
struct lru_gen_folio *lrugen = &lruvec->lrugen;
struct mem_cgroup *memcg = lruvec_memcg(lruvec);
@ -68,7 +77,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
for (type = !can_swap; type < ANON_AND_FILE; type++) {
unsigned long seq;
@@ -4495,8 +4501,6 @@ static bool should_run_aging(struct lruv
@@ -4492,8 +4498,6 @@ static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, unsig
* stalls when the number of generations reaches MIN_NR_GENS. Hence, the
* ideal number of generations is MIN_NR_GENS+1.
*/
@ -77,7 +86,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
if (min_seq[!can_swap] + MIN_NR_GENS < max_seq)
return false;
@@ -4515,40 +4519,54 @@ static bool should_run_aging(struct lruv
@@ -4512,40 +4516,54 @@ static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, unsig
return false;
}
@ -153,7 +162,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
}
/* to protect the working set of the last N jiffies */
@@ -4557,46 +4575,32 @@ static unsigned long lru_gen_min_ttl __r
@@ -4554,46 +4572,32 @@ static unsigned long lru_gen_min_ttl __read_mostly;
static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc)
{
struct mem_cgroup *memcg;
@ -207,7 +216,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
*/
if (mutex_trylock(&oom_lock)) {
struct oom_control oc = {
@@ -5104,33 +5108,27 @@ retry:
@@ -5101,33 +5105,27 @@ static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, int swap
* reclaim.
*/
static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc,
@ -247,7 +256,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
}
static unsigned long get_nr_to_reclaim(struct scan_control *sc)
@@ -5149,9 +5147,7 @@ static unsigned long get_nr_to_reclaim(s
@@ -5146,9 +5144,7 @@ static unsigned long get_nr_to_reclaim(struct scan_control *sc)
static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)
{
struct blk_plug plug;
@ -257,7 +266,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
unsigned long nr_to_reclaim = get_nr_to_reclaim(sc);
lru_add_drain();
@@ -5172,13 +5168,13 @@ static void lru_gen_shrink_lruvec(struct
@@ -5169,13 +5165,13 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc
else
swappiness = 0;
@ -274,7 +283,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
scanned += delta;
if (scanned >= nr_to_scan)
@@ -5190,10 +5186,6 @@ static void lru_gen_shrink_lruvec(struct
@@ -5187,10 +5183,6 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc
cond_resched();
}
@ -285,3 +294,6 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
clear_mm_walk();
blk_finish_plug(&plug);
--
2.40.1

View file

@ -1,12 +1,11 @@
From 107d54931df3c28d81648122e219bf0034ef4e99 Mon Sep 17 00:00:00 2001
From eca3858631e0cbad2ca6e40f788892749428e4cb Mon Sep 17 00:00:00 2001
From: Yu Zhao <yuzhao@google.com>
Date: Wed, 21 Dec 2022 21:19:03 -0700
Subject: [PATCH 25/29] mm: multi-gen LRU: shuffle should_run_aging()
Subject: [PATCH 05/19] UPSTREAM: mm: multi-gen LRU: shuffle should_run_aging()
Move should_run_aging() next to its only caller left.
Link: https://lkml.kernel.org/r/20221222041905.2431096-6-yuzhao@google.com
Signed-off-by: Yu Zhao <yuzhao@google.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Michael Larabel <Michael@MichaelLarabel.com>
@ -15,13 +14,21 @@ Cc: Mike Rapoport <rppt@kernel.org>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Suren Baghdasaryan <surenb@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Bug: 274865848
(cherry picked from commit 77d4459a4a1a472b7309e475f962dda87d950abd)
Signed-off-by: T.J. Mercier <tjmercier@google.com>
Change-Id: I3b0383fe16b93a783b4d8c0b3a0b325160392576
Signed-off-by: Yu Zhao <yuzhao@google.com>
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
mm/vmscan.c | 124 ++++++++++++++++++++++++++--------------------------
1 file changed, 62 insertions(+), 62 deletions(-)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 5a2e83e673232..0c47952714b26 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -4457,68 +4457,6 @@ done:
@@ -4454,68 +4454,6 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq,
return true;
}
@ -90,7 +97,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
static bool lruvec_is_sizable(struct lruvec *lruvec, struct scan_control *sc)
{
int gen, type, zone;
@@ -5102,6 +5040,68 @@ retry:
@@ -5099,6 +5037,68 @@ static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, int swap
return scanned;
}
@ -159,3 +166,6 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
/*
* For future optimizations:
* 1. Defer try_to_inc_max_seq() to workqueues to reduce latency for memcg
--
2.40.1

View file

@ -1,7 +1,8 @@
From fa6363828d314e837c5f79e97ea5e8c0d2f7f062 Mon Sep 17 00:00:00 2001
From 8ee8571e47aa75221e5fbd4c9c7802fc4244c346 Mon Sep 17 00:00:00 2001
From: Yu Zhao <yuzhao@google.com>
Date: Wed, 21 Dec 2022 21:19:04 -0700
Subject: [PATCH 26/29] mm: multi-gen LRU: per-node lru_gen_folio lists
Subject: [PATCH 06/19] BACKPORT: mm: multi-gen LRU: per-node lru_gen_folio
lists
For each node, memcgs are divided into two generations: the old and
the young. For each generation, memcgs are randomly sharded into
@ -58,18 +59,26 @@ Cc: Mike Rapoport <rppt@kernel.org>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Suren Baghdasaryan <surenb@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Bug: 274865848
(cherry picked from commit e4dde56cd208674ce899b47589f263499e5b8cdc)
[TJ: Resolved conflicts with older function signatures for
min_cgroup_below_min / min_cgroup_below_low and includes]
Change-Id: Idc8a0f635e035d72dd911f807d1224cb47cbd655
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
include/linux/memcontrol.h | 10 +
include/linux/mm_inline.h | 17 ++
include/linux/mmzone.h | 117 +++++++++++-
mm/memcontrol.c | 16 ++
mm/folio_alloc.c | 1 +
mm/vmscan.c | 373 +++++++++++++++++++++++++++++++++----
6 files changed, 499 insertions(+), 35 deletions(-)
mm/page_alloc.c | 1 +
mm/vmscan.c | 374 +++++++++++++++++++++++++++++++++----
6 files changed, 500 insertions(+), 35 deletions(-)
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index e039763029563..82d28b052a9e5 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -790,6 +790,11 @@ static inline void obj_cgroup_put(struct
@@ -790,6 +790,11 @@ static inline void obj_cgroup_put(struct obj_cgroup *objcg)
percpu_ref_put(&objcg->refcnt);
}
@ -81,7 +90,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
static inline void mem_cgroup_put(struct mem_cgroup *memcg)
{
if (memcg)
@@ -1290,6 +1295,11 @@ static inline void obj_cgroup_put(struct
@@ -1290,6 +1295,11 @@ static inline void obj_cgroup_put(struct obj_cgroup *objcg)
{
}
@ -93,9 +102,11 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
static inline void mem_cgroup_put(struct mem_cgroup *memcg)
{
}
diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h
index da38e3d962e2f..c1fd3922dc5dd 100644
--- a/include/linux/mm_inline.h
+++ b/include/linux/mm_inline.h
@@ -122,6 +122,18 @@ static inline bool lru_gen_in_fault(void
@@ -122,6 +122,18 @@ static inline bool lru_gen_in_fault(void)
return current->in_lru_fault;
}
@ -114,7 +125,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
static inline int lru_gen_from_seq(unsigned long seq)
{
return seq % MAX_NR_GENS;
@@ -297,6 +309,11 @@ static inline bool lru_gen_in_fault(void
@@ -297,6 +309,11 @@ static inline bool lru_gen_in_fault(void)
return false;
}
@ -126,6 +137,8 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
static inline bool lru_gen_add_folio(struct lruvec *lruvec, struct folio *folio, bool reclaiming)
{
return false;
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 02e4323744715..66e067a635682 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -7,6 +7,7 @@
@ -167,7 +180,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
};
enum {
@@ -479,12 +497,87 @@ void lru_gen_init_lruvec(struct lruvec *
@@ -479,12 +497,87 @@ void lru_gen_init_lruvec(struct lruvec *lruvec);
void lru_gen_look_around(struct page_vma_mapped_walk *pvmw);
#ifdef CONFIG_MEMCG
@ -256,7 +269,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
static inline void lru_gen_init_lruvec(struct lruvec *lruvec)
{
}
@@ -494,6 +587,7 @@ static inline void lru_gen_look_around(s
@@ -494,6 +587,7 @@ static inline void lru_gen_look_around(struct page_vma_mapped_walk *pvmw)
}
#ifdef CONFIG_MEMCG
@ -264,7 +277,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
static inline void lru_gen_init_memcg(struct mem_cgroup *memcg)
{
}
@@ -501,7 +595,24 @@ static inline void lru_gen_init_memcg(st
@@ -501,7 +595,24 @@ static inline void lru_gen_init_memcg(struct mem_cgroup *memcg)
static inline void lru_gen_exit_memcg(struct mem_cgroup *memcg)
{
}
@ -299,9 +312,11 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
#endif
CACHELINE_PADDING(_pad2_);
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 3e8f1ad0fe9db..7815d556e38cc 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -477,6 +477,16 @@ static void mem_cgroup_update_tree(struc
@@ -477,6 +477,16 @@ static void mem_cgroup_update_tree(struct mem_cgroup *memcg, int nid)
struct mem_cgroup_per_node *mz;
struct mem_cgroup_tree_per_node *mctz;
@ -318,7 +333,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mctz = soft_limit_tree.rb_tree_per_node[nid];
if (!mctz)
return;
@@ -3522,6 +3532,9 @@ unsigned long mem_cgroup_soft_limit_recl
@@ -3522,6 +3532,9 @@ unsigned long mem_cgroup_soft_limit_reclaim(pg_data_t *pgdat, int order,
struct mem_cgroup_tree_per_node *mctz;
unsigned long excess;
@ -328,7 +343,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
if (order > 0)
return 0;
@@ -5382,6 +5395,7 @@ static int mem_cgroup_css_online(struct
@@ -5382,6 +5395,7 @@ static int mem_cgroup_css_online(struct cgroup_subsys_state *css)
if (unlikely(mem_cgroup_is_root(memcg)))
queue_delayed_work(system_unbound_wq, &stats_flush_dwork,
2UL*HZ);
@ -336,7 +351,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
return 0;
offline_kmem:
memcg_offline_kmem(memcg);
@@ -5413,6 +5427,7 @@ static void mem_cgroup_css_offline(struc
@@ -5413,6 +5427,7 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
memcg_offline_kmem(memcg);
reparent_shrinker_deferred(memcg);
wb_memcg_offline(memcg);
@ -344,7 +359,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
drain_all_stock(memcg);
@@ -5424,6 +5439,7 @@ static void mem_cgroup_css_released(stru
@@ -5424,6 +5439,7 @@ static void mem_cgroup_css_released(struct cgroup_subsys_state *css)
struct mem_cgroup *memcg = mem_cgroup_from_css(css);
invalidate_reclaim_iterators(memcg);
@ -352,9 +367,11 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
}
static void mem_cgroup_css_free(struct cgroup_subsys_state *css)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 69668817fed37..473057b81a9df 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -7957,6 +7957,7 @@ static void __init free_area_init_node(i
@@ -7957,6 +7957,7 @@ static void __init free_area_init_node(int nid)
pgdat_set_deferred_range(pgdat);
free_area_init_core(pgdat);
@ -362,6 +379,8 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
}
static void __init free_area_init_memoryless_node(int nid)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 0c47952714b26..65eb28448f216 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -54,6 +54,8 @@
@ -385,7 +404,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
/* Allocation order */
s8 order;
@@ -3160,6 +3157,9 @@ DEFINE_STATIC_KEY_ARRAY_FALSE(lru_gen_ca
@@ -3160,6 +3157,9 @@ DEFINE_STATIC_KEY_ARRAY_FALSE(lru_gen_caps, NR_LRU_GEN_CAPS);
for ((type) = 0; (type) < ANON_AND_FILE; (type)++) \
for ((zone) = 0; (zone) < MAX_NR_ZONES; (zone)++)
@ -395,7 +414,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
static struct lruvec *get_lruvec(struct mem_cgroup *memcg, int nid)
{
struct pglist_data *pgdat = NODE_DATA(nid);
@@ -4443,8 +4443,7 @@ done:
@@ -4440,8 +4440,7 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq,
if (sc->priority <= DEF_PRIORITY - 2)
wait_event_killable(lruvec->mm_state.wait,
max_seq < READ_ONCE(lrugen->max_seq));
@ -405,7 +424,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
}
VM_WARN_ON_ONCE(max_seq != READ_ONCE(lrugen->max_seq));
@@ -4517,8 +4516,6 @@ static void lru_gen_age_node(struct pgli
@@ -4514,8 +4513,6 @@ static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc)
VM_WARN_ON_ONCE(!current_is_kswapd());
@ -414,7 +433,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
/* check the order to exclude compaction-induced reclaim */
if (!min_ttl || sc->order || sc->priority == DEF_PRIORITY)
return;
@@ -5107,8 +5104,7 @@ static bool should_run_aging(struct lruv
@@ -5104,8 +5101,7 @@ static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq,
* 1. Defer try_to_inc_max_seq() to workqueues to reduce latency for memcg
* reclaim.
*/
@ -424,7 +443,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
{
unsigned long nr_to_scan;
struct mem_cgroup *memcg = lruvec_memcg(lruvec);
@@ -5125,10 +5121,8 @@ static unsigned long get_nr_to_scan(stru
@@ -5122,10 +5118,8 @@ static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *
if (sc->priority == DEF_PRIORITY)
return nr_to_scan;
@ -436,7 +455,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
}
static unsigned long get_nr_to_reclaim(struct scan_control *sc)
@@ -5137,29 +5131,18 @@ static unsigned long get_nr_to_reclaim(s
@@ -5134,29 +5128,18 @@ static unsigned long get_nr_to_reclaim(struct scan_control *sc)
if (!global_reclaim(sc))
return -1;
@ -468,7 +487,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
if (sc->may_swap)
swappiness = get_swappiness(lruvec, sc);
@@ -5169,7 +5152,7 @@ static void lru_gen_shrink_lruvec(struct
@@ -5166,7 +5149,7 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc
swappiness = 0;
nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness);
@ -477,7 +496,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
break;
delta = evict_folios(lruvec, sc, swappiness);
@@ -5186,10 +5169,250 @@ static void lru_gen_shrink_lruvec(struct
@@ -5183,11 +5166,252 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc
cond_resched();
}
@ -515,8 +534,9 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+
+ shrink_slab(sc->gfp_mask, pgdat->node_id, memcg, sc->priority);
+
+ vmpressure(sc->gfp_mask, memcg, false, sc->nr_scanned - scanned,
+ sc->nr_reclaimed - reclaimed);
+ if (!sc->proactive)
+ vmpressure(sc->gfp_mask, memcg, false, sc->nr_scanned - scanned,
+ sc->nr_reclaimed - reclaimed);
+
+ sc->nr_reclaimed += current->reclaim_state->reclaimed_slab;
+ current->reclaim_state->reclaimed_slab = 0;
@ -538,7 +558,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+ struct mem_cgroup *memcg = NULL;
+ unsigned long nr_to_reclaim = get_nr_to_reclaim(sc);
+
+ bin = first_bin = prandom_u32_max(MEMCG_NR_BINS);
+ bin = first_bin = get_random_u32_below(MEMCG_NR_BINS);
+restart:
+ gen = get_memcg_gen(READ_ONCE(pgdat->memcg_lru.seq));
+
@ -601,11 +621,11 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+ if (try_to_shrink_lruvec(lruvec, sc))
+ lru_gen_rotate_memcg(lruvec, MEMCG_LRU_YOUNG);
+
+ clear_mm_walk();
+
+ blk_finish_plug(&plug);
+}
+
clear_mm_walk();
blk_finish_plug(&plug);
}
+#else /* !CONFIG_MEMCG */
+
+static void shrink_many(struct pglist_data *pgdat, struct scan_control *sc)
@ -671,9 +691,9 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+ if (current_is_kswapd())
+ sc->nr_reclaimed += reclaimed;
+
clear_mm_walk();
blk_finish_plug(&plug);
+ clear_mm_walk();
+
+ blk_finish_plug(&plug);
+
+ /* kswapd should never fail */
+ pgdat->kswapd_failures = 0;
@ -684,7 +704,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+{
+ int seg;
+ int old, new;
+ int bin = prandom_u32_max(MEMCG_NR_BINS);
+ int bin = get_random_u32_below(MEMCG_NR_BINS);
+ struct pglist_data *pgdat = lruvec_pgdat(lruvec);
+
+ spin_lock(&pgdat->memcg_lru.lock);
@ -723,12 +743,13 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+ WRITE_ONCE(pgdat->memcg_lru.seq, pgdat->memcg_lru.seq + 1);
+
+ spin_unlock(&pgdat->memcg_lru.lock);
}
+}
+#endif
+
/******************************************************************************
* state change
@@ -5647,11 +5870,11 @@ static int run_cmd(char cmd, int memcg_i
******************************************************************************/
@@ -5644,11 +5868,11 @@ static int run_cmd(char cmd, int memcg_id, int nid, unsigned long seq,
if (!mem_cgroup_disabled()) {
rcu_read_lock();
@ -743,7 +764,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
rcu_read_unlock();
if (!memcg)
@@ -5799,6 +6022,19 @@ void lru_gen_init_lruvec(struct lruvec *
@@ -5796,6 +6020,19 @@ void lru_gen_init_lruvec(struct lruvec *lruvec)
}
#ifdef CONFIG_MEMCG
@ -763,7 +784,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
void lru_gen_init_memcg(struct mem_cgroup *memcg)
{
INIT_LIST_HEAD(&memcg->mm_list.fifo);
@@ -5822,7 +6058,69 @@ void lru_gen_exit_memcg(struct mem_cgrou
@@ -5819,7 +6056,69 @@ void lru_gen_exit_memcg(struct mem_cgroup *memcg)
}
}
}
@ -773,7 +794,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+{
+ int gen;
+ int nid;
+ int bin = prandom_u32_max(MEMCG_NR_BINS);
+ int bin = get_random_u32_below(MEMCG_NR_BINS);
+
+ for_each_node(nid) {
+ struct pglist_data *pgdat = NODE_DATA(nid);
@ -834,7 +855,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
static int __init init_lru_gen(void)
{
@@ -5849,6 +6147,10 @@ static void lru_gen_shrink_lruvec(struct
@@ -5846,6 +6145,10 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc
{
}
@ -845,7 +866,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
#endif /* CONFIG_LRU_GEN */
static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)
@@ -5862,7 +6164,7 @@ static void shrink_lruvec(struct lruvec
@@ -5859,7 +6162,7 @@ static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)
bool proportional_reclaim;
struct blk_plug plug;
@ -854,7 +875,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
lru_gen_shrink_lruvec(lruvec, sc);
return;
}
@@ -6105,6 +6407,11 @@ static void shrink_node(pg_data_t *pgdat
@@ -6102,6 +6405,11 @@ static void shrink_node(pg_data_t *pgdat, struct scan_control *sc)
struct lruvec *target_lruvec;
bool reclaimable = false;
@ -866,3 +887,6 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
target_lruvec = mem_cgroup_lruvec(sc->target_mem_cgroup, pgdat);
again:
--
2.40.1

View file

@ -1,7 +1,7 @@
From 93147736b5b3a21bea24313bfc7a696829932009 Mon Sep 17 00:00:00 2001
From 11b14ee8cbbbebd8204609076a9327a1171cd253 Mon Sep 17 00:00:00 2001
From: Yu Zhao <yuzhao@google.com>
Date: Wed, 21 Dec 2022 21:19:05 -0700
Subject: [PATCH 27/29] mm: multi-gen LRU: clarify scan_control flags
Subject: [PATCH 07/19] BACKPORT: mm: multi-gen LRU: clarify scan_control flags
Among the flags in scan_control:
1. sc->may_swap, which indicates swap constraint due to memsw.max, is
@ -12,7 +12,7 @@ Among the flags in scan_control:
3. !(sc->gfp_mask & __GFP_IO), which indicates IO constraint, lowers
swappiness to prioritize file LRU, since clean file folios are more
likely to exist.
4. sc->may_writefolio and sc->may_unmap, which indicates opportunistic
4. sc->may_writepage and sc->may_unmap, which indicates opportunistic
reclaim, are rejected, since unmapped clean folios are already
prioritized. Scanning for more of them is likely futile and can
cause high reclaim latency when there is a large number of memcgs.
@ -29,13 +29,21 @@ Cc: Mike Rapoport <rppt@kernel.org>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Suren Baghdasaryan <surenb@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Bug: 274865848
(cherry picked from commit e9d4e1ee788097484606c32122f146d802a9c5fb)
[TJ: Resolved conflict with older function signature for min_cgroup_below_min, and over
cdded861182142ac4488a4d64c571107aeb77f53 ("ANDROID: MGLRU: Don't skip anon reclaim if swap low")]
Change-Id: Ic2e779eaf4e91a3921831b4e2fa10c740dc59d50
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
mm/vmscan.c | 55 +++++++++++++++++++++++++++--------------------------
1 file changed, 28 insertions(+), 27 deletions(-)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 65eb28448f216..0a0e1250ffc87 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -3185,6 +3185,9 @@ static int get_swappiness(struct lruvec
@@ -3185,6 +3185,9 @@ static int get_swappiness(struct lruvec *lruvec, struct scan_control *sc)
struct mem_cgroup *memcg = lruvec_memcg(lruvec);
struct pglist_data *pgdat = lruvec_pgdat(lruvec);
@ -45,7 +53,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
if (!can_demote(pgdat->node_id, sc) &&
mem_cgroup_get_nr_swap_pages(memcg) < MIN_LRU_BATCH)
return 0;
@@ -4226,7 +4229,7 @@ static void walk_mm(struct lruvec *lruve
@@ -4223,7 +4226,7 @@ static void walk_mm(struct lruvec *lruvec, struct mm_struct *mm, struct lru_gen_
} while (err == -EAGAIN);
}
@ -54,7 +62,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
{
struct lru_gen_mm_walk *walk = current->reclaim_state->mm_walk;
@@ -4234,7 +4237,7 @@ static struct lru_gen_mm_walk *set_mm_wa
@@ -4231,7 +4234,7 @@ static struct lru_gen_mm_walk *set_mm_walk(struct pglist_data *pgdat)
VM_WARN_ON_ONCE(walk);
walk = &pgdat->mm_walk;
@ -63,7 +71,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
VM_WARN_ON_ONCE(current_is_kswapd());
walk = kzalloc(sizeof(*walk), __GFP_HIGH | __GFP_NOMEMALLOC | __GFP_NOWARN);
@@ -4420,7 +4423,7 @@ static bool try_to_inc_max_seq(struct lr
@@ -4417,7 +4420,7 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq,
goto done;
}
@ -72,7 +80,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
if (!walk) {
success = iterate_mm_list_nowalk(lruvec, max_seq);
goto done;
@@ -4489,8 +4492,6 @@ static bool lruvec_is_reclaimable(struct
@@ -4486,8 +4489,6 @@ static bool lruvec_is_reclaimable(struct lruvec *lruvec, struct scan_control *sc
struct mem_cgroup *memcg = lruvec_memcg(lruvec);
DEFINE_MIN_SEQ(lruvec);
@ -81,7 +89,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
/* see the comment on lru_gen_folio */
gen = lru_gen_from_seq(min_seq[LRU_GEN_FILE]);
birth = READ_ONCE(lruvec->lrugen.timestamps[gen]);
@@ -4746,12 +4747,8 @@ static bool isolate_folio(struct lruvec
@@ -4743,12 +4744,8 @@ static bool isolate_folio(struct lruvec *lruvec, struct folio *folio, struct sca
{
bool success;
@ -95,19 +103,19 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
(folio_test_dirty(folio) ||
(folio_test_anon(folio) && !folio_test_swapcache(folio))))
return false;
@@ -4848,9 +4845,8 @@ static int scan_folios(struct lruvec *lr
@@ -4845,9 +4842,8 @@ static int scan_folios(struct lruvec *lruvec, struct scan_control *sc,
__count_vm_events(PGSCAN_ANON + type, isolated);
/*
- * There might not be eligible pages due to reclaim_idx, may_unmap and
- * may_writepage. Check the remaining to prevent livelock if it's not
- * making progress.
+ * There might not be eligible pages due to reclaim_idx. Check the
+ * There might not be eligible folios due to reclaim_idx. Check the
+ * remaining to prevent livelock if it's not making progress.
*/
return isolated || !remaining ? scanned : 0;
}
@@ -5110,8 +5106,7 @@ static long get_nr_to_scan(struct lruvec
@@ -5107,8 +5103,7 @@ static long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, bool
struct mem_cgroup *memcg = lruvec_memcg(lruvec);
DEFINE_MAX_SEQ(lruvec);
@ -117,7 +125,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
return 0;
if (!should_run_aging(lruvec, max_seq, sc, can_swap, &nr_to_scan))
@@ -5139,17 +5134,14 @@ static bool try_to_shrink_lruvec(struct
@@ -5136,17 +5131,14 @@ static bool try_to_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)
long nr_to_scan;
unsigned long scanned = 0;
unsigned long nr_to_reclaim = get_nr_to_reclaim(sc);
@ -140,7 +148,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness);
if (nr_to_scan <= 0)
@@ -5279,12 +5271,13 @@ static void lru_gen_shrink_lruvec(struct
@@ -5277,12 +5269,13 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc
struct blk_plug plug;
VM_WARN_ON_ONCE(global_reclaim(sc));
@ -155,7 +163,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
if (try_to_shrink_lruvec(lruvec, sc))
lru_gen_rotate_memcg(lruvec, MEMCG_LRU_YOUNG);
@@ -5340,11 +5333,19 @@ static void lru_gen_shrink_node(struct p
@@ -5338,11 +5331,19 @@ static void lru_gen_shrink_node(struct pglist_data *pgdat, struct scan_control *
VM_WARN_ON_ONCE(!global_reclaim(sc));
@ -172,11 +180,11 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
blk_start_plug(&plug);
- set_mm_walk(pgdat);
+ set_mm_walk(NULL, sc->proactive);
+ set_mm_walk(pgdat, sc->proactive);
set_initial_priority(pgdat, sc);
@@ -5362,7 +5363,7 @@ static void lru_gen_shrink_node(struct p
@@ -5360,7 +5361,7 @@ static void lru_gen_shrink_node(struct pglist_data *pgdat, struct scan_control *
clear_mm_walk();
blk_finish_plug(&plug);
@ -185,7 +193,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
/* kswapd should never fail */
pgdat->kswapd_failures = 0;
}
@@ -5934,7 +5935,7 @@ static ssize_t lru_gen_seq_write(struct
@@ -5932,7 +5933,7 @@ static ssize_t lru_gen_seq_write(struct file *file, const char __user *src,
set_task_reclaim_state(current, &sc.reclaim_state);
flags = memalloc_noreclaim_save();
blk_start_plug(&plug);
@ -194,3 +202,6 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
err = -ENOMEM;
goto done;
}
--
2.40.1

View file

@ -1,8 +1,8 @@
From cf3297e4c7a928da8b2b2f0baff2f9c69ea57952 Mon Sep 17 00:00:00 2001
From 25887d48dff860751a06caa4188bfaf6bfb6e4b2 Mon Sep 17 00:00:00 2001
From: Yu Zhao <yuzhao@google.com>
Date: Wed, 21 Dec 2022 21:19:06 -0700
Subject: [PATCH 28/29] mm: multi-gen LRU: simplify arch_has_hw_pte_young()
check
Subject: [PATCH 08/19] UPSTREAM: mm: multi-gen LRU: simplify
arch_has_hw_pte_young() check
Scanning page tables when hardware does not set the accessed bit has
no real use cases.
@ -17,13 +17,19 @@ Cc: Mike Rapoport <rppt@kernel.org>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Suren Baghdasaryan <surenb@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Bug: 274865848
(cherry picked from commit f386e9314025ea99dae639ed2032560a92081430)
Change-Id: I84d97ab665b4e3bb862a9bc7d72f50dea7191a6b
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
mm/vmscan.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 0a0e1250ffc87..aa9746f2bc80b 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -4418,7 +4418,7 @@ static bool try_to_inc_max_seq(struct lr
@@ -4415,7 +4415,7 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq,
* handful of PTEs. Spreading the work out over a period of time usually
* is less efficient, but it avoids bursty page faults.
*/
@ -32,3 +38,6 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
success = iterate_mm_list_nowalk(lruvec, max_seq);
goto done;
}
--
2.40.1

View file

@ -1,7 +1,7 @@
From cc67f962cc53f6e1dfa92eb85b7b26fe83a3c66f Mon Sep 17 00:00:00 2001
From 620b0ee94455e48d124414cd06d8a53f69fb6453 Mon Sep 17 00:00:00 2001
From: Yu Zhao <yuzhao@google.com>
Date: Mon, 13 Feb 2023 00:53:22 -0700
Subject: [PATCH 29/29] mm: multi-gen LRU: avoid futile retries
Subject: [PATCH 09/19] UPSTREAM: mm: multi-gen LRU: avoid futile retries
Recall that the per-node memcg LRU has two generations and they alternate
when the last memcg (of a given node) is moved from one to the other.
@ -19,13 +19,19 @@ Fixes: e4dde56cd208 ("mm: multi-gen LRU: per-node lru_gen_folio lists")
Signed-off-by: Yu Zhao <yuzhao@google.com>
Reported-by: T.J. Mercier <tjmercier@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Bug: 274865848
(cherry picked from commit 9f550d78b40da21b4da515db4c37d8d7b12aa1a6)
Change-Id: Ie92535676b005ec9e7987632b742fdde8d54436f
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
mm/vmscan.c | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index aa9746f2bc80b..49da02f841c81 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -5208,18 +5208,20 @@ static int shrink_one(struct lruvec *lru
@@ -5206,18 +5206,20 @@ static int shrink_one(struct lruvec *lruvec, struct scan_control *sc)
static void shrink_many(struct pglist_data *pgdat, struct scan_control *sc)
{
@ -41,14 +47,14 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
- struct mem_cgroup *memcg = NULL;
unsigned long nr_to_reclaim = get_nr_to_reclaim(sc);
bin = first_bin = prandom_u32_max(MEMCG_NR_BINS);
bin = first_bin = get_random_u32_below(MEMCG_NR_BINS);
restart:
+ op = 0;
+ memcg = NULL;
gen = get_memcg_gen(READ_ONCE(pgdat->memcg_lru.seq));
rcu_read_lock();
@@ -5243,14 +5245,22 @@ restart:
@@ -5241,14 +5243,22 @@ static void shrink_many(struct pglist_data *pgdat, struct scan_control *sc)
op = shrink_one(lruvec, sc);
@ -74,7 +80,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
/* restart if raced with lru_gen_rotate_memcg() */
if (gen != get_nulls_value(pos))
goto restart;
@@ -5259,11 +5269,6 @@ restart:
@@ -5257,11 +5267,6 @@ static void shrink_many(struct pglist_data *pgdat, struct scan_control *sc)
bin = get_memcg_bin(bin + 1);
if (bin != first_bin)
goto restart;
@ -86,3 +92,6 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
}
static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)
--
2.40.1

View file

@ -1,7 +1,7 @@
From 6c7f552a48b49a8612786a28a2239fbc24fac289 Mon Sep 17 00:00:00 2001
From 70d216c71ff5c5b17dd1da6294f97b91fb6aba7a Mon Sep 17 00:00:00 2001
From: Yu Zhao <yuzhao@google.com>
Date: Fri, 30 Dec 2022 14:52:51 -0700
Subject: [PATCH 19/29] mm: add vma_has_recency()
Subject: [PATCH 10/19] UPSTREAM: mm: add vma_has_recency()
Add vma_has_recency() to indicate whether a VMA may exhibit temporal
locality that the LRU algorithm relies on.
@ -43,22 +43,28 @@ results are available in that thread.
[1] https://lore.kernel.org/r/Y31s%2FK8T85jh05wH@google.com/
Link: https://lkml.kernel.org/r/20221230215252.2628425-1-yuzhao@google.com
Change-Id: I291dcb795197659e40e46539cd32b857677c34ad
Signed-off-by: Yu Zhao <yuzhao@google.com>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Andrea Righi <andrea.righi@canonical.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michael Larabel <Michael@MichaelLarabel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
(cherry picked from commit 8788f6781486769d9598dcaedc3fe0eb12fc3e59)
Bug: 274865848
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
include/linux/mm_inline.h | 9 +++++++++
mm/memory.c | 8 ++++----
include/linux/mm_inline.h | 8 ++++++++
mm/memory.c | 7 +++----
mm/rmap.c | 42 +++++++++++++++++----------------------
mm/vmscan.c | 5 ++++-
4 files changed, 35 insertions(+), 29 deletions(-)
4 files changed, 33 insertions(+), 29 deletions(-)
diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h
index c1fd3922dc5dd..7bb2e5f94734c 100644
--- a/include/linux/mm_inline.h
+++ b/include/linux/mm_inline.h
@@ -578,4 +578,12 @@ pte_install_uffd_wp_if_needed(struct vm_
@@ -595,4 +595,12 @@ pte_install_uffd_wp_if_needed(struct vm_area_struct *vma, unsigned long addr,
#endif
}
@ -71,9 +77,11 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+}
+
#endif
diff --git a/mm/memory.c b/mm/memory.c
index 747b7ea30f890..c2f48f8003c2e 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1435,8 +1435,7 @@ again:
@@ -1435,8 +1435,7 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
force_flush = 1;
set_page_dirty(page);
}
@ -83,7 +91,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mark_page_accessed(page);
}
rss[mm_counter(page)]--;
@@ -5170,8 +5169,8 @@ static inline void mm_account_fault(stru
@@ -5170,8 +5169,8 @@ static inline void mm_account_fault(struct pt_regs *regs,
#ifdef CONFIG_LRU_GEN
static void lru_gen_enter_fault(struct vm_area_struct *vma)
{
@ -94,9 +102,11 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
}
static void lru_gen_exit_fault(void)
diff --git a/mm/rmap.c b/mm/rmap.c
index 7da2d8d097d9b..825dac3caa1e5 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -823,25 +823,14 @@ static bool folio_referenced_one(struct
@@ -823,25 +823,14 @@ static bool folio_referenced_one(struct folio *folio,
}
if (pvmw.pte) {
@ -125,16 +135,16 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
} else if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {
if (pmdp_clear_flush_young_notify(vma, address,
pvmw.pmd))
@@ -875,7 +864,20 @@ static bool invalid_folio_referenced_vma
@@ -875,7 +864,20 @@ static bool invalid_folio_referenced_vma(struct vm_area_struct *vma, void *arg)
struct folio_referenced_arg *pra = arg;
struct mem_cgroup *memcg = pra->memcg;
- if (!mm_match_cgroup(vma->vm_mm, memcg))
+ /*
+ * Ignore references from this mapping if it has no recency. If the
+ * page has been used in another mapping, we will catch it; if this
+ * folio has been used in another mapping, we will catch it; if this
+ * other mapping is already gone, the unmap path will have set the
+ * referenced flag or activated the page in zap_pte_range().
+ * referenced flag or activated the folio in zap_pte_range().
+ */
+ if (!vma_has_recency(vma))
+ return true;
@ -147,7 +157,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
return true;
return false;
@@ -906,6 +908,7 @@ int folio_referenced(struct folio *folio
@@ -906,6 +908,7 @@ int folio_referenced(struct folio *folio, int is_locked,
.arg = (void *)&pra,
.anon_lock = folio_lock_anon_vma_read,
.try_lock = true,
@ -155,7 +165,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
};
*vm_flags = 0;
@@ -921,15 +924,6 @@ int folio_referenced(struct folio *folio
@@ -921,15 +924,6 @@ int folio_referenced(struct folio *folio, int is_locked,
return 1;
}
@ -171,9 +181,11 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
rmap_walk(folio, &rwc);
*vm_flags = pra.vm_flags;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 49da02f841c81..596fed6ae0439 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -3766,7 +3766,10 @@ static int should_skip_vma(unsigned long
@@ -3778,7 +3778,10 @@ static int should_skip_vma(unsigned long start, unsigned long end, struct mm_wal
if (is_vm_hugetlb_page(vma))
return true;
@ -185,3 +197,6 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
return true;
if (vma == get_gate_vma(vma->vm_mm))
--
2.40.1

View file

@ -1,7 +1,7 @@
From 686c3d4f71de9e0e7a27f03a5617a712385f90cd Mon Sep 17 00:00:00 2001
From 9ca4e437a24dfc4ec6c362f319eb9850b9eca497 Mon Sep 17 00:00:00 2001
From: Yu Zhao <yuzhao@google.com>
Date: Fri, 30 Dec 2022 14:52:52 -0700
Subject: [PATCH 20/29] mm: support POSIX_FADV_NOREUSE
Subject: [PATCH 11/19] UPSTREAM: mm: support POSIX_FADV_NOREUSE
This patch adds POSIX_FADV_NOREUSE to vma_has_recency() so that the LRU
algorithm can ignore access to mapped files marked by this flag.
@ -22,7 +22,7 @@ Its limitations are:
by two users and one of them having set POSIX_FADV_NOREUSE on the
file, this page will be activated upon the second user accessing
it. This corner case can be covered by checking POSIX_FADV_NOREUSE
before calling mark_page_accessed() on the read path. But it is
before calling folio_mark_accessed() on the read path. But it is
considered not worth the effort.
There have been a few attempts to support POSIX_FADV_NOREUSE, e.g., [1].
@ -67,32 +67,40 @@ which makes it on par with the active/inactive LRU.
[2] https://openbenchmarking.org/result/2209259-PTS-MGLRU8GB57
Link: https://lkml.kernel.org/r/20221230215252.2628425-2-yuzhao@google.com
Change-Id: I0b7f5f971d78014ea1ba44cee6a8ec902a4330d0
Signed-off-by: Yu Zhao <yuzhao@google.com>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Andrea Righi <andrea.righi@canonical.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michael Larabel <Michael@MichaelLarabel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
(cherry picked from commit 17e810229cb3068b692fa078bd9b3a6527e0866a)
Bug: 274865848
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
include/linux/fs.h | 2 ++
include/linux/mm_inline.h | 3 +++
mm/fadvise.c | 5 ++++-
3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index f14ecbeab2a9d..97f9c41c1a43a 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -166,6 +166,8 @@ typedef int (dio_iodone_t)(struct kiocb
@@ -166,6 +166,8 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
/* File supports DIRECT IO */
#define FMODE_CAN_ODIRECT ((__force fmode_t)0x400000)
+#define FMODE_NOREUSE ((__force fmode_t)0x400000)
+#define FMODE_NOREUSE ((__force fmode_t)0x800000)
+
/* File was opened by fanotify and shouldn't generate fanotify events */
#define FMODE_NONOTIFY ((__force fmode_t)0x4000000)
diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h
index 7bb2e5f94734c..9a8e2049333c0 100644
--- a/include/linux/mm_inline.h
+++ b/include/linux/mm_inline.h
@@ -583,6 +583,9 @@ static inline bool vma_has_recency(struc
@@ -600,6 +600,9 @@ static inline bool vma_has_recency(struct vm_area_struct *vma)
if (vma->vm_flags & (VM_SEQ_READ | VM_RAND_READ))
return false;
@ -102,9 +110,11 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
return true;
}
diff --git a/mm/fadvise.c b/mm/fadvise.c
index c76ee665355a4..2ba24d865bf5f 100644
--- a/mm/fadvise.c
+++ b/mm/fadvise.c
@@ -80,7 +80,7 @@ int generic_fadvise(struct file *file, l
@@ -80,7 +80,7 @@ int generic_fadvise(struct file *file, loff_t offset, loff_t len, int advice)
case POSIX_FADV_NORMAL:
file->f_ra.ra_pages = bdi->ra_pages;
spin_lock(&file->f_lock);
@ -113,7 +123,7 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
spin_unlock(&file->f_lock);
break;
case POSIX_FADV_RANDOM:
@@ -107,6 +107,9 @@ int generic_fadvise(struct file *file, l
@@ -107,6 +107,9 @@ int generic_fadvise(struct file *file, loff_t offset, loff_t len, int advice)
force_page_cache_readahead(mapping, file, start_index, nrpages);
break;
case POSIX_FADV_NOREUSE:
@ -123,3 +133,6 @@ Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
break;
case POSIX_FADV_DONTNEED:
__filemap_fdatawrite_range(mapping, offset, endbyte,
--
2.40.1

View file

@ -0,0 +1,74 @@
From 1b5e4c317d80f4826eceb3781702d18d06b14394 Mon Sep 17 00:00:00 2001
From: "T.J. Alumbaugh" <talumbau@google.com>
Date: Wed, 18 Jan 2023 00:18:21 +0000
Subject: [PATCH 12/19] UPSTREAM: mm: multi-gen LRU: section for working set
protection
Patch series "mm: multi-gen LRU: improve".
This patch series improves a few MGLRU functions, collects related
functions, and adds additional documentation.
This patch (of 7):
Add a section for working set protection in the code and the design doc.
The admin doc already contains its usage.
Link: https://lkml.kernel.org/r/20230118001827.1040870-1-talumbau@google.com
Link: https://lkml.kernel.org/r/20230118001827.1040870-2-talumbau@google.com
Change-Id: I65599075fd42951db7739a2ab7cee78516e157b3
Signed-off-by: T.J. Alumbaugh <talumbau@google.com>
Cc: Yu Zhao <yuzhao@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
(cherry picked from commit 7b8144e63d84716f16a1b929e0c7e03ae5c4d5c1)
Bug: 274865848
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
Documentation/mm/multigen_lru.rst | 15 +++++++++++++++
mm/vmscan.c | 4 ++++
2 files changed, 19 insertions(+)
diff --git a/Documentation/mm/multigen_lru.rst b/Documentation/mm/multigen_lru.rst
index d8f721f98868a..6e1483e70fdca 100644
--- a/Documentation/mm/multigen_lru.rst
+++ b/Documentation/mm/multigen_lru.rst
@@ -141,6 +141,21 @@ loop has detected outlying refaults from the tier this page is in. To
this end, the feedback loop uses the first tier as the baseline, for
the reason stated earlier.
+Working set protection
+----------------------
+Each generation is timestamped at birth. If ``lru_gen_min_ttl`` is
+set, an ``lruvec`` is protected from the eviction when its oldest
+generation was born within ``lru_gen_min_ttl`` milliseconds. In other
+words, it prevents the working set of ``lru_gen_min_ttl`` milliseconds
+from getting evicted. The OOM killer is triggered if this working set
+cannot be kept in memory.
+
+This time-based approach has the following advantages:
+
+1. It is easier to configure because it is agnostic to applications
+ and memory sizes.
+2. It is more reliable because it is directly wired to the OOM killer.
+
Summary
-------
The multi-gen LRU can be disassembled into the following parts:
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 596fed6ae0439..ab0b8d3b9d88f 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -4459,6 +4459,10 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq,
return true;
}
+/******************************************************************************
+ * working set protection
+ ******************************************************************************/
+
static bool lruvec_is_sizable(struct lruvec *lruvec, struct scan_control *sc)
{
int gen, type, zone;
--
2.40.1

View file

@ -0,0 +1,64 @@
From 5ddf9d53d375e42af49b744bd7c2f8247c6bce15 Mon Sep 17 00:00:00 2001
From: "T.J. Alumbaugh" <talumbau@google.com>
Date: Wed, 18 Jan 2023 00:18:22 +0000
Subject: [PATCH 13/19] UPSTREAM: mm: multi-gen LRU: section for rmap/PT walk
feedback
Add a section for lru_gen_look_around() in the code and the design doc.
Link: https://lkml.kernel.org/r/20230118001827.1040870-3-talumbau@google.com
Change-Id: I5097af63f61b3b69ec2abee6cdbdc33c296df213
Signed-off-by: T.J. Alumbaugh <talumbau@google.com>
Cc: Yu Zhao <yuzhao@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
(cherry picked from commit db19a43d9b3a8876552f00f656008206ef9a5efa)
Bug: 274865848
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
Documentation/mm/multigen_lru.rst | 14 ++++++++++++++
mm/vmscan.c | 4 ++++
2 files changed, 18 insertions(+)
diff --git a/Documentation/mm/multigen_lru.rst b/Documentation/mm/multigen_lru.rst
index 6e1483e70fdca..bd988a142bc2f 100644
--- a/Documentation/mm/multigen_lru.rst
+++ b/Documentation/mm/multigen_lru.rst
@@ -156,6 +156,20 @@ This time-based approach has the following advantages:
and memory sizes.
2. It is more reliable because it is directly wired to the OOM killer.
+Rmap/PT walk feedback
+---------------------
+Searching the rmap for PTEs mapping each page on an LRU list (to test
+and clear the accessed bit) can be expensive because pages from
+different VMAs (PA space) are not cache friendly to the rmap (VA
+space). For workloads mostly using mapped pages, searching the rmap
+can incur the highest CPU cost in the reclaim path.
+
+``lru_gen_look_around()`` exploits spatial locality to reduce the
+trips into the rmap. It scans the adjacent PTEs of a young PTE and
+promotes hot pages. If the scan was done cacheline efficiently, it
+adds the PMD entry pointing to the PTE table to the Bloom filter. This
+forms a feedback loop between the eviction and the aging.
+
Summary
-------
The multi-gen LRU can be disassembled into the following parts:
diff --git a/mm/vmscan.c b/mm/vmscan.c
index ab0b8d3b9d88f..8fa82630240d6 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -4553,6 +4553,10 @@ static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc)
}
}
+/******************************************************************************
+ * rmap/PT walk feedback
+ ******************************************************************************/
+
/*
* This function exploits spatial locality when shrink_folio_list() walks the
* rmap. It scans the adjacent PTEs of a young PTE and promotes hot pages. If
--
2.40.1

View file

@ -0,0 +1,250 @@
From 397624e12244ec038f51cb1f178ccb7a2ec562e5 Mon Sep 17 00:00:00 2001
From: "T.J. Alumbaugh" <talumbau@google.com>
Date: Wed, 18 Jan 2023 00:18:23 +0000
Subject: [PATCH 14/19] UPSTREAM: mm: multi-gen LRU: section for Bloom filters
Move Bloom filters code into a dedicated section. Improve the design doc
to explain Bloom filter usage and connection between aging and eviction in
their use.
Link: https://lkml.kernel.org/r/20230118001827.1040870-4-talumbau@google.com
Change-Id: I73e866f687c1ed9f5c8538086aa39408b79897db
Signed-off-by: T.J. Alumbaugh <talumbau@google.com>
Cc: Yu Zhao <yuzhao@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
(cherry picked from commit ccbbbb85945d8f0255aa9dbc1b617017e2294f2c)
Bug: 274865848
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
Documentation/mm/multigen_lru.rst | 16 +++
mm/vmscan.c | 180 +++++++++++++++---------------
2 files changed, 108 insertions(+), 88 deletions(-)
diff --git a/Documentation/mm/multigen_lru.rst b/Documentation/mm/multigen_lru.rst
index bd988a142bc2f..770b5d539856c 100644
--- a/Documentation/mm/multigen_lru.rst
+++ b/Documentation/mm/multigen_lru.rst
@@ -170,6 +170,22 @@ promotes hot pages. If the scan was done cacheline efficiently, it
adds the PMD entry pointing to the PTE table to the Bloom filter. This
forms a feedback loop between the eviction and the aging.
+Bloom Filters
+-------------
+Bloom filters are a space and memory efficient data structure for set
+membership test, i.e., test if an element is not in the set or may be
+in the set.
+
+In the eviction path, specifically, in ``lru_gen_look_around()``, if a
+PMD has a sufficient number of hot pages, its address is placed in the
+filter. In the aging path, set membership means that the PTE range
+will be scanned for young pages.
+
+Note that Bloom filters are probabilistic on set membership. If a test
+is false positive, the cost is an additional scan of a range of PTEs,
+which may yield hot pages anyway. Parameters of the filter itself can
+control the false positive rate in the limit.
+
Summary
-------
The multi-gen LRU can be disassembled into the following parts:
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 8fa82630240d6..74b4f9d660b56 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -3208,6 +3208,98 @@ static bool __maybe_unused seq_is_valid(struct lruvec *lruvec)
get_nr_gens(lruvec, LRU_GEN_ANON) <= MAX_NR_GENS;
}
+/******************************************************************************
+ * Bloom filters
+ ******************************************************************************/
+
+/*
+ * Bloom filters with m=1<<15, k=2 and the false positive rates of ~1/5 when
+ * n=10,000 and ~1/2 when n=20,000, where, conventionally, m is the number of
+ * bits in a bitmap, k is the number of hash functions and n is the number of
+ * inserted items.
+ *
+ * Page table walkers use one of the two filters to reduce their search space.
+ * To get rid of non-leaf entries that no longer have enough leaf entries, the
+ * aging uses the double-buffering technique to flip to the other filter each
+ * time it produces a new generation. For non-leaf entries that have enough
+ * leaf entries, the aging carries them over to the next generation in
+ * walk_pmd_range(); the eviction also report them when walking the rmap
+ * in lru_gen_look_around().
+ *
+ * For future optimizations:
+ * 1. It's not necessary to keep both filters all the time. The spare one can be
+ * freed after the RCU grace period and reallocated if needed again.
+ * 2. And when reallocating, it's worth scaling its size according to the number
+ * of inserted entries in the other filter, to reduce the memory overhead on
+ * small systems and false positives on large systems.
+ * 3. Jenkins' hash function is an alternative to Knuth's.
+ */
+#define BLOOM_FILTER_SHIFT 15
+
+static inline int filter_gen_from_seq(unsigned long seq)
+{
+ return seq % NR_BLOOM_FILTERS;
+}
+
+static void get_item_key(void *item, int *key)
+{
+ u32 hash = hash_ptr(item, BLOOM_FILTER_SHIFT * 2);
+
+ BUILD_BUG_ON(BLOOM_FILTER_SHIFT * 2 > BITS_PER_TYPE(u32));
+
+ key[0] = hash & (BIT(BLOOM_FILTER_SHIFT) - 1);
+ key[1] = hash >> BLOOM_FILTER_SHIFT;
+}
+
+static bool test_bloom_filter(struct lruvec *lruvec, unsigned long seq, void *item)
+{
+ int key[2];
+ unsigned long *filter;
+ int gen = filter_gen_from_seq(seq);
+
+ filter = READ_ONCE(lruvec->mm_state.filters[gen]);
+ if (!filter)
+ return true;
+
+ get_item_key(item, key);
+
+ return test_bit(key[0], filter) && test_bit(key[1], filter);
+}
+
+static void update_bloom_filter(struct lruvec *lruvec, unsigned long seq, void *item)
+{
+ int key[2];
+ unsigned long *filter;
+ int gen = filter_gen_from_seq(seq);
+
+ filter = READ_ONCE(lruvec->mm_state.filters[gen]);
+ if (!filter)
+ return;
+
+ get_item_key(item, key);
+
+ if (!test_bit(key[0], filter))
+ set_bit(key[0], filter);
+ if (!test_bit(key[1], filter))
+ set_bit(key[1], filter);
+}
+
+static void reset_bloom_filter(struct lruvec *lruvec, unsigned long seq)
+{
+ unsigned long *filter;
+ int gen = filter_gen_from_seq(seq);
+
+ filter = lruvec->mm_state.filters[gen];
+ if (filter) {
+ bitmap_clear(filter, 0, BIT(BLOOM_FILTER_SHIFT));
+ return;
+ }
+
+ filter = bitmap_zalloc(BIT(BLOOM_FILTER_SHIFT),
+ __GFP_HIGH | __GFP_NOMEMALLOC | __GFP_NOWARN);
+ WRITE_ONCE(lruvec->mm_state.filters[gen], filter);
+}
+
/******************************************************************************
* mm_struct list
******************************************************************************/
@@ -3333,94 +3425,6 @@ void lru_gen_migrate_mm(struct mm_struct *mm)
}
#endif
-/*
- * Bloom filters with m=1<<15, k=2 and the false positive rates of ~1/5 when
- * n=10,000 and ~1/2 when n=20,000, where, conventionally, m is the number of
- * bits in a bitmap, k is the number of hash functions and n is the number of
- * inserted items.
- *
- * Page table walkers use one of the two filters to reduce their search space.
- * To get rid of non-leaf entries that no longer have enough leaf entries, the
- * aging uses the double-buffering technique to flip to the other filter each
- * time it produces a new generation. For non-leaf entries that have enough
- * leaf entries, the aging carries them over to the next generation in
- * walk_pmd_range(); the eviction also report them when walking the rmap
- * in lru_gen_look_around().
- *
- * For future optimizations:
- * 1. It's not necessary to keep both filters all the time. The spare one can be
- * freed after the RCU grace period and reallocated if needed again.
- * 2. And when reallocating, it's worth scaling its size according to the number
- * of inserted entries in the other filter, to reduce the memory overhead on
- * small systems and false positives on large systems.
- * 3. Jenkins' hash function is an alternative to Knuth's.
- */
-#define BLOOM_FILTER_SHIFT 15
-
-static inline int filter_gen_from_seq(unsigned long seq)
-{
- return seq % NR_BLOOM_FILTERS;
-}
-
-static void get_item_key(void *item, int *key)
-{
- u32 hash = hash_ptr(item, BLOOM_FILTER_SHIFT * 2);
-
- BUILD_BUG_ON(BLOOM_FILTER_SHIFT * 2 > BITS_PER_TYPE(u32));
-
- key[0] = hash & (BIT(BLOOM_FILTER_SHIFT) - 1);
- key[1] = hash >> BLOOM_FILTER_SHIFT;
-}
-
-static void reset_bloom_filter(struct lruvec *lruvec, unsigned long seq)
-{
- unsigned long *filter;
- int gen = filter_gen_from_seq(seq);
-
- filter = lruvec->mm_state.filters[gen];
- if (filter) {
- bitmap_clear(filter, 0, BIT(BLOOM_FILTER_SHIFT));
- return;
- }
-
- filter = bitmap_zalloc(BIT(BLOOM_FILTER_SHIFT),
- __GFP_HIGH | __GFP_NOMEMALLOC | __GFP_NOWARN);
- WRITE_ONCE(lruvec->mm_state.filters[gen], filter);
-}
-
-static void update_bloom_filter(struct lruvec *lruvec, unsigned long seq, void *item)
-{
- int key[2];
- unsigned long *filter;
- int gen = filter_gen_from_seq(seq);
-
- filter = READ_ONCE(lruvec->mm_state.filters[gen]);
- if (!filter)
- return;
-
- get_item_key(item, key);
-
- if (!test_bit(key[0], filter))
- set_bit(key[0], filter);
- if (!test_bit(key[1], filter))
- set_bit(key[1], filter);
-}
-
-static bool test_bloom_filter(struct lruvec *lruvec, unsigned long seq, void *item)
-{
- int key[2];
- unsigned long *filter;
- int gen = filter_gen_from_seq(seq);
-
- filter = READ_ONCE(lruvec->mm_state.filters[gen]);
- if (!filter)
- return true;
-
- get_item_key(item, key);
-
- return test_bit(key[0], filter) && test_bit(key[1], filter);
-}
-
static void reset_mm_stats(struct lruvec *lruvec, struct lru_gen_mm_walk *walk, bool last)
{
int i;
--
2.40.1

View file

@ -0,0 +1,440 @@
From 48c916b812652f9453be5bd45a703728926d41ca Mon Sep 17 00:00:00 2001
From: "T.J. Alumbaugh" <talumbau@google.com>
Date: Wed, 18 Jan 2023 00:18:24 +0000
Subject: [PATCH 15/19] UPSTREAM: mm: multi-gen LRU: section for memcg LRU
Move memcg LRU code into a dedicated section. Improve the design doc to
outline its architecture.
Link: https://lkml.kernel.org/r/20230118001827.1040870-5-talumbau@google.com
Change-Id: Id252e420cff7a858acb098cf2b3642da5c40f602
Signed-off-by: T.J. Alumbaugh <talumbau@google.com>
Cc: Yu Zhao <yuzhao@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
(cherry picked from commit 36c7b4db7c942ae9e1b111f0c6b468c8b2e33842)
Bug: 274865848
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
Documentation/mm/multigen_lru.rst | 33 +++-
include/linux/mm_inline.h | 17 --
include/linux/mmzone.h | 13 +-
mm/memcontrol.c | 8 +-
mm/vmscan.c | 250 +++++++++++++++++-------------
5 files changed, 178 insertions(+), 143 deletions(-)
diff --git a/Documentation/mm/multigen_lru.rst b/Documentation/mm/multigen_lru.rst
index 770b5d539856c..5f1f6ecbb79b9 100644
--- a/Documentation/mm/multigen_lru.rst
+++ b/Documentation/mm/multigen_lru.rst
@@ -186,9 +186,40 @@ is false positive, the cost is an additional scan of a range of PTEs,
which may yield hot pages anyway. Parameters of the filter itself can
control the false positive rate in the limit.
+Memcg LRU
+---------
+An memcg LRU is a per-node LRU of memcgs. It is also an LRU of LRUs,
+since each node and memcg combination has an LRU of folios (see
+``mem_cgroup_lruvec()``). Its goal is to improve the scalability of
+global reclaim, which is critical to system-wide memory overcommit in
+data centers. Note that memcg LRU only applies to global reclaim.
+
+The basic structure of an memcg LRU can be understood by an analogy to
+the active/inactive LRU (of folios):
+
+1. It has the young and the old (generations), i.e., the counterparts
+ to the active and the inactive;
+2. The increment of ``max_seq`` triggers promotion, i.e., the
+ counterpart to activation;
+3. Other events trigger similar operations, e.g., offlining an memcg
+ triggers demotion, i.e., the counterpart to deactivation.
+
+In terms of global reclaim, it has two distinct features:
+
+1. Sharding, which allows each thread to start at a random memcg (in
+ the old generation) and improves parallelism;
+2. Eventual fairness, which allows direct reclaim to bail out at will
+ and reduces latency without affecting fairness over some time.
+
+In terms of traversing memcgs during global reclaim, it improves the
+best-case complexity from O(n) to O(1) and does not affect the
+worst-case complexity O(n). Therefore, on average, it has a sublinear
+complexity.
+
Summary
-------
-The multi-gen LRU can be disassembled into the following parts:
+The multi-gen LRU (of folios) can be disassembled into the following
+parts:
* Generations
* Rmap walks
diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h
index 9a8e2049333c0..5567f4850243b 100644
--- a/include/linux/mm_inline.h
+++ b/include/linux/mm_inline.h
@@ -122,18 +122,6 @@ static inline bool lru_gen_in_fault(void)
return current->in_lru_fault;
}
-#ifdef CONFIG_MEMCG
-static inline int lru_gen_memcg_seg(struct lruvec *lruvec)
-{
- return READ_ONCE(lruvec->lrugen.seg);
-}
-#else
-static inline int lru_gen_memcg_seg(struct lruvec *lruvec)
-{
- return 0;
-}
-#endif
-
static inline int lru_gen_from_seq(unsigned long seq)
{
return seq % MAX_NR_GENS;
@@ -309,11 +297,6 @@ static inline bool lru_gen_in_fault(void)
return false;
}
-static inline int lru_gen_memcg_seg(struct lruvec *lruvec)
-{
- return 0;
-}
-
static inline bool lru_gen_add_folio(struct lruvec *lruvec, struct folio *folio, bool reclaiming)
{
return false;
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 66e067a635682..403c7461e7a70 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -368,15 +368,6 @@ struct page_vma_mapped_walk;
#define LRU_GEN_MASK ((BIT(LRU_GEN_WIDTH) - 1) << LRU_GEN_PGOFF)
#define LRU_REFS_MASK ((BIT(LRU_REFS_WIDTH) - 1) << LRU_REFS_PGOFF)
-/* see the comment on MEMCG_NR_GENS */
-enum {
- MEMCG_LRU_NOP,
- MEMCG_LRU_HEAD,
- MEMCG_LRU_TAIL,
- MEMCG_LRU_OLD,
- MEMCG_LRU_YOUNG,
-};
-
#ifdef CONFIG_LRU_GEN
enum {
@@ -557,7 +548,7 @@ void lru_gen_exit_memcg(struct mem_cgroup *memcg);
void lru_gen_online_memcg(struct mem_cgroup *memcg);
void lru_gen_offline_memcg(struct mem_cgroup *memcg);
void lru_gen_release_memcg(struct mem_cgroup *memcg);
-void lru_gen_rotate_memcg(struct lruvec *lruvec, int op);
+void lru_gen_soft_reclaim(struct lruvec *lruvec);
#else /* !CONFIG_MEMCG */
@@ -608,7 +599,7 @@ static inline void lru_gen_release_memcg(struct mem_cgroup *memcg)
{
}
-static inline void lru_gen_rotate_memcg(struct lruvec *lruvec, int op)
+static inline void lru_gen_soft_reclaim(struct lruvec *lruvec)
{
}
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 7815d556e38cc..5397aeb43986d 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -478,12 +478,8 @@ static void mem_cgroup_update_tree(struct mem_cgroup *memcg, int nid)
struct mem_cgroup_tree_per_node *mctz;
if (lru_gen_enabled()) {
- struct lruvec *lruvec = &memcg->nodeinfo[nid]->lruvec;
-
- /* see the comment on MEMCG_NR_GENS */
- if (soft_limit_excess(memcg) && lru_gen_memcg_seg(lruvec) != MEMCG_LRU_HEAD)
- lru_gen_rotate_memcg(lruvec, MEMCG_LRU_HEAD);
-
+ if (soft_limit_excess(memcg))
+ lru_gen_soft_reclaim(&memcg->nodeinfo[nid]->lruvec);
return;
}
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 74b4f9d660b56..ccde215c084ca 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -4689,6 +4689,148 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw)
mem_cgroup_unlock_pages();
}
+/******************************************************************************
+ * memcg LRU
+ ******************************************************************************/
+
+/* see the comment on MEMCG_NR_GENS */
+enum {
+ MEMCG_LRU_NOP,
+ MEMCG_LRU_HEAD,
+ MEMCG_LRU_TAIL,
+ MEMCG_LRU_OLD,
+ MEMCG_LRU_YOUNG,
+};
+
+#ifdef CONFIG_MEMCG
+
+static int lru_gen_memcg_seg(struct lruvec *lruvec)
+{
+ return READ_ONCE(lruvec->lrugen.seg);
+}
+
+static void lru_gen_rotate_memcg(struct lruvec *lruvec, int op)
+{
+ int seg;
+ int old, new;
+ int bin = get_random_u32_below(MEMCG_NR_BINS);
+ struct pglist_data *pgdat = lruvec_pgdat(lruvec);
+
+ spin_lock(&pgdat->memcg_lru.lock);
+
+ VM_WARN_ON_ONCE(hlist_nulls_unhashed(&lruvec->lrugen.list));
+
+ seg = 0;
+ new = old = lruvec->lrugen.gen;
+
+ /* see the comment on MEMCG_NR_GENS */
+ if (op == MEMCG_LRU_HEAD)
+ seg = MEMCG_LRU_HEAD;
+ else if (op == MEMCG_LRU_TAIL)
+ seg = MEMCG_LRU_TAIL;
+ else if (op == MEMCG_LRU_OLD)
+ new = get_memcg_gen(pgdat->memcg_lru.seq);
+ else if (op == MEMCG_LRU_YOUNG)
+ new = get_memcg_gen(pgdat->memcg_lru.seq + 1);
+ else
+ VM_WARN_ON_ONCE(true);
+
+ hlist_nulls_del_rcu(&lruvec->lrugen.list);
+
+ if (op == MEMCG_LRU_HEAD || op == MEMCG_LRU_OLD)
+ hlist_nulls_add_head_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[new][bin]);
+ else
+ hlist_nulls_add_tail_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[new][bin]);
+
+ pgdat->memcg_lru.nr_memcgs[old]--;
+ pgdat->memcg_lru.nr_memcgs[new]++;
+
+ lruvec->lrugen.gen = new;
+ WRITE_ONCE(lruvec->lrugen.seg, seg);
+
+ if (!pgdat->memcg_lru.nr_memcgs[old] && old == get_memcg_gen(pgdat->memcg_lru.seq))
+ WRITE_ONCE(pgdat->memcg_lru.seq, pgdat->memcg_lru.seq + 1);
+
+ spin_unlock(&pgdat->memcg_lru.lock);
+}
+
+void lru_gen_online_memcg(struct mem_cgroup *memcg)
+{
+ int gen;
+ int nid;
+ int bin = get_random_u32_below(MEMCG_NR_BINS);
+
+ for_each_node(nid) {
+ struct pglist_data *pgdat = NODE_DATA(nid);
+ struct lruvec *lruvec = get_lruvec(memcg, nid);
+
+ spin_lock(&pgdat->memcg_lru.lock);
+
+ VM_WARN_ON_ONCE(!hlist_nulls_unhashed(&lruvec->lrugen.list));
+
+ gen = get_memcg_gen(pgdat->memcg_lru.seq);
+
+ hlist_nulls_add_tail_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[gen][bin]);
+ pgdat->memcg_lru.nr_memcgs[gen]++;
+
+ lruvec->lrugen.gen = gen;
+
+ spin_unlock(&pgdat->memcg_lru.lock);
+ }
+}
+
+void lru_gen_offline_memcg(struct mem_cgroup *memcg)
+{
+ int nid;
+
+ for_each_node(nid) {
+ struct lruvec *lruvec = get_lruvec(memcg, nid);
+
+ lru_gen_rotate_memcg(lruvec, MEMCG_LRU_OLD);
+ }
+}
+
+void lru_gen_release_memcg(struct mem_cgroup *memcg)
+{
+ int gen;
+ int nid;
+
+ for_each_node(nid) {
+ struct pglist_data *pgdat = NODE_DATA(nid);
+ struct lruvec *lruvec = get_lruvec(memcg, nid);
+
+ spin_lock(&pgdat->memcg_lru.lock);
+
+ VM_WARN_ON_ONCE(hlist_nulls_unhashed(&lruvec->lrugen.list));
+
+ gen = lruvec->lrugen.gen;
+
+ hlist_nulls_del_rcu(&lruvec->lrugen.list);
+ pgdat->memcg_lru.nr_memcgs[gen]--;
+
+ if (!pgdat->memcg_lru.nr_memcgs[gen] && gen == get_memcg_gen(pgdat->memcg_lru.seq))
+ WRITE_ONCE(pgdat->memcg_lru.seq, pgdat->memcg_lru.seq + 1);
+
+ spin_unlock(&pgdat->memcg_lru.lock);
+ }
+}
+
+void lru_gen_soft_reclaim(struct lruvec *lruvec)
+{
+ /* see the comment on MEMCG_NR_GENS */
+ if (lru_gen_memcg_seg(lruvec) != MEMCG_LRU_HEAD)
+ lru_gen_rotate_memcg(lruvec, MEMCG_LRU_HEAD);
+}
+
+#else /* !CONFIG_MEMCG */
+
+static int lru_gen_memcg_seg(struct lruvec *lruvec)
+{
+ return 0;
+}
+
+#endif
+
/******************************************************************************
* the eviction
******************************************************************************/
@@ -5386,53 +5528,6 @@ static void lru_gen_shrink_node(struct pglist_data *pgdat, struct scan_control *
pgdat->kswapd_failures = 0;
}
-#ifdef CONFIG_MEMCG
-void lru_gen_rotate_memcg(struct lruvec *lruvec, int op)
-{
- int seg;
- int old, new;
- int bin = get_random_u32_below(MEMCG_NR_BINS);
- struct pglist_data *pgdat = lruvec_pgdat(lruvec);
-
- spin_lock(&pgdat->memcg_lru.lock);
-
- VM_WARN_ON_ONCE(hlist_nulls_unhashed(&lruvec->lrugen.list));
-
- seg = 0;
- new = old = lruvec->lrugen.gen;
-
- /* see the comment on MEMCG_NR_GENS */
- if (op == MEMCG_LRU_HEAD)
- seg = MEMCG_LRU_HEAD;
- else if (op == MEMCG_LRU_TAIL)
- seg = MEMCG_LRU_TAIL;
- else if (op == MEMCG_LRU_OLD)
- new = get_memcg_gen(pgdat->memcg_lru.seq);
- else if (op == MEMCG_LRU_YOUNG)
- new = get_memcg_gen(pgdat->memcg_lru.seq + 1);
- else
- VM_WARN_ON_ONCE(true);
-
- hlist_nulls_del_rcu(&lruvec->lrugen.list);
-
- if (op == MEMCG_LRU_HEAD || op == MEMCG_LRU_OLD)
- hlist_nulls_add_head_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[new][bin]);
- else
- hlist_nulls_add_tail_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[new][bin]);
-
- pgdat->memcg_lru.nr_memcgs[old]--;
- pgdat->memcg_lru.nr_memcgs[new]++;
-
- lruvec->lrugen.gen = new;
- WRITE_ONCE(lruvec->lrugen.seg, seg);
-
- if (!pgdat->memcg_lru.nr_memcgs[old] && old == get_memcg_gen(pgdat->memcg_lru.seq))
- WRITE_ONCE(pgdat->memcg_lru.seq, pgdat->memcg_lru.seq + 1);
-
- spin_unlock(&pgdat->memcg_lru.lock);
-}
-#endif
-
/******************************************************************************
* state change
******************************************************************************/
@@ -6078,67 +6173,6 @@ void lru_gen_exit_memcg(struct mem_cgroup *memcg)
}
}
-void lru_gen_online_memcg(struct mem_cgroup *memcg)
-{
- int gen;
- int nid;
- int bin = get_random_u32_below(MEMCG_NR_BINS);
-
- for_each_node(nid) {
- struct pglist_data *pgdat = NODE_DATA(nid);
- struct lruvec *lruvec = get_lruvec(memcg, nid);
-
- spin_lock(&pgdat->memcg_lru.lock);
-
- VM_WARN_ON_ONCE(!hlist_nulls_unhashed(&lruvec->lrugen.list));
-
- gen = get_memcg_gen(pgdat->memcg_lru.seq);
-
- hlist_nulls_add_tail_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[gen][bin]);
- pgdat->memcg_lru.nr_memcgs[gen]++;
-
- lruvec->lrugen.gen = gen;
-
- spin_unlock(&pgdat->memcg_lru.lock);
- }
-}
-
-void lru_gen_offline_memcg(struct mem_cgroup *memcg)
-{
- int nid;
-
- for_each_node(nid) {
- struct lruvec *lruvec = get_lruvec(memcg, nid);
-
- lru_gen_rotate_memcg(lruvec, MEMCG_LRU_OLD);
- }
-}
-
-void lru_gen_release_memcg(struct mem_cgroup *memcg)
-{
- int gen;
- int nid;
-
- for_each_node(nid) {
- struct pglist_data *pgdat = NODE_DATA(nid);
- struct lruvec *lruvec = get_lruvec(memcg, nid);
-
- spin_lock(&pgdat->memcg_lru.lock);
-
- VM_WARN_ON_ONCE(hlist_nulls_unhashed(&lruvec->lrugen.list));
-
- gen = lruvec->lrugen.gen;
-
- hlist_nulls_del_rcu(&lruvec->lrugen.list);
- pgdat->memcg_lru.nr_memcgs[gen]--;
-
- if (!pgdat->memcg_lru.nr_memcgs[gen] && gen == get_memcg_gen(pgdat->memcg_lru.seq))
- WRITE_ONCE(pgdat->memcg_lru.seq, pgdat->memcg_lru.seq + 1);
-
- spin_unlock(&pgdat->memcg_lru.lock);
- }
-}
-
#endif /* CONFIG_MEMCG */
static int __init init_lru_gen(void)
--
2.40.1

View file

@ -0,0 +1,45 @@
From bec433f29537652ed054148edfd7e2183ddcf7c3 Mon Sep 17 00:00:00 2001
From: "T.J. Alumbaugh" <talumbau@google.com>
Date: Wed, 18 Jan 2023 00:18:25 +0000
Subject: [PATCH 16/19] UPSTREAM: mm: multi-gen LRU: improve
lru_gen_exit_memcg()
Add warnings and poison ->next.
Link: https://lkml.kernel.org/r/20230118001827.1040870-6-talumbau@google.com
Change-Id: I53de9e04c1ae941e122b33cd45d2bbb5f34aae0c
Signed-off-by: T.J. Alumbaugh <talumbau@google.com>
Cc: Yu Zhao <yuzhao@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
(cherry picked from commit 37cc99979d04cca677c0ad5c0acd1149ec165d1b)
Bug: 274865848
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
mm/vmscan.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index ccde215c084ca..d5d6f8d94f58a 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -6160,12 +6160,17 @@ void lru_gen_exit_memcg(struct mem_cgroup *memcg)
int i;
int nid;
+ VM_WARN_ON_ONCE(!list_empty(&memcg->mm_list.fifo));
+
for_each_node(nid) {
struct lruvec *lruvec = get_lruvec(memcg, nid);
+ VM_WARN_ON_ONCE(lruvec->mm_state.nr_walkers);
VM_WARN_ON_ONCE(memchr_inv(lruvec->lrugen.nr_pages, 0,
sizeof(lruvec->lrugen.nr_pages)));
+ lruvec->lrugen.list.next = LIST_POISON1;
+
for (i = 0; i < NR_BLOOM_FILTERS; i++) {
bitmap_free(lruvec->mm_state.filters[i]);
lruvec->mm_state.filters[i] = NULL;
--
2.40.1

View file

@ -0,0 +1,140 @@
From fc0e3b06e0f19917b7ecad7967a72f61d4743644 Mon Sep 17 00:00:00 2001
From: "T.J. Alumbaugh" <talumbau@google.com>
Date: Wed, 18 Jan 2023 00:18:26 +0000
Subject: [PATCH 17/19] UPSTREAM: mm: multi-gen LRU: improve walk_pmd_range()
Improve readability of walk_pmd_range() and walk_pmd_range_locked().
Link: https://lkml.kernel.org/r/20230118001827.1040870-7-talumbau@google.com
Change-Id: Ia084fbf53fe989673b7804ca8ca520af12d7d52a
Signed-off-by: T.J. Alumbaugh <talumbau@google.com>
Cc: Yu Zhao <yuzhao@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
(cherry picked from commit b5ff4133617d0eced35b685da0bd0929dd9fabb7)
Bug: 274865848
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
mm/vmscan.c | 40 ++++++++++++++++++++--------------------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index d5d6f8d94f58a..8f496c2e670a9 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -3980,8 +3980,8 @@ static bool walk_pte_range(pmd_t *pmd, unsigned long start, unsigned long end,
}
#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG)
-static void walk_pmd_range_locked(pud_t *pud, unsigned long next, struct vm_area_struct *vma,
- struct mm_walk *args, unsigned long *bitmap, unsigned long *start)
+static void walk_pmd_range_locked(pud_t *pud, unsigned long addr, struct vm_area_struct *vma,
+ struct mm_walk *args, unsigned long *bitmap, unsigned long *first)
{
int i;
pmd_t *pmd;
@@ -3994,18 +3994,19 @@ static void walk_pmd_range_locked(pud_t *pud, unsigned long next, struct vm_area
VM_WARN_ON_ONCE(pud_leaf(*pud));
/* try to batch at most 1+MIN_LRU_BATCH+1 entries */
- if (*start == -1) {
- *start = next;
+ if (*first == -1) {
+ *first = addr;
+ bitmap_zero(bitmap, MIN_LRU_BATCH);
return;
}
- i = next == -1 ? 0 : pmd_index(next) - pmd_index(*start);
+ i = addr == -1 ? 0 : pmd_index(addr) - pmd_index(*first);
if (i && i <= MIN_LRU_BATCH) {
__set_bit(i - 1, bitmap);
return;
}
- pmd = pmd_offset(pud, *start);
+ pmd = pmd_offset(pud, *first);
ptl = pmd_lockptr(args->mm, pmd);
if (!spin_trylock(ptl))
@@ -4016,15 +4017,16 @@ static void walk_pmd_range_locked(pud_t *pud, unsigned long next, struct vm_area
do {
unsigned long pfn;
struct folio *folio;
- unsigned long addr = i ? (*start & PMD_MASK) + i * PMD_SIZE : *start;
+
+ /* don't round down the first address */
+ addr = i ? (*first & PMD_MASK) + i * PMD_SIZE : *first;
pfn = get_pmd_pfn(pmd[i], vma, addr);
if (pfn == -1)
goto next;
if (!pmd_trans_huge(pmd[i])) {
- if (arch_has_hw_nonleaf_pmd_young() &&
- get_cap(LRU_GEN_NONLEAF_YOUNG))
+ if (arch_has_hw_nonleaf_pmd_young() && get_cap(LRU_GEN_NONLEAF_YOUNG))
pmdp_test_and_clear_young(vma, addr, pmd + i);
goto next;
}
@@ -4053,12 +4055,11 @@ static void walk_pmd_range_locked(pud_t *pud, unsigned long next, struct vm_area
arch_leave_lazy_mmu_mode();
spin_unlock(ptl);
done:
- *start = -1;
- bitmap_zero(bitmap, MIN_LRU_BATCH);
+ *first = -1;
}
#else
-static void walk_pmd_range_locked(pud_t *pud, unsigned long next, struct vm_area_struct *vma,
- struct mm_walk *args, unsigned long *bitmap, unsigned long *start)
+static void walk_pmd_range_locked(pud_t *pud, unsigned long addr, struct vm_area_struct *vma,
+ struct mm_walk *args, unsigned long *bitmap, unsigned long *first)
{
}
#endif
@@ -4071,9 +4072,9 @@ static void walk_pmd_range(pud_t *pud, unsigned long start, unsigned long end,
unsigned long next;
unsigned long addr;
struct vm_area_struct *vma;
- unsigned long pos = -1;
+ unsigned long bitmap[BITS_TO_LONGS(MIN_LRU_BATCH)];
+ unsigned long first = -1;
struct lru_gen_mm_walk *walk = args->private;
- unsigned long bitmap[BITS_TO_LONGS(MIN_LRU_BATCH)] = {};
VM_WARN_ON_ONCE(pud_leaf(*pud));
@@ -4115,18 +4116,17 @@ static void walk_pmd_range(pud_t *pud, unsigned long start, unsigned long end,
if (pfn < pgdat->node_start_pfn || pfn >= pgdat_end_pfn(pgdat))
continue;
- walk_pmd_range_locked(pud, addr, vma, args, bitmap, &pos);
+ walk_pmd_range_locked(pud, addr, vma, args, bitmap, &first);
continue;
}
#endif
walk->mm_stats[MM_NONLEAF_TOTAL]++;
- if (arch_has_hw_nonleaf_pmd_young() &&
- get_cap(LRU_GEN_NONLEAF_YOUNG)) {
+ if (arch_has_hw_nonleaf_pmd_young() && get_cap(LRU_GEN_NONLEAF_YOUNG)) {
if (!pmd_young(val))
continue;
- walk_pmd_range_locked(pud, addr, vma, args, bitmap, &pos);
+ walk_pmd_range_locked(pud, addr, vma, args, bitmap, &first);
}
if (!walk->force_scan && !test_bloom_filter(walk->lruvec, walk->max_seq, pmd + i))
@@ -4143,7 +4143,7 @@ static void walk_pmd_range(pud_t *pud, unsigned long start, unsigned long end,
update_bloom_filter(walk->lruvec, walk->max_seq + 1, pmd + i);
}
- walk_pmd_range_locked(pud, -1, vma, args, bitmap, &pos);
+ walk_pmd_range_locked(pud, -1, vma, args, bitmap, &first);
if (i < PTRS_PER_PMD && get_next_vma(PUD_MASK, PMD_SIZE, args, &start, &end))
goto restart;
--
2.40.1

View file

@ -0,0 +1,153 @@
From e604c3ccb4dfbdde2467fccef9bb36170a392695 Mon Sep 17 00:00:00 2001
From: "T.J. Alumbaugh" <talumbau@google.com>
Date: Wed, 18 Jan 2023 00:18:27 +0000
Subject: [PATCH 18/19] UPSTREAM: mm: multi-gen LRU: simplify
lru_gen_look_around()
Update the folio generation in place with or without
current->reclaim_state->mm_walk. The LRU lock is held for longer, if
mm_walk is NULL and the number of folios to update is more than
PAGEVEC_SIZE.
This causes a measurable regression from the LRU lock contention during a
microbencmark. But a tiny regression is not worth the complexity.
Link: https://lkml.kernel.org/r/20230118001827.1040870-8-talumbau@google.com
Change-Id: I9ce18b4f4062e6c1c13c98ece9422478eb8e1846
Signed-off-by: T.J. Alumbaugh <talumbau@google.com>
Cc: Yu Zhao <yuzhao@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
(cherry picked from commit abf086721a2f1e6897c57796f7268df1b194c750)
Bug: 274865848
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
mm/vmscan.c | 73 +++++++++++++++++------------------------------------
1 file changed, 23 insertions(+), 50 deletions(-)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 8f496c2e670a9..f6ce7a1fd78a3 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -4571,13 +4571,12 @@ static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc)
void lru_gen_look_around(struct page_vma_mapped_walk *pvmw)
{
int i;
- pte_t *pte;
unsigned long start;
unsigned long end;
- unsigned long addr;
struct lru_gen_mm_walk *walk;
int young = 0;
- unsigned long bitmap[BITS_TO_LONGS(MIN_LRU_BATCH)] = {};
+ pte_t *pte = pvmw->pte;
+ unsigned long addr = pvmw->address;
struct folio *folio = pfn_folio(pvmw->pfn);
struct mem_cgroup *memcg = folio_memcg(folio);
struct pglist_data *pgdat = folio_pgdat(folio);
@@ -4594,25 +4593,28 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw)
/* avoid taking the LRU lock under the PTL when possible */
walk = current->reclaim_state ? current->reclaim_state->mm_walk : NULL;
- start = max(pvmw->address & PMD_MASK, pvmw->vma->vm_start);
- end = min(pvmw->address | ~PMD_MASK, pvmw->vma->vm_end - 1) + 1;
+ start = max(addr & PMD_MASK, pvmw->vma->vm_start);
+ end = min(addr | ~PMD_MASK, pvmw->vma->vm_end - 1) + 1;
if (end - start > MIN_LRU_BATCH * PAGE_SIZE) {
- if (pvmw->address - start < MIN_LRU_BATCH * PAGE_SIZE / 2)
+ if (addr - start < MIN_LRU_BATCH * PAGE_SIZE / 2)
end = start + MIN_LRU_BATCH * PAGE_SIZE;
- else if (end - pvmw->address < MIN_LRU_BATCH * PAGE_SIZE / 2)
+ else if (end - addr < MIN_LRU_BATCH * PAGE_SIZE / 2)
start = end - MIN_LRU_BATCH * PAGE_SIZE;
else {
- start = pvmw->address - MIN_LRU_BATCH * PAGE_SIZE / 2;
- end = pvmw->address + MIN_LRU_BATCH * PAGE_SIZE / 2;
+ start = addr - MIN_LRU_BATCH * PAGE_SIZE / 2;
+ end = addr + MIN_LRU_BATCH * PAGE_SIZE / 2;
}
}
- pte = pvmw->pte - (pvmw->address - start) / PAGE_SIZE;
+ /* folio_update_gen() requires stable folio_memcg() */
+ if (!mem_cgroup_trylock_pages(memcg))
+ return;
- rcu_read_lock();
arch_enter_lazy_mmu_mode();
+ pte -= (addr - start) / PAGE_SIZE;
+
for (i = 0, addr = start; addr != end; i++, addr += PAGE_SIZE) {
unsigned long pfn;
@@ -4637,56 +4639,27 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw)
!folio_test_swapcache(folio)))
folio_mark_dirty(folio);
+ if (walk) {
+ old_gen = folio_update_gen(folio, new_gen);
+ if (old_gen >= 0 && old_gen != new_gen)
+ update_batch_size(walk, folio, old_gen, new_gen);
+
+ continue;
+ }
+
old_gen = folio_lru_gen(folio);
if (old_gen < 0)
folio_set_referenced(folio);
else if (old_gen != new_gen)
- __set_bit(i, bitmap);
+ folio_activate(folio);
}
arch_leave_lazy_mmu_mode();
- rcu_read_unlock();
+ mem_cgroup_unlock_pages();
/* feedback from rmap walkers to page table walkers */
if (suitable_to_scan(i, young))
update_bloom_filter(lruvec, max_seq, pvmw->pmd);
-
- if (!walk && bitmap_weight(bitmap, MIN_LRU_BATCH) < PAGEVEC_SIZE) {
- for_each_set_bit(i, bitmap, MIN_LRU_BATCH) {
- folio = pfn_folio(pte_pfn(pte[i]));
- folio_activate(folio);
- }
- return;
- }
-
- /* folio_update_gen() requires stable folio_memcg() */
- if (!mem_cgroup_trylock_pages(memcg))
- return;
-
- if (!walk) {
- spin_lock_irq(&lruvec->lru_lock);
- new_gen = lru_gen_from_seq(lruvec->lrugen.max_seq);
- }
-
- for_each_set_bit(i, bitmap, MIN_LRU_BATCH) {
- folio = pfn_folio(pte_pfn(pte[i]));
- if (folio_memcg_rcu(folio) != memcg)
- continue;
-
- old_gen = folio_update_gen(folio, new_gen);
- if (old_gen < 0 || old_gen == new_gen)
- continue;
-
- if (walk)
- update_batch_size(walk, folio, old_gen, new_gen);
- else
- lru_gen_update_size(lruvec, folio, old_gen, new_gen);
- }
-
- if (!walk)
- spin_unlock_irq(&lruvec->lru_lock);
-
- mem_cgroup_unlock_pages();
}
/******************************************************************************
--
2.40.1

View file

@ -0,0 +1,280 @@
From 418038c22452df38cde519cc8c662bb15139764a Mon Sep 17 00:00:00 2001
From: Kalesh Singh <kaleshsingh@google.com>
Date: Thu, 13 Apr 2023 14:43:26 -0700
Subject: [PATCH 19/19] mm: Multi-gen LRU: remove wait_event_killable()
Android 14 and later default to MGLRU [1] and field telemetry showed
occasional long tail latency (>100ms) in the reclaim path.
Tracing revealed priority inversion in the reclaim path. In
try_to_inc_max_seq(), when high priority tasks were blocked on
wait_event_killable(), the preemption of the low priority task to call
wake_up_all() caused those high priority tasks to wait longer than
necessary. In general, this problem is not different from others of its
kind, e.g., one caused by mutex_lock(). However, it is specific to MGLRU
because it introduced the new wait queue lruvec->mm_state.wait.
The purpose of this new wait queue is to avoid the thundering herd
problem. If many direct reclaimers rush into try_to_inc_max_seq(), only
one can succeed, i.e., the one to wake up the rest, and the rest who
failed might cause premature OOM kills if they do not wait. So far there
is no evidence supporting this scenario, based on how often the wait has
been hit. And this begs the question how useful the wait queue is in
practice.
Based on Minchan's recommendation, which is in line with his commit
6d4675e60135 ("mm: don't be stuck to rmap lock on reclaim path") and the
rest of the MGLRU code which also uses trylock when possible, remove the
wait queue.
[1] https://android-review.googlesource.com/q/I7ed7fbfd6ef9ce10053347528125dd98c39e50bf
Link: https://lkml.kernel.org/r/20230413214326.2147568-1-kaleshsingh@google.com
Fixes: bd74fdaea146 ("mm: multi-gen LRU: support page table walks")
Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
Suggested-by: Minchan Kim <minchan@kernel.org>
Reported-by: Wei Wang <wvw@google.com>
Acked-by: Yu Zhao <yuzhao@google.com>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Jan Alexander Steffens (heftig) <heftig@archlinux.org>
Cc: Oleksandr Natalenko <oleksandr@natalenko.name>
Cc: Suleiman Souhlal <suleiman@google.com>
Cc: Suren Baghdasaryan <surenb@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
include/linux/mmzone.h | 8 +--
mm/vmscan.c | 112 +++++++++++++++--------------------------
2 files changed, 42 insertions(+), 78 deletions(-)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 403c7461e7a70..d62a5accf1be4 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -453,18 +453,14 @@ enum {
struct lru_gen_mm_state {
/* set to max_seq after each iteration */
unsigned long seq;
- /* where the current iteration continues (inclusive) */
+ /* where the current iteration continues after */
struct list_head *head;
- /* where the last iteration ended (exclusive) */
+ /* where the last iteration ended before */
struct list_head *tail;
- /* to wait for the last page table walker to finish */
- struct wait_queue_head wait;
/* Bloom filters flip after each iteration */
unsigned long *filters[NR_BLOOM_FILTERS];
/* the mm stats for debugging */
unsigned long stats[NR_HIST_GENS][NR_MM_STATS];
- /* the number of concurrent page table walkers */
- int nr_walkers;
};
struct lru_gen_mm_walk {
diff --git a/mm/vmscan.c b/mm/vmscan.c
index f6ce7a1fd78a3..851758303dbf4 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -3371,18 +3371,13 @@ void lru_gen_del_mm(struct mm_struct *mm)
if (!lruvec)
continue;
- /* where the last iteration ended (exclusive) */
+ /* where the current iteration continues after */
+ if (lruvec->mm_state.head == &mm->lru_gen.list)
+ lruvec->mm_state.head = lruvec->mm_state.head->prev;
+
+ /* where the last iteration ended before */
if (lruvec->mm_state.tail == &mm->lru_gen.list)
lruvec->mm_state.tail = lruvec->mm_state.tail->next;
-
- /* where the current iteration continues (inclusive) */
- if (lruvec->mm_state.head != &mm->lru_gen.list)
- continue;
-
- lruvec->mm_state.head = lruvec->mm_state.head->next;
- /* the deletion ends the current iteration */
- if (lruvec->mm_state.head == &mm_list->fifo)
- WRITE_ONCE(lruvec->mm_state.seq, lruvec->mm_state.seq + 1);
}
list_del_init(&mm->lru_gen.list);
@@ -3478,68 +3473,54 @@ static bool iterate_mm_list(struct lruvec *lruvec, struct lru_gen_mm_walk *walk,
struct mm_struct **iter)
{
bool first = false;
- bool last = true;
+ bool last = false;
struct mm_struct *mm = NULL;
struct mem_cgroup *memcg = lruvec_memcg(lruvec);
struct lru_gen_mm_list *mm_list = get_mm_list(memcg);
struct lru_gen_mm_state *mm_state = &lruvec->mm_state;
/*
- * There are four interesting cases for this page table walker:
- * 1. It tries to start a new iteration of mm_list with a stale max_seq;
- * there is nothing left to do.
- * 2. It's the first of the current generation, and it needs to reset
- * the Bloom filter for the next generation.
- * 3. It reaches the end of mm_list, and it needs to increment
- * mm_state->seq; the iteration is done.
- * 4. It's the last of the current generation, and it needs to reset the
- * mm stats counters for the next generation.
+ * mm_state->seq is incremented after each iteration of mm_list. There
+ * are three interesting cases for this page table walker:
+ * 1. It tries to start a new iteration with a stale max_seq: there is
+ * nothing left to do.
+ * 2. It started the next iteration: it needs to reset the Bloom filter
+ * so that a fresh set of PTE tables can be recorded.
+ * 3. It ended the current iteration: it needs to reset the mm stats
+ * counters and tell its caller to increment max_seq.
*/
spin_lock(&mm_list->lock);
VM_WARN_ON_ONCE(mm_state->seq + 1 < walk->max_seq);
- VM_WARN_ON_ONCE(*iter && mm_state->seq > walk->max_seq);
- VM_WARN_ON_ONCE(*iter && !mm_state->nr_walkers);
- if (walk->max_seq <= mm_state->seq) {
- if (!*iter)
- last = false;
+ if (walk->max_seq <= mm_state->seq)
goto done;
- }
- if (!mm_state->nr_walkers) {
- VM_WARN_ON_ONCE(mm_state->head && mm_state->head != &mm_list->fifo);
+ if (!mm_state->head)
+ mm_state->head = &mm_list->fifo;
- mm_state->head = mm_list->fifo.next;
+ if (mm_state->head == &mm_list->fifo)
first = true;
- }
-
- while (!mm && mm_state->head != &mm_list->fifo) {
- mm = list_entry(mm_state->head, struct mm_struct, lru_gen.list);
+ do {
mm_state->head = mm_state->head->next;
+ if (mm_state->head == &mm_list->fifo) {
+ WRITE_ONCE(mm_state->seq, mm_state->seq + 1);
+ last = true;
+ break;
+ }
/* force scan for those added after the last iteration */
- if (!mm_state->tail || mm_state->tail == &mm->lru_gen.list) {
- mm_state->tail = mm_state->head;
+ if (!mm_state->tail || mm_state->tail == mm_state->head) {
+ mm_state->tail = mm_state->head->next;
walk->force_scan = true;
}
+ mm = list_entry(mm_state->head, struct mm_struct, lru_gen.list);
if (should_skip_mm(mm, walk))
mm = NULL;
- }
-
- if (mm_state->head == &mm_list->fifo)
- WRITE_ONCE(mm_state->seq, mm_state->seq + 1);
+ } while (!mm);
done:
- if (*iter && !mm)
- mm_state->nr_walkers--;
- if (!*iter && mm)
- mm_state->nr_walkers++;
-
- if (mm_state->nr_walkers)
- last = false;
-
if (*iter || last)
reset_mm_stats(lruvec, walk, last);
@@ -3567,9 +3548,9 @@ static bool iterate_mm_list_nowalk(struct lruvec *lruvec, unsigned long max_seq)
VM_WARN_ON_ONCE(mm_state->seq + 1 < max_seq);
- if (max_seq > mm_state->seq && !mm_state->nr_walkers) {
- VM_WARN_ON_ONCE(mm_state->head && mm_state->head != &mm_list->fifo);
-
+ if (max_seq > mm_state->seq) {
+ mm_state->head = NULL;
+ mm_state->tail = NULL;
WRITE_ONCE(mm_state->seq, mm_state->seq + 1);
reset_mm_stats(lruvec, NULL, true);
success = true;
@@ -4172,10 +4153,6 @@ static int walk_pud_range(p4d_t *p4d, unsigned long start, unsigned long end,
walk_pmd_range(&val, addr, next, args);
- /* a racy check to curtail the waiting time */
- if (wq_has_sleeper(&walk->lruvec->mm_state.wait))
- return 1;
-
if (need_resched() || walk->batched >= MAX_LRU_BATCH) {
end = (addr | ~PUD_MASK) + 1;
goto done;
@@ -4208,8 +4185,14 @@ static void walk_mm(struct lruvec *lruvec, struct mm_struct *mm, struct lru_gen_
walk->next_addr = FIRST_USER_ADDRESS;
do {
+ DEFINE_MAX_SEQ(lruvec);
+
err = -EBUSY;
+ /* another thread might have called inc_max_seq() */
+ if (walk->max_seq != max_seq)
+ break;
+
/* folio_update_gen() requires stable folio_memcg() */
if (!mem_cgroup_trylock_pages(memcg))
break;
@@ -4442,25 +4425,12 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq,
success = iterate_mm_list(lruvec, walk, &mm);
if (mm)
walk_mm(lruvec, mm, walk);
-
- cond_resched();
} while (mm);
done:
- if (!success) {
- if (sc->priority <= DEF_PRIORITY - 2)
- wait_event_killable(lruvec->mm_state.wait,
- max_seq < READ_ONCE(lrugen->max_seq));
- return false;
- }
+ if (success)
+ inc_max_seq(lruvec, can_swap, force_scan);
- VM_WARN_ON_ONCE(max_seq != READ_ONCE(lrugen->max_seq));
-
- inc_max_seq(lruvec, can_swap, force_scan);
- /* either this sees any waiters or they will see updated max_seq */
- if (wq_has_sleeper(&lruvec->mm_state.wait))
- wake_up_all(&lruvec->mm_state.wait);
-
- return true;
+ return success;
}
/******************************************************************************
@@ -6105,7 +6075,6 @@ void lru_gen_init_lruvec(struct lruvec *lruvec)
INIT_LIST_HEAD(&lrugen->folios[gen][type][zone]);
lruvec->mm_state.seq = MIN_NR_GENS;
- init_waitqueue_head(&lruvec->mm_state.wait);
}
#ifdef CONFIG_MEMCG
@@ -6138,7 +6107,6 @@ void lru_gen_exit_memcg(struct mem_cgroup *memcg)
for_each_node(nid) {
struct lruvec *lruvec = get_lruvec(memcg, nid);
- VM_WARN_ON_ONCE(lruvec->mm_state.nr_walkers);
VM_WARN_ON_ONCE(memchr_inv(lruvec->lrugen.nr_pages, 0,
sizeof(lruvec->lrugen.nr_pages)));
--
2.40.1

View file

@ -343,7 +343,7 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8
# CONFIG_ARM64_ERRATUM_858921 is not set
# CONFIG_ARM64_HW_AFDBM is not set
# CONFIG_ARM64_LSE_ATOMICS is not set
# CONFIG_ARM64_MODULE_PLTS is not set
CONFIG_ARM64_MODULE_PLTS=y
# CONFIG_ARM64_MTE is not set
# CONFIG_ARM64_PAN is not set
# CONFIG_ARM64_PMEM is not set
@ -408,7 +408,7 @@ CONFIG_ARM_GIC_MAX_NR=1
# CONFIG_ARM_LPAE is not set
# CONFIG_ARM_MEDIATEK_CPUFREQ_HW is not set
# CONFIG_ARM_MHU is not set
# CONFIG_ARM_MODULE_PLTS is not set
CONFIG_ARM_MODULE_PLTS=y
# CONFIG_ARM_PATCH_PHYS_VIRT is not set
# CONFIG_ARM_PSCI is not set
# CONFIG_ARM_PSCI_CHECKER is not set
@ -7262,7 +7262,6 @@ CONFIG_VHOST_MENU=y
# CONFIG_VIDEO_HEXIUM_ORION is not set
# CONFIG_VIDEO_HI556 is not set
# CONFIG_VIDEO_I2C is not set
# CONFIG_VIDEO_IMX_PXP is not set
# CONFIG_VIDEO_IMX208 is not set
# CONFIG_VIDEO_IMX214 is not set
# CONFIG_VIDEO_IMX219 is not set
@ -7276,6 +7275,7 @@ CONFIG_VHOST_MENU=y
# CONFIG_VIDEO_IMX412 is not set
# CONFIG_VIDEO_IMX477 is not set
# CONFIG_VIDEO_IMX8_JPEG is not set
# CONFIG_VIDEO_IMX_PXP is not set
# CONFIG_VIDEO_IRS1125 is not set
# CONFIG_VIDEO_IR_I2C is not set
# CONFIG_VIDEO_IVTV is not set

View file

@ -277,6 +277,7 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8
# CONFIG_ARCH_NOMADIK is not set
# CONFIG_ARCH_NPCM is not set
# CONFIG_ARCH_NSPIRE is not set
# CONFIG_ARCH_NXP is not set
# CONFIG_ARCH_OMAP is not set
# CONFIG_ARCH_OMAP1 is not set
# CONFIG_ARCH_OMAP2 is not set
@ -367,7 +368,7 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8
# CONFIG_ARM64_ERRATUM_858921 is not set
# CONFIG_ARM64_HW_AFDBM is not set
# CONFIG_ARM64_LSE_ATOMICS is not set
# CONFIG_ARM64_MODULE_PLTS is not set
CONFIG_ARM64_MODULE_PLTS=y
# CONFIG_ARM64_MTE is not set
# CONFIG_ARM64_PAN is not set
# CONFIG_ARM64_PMEM is not set
@ -433,7 +434,7 @@ CONFIG_ARM_GIC_MAX_NR=1
# CONFIG_ARM_LPAE is not set
# CONFIG_ARM_MEDIATEK_CPUFREQ_HW is not set
# CONFIG_ARM_MHU is not set
# CONFIG_ARM_MODULE_PLTS is not set
CONFIG_ARM_MODULE_PLTS=y
# CONFIG_ARM_PATCH_PHYS_VIRT is not set
# CONFIG_ARM_PSCI is not set
# CONFIG_ARM_PSCI_CHECKER is not set
@ -912,8 +913,8 @@ CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
# CONFIG_CEPH_FS is not set
# CONFIG_CEPH_LIB is not set
# CONFIG_CFG80211 is not set
CONFIG_CFG80211_HEADERS=y
# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
CONFIG_CFG80211_HEADERS=y
# CONFIG_CGROUPS is not set
# CONFIG_CGROUP_FAVOR_DYNMODS is not set
# CONFIG_CGROUP_MISC is not set
@ -1070,6 +1071,7 @@ CONFIG_CONSTRUCTORS=y
# CONFIG_CPU_IDLE_GOV_TEO is not set
# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set
# CONFIG_CPU_ISOLATION is not set
# CONFIG_CPU_LITTLE_ENDIAN is not set
# CONFIG_CPU_NO_EFFICIENT_FFS is not set
CONFIG_CPU_SW_DOMAIN_PAN=y
# CONFIG_CPU_THERMAL is not set
@ -2479,6 +2481,7 @@ CONFIG_HIGH_RES_TIMERS=y
CONFIG_HPET_MMAP_DEFAULT=y
# CONFIG_HPFS_FS is not set
# CONFIG_HP_ILO is not set
# CONFIG_HP_WATCHDOG is not set
# CONFIG_HP_WIRELESS is not set
# CONFIG_HSA_AMD is not set
# CONFIG_HSI is not set
@ -4560,6 +4563,7 @@ CONFIG_NMI_LOG_BUF_SHIFT=13
# CONFIG_OCFS2_FS is not set
# CONFIG_OCTEONTX2_AF is not set
# CONFIG_OCTEONTX2_PF is not set
# CONFIG_OCTEON_EP is not set
# CONFIG_OF_OVERLAY is not set
CONFIG_OF_RESERVED_MEM=y
# CONFIG_OF_UNITTEST is not set
@ -6535,6 +6539,7 @@ CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES=y
# CONFIG_SUNXI_SRAM is not set
# CONFIG_SUN_PARTITION is not set
# CONFIG_SURFACE_3_BUTTON is not set
# CONFIG_SURFACE_PLATFORMS is not set
# CONFIG_SUSPEND is not set
# CONFIG_SUSPEND_SKIP_SYNC is not set
CONFIG_SWAP=y
@ -7450,7 +7455,6 @@ CONFIG_VHOST_MENU=y
# CONFIG_VIDEO_HI846 is not set
# CONFIG_VIDEO_HI847 is not set
# CONFIG_VIDEO_I2C is not set
# CONFIG_VIDEO_IMX_PXP is not set
# CONFIG_VIDEO_IMX208 is not set
# CONFIG_VIDEO_IMX214 is not set
# CONFIG_VIDEO_IMX219 is not set
@ -7464,6 +7468,7 @@ CONFIG_VHOST_MENU=y
# CONFIG_VIDEO_IMX412 is not set
# CONFIG_VIDEO_IMX477 is not set
# CONFIG_VIDEO_IMX8_JPEG is not set
# CONFIG_VIDEO_IMX_PXP is not set
# CONFIG_VIDEO_IRS1125 is not set
# CONFIG_VIDEO_IR_I2C is not set
# CONFIG_VIDEO_ISL7998X is not set
@ -7605,6 +7610,7 @@ CONFIG_VLAN_8021Q=y
CONFIG_VMSPLIT_3G=y
# CONFIG_VMSPLIT_3G_OPT is not set
# CONFIG_VMWARE_PVSCSI is not set
# CONFIG_VMWARE_VMCI is not set
# CONFIG_VMXNET3 is not set
# CONFIG_VM_EVENT_COUNTERS is not set
# CONFIG_VOP_BUS is not set

View file

@ -10,6 +10,7 @@ CONFIG_CLANG_VERSION=.*
# CONFIG_LD_.* is not set
CONFIG_LLD_VERSION=.*
CONFIG_PAHOLE_VERSION=.*
CONFIG_PAHOLE_HAS_SPLIT_BTF=.*
CONFIG_PLUGIN_HOSTCC=".*"
# CONFIG_SET_FS is not set
# CONFIG_TASKS_.* is not set

View file

@ -15,7 +15,7 @@ Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -2347,6 +2347,10 @@ mt7531_setup(struct dsa_switch *ds)
@@ -2440,6 +2440,10 @@ mt7531_setup(struct dsa_switch *ds)
return -ENODEV;
}

View file

@ -0,0 +1,223 @@
From 663fa1b7e0cb2c929008482014a70c6625caad75 Mon Sep 17 00:00:00 2001
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Tue, 7 Mar 2023 15:55:13 +0000
Subject: [PATCH 1/7] net: ethernet: mtk_eth_soc: add MTK_NETSYS_V1 capability
bit
Introduce MTK_NETSYS_V1 bit in the device capabilities for
MT7621/MT7622/MT7623/MT7628/MT7629 SoCs.
Use !MTK_NETSYS_V1 instead of MTK_NETSYS_V2 in the driver codebase.
This is a preliminary patch to introduce support for MT7988 SoC.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 30 +++++++-------
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 45 ++++++++++++---------
2 files changed, 41 insertions(+), 34 deletions(-)
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -597,7 +597,7 @@ static void mtk_set_queue_speed(struct m
FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) |
FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) |
MTK_QTX_SCH_LEAKY_BUCKET_SIZE;
- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1))
val |= MTK_QTX_SCH_LEAKY_BUCKET_EN;
if (IS_ENABLED(CONFIG_SOC_MT7621)) {
@@ -974,7 +974,7 @@ static bool mtk_rx_get_desc(struct mtk_e
rxd->rxd1 = READ_ONCE(dma_rxd->rxd1);
rxd->rxd3 = READ_ONCE(dma_rxd->rxd3);
rxd->rxd4 = READ_ONCE(dma_rxd->rxd4);
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) {
rxd->rxd5 = READ_ONCE(dma_rxd->rxd5);
rxd->rxd6 = READ_ONCE(dma_rxd->rxd6);
}
@@ -1032,7 +1032,7 @@ static int mtk_init_fq_dma(struct mtk_et
txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE);
txd->txd4 = 0;
- if (MTK_HAS_CAPS(soc->caps, MTK_NETSYS_V2)) {
+ if (!MTK_HAS_CAPS(soc->caps, MTK_NETSYS_V1)) {
txd->txd5 = 0;
txd->txd6 = 0;
txd->txd7 = 0;
@@ -1221,7 +1221,7 @@ static void mtk_tx_set_dma_desc(struct n
struct mtk_mac *mac = netdev_priv(dev);
struct mtk_eth *eth = mac->hw;
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1))
mtk_tx_set_dma_desc_v2(dev, txd, info);
else
mtk_tx_set_dma_desc_v1(dev, txd, info);
@@ -1902,7 +1902,7 @@ static int mtk_poll_rx(struct napi_struc
break;
/* find out which mac the packet come from. values start at 1 */
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1))
mac = RX_DMA_GET_SPORT_V2(trxd.rxd5) - 1;
else if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) &&
!(trxd.rxd4 & RX_DMA_SPECIAL_TAG))
@@ -1998,7 +1998,7 @@ static int mtk_poll_rx(struct napi_struc
skb->dev = netdev;
bytes += skb->len;
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) {
reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON, trxd.rxd5);
hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY;
if (hash != MTK_RXD5_FOE_ENTRY)
@@ -2023,7 +2023,7 @@ static int mtk_poll_rx(struct napi_struc
/* When using VLAN untagging in combination with DSA, the
* hardware treats the MTK special tag as a VLAN and untags it.
*/
- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) &&
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1) &&
(trxd.rxd2 & RX_DMA_VTAG) && netdev_uses_dsa(netdev)) {
unsigned int port = RX_DMA_VPID(trxd.rxd3) & GENMASK(2, 0);
@@ -2328,7 +2328,7 @@ static int mtk_tx_alloc(struct mtk_eth *
txd->txd2 = next_ptr;
txd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU;
txd->txd4 = 0;
- if (MTK_HAS_CAPS(soc->caps, MTK_NETSYS_V2)) {
+ if (!MTK_HAS_CAPS(soc->caps, MTK_NETSYS_V1)) {
txd->txd5 = 0;
txd->txd6 = 0;
txd->txd7 = 0;
@@ -2381,7 +2381,7 @@ static int mtk_tx_alloc(struct mtk_eth *
FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) |
FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) |
MTK_QTX_SCH_LEAKY_BUCKET_SIZE;
- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1))
val |= MTK_QTX_SCH_LEAKY_BUCKET_EN;
mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs);
ofs += MTK_QTX_OFFSET;
@@ -2515,7 +2515,7 @@ static int mtk_rx_alloc(struct mtk_eth *
rxd->rxd3 = 0;
rxd->rxd4 = 0;
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) {
rxd->rxd5 = 0;
rxd->rxd6 = 0;
rxd->rxd7 = 0;
@@ -3063,7 +3063,7 @@ static int mtk_start_dma(struct mtk_eth
MTK_TX_BT_32DWORDS | MTK_NDP_CO_PRO |
MTK_RX_2B_OFFSET | MTK_TX_WB_DDONE;
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1))
val |= MTK_MUTLI_CNT | MTK_RESV_BUF |
MTK_WCOMP_EN | MTK_DMAD_WR_WDONE |
MTK_CHK_DDONE_EN | MTK_LEAKY_BUCKET_EN;
@@ -3475,7 +3475,7 @@ static void mtk_hw_reset(struct mtk_eth
{
u32 val;
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) {
regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0);
val = RSTCTRL_PPE0_V2;
} else {
@@ -3487,7 +3487,7 @@ static void mtk_hw_reset(struct mtk_eth
ethsys_reset(eth, RSTCTRL_ETH | RSTCTRL_FE | val);
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1))
regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN,
0x3ffffff);
}
@@ -3683,7 +3683,7 @@ static int mtk_hw_init(struct mtk_eth *e
else
mtk_hw_reset(eth);
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) {
/* Set FE to PDMAv2 if necessary */
val = mtk_r32(eth, MTK_FE_GLO_MISC);
mtk_w32(eth, val | BIT(4), MTK_FE_GLO_MISC);
@@ -3720,7 +3720,7 @@ static int mtk_hw_init(struct mtk_eth *e
*/
val = mtk_r32(eth, MTK_CDMQ_IG_CTRL);
mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL);
- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) {
val = mtk_r32(eth, MTK_CDMP_IG_CTRL);
mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL);
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -816,6 +816,7 @@ enum mkt_eth_capabilities {
MTK_SHARED_INT_BIT,
MTK_TRGMII_MT7621_CLK_BIT,
MTK_QDMA_BIT,
+ MTK_NETSYS_V1_BIT,
MTK_NETSYS_V2_BIT,
MTK_SOC_MT7628_BIT,
MTK_RSTCTRL_PPE1_BIT,
@@ -851,6 +852,7 @@ enum mkt_eth_capabilities {
#define MTK_SHARED_INT BIT(MTK_SHARED_INT_BIT)
#define MTK_TRGMII_MT7621_CLK BIT(MTK_TRGMII_MT7621_CLK_BIT)
#define MTK_QDMA BIT(MTK_QDMA_BIT)
+#define MTK_NETSYS_V1 BIT(MTK_NETSYS_V1_BIT)
#define MTK_NETSYS_V2 BIT(MTK_NETSYS_V2_BIT)
#define MTK_SOC_MT7628 BIT(MTK_SOC_MT7628_BIT)
#define MTK_RSTCTRL_PPE1 BIT(MTK_RSTCTRL_PPE1_BIT)
@@ -913,25 +915,30 @@ enum mkt_eth_capabilities {
#define MTK_HAS_CAPS(caps, _x) (((caps) & (_x) & ~(MTK_CAP_MASK)) == (_x))
-#define MT7621_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | \
- MTK_GMAC2_RGMII | MTK_SHARED_INT | \
- MTK_TRGMII_MT7621_CLK | MTK_QDMA)
-
-#define MT7622_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_SGMII | MTK_GMAC2_RGMII | \
- MTK_GMAC2_SGMII | MTK_GDM1_ESW | \
- MTK_MUX_GDM1_TO_GMAC1_ESW | \
- MTK_MUX_GMAC1_GMAC2_TO_SGMII_RGMII | MTK_QDMA)
-
-#define MT7623_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | MTK_GMAC2_RGMII | \
- MTK_QDMA)
-
-#define MT7628_CAPS (MTK_SHARED_INT | MTK_SOC_MT7628)
-
-#define MT7629_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \
- MTK_GDM1_ESW | MTK_MUX_GDM1_TO_GMAC1_ESW | \
- MTK_MUX_GMAC2_GMAC0_TO_GEPHY | \
- MTK_MUX_U3_GMAC2_TO_QPHY | \
- MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA)
+#define MT7621_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | \
+ MTK_GMAC2_RGMII | MTK_SHARED_INT | \
+ MTK_TRGMII_MT7621_CLK | MTK_QDMA | \
+ MTK_NETSYS_V1)
+
+#define MT7622_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_SGMII | \
+ MTK_GMAC2_RGMII | MTK_GMAC2_SGMII | \
+ MTK_GDM1_ESW | MTK_MUX_GDM1_TO_GMAC1_ESW |\
+ MTK_MUX_GMAC1_GMAC2_TO_SGMII_RGMII | \
+ MTK_QDMA | MTK_NETSYS_V1)
+
+#define MT7623_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | \
+ MTK_GMAC2_RGMII | MTK_QDMA | \
+ MTK_NETSYS_V1)
+
+#define MT7628_CAPS (MTK_SHARED_INT | MTK_SOC_MT7628 | \
+ MTK_NETSYS_V1)
+
+#define MT7629_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \
+ MTK_GMAC2_GEPHY | MTK_GDM1_ESW | \
+ MTK_MUX_GMAC2_GMAC0_TO_GEPHY | MTK_QDMA | \
+ MTK_MUX_U3_GMAC2_TO_QPHY | MTK_NETSYS_V1 |\
+ MTK_MUX_GDM1_TO_GMAC1_ESW | \
+ MTK_MUX_GMAC12_TO_GEPHY_SGMII)
#define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \
MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \

View file

@ -0,0 +1,181 @@
From 5af2b2dc4d6ba0ff7696e79f18e5b2bf862194eb Mon Sep 17 00:00:00 2001
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Tue, 7 Mar 2023 15:55:24 +0000
Subject: [PATCH 2/7] net: ethernet: mtk_eth_soc: move MAX_DEVS in mtk_soc_data
This is a preliminary patch to add MT7988 SoC support since it runs 3
macs instead of 2.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 34 +++++++++++++++++++--
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 11 +++----
2 files changed, 36 insertions(+), 9 deletions(-)
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -3989,7 +3989,10 @@ static void mtk_sgmii_destroy(struct mtk
{
int i;
- for (i = 0; i < MTK_MAX_DEVS; i++)
+ if (!eth->sgmii_pcs)
+ return;
+
+ for (i = 0; i < eth->soc->num_devs; i++)
mtk_pcs_lynxi_destroy(eth->sgmii_pcs[i]);
}
@@ -4432,7 +4435,12 @@ static int mtk_sgmii_init(struct mtk_eth
u32 flags;
int i;
- for (i = 0; i < MTK_MAX_DEVS; i++) {
+ eth->sgmii_pcs = devm_kzalloc(eth->dev,
+ sizeof(*eth->sgmii_pcs) *
+ eth->soc->num_devs,
+ GFP_KERNEL);
+
+ for (i = 0; i < eth->soc->num_devs; i++) {
np = of_parse_phandle(eth->dev->of_node, "mediatek,sgmiisys", i);
if (!np)
break;
@@ -4477,6 +4485,18 @@ static int mtk_probe(struct platform_dev
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628))
eth->ip_align = NET_IP_ALIGN;
+ eth->netdev = devm_kzalloc(eth->dev,
+ sizeof(*eth->netdev) * eth->soc->num_devs,
+ GFP_KERNEL);
+ if (!eth->netdev)
+ return -ENOMEM;
+
+ eth->mac = devm_kzalloc(eth->dev,
+ sizeof(*eth->mac) * eth->soc->num_devs,
+ GFP_KERNEL);
+ if (!eth->mac)
+ return -ENOMEM;
+
spin_lock_init(&eth->page_lock);
spin_lock_init(&eth->tx_irq_lock);
spin_lock_init(&eth->rx_irq_lock);
@@ -4662,7 +4682,7 @@ static int mtk_probe(struct platform_dev
goto err_free_dev;
}
- for (i = 0; i < MTK_MAX_DEVS; i++) {
+ for (i = 0; i < eth->soc->num_devs; i++) {
if (!eth->netdev[i])
continue;
@@ -4739,6 +4759,7 @@ static const struct mtk_soc_data mt2701_
.hw_features = MTK_HW_FEATURES,
.required_clks = MT7623_CLKS_BITMAP,
.required_pctl = true,
+ .num_devs = 2,
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma),
.rxd_size = sizeof(struct mtk_rx_dma),
@@ -4757,6 +4778,7 @@ static const struct mtk_soc_data mt7621_
.required_pctl = false,
.offload_version = 1,
.hash_offset = 2,
+ .num_devs = 2,
.foe_entry_size = sizeof(struct mtk_foe_entry) - 16,
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma),
@@ -4778,6 +4800,7 @@ static const struct mtk_soc_data mt7622_
.offload_version = 2,
.hash_offset = 2,
.has_accounting = true,
+ .num_devs = 2,
.foe_entry_size = sizeof(struct mtk_foe_entry) - 16,
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma),
@@ -4797,6 +4820,7 @@ static const struct mtk_soc_data mt7623_
.required_pctl = true,
.offload_version = 1,
.hash_offset = 2,
+ .num_devs = 2,
.foe_entry_size = sizeof(struct mtk_foe_entry) - 16,
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma),
@@ -4816,6 +4840,7 @@ static const struct mtk_soc_data mt7629_
.required_clks = MT7629_CLKS_BITMAP,
.required_pctl = false,
.has_accounting = true,
+ .num_devs = 2,
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma),
.rxd_size = sizeof(struct mtk_rx_dma),
@@ -4837,6 +4862,7 @@ static const struct mtk_soc_data mt7981_
.hash_offset = 4,
.foe_entry_size = sizeof(struct mtk_foe_entry),
.has_accounting = true,
+ .num_devs = 2,
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma_v2),
.rxd_size = sizeof(struct mtk_rx_dma_v2),
@@ -4856,6 +4882,7 @@ static const struct mtk_soc_data mt7986_
.required_pctl = false,
.offload_version = 2,
.hash_offset = 4,
+ .num_devs = 2,
.foe_entry_size = sizeof(struct mtk_foe_entry),
.has_accounting = true,
.txrx = {
@@ -4874,6 +4901,7 @@ static const struct mtk_soc_data rt5350_
.hw_features = MTK_HW_FEATURES_MT7628,
.required_clks = MT7628_CLKS_BITMAP,
.required_pctl = false,
+ .num_devs = 2,
.txrx = {
.txd_size = sizeof(struct mtk_tx_dma),
.rxd_size = sizeof(struct mtk_rx_dma),
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -1018,6 +1018,7 @@ struct mtk_reg_map {
* @required_pctl A bool value to show whether the SoC requires
* the extra setup for those pins used by GMAC.
* @hash_offset Flow table hash offset.
+ * @num_devs SoC number of macs.
* @foe_entry_size Foe table entry size.
* @has_accounting Bool indicating support for accounting of
* offloaded flows.
@@ -1036,6 +1037,7 @@ struct mtk_soc_data {
bool required_pctl;
u8 offload_version;
u8 hash_offset;
+ u8 num_devs;
u16 foe_entry_size;
netdev_features_t hw_features;
bool has_accounting;
@@ -1051,9 +1053,6 @@ struct mtk_soc_data {
#define MTK_DMA_MONITOR_TIMEOUT msecs_to_jiffies(1000)
-/* currently no SoC has more than 2 macs */
-#define MTK_MAX_DEVS 2
-
/* struct mtk_eth - This is the main datasructure for holding the state
* of the driver
* @dev: The device pointer
@@ -1108,14 +1107,14 @@ struct mtk_eth {
spinlock_t tx_irq_lock;
spinlock_t rx_irq_lock;
struct net_device dummy_dev;
- struct net_device *netdev[MTK_MAX_DEVS];
- struct mtk_mac *mac[MTK_MAX_DEVS];
+ struct net_device **netdev;
+ struct mtk_mac **mac;
int irq[3];
u32 msg_enable;
unsigned long sysclk;
struct regmap *ethsys;
struct regmap *infra;
- struct phylink_pcs *sgmii_pcs[MTK_MAX_DEVS];
+ struct phylink_pcs **sgmii_pcs;
struct regmap *pctl;
bool hwlro;
refcount_t dma_refcnt;

View file

@ -0,0 +1,153 @@
From 4e35e80750b33727e606be9e7ce447bde2e0deb7 Mon Sep 17 00:00:00 2001
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Tue, 7 Mar 2023 15:55:35 +0000
Subject: [PATCH 3/7] net: ethernet: mtk_eth_soc: rely on num_devs and remove
MTK_MAC_COUNT
Get rid of MTK_MAC_COUNT since it is a duplicated of eth->soc->num_devs.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 30 ++++++++++-----------
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 -
2 files changed, 15 insertions(+), 16 deletions(-)
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -900,7 +900,7 @@ static void mtk_stats_update(struct mtk_
{
int i;
- for (i = 0; i < MTK_MAC_COUNT; i++) {
+ for (i = 0; i < eth->soc->num_devs; i++) {
if (!eth->mac[i] || !eth->mac[i]->hw_stats)
continue;
if (spin_trylock(&eth->mac[i]->hw_stats->stats_lock)) {
@@ -1403,7 +1403,7 @@ static int mtk_queue_stopped(struct mtk_
{
int i;
- for (i = 0; i < MTK_MAC_COUNT; i++) {
+ for (i = 0; i < eth->soc->num_devs; i++) {
if (!eth->netdev[i])
continue;
if (netif_queue_stopped(eth->netdev[i]))
@@ -1417,7 +1417,7 @@ static void mtk_wake_queue(struct mtk_et
{
int i;
- for (i = 0; i < MTK_MAC_COUNT; i++) {
+ for (i = 0; i < eth->soc->num_devs; i++) {
if (!eth->netdev[i])
continue;
netif_tx_wake_all_queues(eth->netdev[i]);
@@ -1908,7 +1908,7 @@ static int mtk_poll_rx(struct napi_struc
!(trxd.rxd4 & RX_DMA_SPECIAL_TAG))
mac = RX_DMA_GET_SPORT(trxd.rxd4) - 1;
- if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT ||
+ if (unlikely(mac < 0 || mac >= eth->soc->num_devs ||
!eth->netdev[mac]))
goto release_desc;
@@ -2937,7 +2937,7 @@ static void mtk_dma_free(struct mtk_eth
const struct mtk_soc_data *soc = eth->soc;
int i;
- for (i = 0; i < MTK_MAC_COUNT; i++)
+ for (i = 0; i < soc->num_devs; i++)
if (eth->netdev[i])
netdev_reset_queue(eth->netdev[i]);
if (eth->scratch_ring) {
@@ -3091,7 +3091,7 @@ static void mtk_gdm_config(struct mtk_et
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628))
return;
- for (i = 0; i < MTK_MAC_COUNT; i++) {
+ for (i = 0; i < eth->soc->num_devs; i++) {
u32 val = mtk_r32(eth, MTK_GDMA_FWD_CFG(i));
/* default setup the forward port to send frame to PDMA */
@@ -3704,7 +3704,7 @@ static int mtk_hw_init(struct mtk_eth *e
* up with the more appropriate value when mtk_mac_config call is being
* invoked.
*/
- for (i = 0; i < MTK_MAC_COUNT; i++) {
+ for (i = 0; i < eth->soc->num_devs; i++) {
struct net_device *dev = eth->netdev[i];
mtk_w32(eth, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(i));
@@ -3909,7 +3909,7 @@ static void mtk_pending_work(struct work
mtk_prepare_for_reset(eth);
/* stop all devices to make sure that dma is properly shut down */
- for (i = 0; i < MTK_MAC_COUNT; i++) {
+ for (i = 0; i < eth->soc->num_devs; i++) {
if (!eth->netdev[i] || !netif_running(eth->netdev[i]))
continue;
@@ -3925,7 +3925,7 @@ static void mtk_pending_work(struct work
mtk_hw_init(eth, true);
/* restart DMA and enable IRQs */
- for (i = 0; i < MTK_MAC_COUNT; i++) {
+ for (i = 0; i < eth->soc->num_devs; i++) {
if (!test_bit(i, &restart))
continue;
@@ -3953,7 +3953,7 @@ static int mtk_free_dev(struct mtk_eth *
{
int i;
- for (i = 0; i < MTK_MAC_COUNT; i++) {
+ for (i = 0; i < eth->soc->num_devs; i++) {
if (!eth->netdev[i])
continue;
free_netdev(eth->netdev[i]);
@@ -3972,7 +3972,7 @@ static int mtk_unreg_dev(struct mtk_eth
{
int i;
- for (i = 0; i < MTK_MAC_COUNT; i++) {
+ for (i = 0; i < eth->soc->num_devs; i++) {
struct mtk_mac *mac;
if (!eth->netdev[i])
continue;
@@ -4277,7 +4277,7 @@ static int mtk_add_mac(struct mtk_eth *e
}
id = be32_to_cpup(_id);
- if (id >= MTK_MAC_COUNT) {
+ if (id >= eth->soc->num_devs) {
dev_err(eth->dev, "%d is not a valid mac id\n", id);
return -EINVAL;
}
@@ -4407,7 +4407,7 @@ void mtk_eth_set_dma_device(struct mtk_e
rtnl_lock();
- for (i = 0; i < MTK_MAC_COUNT; i++) {
+ for (i = 0; i < eth->soc->num_devs; i++) {
dev = eth->netdev[i];
if (!dev || !(dev->flags & IFF_UP))
@@ -4734,7 +4734,7 @@ static int mtk_remove(struct platform_de
int i;
/* stop all devices to make sure that dma is properly shut down */
- for (i = 0; i < MTK_MAC_COUNT; i++) {
+ for (i = 0; i < eth->soc->num_devs; i++) {
if (!eth->netdev[i])
continue;
mtk_stop(eth->netdev[i]);
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -33,7 +33,6 @@
#define MTK_TX_DMA_BUF_LEN_V2 0xffff
#define MTK_QDMA_RING_SIZE 2048
#define MTK_DMA_SIZE 512
-#define MTK_MAC_COUNT 2
#define MTK_RX_ETH_HLEN (VLAN_ETH_HLEN + ETH_FCS_LEN)
#define MTK_RX_HLEN (NET_SKB_PAD + MTK_RX_ETH_HLEN + NET_IP_ALIGN)
#define MTK_DMA_DUMMY_DESC 0xffffffff

View file

@ -0,0 +1,292 @@
From ab817f559d505329d8a413c7d29250f6d87d77a0 Mon Sep 17 00:00:00 2001
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Tue, 7 Mar 2023 15:55:47 +0000
Subject: [PATCH 4/7] net: ethernet: mtk_eth_soc: add MTK_NETSYS_V3 capability
bit
Introduce MTK_NETSYS_V3 bit in the device capabilities.
This is a preliminary patch to introduce support for MT7988 SoC.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 115 ++++++++++++++++----
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 44 +++++++-
2 files changed, 134 insertions(+), 25 deletions(-)
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -880,17 +880,32 @@ void mtk_stats_update_mac(struct mtk_mac
mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x20 + offs);
hw_stats->rx_flow_control_packets +=
mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x24 + offs);
- hw_stats->tx_skip +=
- mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x28 + offs);
- hw_stats->tx_collisions +=
- mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x2c + offs);
- hw_stats->tx_bytes +=
- mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x30 + offs);
- stats = mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x34 + offs);
- if (stats)
- hw_stats->tx_bytes += (stats << 32);
- hw_stats->tx_packets +=
- mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x38 + offs);
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+ hw_stats->tx_skip +=
+ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x50 + offs);
+ hw_stats->tx_collisions +=
+ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x54 + offs);
+ hw_stats->tx_bytes +=
+ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x40 + offs);
+ stats = mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x44 + offs);
+ if (stats)
+ hw_stats->tx_bytes += (stats << 32);
+ hw_stats->tx_packets +=
+ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x48 + offs);
+ } else {
+ hw_stats->tx_skip +=
+ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x28 + offs);
+ hw_stats->tx_collisions +=
+ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x2c + offs);
+ hw_stats->tx_bytes +=
+ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x30 + offs);
+ stats = mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x34 + offs);
+ if (stats)
+ hw_stats->tx_bytes += (stats << 32);
+ hw_stats->tx_packets +=
+ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x38 + offs);
+ }
}
u64_stats_update_end(&hw_stats->syncp);
@@ -1192,7 +1207,10 @@ static void mtk_tx_set_dma_desc_v2(struc
data |= TX_DMA_LS0;
WRITE_ONCE(desc->txd3, data);
- data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */
+ if (mac->id == MTK_GMAC3_ID)
+ data = PSE_GDM3_PORT;
+ else
+ data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */
data |= TX_DMA_SWC_V2 | QID_BITS_V2(info->qid);
WRITE_ONCE(desc->txd4, data);
@@ -1203,6 +1221,9 @@ static void mtk_tx_set_dma_desc_v2(struc
/* tx checksum offload */
if (info->csum)
data |= TX_DMA_CHKSUM_V2;
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3) &&
+ netdev_uses_dsa(dev))
+ data |= TX_DMA_SPTAG_V3;
}
WRITE_ONCE(desc->txd5, data);
@@ -1268,8 +1289,13 @@ static int mtk_tx_map(struct sk_buff *sk
mtk_tx_set_dma_desc(dev, itxd, &txd_info);
itx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
- itx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 :
- MTK_TX_FLAGS_FPORT1;
+ if (mac->id == MTK_GMAC1_ID)
+ itx_buf->flags |= MTK_TX_FLAGS_FPORT0;
+ else if (mac->id == MTK_GMAC2_ID)
+ itx_buf->flags |= MTK_TX_FLAGS_FPORT1;
+ else
+ itx_buf->flags |= MTK_TX_FLAGS_FPORT2;
+
setup_tx_buf(eth, itx_buf, itxd_pdma, txd_info.addr, txd_info.size,
k++);
@@ -1317,8 +1343,13 @@ static int mtk_tx_map(struct sk_buff *sk
memset(tx_buf, 0, sizeof(*tx_buf));
tx_buf->data = (void *)MTK_DMA_DUMMY_DESC;
tx_buf->flags |= MTK_TX_FLAGS_PAGE0;
- tx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 :
- MTK_TX_FLAGS_FPORT1;
+
+ if (mac->id == MTK_GMAC1_ID)
+ tx_buf->flags |= MTK_TX_FLAGS_FPORT0;
+ else if (mac->id == MTK_GMAC2_ID)
+ tx_buf->flags |= MTK_TX_FLAGS_FPORT1;
+ else
+ tx_buf->flags |= MTK_TX_FLAGS_FPORT2;
setup_tx_buf(eth, tx_buf, txd_pdma, txd_info.addr,
txd_info.size, k++);
@@ -1902,11 +1933,24 @@ static int mtk_poll_rx(struct napi_struc
break;
/* find out which mac the packet come from. values start at 1 */
- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1))
- mac = RX_DMA_GET_SPORT_V2(trxd.rxd5) - 1;
- else if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) &&
- !(trxd.rxd4 & RX_DMA_SPECIAL_TAG))
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) {
+ u32 val = RX_DMA_GET_SPORT_V2(trxd.rxd5);
+
+ switch (val) {
+ case PSE_GDM1_PORT:
+ case PSE_GDM2_PORT:
+ mac = val - 1;
+ break;
+ case PSE_GDM3_PORT:
+ mac = MTK_GMAC3_ID;
+ break;
+ default:
+ break;
+ }
+ } else if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) &&
+ !(trxd.rxd4 & RX_DMA_SPECIAL_TAG)) {
mac = RX_DMA_GET_SPORT(trxd.rxd4) - 1;
+ }
if (unlikely(mac < 0 || mac >= eth->soc->num_devs ||
!eth->netdev[mac]))
@@ -2135,7 +2179,9 @@ static int mtk_poll_tx_qdma(struct mtk_e
tx_buf = mtk_desc_to_tx_buf(ring, desc,
eth->soc->txrx.txd_size);
if (tx_buf->flags & MTK_TX_FLAGS_FPORT1)
- mac = 1;
+ mac = MTK_GMAC2_ID;
+ else if (tx_buf->flags & MTK_TX_FLAGS_FPORT2)
+ mac = MTK_GMAC3_ID;
if (!tx_buf->data)
break;
@@ -3742,7 +3788,26 @@ static int mtk_hw_init(struct mtk_eth *e
mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->qdma.int_grp + 4);
mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP);
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+ /* PSE should not drop port1, port8 and port9 packets */
+ mtk_w32(eth, 0x00000302, PSE_DROP_CFG);
+
+ /* GDM and CDM Threshold */
+ mtk_w32(eth, 0x00000707, MTK_CDMW0_THRES);
+ mtk_w32(eth, 0x00000077, MTK_CDMW1_THRES);
+
+ /* Disable GDM1 RX CRC stripping */
+ val = mtk_r32(eth, MTK_GDMA_FWD_CFG(0));
+ val &= ~MTK_GDMA_STRP_CRC;
+ mtk_w32(eth, val, MTK_GDMA_FWD_CFG(0));
+
+ /* PSE GDM3 MIB counter has incorrect hw default values,
+ * so the driver ought to read clear the values beforehand
+ * in case ethtool retrieve wrong mib values.
+ */
+ for (i = 0; i < 0x80; i += 0x4)
+ mtk_r32(eth, reg_map->gdm1_cnt + 0x100 + i);
+ } else if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
/* PSE should not drop port8 and port9 packets from WDMA Tx */
mtk_w32(eth, 0x00000300, PSE_DROP_CFG);
@@ -4314,7 +4379,11 @@ static int mtk_add_mac(struct mtk_eth *e
}
spin_lock_init(&mac->hw_stats->stats_lock);
u64_stats_init(&mac->hw_stats->syncp);
- mac->hw_stats->reg_offset = id * MTK_STAT_OFFSET;
+
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3))
+ mac->hw_stats->reg_offset = id * 0x80;
+ else
+ mac->hw_stats->reg_offset = id * 0x40;
/* phylink create */
err = of_get_phy_mode(np, &phy_mode);
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -121,6 +121,7 @@
#define MTK_GDMA_ICS_EN BIT(22)
#define MTK_GDMA_TCS_EN BIT(21)
#define MTK_GDMA_UCS_EN BIT(20)
+#define MTK_GDMA_STRP_CRC BIT(16)
#define MTK_GDMA_TO_PDMA 0x0
#define MTK_GDMA_DROP_ALL 0x7777
@@ -286,8 +287,6 @@
/* QDMA Interrupt grouping registers */
#define MTK_RLS_DONE_INT BIT(0)
-#define MTK_STAT_OFFSET 0x40
-
/* QDMA TX NUM */
#define QID_BITS_V2(x) (((x) & 0x3f) << 16)
#define MTK_QDMA_GMAC2_QID 8
@@ -300,6 +299,8 @@
#define TX_DMA_CHKSUM_V2 (0x7 << 28)
#define TX_DMA_TSO_V2 BIT(31)
+#define TX_DMA_SPTAG_V3 BIT(27)
+
/* QDMA V2 descriptor txd4 */
#define TX_DMA_FPORT_SHIFT_V2 8
#define TX_DMA_FPORT_MASK_V2 0xf
@@ -636,6 +637,7 @@ enum mtk_tx_flags {
*/
MTK_TX_FLAGS_FPORT0 = 0x04,
MTK_TX_FLAGS_FPORT1 = 0x08,
+ MTK_TX_FLAGS_FPORT2 = 0x10,
};
/* This enum allows us to identify how the clock is defined on the array of the
@@ -721,6 +723,42 @@ enum mtk_dev_state {
MTK_RESETTING
};
+/* PSE Port Definition */
+enum mtk_pse_port {
+ PSE_ADMA_PORT = 0,
+ PSE_GDM1_PORT,
+ PSE_GDM2_PORT,
+ PSE_PPE0_PORT,
+ PSE_PPE1_PORT,
+ PSE_QDMA_TX_PORT,
+ PSE_QDMA_RX_PORT,
+ PSE_DROP_PORT,
+ PSE_WDMA0_PORT,
+ PSE_WDMA1_PORT,
+ PSE_TDMA_PORT,
+ PSE_NONE_PORT,
+ PSE_PPE2_PORT,
+ PSE_WDMA2_PORT,
+ PSE_EIP197_PORT,
+ PSE_GDM3_PORT,
+ PSE_PORT_MAX
+};
+
+/* GMAC Identifier */
+enum mtk_gmac_id {
+ MTK_GMAC1_ID = 0,
+ MTK_GMAC2_ID,
+ MTK_GMAC3_ID,
+ MTK_GMAC_ID_MAX
+};
+
+/* GDM Type */
+enum mtk_gdm_type {
+ MTK_GDM_TYPE = 0,
+ MTK_XGDM_TYPE,
+ MTK_GDM_TYPE_MAX
+};
+
enum mtk_tx_buf_type {
MTK_TYPE_SKB,
MTK_TYPE_XDP_TX,
@@ -817,6 +855,7 @@ enum mkt_eth_capabilities {
MTK_QDMA_BIT,
MTK_NETSYS_V1_BIT,
MTK_NETSYS_V2_BIT,
+ MTK_NETSYS_V3_BIT,
MTK_SOC_MT7628_BIT,
MTK_RSTCTRL_PPE1_BIT,
MTK_U3_COPHY_V2_BIT,
@@ -853,6 +892,7 @@ enum mkt_eth_capabilities {
#define MTK_QDMA BIT(MTK_QDMA_BIT)
#define MTK_NETSYS_V1 BIT(MTK_NETSYS_V1_BIT)
#define MTK_NETSYS_V2 BIT(MTK_NETSYS_V2_BIT)
+#define MTK_NETSYS_V3 BIT(MTK_NETSYS_V3_BIT)
#define MTK_SOC_MT7628 BIT(MTK_SOC_MT7628_BIT)
#define MTK_RSTCTRL_PPE1 BIT(MTK_RSTCTRL_PPE1_BIT)
#define MTK_U3_COPHY_V2 BIT(MTK_U3_COPHY_V2_BIT)

View file

@ -0,0 +1,197 @@
From 45b575fd9e6a455090820248bf1b98b1f2c7b6c8 Mon Sep 17 00:00:00 2001
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Tue, 7 Mar 2023 15:56:00 +0000
Subject: [PATCH 5/7] net: ethernet: mtk_eth_soc: convert caps in mtk_soc_data
struct to u64
This is a preliminary patch to introduce support for MT7988 SoC.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/ethernet/mediatek/mtk_eth_path.c | 22 +++----
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 62 ++++++++++----------
2 files changed, 42 insertions(+), 42 deletions(-)
--- a/drivers/net/ethernet/mediatek/mtk_eth_path.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c
@@ -15,10 +15,10 @@
struct mtk_eth_muxc {
const char *name;
int cap_bit;
- int (*set_path)(struct mtk_eth *eth, int path);
+ int (*set_path)(struct mtk_eth *eth, u64 path);
};
-static const char *mtk_eth_path_name(int path)
+static const char *mtk_eth_path_name(u64 path)
{
switch (path) {
case MTK_ETH_PATH_GMAC1_RGMII:
@@ -40,7 +40,7 @@ static const char *mtk_eth_path_name(int
}
}
-static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, int path)
+static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, u64 path)
{
bool updated = true;
u32 val, mask, set;
@@ -71,7 +71,7 @@ static int set_mux_gdm1_to_gmac1_esw(str
return 0;
}
-static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, int path)
+static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, u64 path)
{
unsigned int val = 0;
bool updated = true;
@@ -94,7 +94,7 @@ static int set_mux_gmac2_gmac0_to_gephy(
return 0;
}
-static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, int path)
+static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, u64 path)
{
unsigned int val = 0, mask = 0, reg = 0;
bool updated = true;
@@ -125,7 +125,7 @@ static int set_mux_u3_gmac2_to_qphy(stru
return 0;
}
-static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, int path)
+static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, u64 path)
{
unsigned int val = 0;
bool updated = true;
@@ -163,7 +163,7 @@ static int set_mux_gmac1_gmac2_to_sgmii_
return 0;
}
-static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, int path)
+static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, u64 path)
{
unsigned int val = 0;
bool updated = true;
@@ -218,7 +218,7 @@ static const struct mtk_eth_muxc mtk_eth
},
};
-static int mtk_eth_mux_setup(struct mtk_eth *eth, int path)
+static int mtk_eth_mux_setup(struct mtk_eth *eth, u64 path)
{
int i, err = 0;
@@ -249,7 +249,7 @@ out:
int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
{
- int path;
+ u64 path;
path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_SGMII :
MTK_ETH_PATH_GMAC2_SGMII;
@@ -260,7 +260,7 @@ int mtk_gmac_sgmii_path_setup(struct mtk
int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
{
- int path = 0;
+ u64 path = 0;
if (mac_id == 1)
path = MTK_ETH_PATH_GMAC2_GEPHY;
@@ -274,7 +274,7 @@ int mtk_gmac_gephy_path_setup(struct mtk
int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
{
- int path;
+ u64 path;
path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_RGMII :
MTK_ETH_PATH_GMAC2_RGMII;
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -878,44 +878,44 @@ enum mkt_eth_capabilities {
};
/* Supported hardware group on SoCs */
-#define MTK_RGMII BIT(MTK_RGMII_BIT)
-#define MTK_TRGMII BIT(MTK_TRGMII_BIT)
-#define MTK_SGMII BIT(MTK_SGMII_BIT)
-#define MTK_ESW BIT(MTK_ESW_BIT)
-#define MTK_GEPHY BIT(MTK_GEPHY_BIT)
-#define MTK_MUX BIT(MTK_MUX_BIT)
-#define MTK_INFRA BIT(MTK_INFRA_BIT)
-#define MTK_SHARED_SGMII BIT(MTK_SHARED_SGMII_BIT)
-#define MTK_HWLRO BIT(MTK_HWLRO_BIT)
-#define MTK_SHARED_INT BIT(MTK_SHARED_INT_BIT)
-#define MTK_TRGMII_MT7621_CLK BIT(MTK_TRGMII_MT7621_CLK_BIT)
-#define MTK_QDMA BIT(MTK_QDMA_BIT)
-#define MTK_NETSYS_V1 BIT(MTK_NETSYS_V1_BIT)
-#define MTK_NETSYS_V2 BIT(MTK_NETSYS_V2_BIT)
-#define MTK_NETSYS_V3 BIT(MTK_NETSYS_V3_BIT)
-#define MTK_SOC_MT7628 BIT(MTK_SOC_MT7628_BIT)
-#define MTK_RSTCTRL_PPE1 BIT(MTK_RSTCTRL_PPE1_BIT)
-#define MTK_U3_COPHY_V2 BIT(MTK_U3_COPHY_V2_BIT)
+#define MTK_RGMII BIT_ULL(MTK_RGMII_BIT)
+#define MTK_TRGMII BIT_ULL(MTK_TRGMII_BIT)
+#define MTK_SGMII BIT_ULL(MTK_SGMII_BIT)
+#define MTK_ESW BIT_ULL(MTK_ESW_BIT)
+#define MTK_GEPHY BIT_ULL(MTK_GEPHY_BIT)
+#define MTK_MUX BIT_ULL(MTK_MUX_BIT)
+#define MTK_INFRA BIT_ULL(MTK_INFRA_BIT)
+#define MTK_SHARED_SGMII BIT_ULL(MTK_SHARED_SGMII_BIT)
+#define MTK_HWLRO BIT_ULL(MTK_HWLRO_BIT)
+#define MTK_SHARED_INT BIT_ULL(MTK_SHARED_INT_BIT)
+#define MTK_TRGMII_MT7621_CLK BIT_ULL(MTK_TRGMII_MT7621_CLK_BIT)
+#define MTK_QDMA BIT_ULL(MTK_QDMA_BIT)
+#define MTK_NETSYS_V1 BIT_ULL(MTK_NETSYS_V1_BIT)
+#define MTK_NETSYS_V2 BIT_ULL(MTK_NETSYS_V2_BIT)
+#define MTK_NETSYS_V3 BIT_ULL(MTK_NETSYS_V3_BIT)
+#define MTK_SOC_MT7628 BIT_ULL(MTK_SOC_MT7628_BIT)
+#define MTK_RSTCTRL_PPE1 BIT_ULL(MTK_RSTCTRL_PPE1_BIT)
+#define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT)
#define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \
- BIT(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT)
+ BIT_ULL(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT)
#define MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY \
- BIT(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT)
+ BIT_ULL(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT)
#define MTK_ETH_MUX_U3_GMAC2_TO_QPHY \
- BIT(MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT)
+ BIT_ULL(MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT)
#define MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII \
- BIT(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT)
+ BIT_ULL(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT)
#define MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII \
- BIT(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT)
+ BIT_ULL(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT)
/* Supported path present on SoCs */
-#define MTK_ETH_PATH_GMAC1_RGMII BIT(MTK_ETH_PATH_GMAC1_RGMII_BIT)
-#define MTK_ETH_PATH_GMAC1_TRGMII BIT(MTK_ETH_PATH_GMAC1_TRGMII_BIT)
-#define MTK_ETH_PATH_GMAC1_SGMII BIT(MTK_ETH_PATH_GMAC1_SGMII_BIT)
-#define MTK_ETH_PATH_GMAC2_RGMII BIT(MTK_ETH_PATH_GMAC2_RGMII_BIT)
-#define MTK_ETH_PATH_GMAC2_SGMII BIT(MTK_ETH_PATH_GMAC2_SGMII_BIT)
-#define MTK_ETH_PATH_GMAC2_GEPHY BIT(MTK_ETH_PATH_GMAC2_GEPHY_BIT)
-#define MTK_ETH_PATH_GDM1_ESW BIT(MTK_ETH_PATH_GDM1_ESW_BIT)
+#define MTK_ETH_PATH_GMAC1_RGMII BIT_ULL(MTK_ETH_PATH_GMAC1_RGMII_BIT)
+#define MTK_ETH_PATH_GMAC1_TRGMII BIT_ULL(MTK_ETH_PATH_GMAC1_TRGMII_BIT)
+#define MTK_ETH_PATH_GMAC1_SGMII BIT_ULL(MTK_ETH_PATH_GMAC1_SGMII_BIT)
+#define MTK_ETH_PATH_GMAC2_RGMII BIT_ULL(MTK_ETH_PATH_GMAC2_RGMII_BIT)
+#define MTK_ETH_PATH_GMAC2_SGMII BIT_ULL(MTK_ETH_PATH_GMAC2_SGMII_BIT)
+#define MTK_ETH_PATH_GMAC2_GEPHY BIT_ULL(MTK_ETH_PATH_GMAC2_GEPHY_BIT)
+#define MTK_ETH_PATH_GDM1_ESW BIT_ULL(MTK_ETH_PATH_GDM1_ESW_BIT)
#define MTK_GMAC1_RGMII (MTK_ETH_PATH_GMAC1_RGMII | MTK_RGMII)
#define MTK_GMAC1_TRGMII (MTK_ETH_PATH_GMAC1_TRGMII | MTK_TRGMII)
@@ -1071,7 +1071,7 @@ struct mtk_reg_map {
struct mtk_soc_data {
const struct mtk_reg_map *reg_map;
u32 ana_rgc3;
- u32 caps;
+ u64 caps;
u32 required_clks;
bool required_pctl;
u8 offload_version;

View file

@ -0,0 +1,495 @@
From 661bacf4363ca68939c15e20056b5f72fbd034e7 Mon Sep 17 00:00:00 2001
From: Lorenzo Bianconi <lorenzo@kernel.org>
Date: Sat, 25 Feb 2023 00:08:24 +0100
Subject: [PATCH 6/7] net: ethernet: mtk_eth_soc: add support for MT7988 SoC
Introduce support for ethernet chip available in MT7988 SoC to
mtk_eth_soc driver.
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 153 ++++++++++++++--
drivers/net/ethernet/mediatek/mtk_eth_soc.h | 193 ++++++++++++++------
2 files changed, 279 insertions(+), 67 deletions(-)
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -152,6 +152,54 @@ static const struct mtk_reg_map mt7986_r
.pse_oq_sta = 0x01a0,
};
+static const struct mtk_reg_map mt7988_reg_map = {
+ .tx_irq_mask = 0x461c,
+ .tx_irq_status = 0x4618,
+ .pdma = {
+ .rx_ptr = 0x6900,
+ .rx_cnt_cfg = 0x6904,
+ .pcrx_ptr = 0x6908,
+ .glo_cfg = 0x6a04,
+ .rst_idx = 0x6a08,
+ .delay_irq = 0x6a0c,
+ .irq_status = 0x6a20,
+ .irq_mask = 0x6a28,
+ .adma_rx_dbg0 = 0x6a38,
+ .int_grp = 0x6a50,
+ },
+ .qdma = {
+ .qtx_cfg = 0x4400,
+ .qtx_sch = 0x4404,
+ .rx_ptr = 0x4500,
+ .rx_cnt_cfg = 0x4504,
+ .qcrx_ptr = 0x4508,
+ .glo_cfg = 0x4604,
+ .rst_idx = 0x4608,
+ .delay_irq = 0x460c,
+ .fc_th = 0x4610,
+ .int_grp = 0x4620,
+ .hred = 0x4644,
+ .ctx_ptr = 0x4700,
+ .dtx_ptr = 0x4704,
+ .crx_ptr = 0x4710,
+ .drx_ptr = 0x4714,
+ .fq_head = 0x4720,
+ .fq_tail = 0x4724,
+ .fq_count = 0x4728,
+ .fq_blen = 0x472c,
+ .tx_sch_rate = 0x4798,
+ },
+ .gdm1_cnt = 0x1c00,
+ .gdma_to_ppe0 = 0x3333,
+ .ppe_base = 0x2200,
+ .wdma_base = {
+ [0] = 0x4800,
+ [1] = 0x4c00,
+ },
+ .pse_iq_sta = 0x0180,
+ .pse_oq_sta = 0x01a0,
+};
+
/* strings used by ethtool */
static const struct mtk_ethtool_stats {
char str[ETH_GSTRING_LEN];
@@ -179,10 +227,54 @@ static const struct mtk_ethtool_stats {
};
static const char * const mtk_clks_source_name[] = {
- "ethif", "sgmiitop", "esw", "gp0", "gp1", "gp2", "fe", "trgpll",
- "sgmii_tx250m", "sgmii_rx250m", "sgmii_cdr_ref", "sgmii_cdr_fb",
- "sgmii2_tx250m", "sgmii2_rx250m", "sgmii2_cdr_ref", "sgmii2_cdr_fb",
- "sgmii_ck", "eth2pll", "wocpu0", "wocpu1", "netsys0", "netsys1"
+ "ethif",
+ "sgmiitop",
+ "esw",
+ "gp0",
+ "gp1",
+ "gp2",
+ "gp3",
+ "xgp1",
+ "xgp2",
+ "xgp3",
+ "crypto",
+ "fe",
+ "trgpll",
+ "sgmii_tx250m",
+ "sgmii_rx250m",
+ "sgmii_cdr_ref",
+ "sgmii_cdr_fb",
+ "sgmii2_tx250m",
+ "sgmii2_rx250m",
+ "sgmii2_cdr_ref",
+ "sgmii2_cdr_fb",
+ "sgmii_ck",
+ "eth2pll",
+ "wocpu0",
+ "wocpu1",
+ "netsys0",
+ "netsys1",
+ "ethwarp_wocpu2",
+ "ethwarp_wocpu1",
+ "ethwarp_wocpu0",
+ "top_usxgmii0_sel",
+ "top_usxgmii1_sel",
+ "top_sgm0_sel",
+ "top_sgm1_sel",
+ "top_xfi_phy0_xtal_sel",
+ "top_xfi_phy1_xtal_sel",
+ "top_eth_gmii_sel",
+ "top_eth_refck_50m_sel",
+ "top_eth_sys_200m_sel",
+ "top_eth_sys_sel",
+ "top_eth_xgmii_sel",
+ "top_eth_mii_sel",
+ "top_netsys_sel",
+ "top_netsys_500m_sel",
+ "top_netsys_pao_2x_sel",
+ "top_netsys_sync_250m_sel",
+ "top_netsys_ppefb_250m_sel",
+ "top_netsys_warp_sel",
};
void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg)
@@ -1207,10 +1299,19 @@ static void mtk_tx_set_dma_desc_v2(struc
data |= TX_DMA_LS0;
WRITE_ONCE(desc->txd3, data);
- if (mac->id == MTK_GMAC3_ID)
- data = PSE_GDM3_PORT;
- else
- data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */
+ /* set forward port */
+ switch (mac->id) {
+ case MTK_GMAC1_ID:
+ data = PSE_GDM1_PORT << TX_DMA_FPORT_SHIFT_V2;
+ break;
+ case MTK_GMAC2_ID:
+ data = PSE_GDM2_PORT << TX_DMA_FPORT_SHIFT_V2;
+ break;
+ case MTK_GMAC3_ID:
+ data = PSE_GDM3_PORT << TX_DMA_FPORT_SHIFT_V2;
+ break;
+ }
+
data |= TX_DMA_SWC_V2 | QID_BITS_V2(info->qid);
WRITE_ONCE(desc->txd4, data);
@@ -4964,6 +5065,25 @@ static const struct mtk_soc_data mt7986_
},
};
+static const struct mtk_soc_data mt7988_data = {
+ .reg_map = &mt7988_reg_map,
+ .ana_rgc3 = 0x128,
+ .caps = MT7988_CAPS,
+ .hw_features = MTK_HW_FEATURES,
+ .required_clks = MT7988_CLKS_BITMAP,
+ .required_pctl = false,
+ .num_devs = 3,
+ .txrx = {
+ .txd_size = sizeof(struct mtk_tx_dma_v2),
+ .rxd_size = sizeof(struct mtk_rx_dma_v2),
+ .rx_irq_done_mask = MTK_RX_DONE_INT_V2,
+ .rx_dma_l4_valid = RX_DMA_L4_VALID_V2,
+ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
+ .dma_len_offset = 8,
+ },
+};
+
+
static const struct mtk_soc_data rt5350_data = {
.reg_map = &mt7628_reg_map,
.caps = MT7628_CAPS,
@@ -4982,14 +5102,15 @@ static const struct mtk_soc_data rt5350_
};
const struct of_device_id of_mtk_match[] = {
- { .compatible = "mediatek,mt2701-eth", .data = &mt2701_data},
- { .compatible = "mediatek,mt7621-eth", .data = &mt7621_data},
- { .compatible = "mediatek,mt7622-eth", .data = &mt7622_data},
- { .compatible = "mediatek,mt7623-eth", .data = &mt7623_data},
- { .compatible = "mediatek,mt7629-eth", .data = &mt7629_data},
- { .compatible = "mediatek,mt7981-eth", .data = &mt7981_data},
- { .compatible = "mediatek,mt7986-eth", .data = &mt7986_data},
- { .compatible = "ralink,rt5350-eth", .data = &rt5350_data},
+ { .compatible = "mediatek,mt2701-eth", .data = &mt2701_data },
+ { .compatible = "mediatek,mt7621-eth", .data = &mt7621_data },
+ { .compatible = "mediatek,mt7622-eth", .data = &mt7622_data },
+ { .compatible = "mediatek,mt7623-eth", .data = &mt7623_data },
+ { .compatible = "mediatek,mt7629-eth", .data = &mt7629_data },
+ { .compatible = "mediatek,mt7981-eth", .data = &mt7981_data },
+ { .compatible = "mediatek,mt7986-eth", .data = &mt7986_data },
+ { .compatible = "mediatek,mt7988-eth", .data = &mt7988_data },
+ { .compatible = "ralink,rt5350-eth", .data = &rt5350_data },
{},
};
MODULE_DEVICE_TABLE(of, of_mtk_match);
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -116,7 +116,8 @@
#define MTK_CDMP_EG_CTRL 0x404
/* GDM Exgress Control Register */
-#define MTK_GDMA_FWD_CFG(x) (0x500 + (x * 0x1000))
+#define MTK_GDMA_FWD_CFG(x) ((x == MTK_GMAC3_ID) ? \
+ 0x540 : 0x500 + (x * 0x1000))
#define MTK_GDMA_SPECIAL_TAG BIT(24)
#define MTK_GDMA_ICS_EN BIT(22)
#define MTK_GDMA_TCS_EN BIT(21)
@@ -650,6 +651,11 @@ enum mtk_clks_map {
MTK_CLK_GP0,
MTK_CLK_GP1,
MTK_CLK_GP2,
+ MTK_CLK_GP3,
+ MTK_CLK_XGP1,
+ MTK_CLK_XGP2,
+ MTK_CLK_XGP3,
+ MTK_CLK_CRYPTO,
MTK_CLK_FE,
MTK_CLK_TRGPLL,
MTK_CLK_SGMII_TX_250M,
@@ -666,57 +672,108 @@ enum mtk_clks_map {
MTK_CLK_WOCPU1,
MTK_CLK_NETSYS0,
MTK_CLK_NETSYS1,
+ MTK_CLK_ETHWARP_WOCPU2,
+ MTK_CLK_ETHWARP_WOCPU1,
+ MTK_CLK_ETHWARP_WOCPU0,
+ MTK_CLK_TOP_USXGMII_SBUS_0_SEL,
+ MTK_CLK_TOP_USXGMII_SBUS_1_SEL,
+ MTK_CLK_TOP_SGM_0_SEL,
+ MTK_CLK_TOP_SGM_1_SEL,
+ MTK_CLK_TOP_XFI_PHY_0_XTAL_SEL,
+ MTK_CLK_TOP_XFI_PHY_1_XTAL_SEL,
+ MTK_CLK_TOP_ETH_GMII_SEL,
+ MTK_CLK_TOP_ETH_REFCK_50M_SEL,
+ MTK_CLK_TOP_ETH_SYS_200M_SEL,
+ MTK_CLK_TOP_ETH_SYS_SEL,
+ MTK_CLK_TOP_ETH_XGMII_SEL,
+ MTK_CLK_TOP_ETH_MII_SEL,
+ MTK_CLK_TOP_NETSYS_SEL,
+ MTK_CLK_TOP_NETSYS_500M_SEL,
+ MTK_CLK_TOP_NETSYS_PAO_2X_SEL,
+ MTK_CLK_TOP_NETSYS_SYNC_250M_SEL,
+ MTK_CLK_TOP_NETSYS_PPEFB_250M_SEL,
+ MTK_CLK_TOP_NETSYS_WARP_SEL,
MTK_CLK_MAX
};
-#define MT7623_CLKS_BITMAP (BIT(MTK_CLK_ETHIF) | BIT(MTK_CLK_ESW) | \
- BIT(MTK_CLK_GP1) | BIT(MTK_CLK_GP2) | \
- BIT(MTK_CLK_TRGPLL))
-#define MT7622_CLKS_BITMAP (BIT(MTK_CLK_ETHIF) | BIT(MTK_CLK_ESW) | \
- BIT(MTK_CLK_GP0) | BIT(MTK_CLK_GP1) | \
- BIT(MTK_CLK_GP2) | \
- BIT(MTK_CLK_SGMII_TX_250M) | \
- BIT(MTK_CLK_SGMII_RX_250M) | \
- BIT(MTK_CLK_SGMII_CDR_REF) | \
- BIT(MTK_CLK_SGMII_CDR_FB) | \
- BIT(MTK_CLK_SGMII_CK) | \
- BIT(MTK_CLK_ETH2PLL))
+#define MT7623_CLKS_BITMAP (BIT_ULL(MTK_CLK_ETHIF) | BIT_ULL(MTK_CLK_ESW) | \
+ BIT_ULL(MTK_CLK_GP1) | BIT_ULL(MTK_CLK_GP2) | \
+ BIT_ULL(MTK_CLK_TRGPLL))
+#define MT7622_CLKS_BITMAP (BIT_ULL(MTK_CLK_ETHIF) | BIT_ULL(MTK_CLK_ESW) | \
+ BIT_ULL(MTK_CLK_GP0) | BIT_ULL(MTK_CLK_GP1) | \
+ BIT_ULL(MTK_CLK_GP2) | \
+ BIT_ULL(MTK_CLK_SGMII_TX_250M) | \
+ BIT_ULL(MTK_CLK_SGMII_RX_250M) | \
+ BIT_ULL(MTK_CLK_SGMII_CDR_REF) | \
+ BIT_ULL(MTK_CLK_SGMII_CDR_FB) | \
+ BIT_ULL(MTK_CLK_SGMII_CK) | \
+ BIT_ULL(MTK_CLK_ETH2PLL))
#define MT7621_CLKS_BITMAP (0)
#define MT7628_CLKS_BITMAP (0)
-#define MT7629_CLKS_BITMAP (BIT(MTK_CLK_ETHIF) | BIT(MTK_CLK_ESW) | \
- BIT(MTK_CLK_GP0) | BIT(MTK_CLK_GP1) | \
- BIT(MTK_CLK_GP2) | BIT(MTK_CLK_FE) | \
- BIT(MTK_CLK_SGMII_TX_250M) | \
- BIT(MTK_CLK_SGMII_RX_250M) | \
- BIT(MTK_CLK_SGMII_CDR_REF) | \
- BIT(MTK_CLK_SGMII_CDR_FB) | \
- BIT(MTK_CLK_SGMII2_TX_250M) | \
- BIT(MTK_CLK_SGMII2_RX_250M) | \
- BIT(MTK_CLK_SGMII2_CDR_REF) | \
- BIT(MTK_CLK_SGMII2_CDR_FB) | \
- BIT(MTK_CLK_SGMII_CK) | \
- BIT(MTK_CLK_ETH2PLL) | BIT(MTK_CLK_SGMIITOP))
-#define MT7981_CLKS_BITMAP (BIT(MTK_CLK_FE) | BIT(MTK_CLK_GP2) | BIT(MTK_CLK_GP1) | \
- BIT(MTK_CLK_WOCPU0) | \
- BIT(MTK_CLK_SGMII_TX_250M) | \
- BIT(MTK_CLK_SGMII_RX_250M) | \
- BIT(MTK_CLK_SGMII_CDR_REF) | \
- BIT(MTK_CLK_SGMII_CDR_FB) | \
- BIT(MTK_CLK_SGMII2_TX_250M) | \
- BIT(MTK_CLK_SGMII2_RX_250M) | \
- BIT(MTK_CLK_SGMII2_CDR_REF) | \
- BIT(MTK_CLK_SGMII2_CDR_FB) | \
- BIT(MTK_CLK_SGMII_CK))
-#define MT7986_CLKS_BITMAP (BIT(MTK_CLK_FE) | BIT(MTK_CLK_GP2) | BIT(MTK_CLK_GP1) | \
- BIT(MTK_CLK_WOCPU1) | BIT(MTK_CLK_WOCPU0) | \
- BIT(MTK_CLK_SGMII_TX_250M) | \
- BIT(MTK_CLK_SGMII_RX_250M) | \
- BIT(MTK_CLK_SGMII_CDR_REF) | \
- BIT(MTK_CLK_SGMII_CDR_FB) | \
- BIT(MTK_CLK_SGMII2_TX_250M) | \
- BIT(MTK_CLK_SGMII2_RX_250M) | \
- BIT(MTK_CLK_SGMII2_CDR_REF) | \
- BIT(MTK_CLK_SGMII2_CDR_FB))
+#define MT7629_CLKS_BITMAP (BIT_ULL(MTK_CLK_ETHIF) | BIT_ULL(MTK_CLK_ESW) | \
+ BIT_ULL(MTK_CLK_GP0) | BIT_ULL(MTK_CLK_GP1) | \
+ BIT_ULL(MTK_CLK_GP2) | BIT_ULL(MTK_CLK_FE) | \
+ BIT_ULL(MTK_CLK_SGMII_TX_250M) | \
+ BIT_ULL(MTK_CLK_SGMII_RX_250M) | \
+ BIT_ULL(MTK_CLK_SGMII_CDR_REF) | \
+ BIT_ULL(MTK_CLK_SGMII_CDR_FB) | \
+ BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \
+ BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \
+ BIT_ULL(MTK_CLK_SGMII2_CDR_REF) | \
+ BIT_ULL(MTK_CLK_SGMII2_CDR_FB) | \
+ BIT_ULL(MTK_CLK_SGMII_CK) | \
+ BIT_ULL(MTK_CLK_ETH2PLL) | BIT_ULL(MTK_CLK_SGMIITOP))
+#define MT7981_CLKS_BITMAP (BIT_ULL(MTK_CLK_FE) | BIT_ULL(MTK_CLK_GP2) | BIT_ULL(MTK_CLK_GP1) | \
+ BIT_ULL(MTK_CLK_WOCPU0) | \
+ BIT_ULL(MTK_CLK_SGMII_TX_250M) | \
+ BIT_ULL(MTK_CLK_SGMII_RX_250M) | \
+ BIT_ULL(MTK_CLK_SGMII_CDR_REF) | \
+ BIT_ULL(MTK_CLK_SGMII_CDR_FB) | \
+ BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \
+ BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \
+ BIT_ULL(MTK_CLK_SGMII2_CDR_REF) | \
+ BIT_ULL(MTK_CLK_SGMII2_CDR_FB) | \
+ BIT_ULL(MTK_CLK_SGMII_CK))
+#define MT7986_CLKS_BITMAP (BIT_ULL(MTK_CLK_FE) | BIT_ULL(MTK_CLK_GP2) | BIT_ULL(MTK_CLK_GP1) | \
+ BIT_ULL(MTK_CLK_WOCPU1) | BIT_ULL(MTK_CLK_WOCPU0) | \
+ BIT_ULL(MTK_CLK_SGMII_TX_250M) | \
+ BIT_ULL(MTK_CLK_SGMII_RX_250M) | \
+ BIT_ULL(MTK_CLK_SGMII_CDR_REF) | \
+ BIT_ULL(MTK_CLK_SGMII_CDR_FB) | \
+ BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \
+ BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \
+ BIT_ULL(MTK_CLK_SGMII2_CDR_REF) | \
+ BIT_ULL(MTK_CLK_SGMII2_CDR_FB))
+#define MT7988_CLKS_BITMAP (BIT_ULL(MTK_CLK_FE) | BIT_ULL(MTK_CLK_ESW) | \
+ BIT_ULL(MTK_CLK_GP1) | BIT_ULL(MTK_CLK_GP2) | \
+ BIT_ULL(MTK_CLK_GP3) | BIT_ULL(MTK_CLK_XGP1) | \
+ BIT_ULL(MTK_CLK_XGP2) | BIT_ULL(MTK_CLK_XGP3) | \
+ BIT_ULL(MTK_CLK_CRYPTO) | \
+ BIT_ULL(MTK_CLK_SGMII_TX_250M) | \
+ BIT_ULL(MTK_CLK_SGMII_RX_250M) | \
+ BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \
+ BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \
+ BIT_ULL(MTK_CLK_ETHWARP_WOCPU2) | \
+ BIT_ULL(MTK_CLK_ETHWARP_WOCPU1) | \
+ BIT_ULL(MTK_CLK_ETHWARP_WOCPU0) | \
+ BIT_ULL(MTK_CLK_TOP_USXGMII_SBUS_0_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_USXGMII_SBUS_1_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_SGM_0_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_SGM_1_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_XFI_PHY_0_XTAL_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_XFI_PHY_1_XTAL_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_ETH_GMII_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_ETH_REFCK_50M_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_ETH_SYS_200M_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_ETH_SYS_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_ETH_XGMII_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_ETH_MII_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_NETSYS_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_NETSYS_500M_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_NETSYS_PAO_2X_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_NETSYS_SYNC_250M_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_NETSYS_PPEFB_250M_SEL) | \
+ BIT_ULL(MTK_CLK_TOP_NETSYS_WARP_SEL))
enum mtk_dev_state {
MTK_HW_INIT,
@@ -844,6 +901,7 @@ enum mkt_eth_capabilities {
MTK_RGMII_BIT = 0,
MTK_TRGMII_BIT,
MTK_SGMII_BIT,
+ MTK_USXGMII_BIT,
MTK_ESW_BIT,
MTK_GEPHY_BIT,
MTK_MUX_BIT,
@@ -866,6 +924,8 @@ enum mkt_eth_capabilities {
MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT,
MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT,
MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT,
+ MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII_BIT,
+ MTK_ETH_MUX_GMAC123_TO_USXGMII_BIT,
/* PATH BITS */
MTK_ETH_PATH_GMAC1_RGMII_BIT,
@@ -874,13 +934,18 @@ enum mkt_eth_capabilities {
MTK_ETH_PATH_GMAC2_RGMII_BIT,
MTK_ETH_PATH_GMAC2_SGMII_BIT,
MTK_ETH_PATH_GMAC2_GEPHY_BIT,
+ MTK_ETH_PATH_GMAC3_SGMII_BIT,
MTK_ETH_PATH_GDM1_ESW_BIT,
+ MTK_ETH_PATH_GMAC1_USXGMII_BIT,
+ MTK_ETH_PATH_GMAC2_USXGMII_BIT,
+ MTK_ETH_PATH_GMAC3_USXGMII_BIT,
};
/* Supported hardware group on SoCs */
#define MTK_RGMII BIT_ULL(MTK_RGMII_BIT)
#define MTK_TRGMII BIT_ULL(MTK_TRGMII_BIT)
#define MTK_SGMII BIT_ULL(MTK_SGMII_BIT)
+#define MTK_USXGMII BIT_ULL(MTK_USXGMII_BIT)
#define MTK_ESW BIT_ULL(MTK_ESW_BIT)
#define MTK_GEPHY BIT_ULL(MTK_GEPHY_BIT)
#define MTK_MUX BIT_ULL(MTK_MUX_BIT)
@@ -907,6 +972,10 @@ enum mkt_eth_capabilities {
BIT_ULL(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT)
#define MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII \
BIT_ULL(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT)
+#define MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII \
+ BIT_ULL(MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII_BIT)
+#define MTK_ETH_MUX_GMAC123_TO_USXGMII \
+ BIT_ULL(MTK_ETH_MUX_GMAC123_TO_USXGMII_BIT)
/* Supported path present on SoCs */
#define MTK_ETH_PATH_GMAC1_RGMII BIT_ULL(MTK_ETH_PATH_GMAC1_RGMII_BIT)
@@ -915,7 +984,11 @@ enum mkt_eth_capabilities {
#define MTK_ETH_PATH_GMAC2_RGMII BIT_ULL(MTK_ETH_PATH_GMAC2_RGMII_BIT)
#define MTK_ETH_PATH_GMAC2_SGMII BIT_ULL(MTK_ETH_PATH_GMAC2_SGMII_BIT)
#define MTK_ETH_PATH_GMAC2_GEPHY BIT_ULL(MTK_ETH_PATH_GMAC2_GEPHY_BIT)
+#define MTK_ETH_PATH_GMAC3_SGMII BIT_ULL(MTK_ETH_PATH_GMAC3_SGMII_BIT)
#define MTK_ETH_PATH_GDM1_ESW BIT_ULL(MTK_ETH_PATH_GDM1_ESW_BIT)
+#define MTK_ETH_PATH_GMAC1_USXGMII BIT_ULL(MTK_ETH_PATH_GMAC1_USXGMII_BIT)
+#define MTK_ETH_PATH_GMAC2_USXGMII BIT_ULL(MTK_ETH_PATH_GMAC2_USXGMII_BIT)
+#define MTK_ETH_PATH_GMAC3_USXGMII BIT_ULL(MTK_ETH_PATH_GMAC3_USXGMII_BIT)
#define MTK_GMAC1_RGMII (MTK_ETH_PATH_GMAC1_RGMII | MTK_RGMII)
#define MTK_GMAC1_TRGMII (MTK_ETH_PATH_GMAC1_TRGMII | MTK_TRGMII)
@@ -923,7 +996,11 @@ enum mkt_eth_capabilities {
#define MTK_GMAC2_RGMII (MTK_ETH_PATH_GMAC2_RGMII | MTK_RGMII)
#define MTK_GMAC2_SGMII (MTK_ETH_PATH_GMAC2_SGMII | MTK_SGMII)
#define MTK_GMAC2_GEPHY (MTK_ETH_PATH_GMAC2_GEPHY | MTK_GEPHY)
+#define MTK_GMAC3_SGMII (MTK_ETH_PATH_GMAC3_SGMII | MTK_SGMII)
#define MTK_GDM1_ESW (MTK_ETH_PATH_GDM1_ESW | MTK_ESW)
+#define MTK_GMAC1_USXGMII (MTK_ETH_PATH_GMAC1_USXGMII | MTK_USXGMII)
+#define MTK_GMAC2_USXGMII (MTK_ETH_PATH_GMAC2_USXGMII | MTK_USXGMII)
+#define MTK_GMAC3_USXGMII (MTK_ETH_PATH_GMAC3_USXGMII | MTK_USXGMII)
/* MUXes present on SoCs */
/* 0: GDM1 -> GMAC1, 1: GDM1 -> ESW */
@@ -946,6 +1023,12 @@ enum mkt_eth_capabilities {
#define MTK_MUX_GMAC12_TO_GEPHY_SGMII \
(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII | MTK_MUX)
+#define MTK_MUX_GMAC123_TO_GEPHY_SGMII \
+ (MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII | MTK_MUX)
+
+#define MTK_MUX_GMAC123_TO_USXGMII \
+ (MTK_ETH_MUX_GMAC123_TO_USXGMII | MTK_MUX | MTK_INFRA)
+
#ifdef CONFIG_SOC_MT7621
#define MTK_CAP_MASK MTK_NETSYS_V2
#else
@@ -984,9 +1067,17 @@ enum mkt_eth_capabilities {
MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \
MTK_NETSYS_V2 | MTK_RSTCTRL_PPE1)
-#define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \
- MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \
- MTK_NETSYS_V2 | MTK_RSTCTRL_PPE1)
+#define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \
+ MTK_MUX_GMAC12_TO_GEPHY_SGMII | \
+ MTK_QDMA | MTK_NETSYS_V2 | \
+ MTK_RSTCTRL_PPE1)
+
+#define MT7988_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \
+ MTK_GMAC3_SGMII | MTK_QDMA | \
+ MTK_MUX_GMAC123_TO_GEPHY_SGMII | \
+ MTK_NETSYS_V3 | MTK_RSTCTRL_PPE1 | \
+ MTK_GMAC1_USXGMII | MTK_GMAC2_USXGMII | \
+ MTK_GMAC3_USXGMII | MTK_MUX_GMAC123_TO_USXGMII)
struct mtk_tx_dma_desc_info {
dma_addr_t addr;
@@ -1072,7 +1163,7 @@ struct mtk_soc_data {
const struct mtk_reg_map *reg_map;
u32 ana_rgc3;
u64 caps;
- u32 required_clks;
+ u64 required_clks;
bool required_pctl;
u8 offload_version;
u8 hash_offset;

View file

@ -16,7 +16,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -2081,10 +2081,13 @@ mt7530_setup_mdio(struct mt7530_priv *pr
@@ -2121,10 +2121,13 @@ mt7530_setup_mdio(struct mt7530_priv *pr
{
struct dsa_switch *ds = priv->ds;
struct device *dev = priv->dev;
@ -30,7 +30,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
bus = devm_mdiobus_alloc(dev);
if (!bus)
return -ENOMEM;
@@ -2101,7 +2104,9 @@ mt7530_setup_mdio(struct mt7530_priv *pr
@@ -2141,7 +2144,9 @@ mt7530_setup_mdio(struct mt7530_priv *pr
if (priv->irq)
mt7530_setup_mdio_irq(priv);

View file

@ -37,6 +37,7 @@ netgear,d7800 |\
netgear,r7500 |\
netgear,r7500v2 |\
netgear,r7800 |\
netgear,xr450 |\
netgear,xr500)
ucidef_set_led_usbport "usb1" "USB 1" "white:usb1" "usb1-port1" "usb2-port1"
ucidef_set_led_usbport "usb2" "USB 2" "white:usb2" "usb3-port1" "usb4-port1"

View file

@ -59,6 +59,7 @@ nec,wg2600hp3)
"2:lan" "3:lan" "4:lan" "5:lan" "0@eth1" "1:wan" "6@eth0"
;;
netgear,r7800 |\
netgear,xr450 |\
netgear,xr500 |\
tplink,c2600 |\
tplink,vr2600v)

View file

@ -17,6 +17,7 @@ platform_do_upgrade() {
netgear,r7500 |\
netgear,r7500v2 |\
netgear,r7800 |\
netgear,xr450 |\
netgear,xr500 |\
nokia,ac400i |\
qcom,ipq8064-ap148 |\

View file

@ -39,7 +39,6 @@ CONFIG_ARM_HAS_SG_CHAIN=y
# CONFIG_ARM_KRAIT_CACHE_DEVFREQ is not set
CONFIG_ARM_L1_CACHE_SHIFT=6
CONFIG_ARM_L1_CACHE_SHIFT_6=y
CONFIG_ARM_MODULE_PLTS=y
CONFIG_ARM_PATCH_IDIV=y
CONFIG_ARM_PATCH_PHYS_VIRT=y
# CONFIG_ARM_QCOM_CPUFREQ_HW is not set

View file

@ -43,7 +43,6 @@ CONFIG_ARM_HAS_SG_CHAIN=y
# CONFIG_ARM_KRAIT_CACHE_DEVFREQ is not set
CONFIG_ARM_L1_CACHE_SHIFT=6
CONFIG_ARM_L1_CACHE_SHIFT_6=y
CONFIG_ARM_MODULE_PLTS=y
CONFIG_ARM_PATCH_IDIV=y
CONFIG_ARM_PATCH_PHYS_VIRT=y
# CONFIG_ARM_QCOM_CPUFREQ_HW is not set

View file

@ -0,0 +1,50 @@
// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
#include "qcom-ipq8065-nighthawk.dtsi"
/ {
model = "Netgear Nighthawk XR450";
compatible = "netgear,xr450", "qcom,ipq8065", "qcom,ipq8064";
};
&leds {
usb1 {
label = "white:usb1";
gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>;
};
usb2 {
label = "white:usb2";
gpios = <&qcom_pinmux 26 GPIO_ACTIVE_HIGH>;
};
};
&partitions {
partition@1880000 {
label = "ubi";
reg = <0x1880000 0xce00000>;
};
partition@e680000 {
label = "reserve";
reg = <0xe680000 0x0780000>;
read-only;
};
};
&wifi0 {
nvmem-cells = <&macaddr_art_c>, <&precal_art_1000>;
nvmem-cell-names = "mac-address", "pre-calibration";
};
&wifi1 {
nvmem-cells = <&macaddr_art_0>, <&precal_art_5000>;
nvmem-cell-names = "mac-address", "pre-calibration";
};
&art {
macaddr_art_c: macaddr@c {
reg = <0xc 0x6>;
};
};

View file

@ -320,6 +320,20 @@ define Device/netgear_r7800
endef
TARGET_DEVICES += netgear_r7800
define Device/netgear_xr450
$(call Device/DniImage)
DEVICE_VENDOR := NETGEAR
DEVICE_MODEL := Nighthawk XR450
SOC := qcom-ipq8065
KERNEL_SIZE := 4096k
NETGEAR_BOARD_ID := XR450
NETGEAR_HW_ID := 29764958+0+256+512+4x4+4x4+cascade
BLOCKSIZE := 128k
PAGESIZE := 2048
DEVICE_PACKAGES := ath10k-firmware-qca9984-ct kmod-ramoops
endef
TARGET_DEVICES += netgear_xr450
define Device/netgear_xr500
$(call Device/DniImage)
DEVICE_VENDOR := NETGEAR

View file

@ -30,7 +30,6 @@ CONFIG_ARM64_ERRATUM_832075=y
CONFIG_ARM64_ERRATUM_843419=y
CONFIG_ARM64_HW_AFDBM=y
CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y
CONFIG_ARM64_MODULE_PLTS=y
CONFIG_ARM64_PAGE_SHIFT=12
CONFIG_ARM64_PAN=y
CONFIG_ARM64_PA_BITS=48

View file

@ -555,14 +555,15 @@
"mediatek,mt7981-mmc";
reg = <0 0x11230000 0 0x1000>, <0 0x11c20000 0 0x1000>;
interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&topckgen CLK_TOP_EMMC_208M>,
<&topckgen CLK_TOP_EMMC_400M>,
<&infracfg CLK_INFRA_MSDC_CK>;
clocks = <&infracfg CLK_INFRA_MSDC_CK>,
<&infracfg CLK_INFRA_MSDC_HCK_CK>,
<&infracfg CLK_INFRA_MSDC_66M_CK>,
<&infracfg CLK_INFRA_MSDC_133M_CK>;
assigned-clocks = <&topckgen CLK_TOP_EMMC_208M_SEL>,
<&topckgen CLK_TOP_EMMC_400M_SEL>;
assigned-clock-parents = <&topckgen CLK_TOP_CB_M_D2>,
<&topckgen CLK_TOP_CB_NET2_D2>;
clock-names = "source", "hclk", "source_cg";
clock-names = "source", "hclk", "axi_cg", "ahb_cg";
status = "disabled";
};
@ -640,7 +641,6 @@
phys = <&u2port0 PHY_TYPE_USB2>,
<&u3port0 PHY_TYPE_USB3>;
vusb33-supply = <&reg_3p3v>;
mediatek,u3p-dis-msk = <0x01>;
status = "disabled";
};

View file

@ -0,0 +1,200 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Copyright (C) 2022 MediaTek Inc.
* Author: Sam.Shih <sam.shih@mediatek.com>
*/
/dts-v1/;
#include "mt7988a-rfb-spim-nand.dtsi"
#include <dt-bindings/pinctrl/mt65xx.h>
/ {
model = "MediaTek MT7988A DSA 10G SPIM-NAND RFB";
compatible = "mediatek,mt7988a-dsa-10g-spim-snand",
"mediatek,mt7988a-rfb-snand",
"mediatek,mt7988";
chosen {
bootargs = "console=ttyS0,115200n1 loglevel=8 \
earlycon=uart8250,mmio32,0x11000000 \
pci=pcie_bus_perf";
};
memory {
reg = <0 0x40000000 0 0x40000000>;
};
};
&eth {
pinctrl-0 = <&mdio0_pins>;
pinctrl-names = "default";
status = "okay";
gmac0: mac@0 {
compatible = "mediatek,eth-mac";
reg = <0>;
phy-mode = "internal";
fixed-link {
speed = <10000>;
full-duplex;
pause;
};
};
gmac1: mac@1 {
compatible = "mediatek,eth-mac";
reg = <1>;
phy-mode = "internal";
phy-connection-type = "internal";
phy = <&phy15>;
};
gmac2: mac@2 {
compatible = "mediatek,eth-mac";
reg = <2>;
phy-mode = "10gbase-kr";
phy-connection-type = "10gbase-kr";
phy = <&phy8>;
};
mdio0: mdio-bus {
#address-cells = <1>;
#size-cells = <0>;
/* external Aquantia AQR113C */
phy0: ethernet-phy@0 {
reg = <0>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 72 1>;
reset-assert-us = <100000>;
reset-deassert-us = <221000>;
};
/* external Aquantia AQR113C */
phy8: ethernet-phy@8 {
reg = <8>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 71 1>;
reset-assert-us = <100000>;
reset-deassert-us = <221000>;
};
/* external Maxlinear GPY211C */
phy5: ethernet-phy@5 {
reg = <5>;
compatible = "ethernet-phy-ieee802.3-c45";
phy-mode = "2500base-x";
};
/* external Maxlinear GPY211C */
phy13: ethernet-phy@13 {
reg = <13>;
compatible = "ethernet-phy-ieee802.3-c45";
phy-mode = "2500base-x";
};
/* internal 2.5G PHY */
phy15: ethernet-phy@15 {
reg = <15>;
pinctrl-names = "i2p5gbe-led";
pinctrl-0 = <&i2p5gbe_led0_pins>;
compatible = "ethernet-phy-ieee802.3-c45";
phy-mode = "internal";
};
};
};
&switch {
status = "okay";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
label = "lan0";
phy-mode = "internal";
phy-handle = <&gsw_phy0>;
};
port@1 {
reg = <1>;
label = "lan1";
phy-mode = "internal";
phy-handle = <&gsw_phy1>;
};
port@2 {
reg = <2>;
label = "lan2";
phy-mode = "internal";
phy-handle = <&gsw_phy2>;
};
port@3 {
reg = <3>;
label = "lan3";
phy-mode = "internal";
phy-handle = <&gsw_phy3>;
};
port@6 {
reg = <6>;
ethernet = <&gmac0>;
phy-mode = "internal";
fixed-link {
speed = <10000>;
full-duplex;
pause;
};
};
};
mdio {
#address-cells = <1>;
#size-cells = <0>;
gsw_phy0: ethernet-phy@0 {
compatible = "ethernet-phy-id03a2.9481";
reg = <0>;
phy-mode = "internal";
pinctrl-names = "gbe-led";
pinctrl-0 = <&gbe0_led0_pins>;
nvmem-cells = <&phy_calibration_p0>;
nvmem-cell-names = "phy-cal-data";
};
gsw_phy1: ethernet-phy@1 {
compatible = "ethernet-phy-id03a2.9481";
reg = <1>;
phy-mode = "internal";
pinctrl-names = "gbe-led";
pinctrl-0 = <&gbe1_led0_pins>;
nvmem-cells = <&phy_calibration_p1>;
nvmem-cell-names = "phy-cal-data";
};
gsw_phy2: ethernet-phy@2 {
compatible = "ethernet-phy-id03a2.9481";
reg = <2>;
phy-mode = "internal";
pinctrl-names = "gbe-led";
pinctrl-0 = <&gbe2_led0_pins>;
nvmem-cells = <&phy_calibration_p2>;
nvmem-cell-names = "phy-cal-data";
};
gsw_phy3: ethernet-phy@3 {
compatible = "ethernet-phy-id03a2.9481";
reg = <3>;
phy-mode = "internal";
pinctrl-names = "gbe-led";
pinctrl-0 = <&gbe3_led0_pins>;
nvmem-cells = <&phy_calibration_p3>;
nvmem-cell-names = "phy-cal-data";
};
};
};

View file

@ -0,0 +1,70 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Copyright (C) 2022 MediaTek Inc.
* Author: Sam.Shih <sam.shih@mediatek.com>
*/
/dts-v1/;
#include "mt7988a-rfb.dtsi"
&pio {
spi0_flash_pins: spi0-pins {
mux {
function = "spi";
groups = "spi0", "spi0_wp_hold";
};
};
};
&spi0 {
pinctrl-names = "default";
pinctrl-0 = <&spi0_flash_pins>;
status = "okay";
spi_nand: spi_nand@0 {
compatible = "spi-nand";
reg = <0>;
spi-max-frequency = <52000000>;
spi-tx-buswidth = <4>;
spi-rx-buswidth = <4>;
};
};
&spi_nand {
mediatek,nmbm;
mediatek,bmt-max-ratio = <1>;
mediatek,bmt-max-reserved-blocks = <64>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "BL2";
reg = <0x00000 0x0100000>;
read-only;
};
partition@100000 {
label = "u-boot-env";
reg = <0x0100000 0x0080000>;
};
factory: partition@180000 {
label = "Factory";
reg = <0x180000 0x0400000>;
};
partition@580000 {
label = "FIP";
reg = <0x580000 0x0200000>;
};
partition@780000 {
label = "ubi";
reg = <0x780000 0x7080000>;
};
};
};

View file

@ -0,0 +1,175 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Copyright (C) 2022 MediaTek Inc.
* Author: Sam.Shih <sam.shih@mediatek.com>
*/
/dts-v1/;
#include "mt7988a.dtsi"
#include <dt-bindings/regulator/richtek,rt5190a-regulator.h>
&cpu0 {
proc-supply = <&rt5190_buck3>;
};
&cpu1 {
proc-supply = <&rt5190_buck3>;
};
&cpu2 {
proc-supply = <&rt5190_buck3>;
};
&cpu3 {
proc-supply = <&rt5190_buck3>;
};
&cci {
proc-supply = <&rt5190_buck3>;
};
&eth {
status = "okay";
};
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
status = "okay";
rt5190a_64: rt5190a@64 {
compatible = "richtek,rt5190a";
reg = <0x64>;
/*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/
vin2-supply = <&rt5190_buck1>;
vin3-supply = <&rt5190_buck1>;
vin4-supply = <&rt5190_buck1>;
regulators {
rt5190_buck1: buck1 {
regulator-name = "rt5190a-buck1";
regulator-min-microvolt = <5090000>;
regulator-max-microvolt = <5090000>;
regulator-allowed-modes =
<RT5190A_OPMODE_AUTO RT5190A_OPMODE_FPWM>;
regulator-boot-on;
regulator-always-on;
};
buck2 {
regulator-name = "vcore";
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <1400000>;
regulator-boot-on;
regulator-always-on;
};
rt5190_buck3: buck3 {
regulator-name = "vproc";
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <1400000>;
regulator-boot-on;
};
buck4 {
regulator-name = "rt5190a-buck4";
regulator-min-microvolt = <850000>;
regulator-max-microvolt = <850000>;
regulator-allowed-modes =
<RT5190A_OPMODE_AUTO RT5190A_OPMODE_FPWM>;
regulator-boot-on;
regulator-always-on;
};
ldo {
regulator-name = "rt5190a-ldo";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
regulator-boot-on;
regulator-always-on;
};
};
};
};
&pcie0 {
pinctrl-names = "default";
pinctrl-0 = <&pcie0_pins>;
status = "okay";
};
&pcie1 {
pinctrl-names = "default";
pinctrl-0 = <&pcie1_pins>;
status = "okay";
};
&pcie2 {
pinctrl-names = "default";
pinctrl-0 = <&pcie2_pins>;
status = "disabled";
};
&pcie3 {
pinctrl-names = "default";
pinctrl-0 = <&pcie3_pins>;
status = "okay";
};
&ssusb0 {
status = "okay";
};
&ssusb1 {
status = "okay";
};
&tphy {
status = "okay";
};
&pio {
pcie0_pins: pcie0-pins {
mux {
function = "pcie";
groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0",
"pcie_wake_n0_0";
};
};
pcie1_pins: pcie1-pins {
mux {
function = "pcie";
groups = "pcie_2l_1_pereset", "pcie_clk_req_n1",
"pcie_wake_n1_0";
};
};
pcie2_pins: pcie2-pins {
mux {
function = "pcie";
groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0",
"pcie_wake_n2_0";
};
};
pcie3_pins: pcie3-pins {
mux {
function = "pcie";
groups = "pcie_1l_1_pereset", "pcie_clk_req_n3",
"pcie_wake_n3_0";
};
};
};
&spi0 {
status = "disabled";
};
&uart0 {
status = "okay";
};
&watchdog {
status = "okay";
};
&xphy {
status = "okay";
};

View file

@ -0,0 +1,853 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Copyright (C) 2023 MediaTek Inc.
* Author: Sam.Shih <sam.shih@mediatek.com>
*/
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/reset/ti-syscon.h>
#include <dt-bindings/clock/mediatek,mt7988-clk.h>
#include <dt-bindings/pinctrl/mt65xx.h>
#include <dt-bindings/thermal/thermal.h>
/ {
compatible = "mediatek,mt7988";
interrupt-parent = <&gic>;
#address-cells = <2>;
#size-cells = <2>;
clk40m: oscillator@0 {
compatible = "fixed-clock";
clock-frequency = <40000000>;
#clock-cells = <0>;
clock-output-names = "clkxtal";
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a73";
enable-method = "psci";
reg = <0x0>;
clocks = <&mcusys CLK_MCU_ARM_DIV_SEL>,
<&topckgen CLK_TOP_XTAL>;
clock-names = "cpu", "intermediate";
operating-points-v2 = <&cluster0_opp>;
mediatek,cci = <&cci>;
};
cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a73";
enable-method = "psci";
reg = <0x1>;
clocks = <&mcusys CLK_MCU_ARM_DIV_SEL>,
<&topckgen CLK_TOP_XTAL>;
clock-names = "cpu", "intermediate";
operating-points-v2 = <&cluster0_opp>;
mediatek,cci = <&cci>;
};
cpu2: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a73";
enable-method = "psci";
reg = <0x2>;
clocks = <&mcusys CLK_MCU_ARM_DIV_SEL>,
<&topckgen CLK_TOP_XTAL>;
clock-names = "cpu", "intermediate";
operating-points-v2 = <&cluster0_opp>;
mediatek,cci = <&cci>;
};
cpu3: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a73";
enable-method = "psci";
reg = <0x3>;
clocks = <&mcusys CLK_MCU_ARM_DIV_SEL>,
<&topckgen CLK_TOP_XTAL>;
clock-names = "cpu", "intermediate";
operating-points-v2 = <&cluster0_opp>;
mediatek,cci = <&cci>;
};
cluster0_opp: opp_table0 {
compatible = "operating-points-v2";
opp-shared;
opp00 {
opp-hz = /bits/ 64 <800000000>;
opp-microvolt = <850000>;
};
opp01 {
opp-hz = /bits/ 64 <1100000000>;
opp-microvolt = <850000>;
};
opp02 {
opp-hz = /bits/ 64 <1500000000>;
opp-microvolt = <850000>;
};
opp03 {
opp-hz = /bits/ 64 <1800000000>;
opp-microvolt = <900000>;
};
};
};
cci: cci {
compatible = "mediatek,mt7988-cci",
"mediatek,mt8183-cci";
clocks = <&mcusys CLK_MCU_BUS_DIV_SEL>,
<&topckgen CLK_TOP_XTAL>;
clock-names = "cci", "intermediate";
operating-points-v2 = <&cci_opp>;
};
cci_opp: opp_table_cci {
compatible = "operating-points-v2";
opp-shared;
opp00 {
opp-hz = /bits/ 64 <480000000>;
opp-microvolt = <850000>;
};
opp01 {
opp-hz = /bits/ 64 <660000000>;
opp-microvolt = <850000>;
};
opp02 {
opp-hz = /bits/ 64 <900000000>;
opp-microvolt = <850000>;
};
opp03 {
opp-hz = /bits/ 64 <1080000000>;
opp-microvolt = <900000>;
};
};
pmu {
compatible = "arm,cortex-a73-pmu";
interrupt-parent = <&gic>;
interrupt = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
};
psci {
compatible = "arm,psci-0.2";
method = "smc";
};
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
/* 192 KiB reserved for ARM Trusted Firmware (BL31) */
secmon_reserved: secmon@43000000 {
reg = <0 0x43000000 0 0x30000>;
no-map;
};
};
timer {
compatible = "arm,armv8-timer";
interrupt-parent = <&gic>;
interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
<GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
<GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
<GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
};
soc {
#address-cells = <2>;
#size-cells = <2>;
compatible = "simple-bus";
ranges;
gic: interrupt-controller@c000000 {
compatible = "arm,gic-v3";
#interrupt-cells = <3>;
interrupt-parent = <&gic>;
interrupt-controller;
reg = <0 0x0c000000 0 0x40000>, /* GICD */
<0 0x0c080000 0 0x200000>, /* GICR */
<0 0x0c400000 0 0x2000>, /* GICC */
<0 0x0c410000 0 0x1000>, /* GICH */
<0 0x0c420000 0 0x2000>; /* GICV */
interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
};
phyfw: phy-firmware@f000000 {
compatible = "mediatek,2p5gphy-fw";
reg = <0 0x0f000000 0 0x8000>,
<0 0x0f100000 0 0x20000>,
<0 0x0f0f0000 0 0x200>;
};
infracfg: infracfg@10001000 {
compatible = "mediatek,mt7988-infracfg", "syscon";
reg = <0 0x10001000 0 0x1000>;
#clock-cells = <1>;
};
topckgen: topckgen@1001b000 {
compatible = "mediatek,mt7988-topckgen", "syscon";
reg = <0 0x1001b000 0 0x1000>;
#clock-cells = <1>;
};
watchdog: watchdog@1001c000 {
compatible = "mediatek,mt7988-wdt",
"mediatek,mt6589-wdt",
"syscon";
reg = <0 0x1001c000 0 0x1000>;
interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
#reset-cells = <1>;
};
apmixedsys: apmixedsys@1001e000 {
compatible = "mediatek,mt7988-apmixedsys";
reg = <0 0x1001e000 0 0x1000>;
#clock-cells = <1>;
};
pio: pinctrl@1001f000 {
compatible = "mediatek,mt7988-pinctrl";
reg = <0 0x1001f000 0 0x1000>,
<0 0x11c10000 0 0x1000>,
<0 0x11d00000 0 0x1000>,
<0 0x11d20000 0 0x1000>,
<0 0x11e00000 0 0x1000>,
<0 0x11f00000 0 0x1000>,
<0 0x1000b000 0 0x1000>;
reg-names = "gpio_base", "iocfg_tr_base",
"iocfg_br_base", "iocfg_rb_base",
"iocfg_lb_base", "iocfg_tl_base", "eint";
gpio-controller;
#gpio-cells = <2>;
gpio-ranges = <&pio 0 0 83>;
interrupt-controller;
interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&gic>;
#interrupt-cells = <2>;
mdio0_pins: mdio0-pins {
mux {
function = "eth";
groups = "mdc_mdio0";
};
conf {
groups = "mdc_mdio0";
drive-strength = <MTK_DRIVE_8mA>;
};
};
i2c0_pins: i2c0-pins-g0 {
mux {
function = "i2c";
groups = "i2c0_1";
};
};
i2c1_pins: i2c1-pins-g0 {
mux {
function = "i2c";
groups = "i2c1_0";
};
};
i2c2_pins: i2c2-pins-g0 {
mux {
function = "i2c";
groups = "i2c2_1";
};
};
gbe0_led0_pins: gbe0-pins {
mux {
function = "led";
groups = "gbe0_led0";
};
};
gbe1_led0_pins: gbe1-pins {
mux {
function = "led";
groups = "gbe1_led0";
};
};
gbe2_led0_pins: gbe2-pins {
mux {
function = "led";
groups = "gbe2_led0";
};
};
gbe3_led0_pins: gbe3-pins {
mux {
function = "led";
groups = "gbe3_led0";
};
};
i2p5gbe_led0_pins: 2p5gbe-pins {
mux {
function = "led";
groups = "2p5gbe_led0";
};
};
};
boottrap: boottrap@1001f6f0 {
compatible = "mediatek,boottrap";
reg = <0 0x1001f6f0 0 0x4>;
};
sgmiisys0: syscon@10060000 {
compatible = "mediatek,mt7988-sgmiisys",
"mediatek,mt7988-sgmiisys_0",
"syscon";
reg = <0 0x10060000 0 0x1000>;
#clock-cells = <1>;
};
sgmiisys1: syscon@10070000 {
compatible = "mediatek,mt7988-sgmiisys",
"mediatek,mt7988-sgmiisys_1",
"syscon";
reg = <0 0x10070000 0 0x1000>;
#clock-cells = <1>;
};
usxgmiisys0: usxgmiisys@10080000 {
compatible = "mediatek,mt7988-usxgmiisys",
"mediatek,mt7988-usxgmiisys_0",
"syscon";
reg = <0 0x10080000 0 0x1000>;
#clock-cells = <1>;
};
usxgmiisys1: usxgmiisys@10081000 {
compatible = "mediatek,mt7988-usxgmiisys",
"mediatek,mt7988-usxgmiisys_1",
"syscon";
reg = <0 0x10081000 0 0x1000>;
#clock-cells = <1>;
};
xfi_pextp0: xfi_pextp@11f20000 {
compatible = "mediatek,mt7988-xfi_pextp",
"mediatek,mt7988-xfi_pextp_0",
"syscon";
reg = <0 0x11f20000 0 0x10000>;
#clock-cells = <1>;
};
xfi_pextp1: xfi_pextp@11f30000 {
compatible = "mediatek,mt7988-xfi_pextp",
"mediatek,mt7988-xfi_pextp_1",
"syscon";
reg = <0 0x11f30000 0 0x10000>;
#clock-cells = <1>;
};
xfi_pll: xfi_pll@11f40000 {
compatible = "mediatek,mt7988-xfi_pll", "syscon";
reg = <0 0x11f40000 0 0x1000>;
#clock-cells = <1>;
};
mcusys: mcusys@100e0000 {
compatible = "mediatek,mt7988-mcusys", "syscon";
reg = <0 0x100e0000 0 0x1000>;
#clock-cells = <1>;
};
uart0: serial@11000000 {
compatible = "mediatek,mt7986-uart",
"mediatek,mt6577-uart";
reg = <0 0x11000000 0 0x100>;
interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
/*
* 8250-mtk driver don't control "baud" clock since commit
* e32a83c70cf9 (kernel v5.7), but both "baud" and "bus" clocks
* still need to be passed to the driver to prevent probe fail
*/
clocks = <&topckgen CLK_TOP_UART_SEL>,
<&infracfg CLK_INFRA_52M_UART0_CK>;
clock-names = "baud", "bus";
assigned-clocks = <&topckgen CLK_TOP_UART_SEL>,
<&infracfg CLK_INFRA_MUX_UART0_SEL>;
assigned-clock-parents = <&topckgen CLK_TOP_XTAL>,
<&topckgen CLK_TOP_UART_SEL>;
status = "disabled";
};
i2c0: i2c@11003000 {
compatible = "mediatek,mt7988-i2c",
"mediatek,mt7981-i2c";
reg = <0 0x11003000 0 0x1000>,
<0 0x10217080 0 0x80>;
interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
clock-div = <1>;
clocks = <&infracfg CLK_INFRA_I2C_BCK>,
<&infracfg CLK_INFRA_66M_AP_DMA_BCK>;
clock-names = "main", "dma";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
};
i2c1: i2c@11004000 {
compatible = "mediatek,mt7988-i2c",
"mediatek,mt7981-i2c";
reg = <0 0x11004000 0 0x1000>,
<0 0x10217100 0 0x80>;
interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
clock-div = <1>;
clocks = <&infracfg CLK_INFRA_I2C_BCK>,
<&infracfg CLK_INFRA_66M_AP_DMA_BCK>;
clock-names = "main", "dma";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
};
i2c2: i2c@11005000 {
compatible = "mediatek,mt7988-i2c",
"mediatek,mt7981-i2c";
reg = <0 0x11005000 0 0x1000>,
<0 0x10217180 0 0x80>;
interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
clock-div = <1>;
clocks = <&infracfg CLK_INFRA_I2C_BCK>,
<&infracfg CLK_INFRA_66M_AP_DMA_BCK>;
clock-names = "main", "dma";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
};
spi0: spi@11007000 {
compatible = "mediatek,ipm-spi-quad", "mediatek,spi-ipm";
reg = <0 0x11007000 0 0x100>;
interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&topckgen CLK_TOP_MPLL_D2>,
<&topckgen CLK_TOP_SPI_SEL>,
<&infracfg CLK_INFRA_104M_SPI0>,
<&infracfg CLK_INFRA_66M_SPI0_HCK>;
clock-names = "parent-clk", "sel-clk", "spi-clk",
"spi-hclk";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
};
pcie2: pcie@11280000 {
compatible = "mediatek,mt7988-pcie",
"mediatek,mt7986-pcie",
"mediatek,mt8192-pcie";
device_type = "pci";
#address-cells = <3>;
#size-cells = <2>;
reg = <0 0x11280000 0 0x2000>;
reg-names = "pcie-mac";
linux,pci-domain = <3>;
interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>;
bus-range = <0x00 0xff>;
ranges = <0x81000000 0x00 0x20000000 0x00
0x20000000 0x00 0x00200000>,
<0x82000000 0x00 0x20200000 0x00
0x20200000 0x00 0x07e00000>;
clocks = <&infracfg CLK_INFRA_PCIE_PIPE_P2>,
<&infracfg CLK_INFRA_PCIE_GFMUX_TL_P2>,
<&infracfg CLK_INFRA_PCIE_PERI_26M_CK_P2>,
<&infracfg CLK_INFRA_133M_PCIE_CK_P2>;
clock-names = "pl_250m", "tl_26m", "peri_26m",
"top_133m";
status = "disabled";
phys = <&xphyu3port0 PHY_TYPE_PCIE>;
phy-names = "pcie-phy";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
interrupt-map = <0 0 0 1 &pcie_intc2 0>,
<0 0 0 2 &pcie_intc2 1>,
<0 0 0 3 &pcie_intc2 2>,
<0 0 0 4 &pcie_intc2 3>;
pcie_intc2: interrupt-controller {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-controller;
};
};
pcie3: pcie@11290000 {
compatible = "mediatek,mt7988-pcie",
"mediatek,mt7986-pcie",
"mediatek,mt8192-pcie";
device_type = "pci";
#address-cells = <3>;
#size-cells = <2>;
reg = <0 0x11290000 0 0x2000>;
reg-names = "pcie-mac";
linux,pci-domain = <2>;
interrupts = <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>;
bus-range = <0x00 0xff>;
ranges = <0x81000000 0x00 0x28000000 0x00
0x28000000 0x00 0x00200000>,
<0x82000000 0x00 0x28200000 0x00
0x28200000 0x00 0x07e00000>;
clocks = <&infracfg CLK_INFRA_PCIE_PIPE_P3>,
<&infracfg CLK_INFRA_PCIE_GFMUX_TL_P3>,
<&infracfg CLK_INFRA_PCIE_PERI_26M_CK_P3>,
<&infracfg CLK_INFRA_133M_PCIE_CK_P3>;
clock-names = "pl_250m", "tl_26m", "peri_26m",
"top_133m";
status = "disabled";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
interrupt-map = <0 0 0 1 &pcie_intc3 0>,
<0 0 0 2 &pcie_intc3 1>,
<0 0 0 3 &pcie_intc3 2>,
<0 0 0 4 &pcie_intc3 3>;
pcie_intc3: interrupt-controller {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-controller;
};
};
pcie0: pcie@11300000 {
compatible = "mediatek,mt7988-pcie",
"mediatek,mt7986-pcie",
"mediatek,mt8192-pcie";
device_type = "pci";
#address-cells = <3>;
#size-cells = <2>;
reg = <0 0x11300000 0 0x2000>;
reg-names = "pcie-mac";
linux,pci-domain = <0>;
interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
bus-range = <0x00 0xff>;
ranges = <0x81000000 0x00 0x30000000 0x00
0x30000000 0x00 0x00200000>,
<0x82000000 0x00 0x30200000 0x00
0x30200000 0x00 0x07e00000>;
clocks = <&infracfg CLK_INFRA_PCIE_PIPE_P0>,
<&infracfg CLK_INFRA_PCIE_GFMUX_TL_P0>,
<&infracfg CLK_INFRA_PCIE_PERI_26M_CK_P0>,
<&infracfg CLK_INFRA_133M_PCIE_CK_P0>;
clock-names = "pl_250m", "tl_26m", "peri_26m",
"top_133m";
status = "disabled";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
interrupt-map = <0 0 0 1 &pcie_intc0 0>,
<0 0 0 2 &pcie_intc0 1>,
<0 0 0 3 &pcie_intc0 2>,
<0 0 0 4 &pcie_intc0 3>;
pcie_intc0: interrupt-controller {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-controller;
};
};
pcie1: pcie@11310000 {
compatible = "mediatek,mt7988-pcie",
"mediatek,mt7986-pcie",
"mediatek,mt8192-pcie";
device_type = "pci";
#address-cells = <3>;
#size-cells = <2>;
reg = <0 0x11310000 0 0x2000>;
reg-names = "pcie-mac";
linux,pci-domain = <1>;
interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
bus-range = <0x00 0xff>;
ranges = <0x81000000 0x00 0x38000000 0x00
0x38000000 0x00 0x00200000>,
<0x82000000 0x00 0x38200000 0x00
0x38200000 0x00 0x07e00000>;
clocks = <&infracfg CLK_INFRA_PCIE_PIPE_P1>,
<&infracfg CLK_INFRA_PCIE_GFMUX_TL_P1>,
<&infracfg CLK_INFRA_PCIE_PERI_26M_CK_P1>,
<&infracfg CLK_INFRA_133M_PCIE_CK_P1>;
clock-names = "pl_250m", "tl_26m", "peri_26m",
"top_133m";
status = "disabled";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
interrupt-map = <0 0 0 1 &pcie_intc1 0>,
<0 0 0 2 &pcie_intc1 1>,
<0 0 0 3 &pcie_intc1 2>,
<0 0 0 4 &pcie_intc1 3>;
pcie_intc1: interrupt-controller {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-controller;
};
};
ssusb0: usb@11190000 {
compatible = "mediatek,mt7988-xhci",
"mediatek,mtk-xhci";
reg = <0 0x11190000 0 0x2e00>,
<0 0x11193e00 0 0x0100>;
reg-names = "mac", "ippc";
interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
phys = <&xphyu2port0 PHY_TYPE_USB2>,
<&xphyu3port0 PHY_TYPE_USB3>;
clocks = <&infracfg CLK_INFRA_USB_SYS>,
<&infracfg CLK_INFRA_USB_XHCI>,
<&infracfg CLK_INFRA_USB_REF>,
<&infracfg CLK_INFRA_66M_USB_HCK>,
<&infracfg CLK_INFRA_133M_USB_HCK>;
clock-names = "sys_ck",
"xhci_ck",
"ref_ck",
"mcu_ck",
"dma_ck";
#address-cells = <2>;
#size-cells = <2>;
mediatek,p0_speed_fixup;
status = "disabled";
};
ssusb1: usb@11200000 {
compatible = "mediatek,mt7988-xhci",
"mediatek,mtk-xhci";
reg = <0 0x11200000 0 0x2e00>,
<0 0x11203e00 0 0x0100>;
reg-names = "mac", "ippc";
interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
phys = <&tphyu2port0 PHY_TYPE_USB2>,
<&tphyu3port0 PHY_TYPE_USB3>;
clocks = <&infracfg CLK_INFRA_USB_SYS_CK_P1>,
<&infracfg CLK_INFRA_USB_XHCI_CK_P1>,
<&infracfg CLK_INFRA_USB_CK_P1>,
<&infracfg CLK_INFRA_66M_USB_HCK_CK_P1>,
<&infracfg CLK_INFRA_133M_USB_HCK_CK_P1>;
clock-names = "sys_ck",
"xhci_ck",
"ref_ck",
"mcu_ck",
"dma_ck";
#address-cells = <2>;
#size-cells = <2>;
status = "disabled";
};
tphy: tphy@11c50000 {
compatible = "mediatek,mt7988",
"mediatek,generic-tphy-v2";
#address-cells = <2>;
#size-cells = <2>;
ranges;
status = "disabled";
tphyu2port0: usb-phy@11c50000 {
reg = <0 0x11c50000 0 0x700>;
clocks = <&infracfg CLK_INFRA_USB_UTMI_CK_P1>;
clock-names = "ref";
#phy-cells = <1>;
};
tphyu3port0: usb-phy@11c50700 {
reg = <0 0x11c50700 0 0x900>;
clocks = <&infracfg CLK_INFRA_USB_PIPE_CK_P1>;
clock-names = "ref";
#phy-cells = <1>;
mediatek,usb3-pll-ssc-delta;
mediatek,usb3-pll-ssc-delta1;
};
};
topmisc: topmisc@11d10000 {
compatible = "mediatek,mt7988-topmisc", "syscon",
"mediatek,mt7988-power-controller";
reg = <0 0x11d10000 0 0x10000>;
#clock-cells = <1>;
#power-domain-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
};
xphy: xphy@11e10000 {
compatible = "mediatek,mt7988",
"mediatek,xsphy";
#address-cells = <2>;
#size-cells = <2>;
ranges;
status = "disabled";
xphyu2port0: usb-phy@11e10000 {
reg = <0 0x11e10000 0 0x400>;
clocks = <&infracfg CLK_INFRA_USB_UTMI>;
clock-names = "ref";
#phy-cells = <1>;
};
xphyu3port0: usb-phy@11e13000 {
reg = <0 0x11e13400 0 0x500>;
clocks = <&infracfg CLK_INFRA_USB_PIPE>;
clock-names = "ref";
#phy-cells = <1>;
mediatek,syscon-type = <&topmisc 0x218 0>;
};
};
efuse: efuse@11f50000 {
compatible = "mediatek,efuse";
reg = <0 0x11f50000 0 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
lvts_calibration: calib@918 {
reg = <0x918 0x28>;
};
phy_calibration_p0: calib@940 {
reg = <0x940 0x10>;
};
phy_calibration_p1: calib@954 {
reg = <0x954 0x10>;
};
phy_calibration_p2: calib@968 {
reg = <0x968 0x10>;
};
phy_calibration_p3: calib@97c {
reg = <0x97c 0x10>;
};
cpufreq_calibration: calib@278 {
reg = <0x278 0x1>;
};
};
ethsys: syscon@15000000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "mediatek,mt7988-ethsys", "syscon";
reg = <0 0x15000000 0 0x1000>;
#clock-cells = <1>;
#reset-cells = <1>;
};
switch: switch@15020000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "mediatek,mt7988-switch";
reg = <0 0x15020000 0 0x8000>;
interrupt-controller;
#interrupt-cells = <1>;
interrupt-parent = <&gic>;
interrupts = <GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>;
resets = <&ethrst 0>;
};
ethwarp: syscon@15031000 {
compatible = "mediatek,mt7988-ethwarp", "syscon", "simple-mfd";
reg = <0 0x15031000 0 0x1000>;
#clock-cells = <1>;
ethrst: reset-controller {
compatible = "ti,syscon-reset";
#reset-cells = <1>;
ti,reset-bits = <
0x8 9 0x8 9 0 0 (ASSERT_SET | DEASSERT_CLEAR | STATUS_NONE)
>;
};
};
eth: ethernet@15100000 {
compatible = "mediatek,mt7988-eth";
reg = <0 0x15100000 0 0x80000>,
<0 0x15400000 0 0x380000>;
interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ethsys CLK_ETHDMA_XGP1_EN>,
<&ethsys CLK_ETHDMA_XGP2_EN>,
<&ethsys CLK_ETHDMA_XGP3_EN>,
<&ethsys CLK_ETHDMA_FE_EN>,
<&ethsys CLK_ETHDMA_GP2_EN>,
<&ethsys CLK_ETHDMA_GP1_EN>,
<&ethsys CLK_ETHDMA_GP3_EN>,
<&ethsys CLK_ETHDMA_ESW_EN>,
<&ethsys CLK_ETHDMA_CRYPT0_EN>,
<&sgmiisys0 CLK_SGM0_TX_EN>,
<&sgmiisys0 CLK_SGM0_RX_EN>,
<&sgmiisys1 CLK_SGM1_TX_EN>,
<&sgmiisys1 CLK_SGM1_RX_EN>,
<&ethwarp CLK_ETHWARP_WOCPU2_EN>,
<&ethwarp CLK_ETHWARP_WOCPU1_EN>,
<&ethwarp CLK_ETHWARP_WOCPU0_EN>,
<&topckgen CLK_TOP_USXGMII_SBUS_0_SEL>,
<&topckgen CLK_TOP_USXGMII_SBUS_1_SEL>,
<&topckgen CLK_TOP_SGM_0_SEL>,
<&topckgen CLK_TOP_SGM_1_SEL>,
<&topckgen CLK_TOP_XFI_PHY_0_XTAL_SEL>,
<&topckgen CLK_TOP_XFI_PHY_1_XTAL_SEL>,
<&topckgen CLK_TOP_ETH_GMII_SEL>,
<&topckgen CLK_TOP_ETH_REFCK_50M_SEL>,
<&topckgen CLK_TOP_ETH_SYS_200M_SEL>,
<&topckgen CLK_TOP_ETH_SYS_SEL>,
<&topckgen CLK_TOP_ETH_XGMII_SEL>,
<&topckgen CLK_TOP_ETH_MII_SEL>,
<&topckgen CLK_TOP_NETSYS_SEL>,
<&topckgen CLK_TOP_NETSYS_500M_SEL>,
<&topckgen CLK_TOP_NETSYS_PAO_2X_SEL>,
<&topckgen CLK_TOP_NETSYS_SYNC_250M_SEL>,
<&topckgen CLK_TOP_NETSYS_PPEFB_250M_SEL>,
<&topckgen CLK_TOP_NETSYS_WARP_SEL>;
clock-names = "xgp1", "xgp2", "xgp3", "fe", "gp2", "gp1",
"gp3", "esw", "crypto", "sgmii_tx250m",
"sgmii_rx250m", "sgmii2_tx250m", "sgmii2_rx250m",
"ethwarp_wocpu2", "ethwarp_wocpu1",
"ethwarp_wocpu0", "top_usxgmii0_sel",
"top_usxgmii1_sel", "top_sgm0_sel",
"top_sgm1_sel", "top_xfi_phy0_xtal_sel",
"top_xfi_phy1_xtal_sel", "top_eth_gmii_sel",
"top_eth_refck_50m_sel", "top_eth_sys_200m_sel",
"top_eth_sys_sel", "top_eth_xgmii_sel",
"top_eth_mii_sel", "top_netsys_sel",
"top_netsys_500m_sel", "top_netsys_pao_2x_sel",
"top_netsys_sync_250m_sel",
"top_netsys_ppefb_250m_sel",
"top_netsys_warp_sel";
assigned-clocks = <&topckgen CLK_TOP_NETSYS_2X_SEL>,
<&topckgen CLK_TOP_NETSYS_GSW_SEL>,
<&topckgen CLK_TOP_USXGMII_SBUS_0_SEL>,
<&topckgen CLK_TOP_USXGMII_SBUS_1_SEL>,
<&topckgen CLK_TOP_SGM_0_SEL>,
<&topckgen CLK_TOP_SGM_1_SEL>;
assigned-clock-parents = <&apmixedsys CLK_APMIXED_NET2PLL>,
<&topckgen CLK_TOP_NET1PLL_D4>,
<&topckgen CLK_TOP_NET1PLL_D8_D4>,
<&topckgen CLK_TOP_NET1PLL_D8_D4>,
<&apmixedsys CLK_APMIXED_SGMPLL>,
<&apmixedsys CLK_APMIXED_SGMPLL>;
mediatek,ethsys = <&ethsys>;
mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
mediatek,usxgmiisys = <&usxgmiisys0>, <&usxgmiisys1>;
mediatek,xfi_pextp = <&xfi_pextp0>, <&xfi_pextp1>;
mediatek,xfi_pll = <&xfi_pll>;
mediatek,infracfg = <&topmisc>;
mediatek,toprgu = <&watchdog>;
#reset-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
};
};
};

View file

@ -0,0 +1,113 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2023 MediaTek Inc.
* Author: Sam Shih <sam.shih@mediatek.com>
* Author: Xiufeng Li <Xiufeng.Li@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include "clk-mux.h"
#include <dt-bindings/clock/mediatek,mt7988-clk.h>
#define MT7988_PLL_FMAX (2500UL * MHZ)
#define MT7988_PCW_CHG_SHIFT 2
#define PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _rst_bar_mask, \
_pcwbits, _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \
_tuner_en_bit, _pcw_reg, _pcw_shift, _pcw_chg_reg, \
_div_table) \
{ \
.id = _id, .name = _name, .reg = _reg, .pwr_reg = _pwr_reg, \
.en_mask = _en_mask, .flags = _flags, \
.rst_bar_mask = BIT(_rst_bar_mask), .fmax = MT7988_PLL_FMAX, \
.pcwbits = _pcwbits, .pd_reg = _pd_reg, \
.pd_shift = _pd_shift, .tuner_reg = _tuner_reg, \
.tuner_en_reg = _tuner_en_reg, .tuner_en_bit = _tuner_en_bit, \
.pcw_reg = _pcw_reg, .pcw_shift = _pcw_shift, \
.pcw_chg_reg = _pcw_chg_reg, \
.pcw_chg_shift = MT7988_PCW_CHG_SHIFT, \
.div_table = _div_table, .parent_name = "clkxtal", \
}
#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _rst_bar_mask, \
_pcwbits, _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \
_tuner_en_bit, _pcw_reg, _pcw_shift, _pcw_chg_reg) \
PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _rst_bar_mask, \
_pcwbits, _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \
_tuner_en_bit, _pcw_reg, _pcw_shift, _pcw_chg_reg, NULL)
static const struct mtk_pll_data plls[] = {
PLL(CLK_APMIXED_NETSYSPLL, "netsyspll", 0x0104, 0x0110, 0x00000001, 0,
0, 32, 0x0104, 4, 0, 0, 0, 0x0108, 0, 0x0104),
PLL(CLK_APMIXED_MPLL, "mpll", 0x0114, 0x0120, 0xff000001, HAVE_RST_BAR,
23, 32, 0x0114, 4, 0, 0, 0, 0x0118, 0, 0x0114),
PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0124, 0x0130, 0xff000001,
HAVE_RST_BAR, 23, 32, 0x0124, 4, 0, 0, 0, 0x0128, 0, 0x0124),
PLL(CLK_APMIXED_APLL2, "apll2", 0x0134, 0x0140, 0x00000001, 0, 0, 32,
0x0134, 4, 0x0704, 0x0700, 1, 0x0138, 0, 0x0134),
PLL(CLK_APMIXED_NET1PLL, "net1pll", 0x0144, 0x0150, 0xff000001,
HAVE_RST_BAR, 23, 32, 0x0144, 4, 0, 0, 0, 0x0148, 0, 0x0144),
PLL(CLK_APMIXED_NET2PLL, "net2pll", 0x0154, 0x0160, 0xff000001,
(HAVE_RST_BAR | PLL_AO), 23, 32, 0x0154, 4, 0, 0, 0, 0x0158, 0,
0x0154),
PLL(CLK_APMIXED_WEDMCUPLL, "wedmcupll", 0x0164, 0x0170, 0x00000001, 0,
0, 32, 0x0164, 4, 0, 0, 0, 0x0168, 0, 0x0164),
PLL(CLK_APMIXED_SGMPLL, "sgmpll", 0x0174, 0x0180, 0x00000001, 0, 0, 32,
0x0174, 4, 0, 0, 0, 0x0178, 0, 0x0174),
PLL(CLK_APMIXED_ARM_B, "arm_b", 0x0204, 0x0210, 0xff000001,
(HAVE_RST_BAR | PLL_AO), 23, 32, 0x0204, 4, 0, 0, 0, 0x0208, 0,
0x0204),
PLL(CLK_APMIXED_CCIPLL2_B, "ccipll2_b", 0x0214, 0x0220, 0xff000001,
HAVE_RST_BAR, 23, 32, 0x0214, 4, 0, 0, 0, 0x0218, 0, 0x0214),
PLL(CLK_APMIXED_USXGMIIPLL, "usxgmiipll", 0x0304, 0x0310, 0xff000001,
HAVE_RST_BAR, 23, 32, 0x0304, 4, 0, 0, 0, 0x0308, 0, 0x0304),
PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0314, 0x0320, 0x00000001, 0, 0,
32, 0x0314, 4, 0, 0, 0, 0x0318, 0, 0x0314),
};
static const struct of_device_id of_match_clk_mt7988_apmixed[] = {
{
.compatible = "mediatek,mt7988-apmixedsys",
},
{}
};
static int clk_mt7988_apmixed_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
int r;
clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls));
if (!clk_data)
return -ENOMEM;
mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r) {
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
goto free_apmixed_data;
}
return r;
free_apmixed_data:
mtk_free_clk_data(clk_data);
return r;
}
static struct platform_driver clk_mt7988_apmixed_drv = {
.probe = clk_mt7988_apmixed_probe,
.driver = {
.name = "clk-mt7988-apmixed",
.of_match_table = of_match_clk_mt7988_apmixed,
},
};
builtin_platform_driver(clk_mt7988_apmixed_drv);

View file

@ -0,0 +1,299 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2023 MediaTek Inc.
* Author: Sam Shih <sam.shih@mediatek.com>
* Author: Xiufeng Li <Xiufeng.Li@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mediatek,mt7988-clk.h>
static const struct mtk_gate_regs ethdma_cg_regs = {
.set_ofs = 0x30,
.clr_ofs = 0x30,
.sta_ofs = 0x30,
};
#define GATE_ETHDMA(_id, _name, _parent, _shift) \
{ \
.id = _id, .name = _name, .parent_name = _parent, \
.regs = &ethdma_cg_regs, .shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
}
static const struct mtk_gate ethdma_clks[] = {
GATE_ETHDMA(CLK_ETHDMA_XGP1_EN, "ethdma_xgp1_en", "top_xtal", 0),
GATE_ETHDMA(CLK_ETHDMA_XGP2_EN, "ethdma_xgp2_en", "top_xtal", 1),
GATE_ETHDMA(CLK_ETHDMA_XGP3_EN, "ethdma_xgp3_en", "top_xtal", 2),
GATE_ETHDMA(CLK_ETHDMA_FE_EN, "ethdma_fe_en", "netsys_2x_sel", 6),
GATE_ETHDMA(CLK_ETHDMA_GP2_EN, "ethdma_gp2_en", "top_xtal", 7),
GATE_ETHDMA(CLK_ETHDMA_GP1_EN, "ethdma_gp1_en", "top_xtal", 8),
GATE_ETHDMA(CLK_ETHDMA_GP3_EN, "ethdma_gp3_en", "top_xtal", 10),
GATE_ETHDMA(CLK_ETHDMA_ESW_EN, "ethdma_esw_en", "netsys_gsw_sel", 16),
GATE_ETHDMA(CLK_ETHDMA_CRYPT0_EN, "ethdma_crypt0_en", "eip197_sel",
29),
};
static int clk_mt7988_ethsys_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
int r;
void __iomem *base;
base = of_iomap(node, 0);
if (!base) {
pr_err("%s(): ioremap failed\n", __func__);
return -ENOMEM;
}
clk_data = mtk_alloc_clk_data(ARRAY_SIZE(ethdma_clks));
if (!clk_data)
return -ENOMEM;
mtk_clk_register_gates(node, ethdma_clks, ARRAY_SIZE(ethdma_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r) {
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
goto free_data;
}
return r;
free_data:
mtk_free_clk_data(clk_data);
return r;
}
static const struct mtk_gate_regs sgmii0_cg_regs = {
.set_ofs = 0xe4,
.clr_ofs = 0xe4,
.sta_ofs = 0xe4,
};
#define GATE_SGMII0(_id, _name, _parent, _shift) \
{ \
.id = _id, .name = _name, .parent_name = _parent, \
.regs = &sgmii0_cg_regs, .shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
}
static const struct mtk_gate sgmii0_clks[] = {
GATE_SGMII0(CLK_SGM0_TX_EN, "sgm0_tx_en", "top_xtal", 2),
GATE_SGMII0(CLK_SGM0_RX_EN, "sgm0_rx_en", "top_xtal", 3),
};
static int clk_mt7988_sgmii0_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
int r;
void __iomem *base;
base = of_iomap(node, 0);
if (!base) {
pr_err("%s(): ioremap failed\n", __func__);
return -ENOMEM;
}
clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii0_clks));
if (!clk_data)
return -ENOMEM;
mtk_clk_register_gates(node, sgmii0_clks, ARRAY_SIZE(sgmii0_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r) {
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
goto free_data;
}
return r;
free_data:
mtk_free_clk_data(clk_data);
return r;
}
static const struct mtk_gate_regs sgmii1_cg_regs = {
.set_ofs = 0xe4,
.clr_ofs = 0xe4,
.sta_ofs = 0xe4,
};
#define GATE_SGMII1(_id, _name, _parent, _shift) \
{ \
.id = _id, .name = _name, .parent_name = _parent, \
.regs = &sgmii1_cg_regs, .shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
}
static const struct mtk_gate sgmii1_clks[] = {
GATE_SGMII1(CLK_SGM1_TX_EN, "sgm1_tx_en", "top_xtal", 2),
GATE_SGMII1(CLK_SGM1_RX_EN, "sgm1_rx_en", "top_xtal", 3),
};
static int clk_mt7988_sgmii1_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
int r;
void __iomem *base;
base = of_iomap(node, 0);
if (!base) {
pr_err("%s(): ioremap failed\n", __func__);
return -ENOMEM;
}
clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii1_clks));
if (!clk_data)
return -ENOMEM;
mtk_clk_register_gates(node, sgmii1_clks, ARRAY_SIZE(sgmii1_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r) {
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
goto free_data;
}
return r;
free_data:
mtk_free_clk_data(clk_data);
return r;
}
static const struct mtk_gate_regs ethwarp_cg_regs = {
.set_ofs = 0x14,
.clr_ofs = 0x14,
.sta_ofs = 0x14,
};
#define GATE_ETHWARP(_id, _name, _parent, _shift) \
{ \
.id = _id, .name = _name, .parent_name = _parent, \
.regs = &ethwarp_cg_regs, .shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
}
static const struct mtk_gate ethwarp_clks[] = {
GATE_ETHWARP(CLK_ETHWARP_WOCPU2_EN, "ethwarp_wocpu2_en",
"netsys_mcu_sel", 13),
GATE_ETHWARP(CLK_ETHWARP_WOCPU1_EN, "ethwarp_wocpu1_en",
"netsys_mcu_sel", 14),
GATE_ETHWARP(CLK_ETHWARP_WOCPU0_EN, "ethwarp_wocpu0_en",
"netsys_mcu_sel", 15),
};
static int clk_mt7988_ethwarp_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
int r;
void __iomem *base;
base = of_iomap(node, 0);
if (!base) {
pr_err("%s(): ioremap failed\n", __func__);
return -ENOMEM;
}
clk_data = mtk_alloc_clk_data(ARRAY_SIZE(ethwarp_clks));
if (!clk_data)
return -ENOMEM;
mtk_clk_register_gates(node, ethwarp_clks, ARRAY_SIZE(ethwarp_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r) {
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
goto free_data;
}
return r;
free_data:
mtk_free_clk_data(clk_data);
return r;
}
static const struct of_device_id of_match_clk_mt7988_ethsys[] = {
{
.compatible = "mediatek,mt7988-ethsys",
},
{}
};
static struct platform_driver clk_mt7988_ethsys_drv = {
.probe = clk_mt7988_ethsys_probe,
.driver = {
.name = "clk-mt7988-ethsys",
.of_match_table = of_match_clk_mt7988_ethsys,
},
};
builtin_platform_driver(clk_mt7988_ethsys_drv);
static const struct of_device_id of_match_clk_mt7988_sgmii0[] = {
{
.compatible = "mediatek,mt7988-sgmiisys_0",
},
{}
};
static struct platform_driver clk_mt7988_sgmii0_drv = {
.probe = clk_mt7988_sgmii0_probe,
.driver = {
.name = "clk-mt7988-sgmiisys_0",
.of_match_table = of_match_clk_mt7988_sgmii0,
},
};
builtin_platform_driver(clk_mt7988_sgmii0_drv);
static const struct of_device_id of_match_clk_mt7988_sgmii1[] = {
{
.compatible = "mediatek,mt7988-sgmiisys_1",
},
{}
};
static struct platform_driver clk_mt7988_sgmii1_drv = {
.probe = clk_mt7988_sgmii1_probe,
.driver = {
.name = "clk-mt7988-sgmiisys_1",
.of_match_table = of_match_clk_mt7988_sgmii1,
},
};
builtin_platform_driver(clk_mt7988_sgmii1_drv);
static const struct of_device_id of_match_clk_mt7988_ethwarp[] = {
{
.compatible = "mediatek,mt7988-ethwarp",
},
{}
};
static struct platform_driver clk_mt7988_ethwarp_drv = {
.probe = clk_mt7988_ethwarp_probe,
.driver = {
.name = "clk-mt7988-ethwarp",
.of_match_table = of_match_clk_mt7988_ethwarp,
},
};
builtin_platform_driver(clk_mt7988_ethwarp_drv);

View file

@ -0,0 +1,399 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2023 MediaTek Inc.
* Author: Sam Shih <sam.shih@mediatek.com>
* Author: Xiufeng Li <Xiufeng.Li@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include "clk-mux.h"
#include <dt-bindings/clock/mediatek,mt7988-clk.h>
static DEFINE_SPINLOCK(mt7988_clk_lock);
static const char *const infra_mux_uart0_parents[] __initconst = {
"csw_infra_f26m_sel", "uart_sel"
};
static const char *const infra_mux_uart1_parents[] __initconst = {
"csw_infra_f26m_sel", "uart_sel"
};
static const char *const infra_mux_uart2_parents[] __initconst = {
"csw_infra_f26m_sel", "uart_sel"
};
static const char *const infra_mux_spi0_parents[] __initconst = { "i2c_sel",
"spi_sel" };
static const char *const infra_mux_spi1_parents[] __initconst = {
"i2c_sel", "spim_mst_sel"
};
static const char *const infra_pwm_bck_parents[] __initconst = {
"top_rtc_32p7k", "csw_infra_f26m_sel", "sysaxi_sel", "pwm_sel"
};
static const char *const infra_pcie_gfmux_tl_ck_o_p0_parents[] __initconst = {
"top_rtc_32p7k", "csw_infra_f26m_sel", "csw_infra_f26m_sel",
"pextp_tl_sel"
};
static const char *const infra_pcie_gfmux_tl_ck_o_p1_parents[] __initconst = {
"top_rtc_32p7k", "csw_infra_f26m_sel", "csw_infra_f26m_sel",
"pextp_tl_p1_sel"
};
static const char *const infra_pcie_gfmux_tl_ck_o_p2_parents[] __initconst = {
"top_rtc_32p7k", "csw_infra_f26m_sel", "csw_infra_f26m_sel",
"pextp_tl_p2_sel"
};
static const char *const infra_pcie_gfmux_tl_ck_o_p3_parents[] __initconst = {
"top_rtc_32p7k", "csw_infra_f26m_sel", "csw_infra_f26m_sel",
"pextp_tl_p3_sel"
};
static const struct mtk_mux infra_muxes[] = {
/* MODULE_CLK_SEL_0 */
MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_UART0_SEL, "infra_mux_uart0_sel",
infra_mux_uart0_parents, 0x0018, 0x0010, 0x0014,
0, 1, -1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_UART1_SEL, "infra_mux_uart1_sel",
infra_mux_uart1_parents, 0x0018, 0x0010, 0x0014,
1, 1, -1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_UART2_SEL, "infra_mux_uart2_sel",
infra_mux_uart2_parents, 0x0018, 0x0010, 0x0014,
2, 1, -1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_SPI0_SEL, "infra_mux_spi0_sel",
infra_mux_spi0_parents, 0x0018, 0x0010, 0x0014, 4,
1, -1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_SPI1_SEL, "infra_mux_spi1_sel",
infra_mux_spi1_parents, 0x0018, 0x0010, 0x0014, 5,
1, -1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_SPI2_SEL, "infra_mux_spi2_sel",
infra_mux_spi0_parents, 0x0018, 0x0010, 0x0014, 6,
1, -1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_SEL, "infra_pwm_sel",
infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 14,
2, -1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK1_SEL, "infra_pwm_ck1_sel",
infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 16,
2, -1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK2_SEL, "infra_pwm_ck2_sel",
infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 18,
2, -1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK3_SEL, "infra_pwm_ck3_sel",
infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 20,
2, -1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK4_SEL, "infra_pwm_ck4_sel",
infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 22,
2, -1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK5_SEL, "infra_pwm_ck5_sel",
infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 24,
2, -1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK6_SEL, "infra_pwm_ck6_sel",
infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 26,
2, -1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK7_SEL, "infra_pwm_ck7_sel",
infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 28,
2, -1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK8_SEL, "infra_pwm_ck8_sel",
infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 30,
2, -1, -1, -1),
/* MODULE_CLK_SEL_1 */
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_GFMUX_TL_O_P0_SEL,
"infra_pcie_gfmux_tl_o_p0_sel",
infra_pcie_gfmux_tl_ck_o_p0_parents, 0x0028,
0x0020, 0x0024, 0, 2, -1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_GFMUX_TL_O_P1_SEL,
"infra_pcie_gfmux_tl_o_p1_sel",
infra_pcie_gfmux_tl_ck_o_p1_parents, 0x0028,
0x0020, 0x0024, 2, 2, -1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_GFMUX_TL_O_P2_SEL,
"infra_pcie_gfmux_tl_o_p2_sel",
infra_pcie_gfmux_tl_ck_o_p2_parents, 0x0028,
0x0020, 0x0024, 4, 2, -1, -1, -1),
MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_GFMUX_TL_O_P3_SEL,
"infra_pcie_gfmux_tl_o_p3_sel",
infra_pcie_gfmux_tl_ck_o_p3_parents, 0x0028,
0x0020, 0x0024, 6, 2, -1, -1, -1),
};
static const struct mtk_gate_regs infra0_cg_regs = {
.set_ofs = 0x10,
.clr_ofs = 0x14,
.sta_ofs = 0x18,
};
static const struct mtk_gate_regs infra1_cg_regs = {
.set_ofs = 0x40,
.clr_ofs = 0x44,
.sta_ofs = 0x48,
};
static const struct mtk_gate_regs infra2_cg_regs = {
.set_ofs = 0x50,
.clr_ofs = 0x54,
.sta_ofs = 0x58,
};
static const struct mtk_gate_regs infra3_cg_regs = {
.set_ofs = 0x60,
.clr_ofs = 0x64,
.sta_ofs = 0x68,
};
#define GATE_INFRA0_FLAGS(_id, _name, _parent, _shift, _flags) \
{ \
.id = _id, .name = _name, .parent_name = _parent, \
.regs = &infra0_cg_regs, .shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, .flags = _flags, \
}
#define GATE_INFRA1_FLAGS(_id, _name, _parent, _shift, _flags) \
{ \
.id = _id, .name = _name, .parent_name = _parent, \
.regs = &infra1_cg_regs, .shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, .flags = _flags, \
}
#define GATE_INFRA2_FLAGS(_id, _name, _parent, _shift, _flags) \
{ \
.id = _id, .name = _name, .parent_name = _parent, \
.regs = &infra2_cg_regs, .shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, .flags = _flags, \
}
#define GATE_INFRA3_FLAGS(_id, _name, _parent, _shift, _flags) \
{ \
.id = _id, .name = _name, .parent_name = _parent, \
.regs = &infra3_cg_regs, .shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, .flags = _flags, \
}
#define GATE_INFRA0(_id, _name, _parent, _shift) \
GATE_INFRA0_FLAGS(_id, _name, _parent, _shift, 0)
#define GATE_INFRA1(_id, _name, _parent, _shift) \
GATE_INFRA1_FLAGS(_id, _name, _parent, _shift, 0)
#define GATE_INFRA2(_id, _name, _parent, _shift) \
GATE_INFRA2_FLAGS(_id, _name, _parent, _shift, 0)
#define GATE_INFRA3(_id, _name, _parent, _shift) \
GATE_INFRA3_FLAGS(_id, _name, _parent, _shift, 0)
static const struct mtk_gate infra_clks[] = {
/* INFRA0 */
GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P0,
"infra_pcie_peri_ck_26m_ck_p0", "csw_infra_f26m_sel", 7),
GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P1,
"infra_pcie_peri_ck_26m_ck_p1", "csw_infra_f26m_sel", 8),
GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P2,
"infra_pcie_peri_ck_26m_ck_p2", "csw_infra_f26m_sel", 9),
GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P3,
"infra_pcie_peri_ck_26m_ck_p3", "csw_infra_f26m_sel", 10),
/* INFRA1 */
GATE_INFRA1(CLK_INFRA_66M_GPT_BCK, "infra_hf_66m_gpt_bck",
"sysaxi_sel", 0),
GATE_INFRA1(CLK_INFRA_66M_PWM_HCK, "infra_hf_66m_pwm_hck",
"sysaxi_sel", 1),
GATE_INFRA1(CLK_INFRA_66M_PWM_BCK, "infra_hf_66m_pwm_bck",
"infra_pwm_sel", 2),
GATE_INFRA1(CLK_INFRA_66M_PWM_CK1, "infra_hf_66m_pwm_ck1",
"infra_pwm_ck1_sel", 3),
GATE_INFRA1(CLK_INFRA_66M_PWM_CK2, "infra_hf_66m_pwm_ck2",
"infra_pwm_ck2_sel", 4),
GATE_INFRA1(CLK_INFRA_66M_PWM_CK3, "infra_hf_66m_pwm_ck3",
"infra_pwm_ck3_sel", 5),
GATE_INFRA1(CLK_INFRA_66M_PWM_CK4, "infra_hf_66m_pwm_ck4",
"infra_pwm_ck4_sel", 6),
GATE_INFRA1(CLK_INFRA_66M_PWM_CK5, "infra_hf_66m_pwm_ck5",
"infra_pwm_ck5_sel", 7),
GATE_INFRA1(CLK_INFRA_66M_PWM_CK6, "infra_hf_66m_pwm_ck6",
"infra_pwm_ck6_sel", 8),
GATE_INFRA1(CLK_INFRA_66M_PWM_CK7, "infra_hf_66m_pwm_ck7",
"infra_pwm_ck7_sel", 9),
GATE_INFRA1(CLK_INFRA_66M_PWM_CK8, "infra_hf_66m_pwm_ck8",
"infra_pwm_ck8_sel", 10),
GATE_INFRA1(CLK_INFRA_133M_CQDMA_BCK, "infra_hf_133m_cqdma_bck",
"sysaxi_sel", 12),
GATE_INFRA1(CLK_INFRA_66M_AUD_SLV_BCK, "infra_66m_aud_slv_bck",
"sysaxi_sel", 13),
GATE_INFRA1(CLK_INFRA_AUD_26M, "infra_f_faud_26m",
"csw_infra_f26m_sel", 14),
GATE_INFRA1(CLK_INFRA_AUD_L, "infra_f_faud_l", "aud_l_sel", 15),
GATE_INFRA1(CLK_INFRA_AUD_AUD, "infra_f_aud_aud", "a1sys_sel", 16),
GATE_INFRA1(CLK_INFRA_AUD_EG2, "infra_f_faud_eg2", "a_tuner_sel", 18),
GATE_INFRA1_FLAGS(CLK_INFRA_DRAMC_F26M, "infra_dramc_f26m",
"csw_infra_f26m_sel", 19, CLK_IS_CRITICAL),
// JTAG
GATE_INFRA1_FLAGS(CLK_INFRA_133M_DBG_ACKM, "infra_hf_133m_dbg_ackm",
"sysaxi_sel", 20, CLK_IS_CRITICAL),
GATE_INFRA1(CLK_INFRA_66M_AP_DMA_BCK, "infra_66m_ap_dma_bck",
"sysaxi_sel", 21),
GATE_INFRA1(CLK_INFRA_66M_SEJ_BCK, "infra_hf_66m_sej_bck",
"sysaxi_sel", 29),
GATE_INFRA1(CLK_INFRA_PRE_CK_SEJ_F13M, "infra_pre_ck_sej_f13m",
"csw_infra_f26m_sel", 30),
/* INFRA2 */
GATE_INFRA2(CLK_INFRA_26M_THERM_SYSTEM, "infra_hf_26m_therm_system",
"csw_infra_f26m_sel", 0),
GATE_INFRA2(CLK_INFRA_I2C_BCK, "infra_i2c_bck", "i2c_sel", 1),
GATE_INFRA2(CLK_INFRA_52M_UART0_CK, "infra_f_52m_uart0",
"infra_mux_uart0_sel", 3),
GATE_INFRA2(CLK_INFRA_52M_UART1_CK, "infra_f_52m_uart1",
"infra_mux_uart1_sel", 4),
GATE_INFRA2(CLK_INFRA_52M_UART2_CK, "infra_f_52m_uart2",
"infra_mux_uart2_sel", 5),
GATE_INFRA2(CLK_INFRA_NFI, "infra_f_fnfi", "nfi1x_sel", 9),
GATE_INFRA2(CLK_INFRA_SPINFI, "infra_f_fspinfi", "spinfi_sel", 10),
GATE_INFRA2_FLAGS(CLK_INFRA_66M_NFI_HCK, "infra_hf_66m_nfi_hck",
"sysaxi_sel", 11, CLK_IS_CRITICAL),
GATE_INFRA2_FLAGS(CLK_INFRA_104M_SPI0, "infra_hf_104m_spi0",
"infra_mux_spi0_sel", 12, CLK_IS_CRITICAL),
GATE_INFRA2(CLK_INFRA_104M_SPI1, "infra_hf_104m_spi1",
"infra_mux_spi1_sel", 13),
GATE_INFRA2(CLK_INFRA_104M_SPI2_BCK, "infra_hf_104m_spi2_bck",
"infra_mux_spi2_sel", 14),
GATE_INFRA2_FLAGS(CLK_INFRA_66M_SPI0_HCK, "infra_hf_66m_spi0_hck",
"sysaxi_sel", 15, CLK_IS_CRITICAL),
GATE_INFRA2(CLK_INFRA_66M_SPI1_HCK, "infra_hf_66m_spi1_hck",
"sysaxi_sel", 16),
GATE_INFRA2(CLK_INFRA_66M_SPI2_HCK, "infra_hf_66m_spi2_hck",
"sysaxi_sel", 17),
GATE_INFRA2(CLK_INFRA_66M_FLASHIF_AXI, "infra_hf_66m_flashif_axi",
"sysaxi_sel", 18),
GATE_INFRA2(CLK_INFRA_RTC, "infra_f_frtc", "top_rtc_32k", 19),
GATE_INFRA2(CLK_INFRA_26M_ADC_BCK, "infra_f_26m_adc_bck",
"csw_infra_f26m_sel", 20),
GATE_INFRA2(CLK_INFRA_RC_ADC, "infra_f_frc_adc", "infra_f_26m_adc_bck",
21),
GATE_INFRA2(CLK_INFRA_MSDC400, "infra_f_fmsdc400", "emmc_400m_sel",
22),
GATE_INFRA2(CLK_INFRA_MSDC2_HCK, "infra_f_fmsdc2_hck", "emmc_250m_sel",
23),
GATE_INFRA2(CLK_INFRA_133M_MSDC_0_HCK, "infra_hf_133m_msdc_0_hck",
"sysaxi_sel", 24),
GATE_INFRA2(CLK_INFRA_66M_MSDC_0_HCK, "infra_66m_msdc_0_hck",
"sysaxi_sel", 25),
GATE_INFRA2(CLK_INFRA_133M_CPUM_BCK, "infra_hf_133m_cpum_bck",
"sysaxi_sel", 26),
GATE_INFRA2(CLK_INFRA_BIST2FPC, "infra_hf_fbist2fpc", "nfi1x_sel", 27),
GATE_INFRA2(CLK_INFRA_I2C_X16W_MCK_CK_P1,
"infra_hf_i2c_x16w_mck_ck_p1", "sysaxi_sel", 29),
GATE_INFRA2(CLK_INFRA_I2C_X16W_PCK_CK_P1,
"infra_hf_i2c_x16w_pck_ck_p1", "sysaxi_sel", 31),
/* INFRA3 */
GATE_INFRA3(CLK_INFRA_133M_USB_HCK, "infra_133m_usb_hck", "sysaxi_sel",
0),
GATE_INFRA3(CLK_INFRA_133M_USB_HCK_CK_P1, "infra_133m_usb_hck_ck_p1",
"sysaxi_sel", 1),
GATE_INFRA3(CLK_INFRA_66M_USB_HCK, "infra_66m_usb_hck", "sysaxi_sel",
2),
GATE_INFRA3(CLK_INFRA_66M_USB_HCK_CK_P1, "infra_66m_usb_hck_ck_p1",
"sysaxi_sel", 3),
GATE_INFRA3(CLK_INFRA_USB_SYS, "infra_usb_sys", "usb_sys_sel", 4),
GATE_INFRA3(CLK_INFRA_USB_SYS_CK_P1, "infra_usb_sys_ck_p1",
"usb_sys_p1_sel", 5),
GATE_INFRA3(CLK_INFRA_USB_REF, "infra_usb_ref", "top_xtal", 6),
GATE_INFRA3(CLK_INFRA_USB_CK_P1, "infra_usb_ck_p1", "top_xtal", 7),
GATE_INFRA3_FLAGS(CLK_INFRA_USB_FRMCNT, "infra_usb_frmcnt",
"usb_frmcnt_sel", 8, CLK_IS_CRITICAL),
GATE_INFRA3_FLAGS(CLK_INFRA_USB_FRMCNT_CK_P1, "infra_usb_frmcnt_ck_p1",
"usb_frmcnt_p1_sel", 9, CLK_IS_CRITICAL),
GATE_INFRA3(CLK_INFRA_USB_PIPE, "infra_usb_pipe", "sspxtp_sel", 10),
GATE_INFRA3(CLK_INFRA_USB_PIPE_CK_P1, "infra_usb_pipe_ck_p1",
"usb_phy_sel", 11),
GATE_INFRA3(CLK_INFRA_USB_UTMI, "infra_usb_utmi", "top_xtal", 12),
GATE_INFRA3(CLK_INFRA_USB_UTMI_CK_P1, "infra_usb_utmi_ck_p1",
"top_xtal", 13),
GATE_INFRA3(CLK_INFRA_USB_XHCI, "infra_usb_xhci", "usb_xhci_sel", 14),
GATE_INFRA3(CLK_INFRA_USB_XHCI_CK_P1, "infra_usb_xhci_ck_p1",
"usb_xhci_p1_sel", 15),
GATE_INFRA3(CLK_INFRA_PCIE_GFMUX_TL_P0, "infra_pcie_gfmux_tl_ck_p0",
"infra_pcie_gfmux_tl_o_p0_sel", 20),
GATE_INFRA3(CLK_INFRA_PCIE_GFMUX_TL_P1, "infra_pcie_gfmux_tl_ck_p1",
"infra_pcie_gfmux_tl_o_p1_sel", 21),
GATE_INFRA3(CLK_INFRA_PCIE_GFMUX_TL_P2, "infra_pcie_gfmux_tl_ck_p2",
"infra_pcie_gfmux_tl_o_p2_sel", 22),
GATE_INFRA3(CLK_INFRA_PCIE_GFMUX_TL_P3, "infra_pcie_gfmux_tl_ck_p3",
"infra_pcie_gfmux_tl_o_p3_sel", 23),
GATE_INFRA3(CLK_INFRA_PCIE_PIPE_P0, "infra_pcie_pipe_ck_p0",
"top_xtal", 24),
GATE_INFRA3(CLK_INFRA_PCIE_PIPE_P1, "infra_pcie_pipe_ck_p1",
"top_xtal", 25),
GATE_INFRA3(CLK_INFRA_PCIE_PIPE_P2, "infra_pcie_pipe_ck_p2",
"top_xtal", 26),
GATE_INFRA3(CLK_INFRA_PCIE_PIPE_P3, "infra_pcie_pipe_ck_p3",
"top_xtal", 27),
GATE_INFRA3(CLK_INFRA_133M_PCIE_CK_P0, "infra_133m_pcie_ck_p0",
"sysaxi_sel", 28),
GATE_INFRA3(CLK_INFRA_133M_PCIE_CK_P1, "infra_133m_pcie_ck_p1",
"sysaxi_sel", 29),
GATE_INFRA3(CLK_INFRA_133M_PCIE_CK_P2, "infra_133m_pcie_ck_p2",
"sysaxi_sel", 30),
GATE_INFRA3(CLK_INFRA_133M_PCIE_CK_P3, "infra_133m_pcie_ck_p3",
"sysaxi_sel", 31),
};
static int clk_mt7988_infracfg_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
int r;
void __iomem *base;
int nr = ARRAY_SIZE(infra_muxes) + ARRAY_SIZE(infra_clks);
base = of_iomap(node, 0);
if (!base) {
pr_err("%s(): ioremap failed\n", __func__);
return -ENOMEM;
}
clk_data = mtk_alloc_clk_data(nr);
if (!clk_data)
return -ENOMEM;
mtk_clk_register_muxes(infra_muxes, ARRAY_SIZE(infra_muxes), node,
&mt7988_clk_lock, clk_data);
mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r) {
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
goto free_infracfg_data;
}
return r;
free_infracfg_data:
mtk_free_clk_data(clk_data);
return r;
}
static const struct of_device_id of_match_clk_mt7988_infracfg[] = {
{
.compatible = "mediatek,mt7988-infracfg",
},
{}
};
static struct platform_driver clk_mt7988_infracfg_drv = {
.probe = clk_mt7988_infracfg_probe,
.driver = {
.name = "clk-mt7988-infracfg",
.of_match_table = of_match_clk_mt7988_infracfg,
},
};
builtin_platform_driver(clk_mt7988_infracfg_drv);

View file

@ -0,0 +1,522 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2023 MediaTek Inc.
* Author: Sam Shih <sam.shih@mediatek.com>
* Author: Xiufeng Li <Xiufeng.Li@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include "clk-mux.h"
#include <dt-bindings/clock/mediatek,mt7988-clk.h>
static DEFINE_SPINLOCK(mt7988_clk_lock);
static const struct mtk_fixed_clk top_fixed_clks[] = {
FIXED_CLK(CLK_TOP_XTAL, "top_xtal", "clkxtal", 40000000),
};
static const struct mtk_fixed_factor top_divs[] = {
FACTOR(CLK_TOP_XTAL_D2, "top_xtal_d2", "top_xtal", 1, 2),
FACTOR(CLK_TOP_RTC_32K, "top_rtc_32k", "top_xtal", 1, 1250),
FACTOR(CLK_TOP_RTC_32P7K, "top_rtc_32p7k", "top_xtal", 1, 1220),
FACTOR(CLK_TOP_MPLL_D2, "mpll_d2", "mpll", 1, 2),
FACTOR(CLK_TOP_MPLL_D3_D2, "mpll_d3_d2", "mpll", 1, 2),
FACTOR(CLK_TOP_MPLL_D4, "mpll_d4", "mpll", 1, 4),
FACTOR(CLK_TOP_MPLL_D8, "mpll_d8", "mpll", 1, 8),
FACTOR(CLK_TOP_MPLL_D8_D2, "mpll_d8_d2", "mpll", 1, 16),
FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
FACTOR(CLK_TOP_MMPLL_D3_D5, "mmpll_d3_d5", "mmpll", 1, 15),
FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll", 1, 4),
FACTOR(CLK_TOP_MMPLL_D6_D2, "mmpll_d6_d2", "mmpll", 1, 12),
FACTOR(CLK_TOP_MMPLL_D8, "mmpll_d8", "mmpll", 1, 8),
FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1, 4),
FACTOR(CLK_TOP_NET1PLL_D4, "net1pll_d4", "net1pll", 1, 4),
FACTOR(CLK_TOP_NET1PLL_D5, "net1pll_d5", "net1pll", 1, 5),
FACTOR(CLK_TOP_NET1PLL_D5_D2, "net1pll_d5_d2", "net1pll", 1, 10),
FACTOR(CLK_TOP_NET1PLL_D5_D4, "net1pll_d5_d4", "net1pll", 1, 20),
FACTOR(CLK_TOP_NET1PLL_D8, "net1pll_d8", "net1pll", 1, 8),
FACTOR(CLK_TOP_NET1PLL_D8_D2, "net1pll_d8_d2", "net1pll", 1, 16),
FACTOR(CLK_TOP_NET1PLL_D8_D4, "net1pll_d8_d4", "net1pll", 1, 32),
FACTOR(CLK_TOP_NET1PLL_D8_D8, "net1pll_d8_d8", "net1pll", 1, 64),
FACTOR(CLK_TOP_NET1PLL_D8_D16, "net1pll_d8_d16", "net1pll", 1, 128),
FACTOR(CLK_TOP_NET2PLL_D2, "net2pll_d2", "net2pll", 1, 2),
FACTOR(CLK_TOP_NET2PLL_D4, "net2pll_d4", "net2pll", 1, 4),
FACTOR(CLK_TOP_NET2PLL_D4_D4, "net2pll_d4_d4", "net2pll", 1, 16),
FACTOR(CLK_TOP_NET2PLL_D4_D8, "net2pll_d4_d8", "net2pll", 1, 32),
FACTOR(CLK_TOP_NET2PLL_D6, "net2pll_d6", "net2pll", 1, 6),
FACTOR(CLK_TOP_NET2PLL_D8, "net2pll_d8", "net2pll", 1, 8),
};
static const char *const netsys_parents[] = { "top_xtal", "net2pll_d2",
"mmpll_d2" };
static const char *const netsys_500m_parents[] = { "top_xtal", "net1pll_d5",
"net1pll_d5_d2" };
static const char *const netsys_2x_parents[] = { "top_xtal", "net2pll",
"mmpll" };
static const char *const netsys_gsw_parents[] = { "top_xtal", "net1pll_d4",
"net1pll_d5" };
static const char *const eth_gmii_parents[] = { "top_xtal", "net1pll_d5_d4" };
static const char *const netsys_mcu_parents[] = { "top_xtal", "net2pll",
"mmpll", "net1pll_d4",
"net1pll_d5", "mpll" };
static const char *const eip197_parents[] = { "top_xtal", "netsyspll",
"net2pll", "mmpll",
"net1pll_d4", "net1pll_d5" };
static const char *const axi_infra_parents[] = { "top_xtal", "net1pll_d8_d2" };
static const char *const uart_parents[] = { "top_xtal", "mpll_d8",
"mpll_d8_d2" };
static const char *const emmc_250m_parents[] = { "top_xtal", "net1pll_d5_d2",
"mmpll_d4" };
static const char *const emmc_400m_parents[] = { "top_xtal", "msdcpll",
"mmpll_d2", "mpll_d2",
"mmpll_d4", "net1pll_d8_d2" };
static const char *const spi_parents[] = { "top_xtal", "mpll_d2",
"mmpll_d4", "net1pll_d8_d2",
"net2pll_d6", "net1pll_d5_d4",
"mpll_d4", "net1pll_d8_d4" };
static const char *const nfi1x_parents[] = { "top_xtal", "mmpll_d4",
"net1pll_d8_d2", "net2pll_d6",
"mpll_d4", "mmpll_d8",
"net1pll_d8_d4", "mpll_d8" };
static const char *const spinfi_parents[] = { "top_xtal_d2", "top_xtal",
"net1pll_d5_d4", "mpll_d4",
"mmpll_d8", "net1pll_d8_d4",
"mmpll_d6_d2", "mpll_d8" };
static const char *const pwm_parents[] = { "top_xtal", "net1pll_d8_d2",
"net1pll_d5_d4", "mpll_d4",
"mpll_d8_d2", "top_rtc_32k" };
static const char *const i2c_parents[] = { "top_xtal", "net1pll_d5_d4",
"mpll_d4", "net1pll_d8_d4" };
static const char *const pcie_mbist_250m_parents[] = { "top_xtal",
"net1pll_d5_d2" };
static const char *const pextp_tl_ck_parents[] = { "top_xtal", "net2pll_d6",
"mmpll_d8", "mpll_d8_d2",
"top_rtc_32k" };
static const char *const usb_frmcnt_parents[] = { "top_xtal", "mmpll_d3_d5" };
static const char *const aud_parents[] = { "top_xtal", "apll2" };
static const char *const a1sys_parents[] = { "top_xtal", "apll2_d4" };
static const char *const aud_l_parents[] = { "top_xtal", "apll2",
"mpll_d8_d2" };
static const char *const sspxtp_parents[] = { "top_xtal_d2", "mpll_d8_d2" };
static const char *const usxgmii_sbus_0_parents[] = { "top_xtal",
"net1pll_d8_d4" };
static const char *const sgm_0_parents[] = { "top_xtal", "sgmpll" };
static const char *const sysapb_parents[] = { "top_xtal", "mpll_d3_d2" };
static const char *const eth_refck_50m_parents[] = { "top_xtal",
"net2pll_d4_d4" };
static const char *const eth_sys_200m_parents[] = { "top_xtal", "net2pll_d4" };
static const char *const eth_xgmii_parents[] = { "top_xtal_d2",
"net1pll_d8_d8",
"net1pll_d8_d16" };
static const char *const bus_tops_parents[] = { "top_xtal", "net1pll_d5",
"net2pll_d2" };
static const char *const npu_tops_parents[] = { "top_xtal", "net2pll" };
static const char *const dramc_md32_parents[] = { "top_xtal", "mpll_d2",
"wedmcupll" };
static const char *const da_xtp_glb_p0_parents[] = { "top_xtal",
"net2pll_d8" };
static const char *const mcusys_backup_625m_parents[] = { "top_xtal",
"net1pll_d4" };
static const char *const macsec_parents[] = { "top_xtal", "sgmpll",
"net1pll_d8" };
static const char *const netsys_tops_400m_parents[] = { "top_xtal",
"net2pll_d2" };
static const char *const eth_mii_parents[] = { "top_xtal_d2",
"net2pll_d4_d8" };
static const struct mtk_mux top_muxes[] = {
/* CLK_CFG_0 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents,
0x000, 0x004, 0x008, 0, 2, 7, 0x1c0, 0),
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_500M_SEL, "netsys_500m_sel",
netsys_500m_parents, 0x000, 0x004, 0x008, 8, 2,
15, 0x1C0, 1),
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_2X_SEL, "netsys_2x_sel",
netsys_2x_parents, 0x000, 0x004, 0x008, 16, 2, 23,
0x1C0, 2),
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_GSW_SEL, "netsys_gsw_sel",
netsys_gsw_parents, 0x000, 0x004, 0x008, 24, 2,
31, 0x1C0, 3),
/* CLK_CFG_1 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_GMII_SEL, "eth_gmii_sel",
eth_gmii_parents, 0x010, 0x014, 0x018, 0, 1, 7,
0x1C0, 4),
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel",
netsys_mcu_parents, 0x010, 0x014, 0x018, 8, 3, 15,
0x1C0, 5),
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_PAO_2X_SEL, "netsys_pao_2x_sel",
netsys_mcu_parents, 0x010, 0x014, 0x018, 16, 3,
23, 0x1C0, 6),
MUX_GATE_CLR_SET_UPD(CLK_TOP_EIP197_SEL, "eip197_sel", eip197_parents,
0x010, 0x014, 0x018, 24, 3, 31, 0x1c0, 7),
/* CLK_CFG_2 */
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI_INFRA_SEL, "axi_infra_sel",
axi_infra_parents, 0x020, 0x024, 0x028, 0,
1, 7, 0x1C0, 8, CLK_IS_CRITICAL),
MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x020,
0x024, 0x028, 8, 2, 15, 0x1c0, 9),
MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_250M_SEL, "emmc_250m_sel",
emmc_250m_parents, 0x020, 0x024, 0x028, 16, 2, 23,
0x1C0, 10),
MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_400M_SEL, "emmc_400m_sel",
emmc_400m_parents, 0x020, 0x024, 0x028, 24, 3, 31,
0x1C0, 11),
/* CLK_CFG_3 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x030,
0x034, 0x038, 0, 3, 7, 0x1c0, 12),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents,
0x030, 0x034, 0x038, 8, 3, 15, 0x1c0, 13),
MUX_GATE_CLR_SET_UPD(CLK_TOP_NFI1X_SEL, "nfi1x_sel", nfi1x_parents,
0x030, 0x034, 0x038, 16, 3, 23, 0x1c0, 14),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINFI_SEL, "spinfi_sel", spinfi_parents,
0x030, 0x034, 0x038, 24, 3, 31, 0x1c0, 15),
/* CLK_CFG_4 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x040,
0x044, 0x048, 0, 3, 7, 0x1c0, 16),
MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, 0x040,
0x044, 0x048, 8, 2, 15, 0x1c0, 17),
MUX_GATE_CLR_SET_UPD(CLK_TOP_PCIE_MBIST_250M_SEL,
"pcie_mbist_250m_sel", pcie_mbist_250m_parents,
0x040, 0x044, 0x048, 16, 1, 23, 0x1C0, 18),
MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_SEL, "pextp_tl_sel",
pextp_tl_ck_parents, 0x040, 0x044, 0x048, 24, 3,
31, 0x1C0, 19),
/* CLK_CFG_5 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_P1_SEL, "pextp_tl_p1_sel",
pextp_tl_ck_parents, 0x050, 0x054, 0x058, 0, 3, 7,
0x1C0, 20),
MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_P2_SEL, "pextp_tl_p2_sel",
pextp_tl_ck_parents, 0x050, 0x054, 0x058, 8, 3,
15, 0x1C0, 21),
MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_P3_SEL, "pextp_tl_p3_sel",
pextp_tl_ck_parents, 0x050, 0x054, 0x058, 16, 3,
23, 0x1C0, 22),
MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_SYS_SEL, "usb_sys_sel",
eth_gmii_parents, 0x050, 0x054, 0x058, 24, 1, 31,
0x1C0, 23),
/* CLK_CFG_6 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_SYS_P1_SEL, "usb_sys_p1_sel",
eth_gmii_parents, 0x060, 0x064, 0x068, 0, 1, 7,
0x1C0, 24),
MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_XHCI_SEL, "usb_xhci_sel",
eth_gmii_parents, 0x060, 0x064, 0x068, 8, 1, 15,
0x1C0, 25),
MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_XHCI_P1_SEL, "usb_xhci_p1_sel",
eth_gmii_parents, 0x060, 0x064, 0x068, 16, 1, 23,
0x1C0, 26),
MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_FRMCNT_SEL, "usb_frmcnt_sel",
usb_frmcnt_parents, 0x060, 0x064, 0x068, 24, 1,
31, 0x1C0, 27),
/* CLK_CFG_7 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_FRMCNT_P1_SEL, "usb_frmcnt_p1_sel",
usb_frmcnt_parents, 0x070, 0x074, 0x078, 0, 1, 7,
0x1C0, 28),
MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_SEL, "aud_sel", aud_parents, 0x070,
0x074, 0x078, 8, 1, 15, 0x1c0, 29),
MUX_GATE_CLR_SET_UPD(CLK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents,
0x070, 0x074, 0x078, 16, 1, 23, 0x1c0, 30),
MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents,
0x070, 0x074, 0x078, 24, 2, 31, 0x1c4, 0),
/* CLK_CFG_8 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_A_TUNER_SEL, "a_tuner_sel", a1sys_parents,
0x080, 0x084, 0x088, 0, 1, 7, 0x1c4, 1),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SSPXTP_SEL, "sspxtp_sel", sspxtp_parents,
0x080, 0x084, 0x088, 8, 1, 15, 0x1c4, 2),
MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_PHY_SEL, "usb_phy_sel",
sspxtp_parents, 0x080, 0x084, 0x088, 16, 1, 23,
0x1c4, 3),
MUX_GATE_CLR_SET_UPD(CLK_TOP_USXGMII_SBUS_0_SEL, "usxgmii_sbus_0_sel",
usxgmii_sbus_0_parents, 0x080, 0x084, 0x088, 24,
1, 31, 0x1C4, 4),
/* CLK_CFG_9 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_USXGMII_SBUS_1_SEL, "usxgmii_sbus_1_sel",
usxgmii_sbus_0_parents, 0x090, 0x094, 0x098, 0, 1,
7, 0x1C4, 5),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_0_SEL, "sgm_0_sel", sgm_0_parents,
0x090, 0x094, 0x098, 8, 1, 15, 0x1c4, 6),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SGM_SBUS_0_SEL, "sgm_sbus_0_sel",
usxgmii_sbus_0_parents, 0x090, 0x094, 0x098,
16, 1, 23, 0x1C4, 7, CLK_IS_CRITICAL),
MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_1_SEL, "sgm_1_sel", sgm_0_parents,
0x090, 0x094, 0x098, 24, 1, 31, 0x1c4, 8),
/* CLK_CFG_10 */
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SGM_SBUS_1_SEL, "sgm_sbus_1_sel",
usxgmii_sbus_0_parents, 0x0a0, 0x0a4, 0x0a8,
0, 1, 7, 0x1C4, 9, CLK_IS_CRITICAL),
MUX_GATE_CLR_SET_UPD(CLK_TOP_XFI_PHY_0_XTAL_SEL, "xfi_phy_0_xtal_sel",
sspxtp_parents, 0x0a0, 0x0a4, 0x0a8, 8, 1, 15,
0x1C4, 10),
MUX_GATE_CLR_SET_UPD(CLK_TOP_XFI_PHY_1_XTAL_SEL, "xfi_phy_1_xtal_sel",
sspxtp_parents, 0x0a0, 0x0a4, 0x0a8, 16, 1, 23,
0x1C4, 11),
/* CLK_CFG_11 */
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAXI_SEL, "sysaxi_sel",
axi_infra_parents, 0x0a0, 0x0a4, 0x0a8, 24,
1, 31, 0x1C4, 12, CLK_IS_CRITICAL),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAPB_SEL, "sysapb_sel",
sysapb_parents, 0x0b0, 0x0b4, 0x0b8, 0, 1,
7, 0x1c4, 13, CLK_IS_CRITICAL),
MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_REFCK_50M_SEL, "eth_refck_50m_sel",
eth_refck_50m_parents, 0x0b0, 0x0b4, 0x0b8, 8, 1,
15, 0x1C4, 14),
MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_SYS_200M_SEL, "eth_sys_200m_sel",
eth_sys_200m_parents, 0x0b0, 0x0b4, 0x0b8, 16, 1,
23, 0x1C4, 15),
MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_SYS_SEL, "eth_sys_sel",
pcie_mbist_250m_parents, 0x0b0, 0x0b4, 0x0b8, 24,
1, 31, 0x1C4, 16),
/* CLK_CFG_12 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_XGMII_SEL, "eth_xgmii_sel",
eth_xgmii_parents, 0x0c0, 0x0c4, 0x0c8, 0, 2, 7,
0x1C4, 17),
MUX_GATE_CLR_SET_UPD(CLK_TOP_BUS_TOPS_SEL, "bus_tops_sel",
bus_tops_parents, 0x0c0, 0x0c4, 0x0c8, 8, 2, 15,
0x1C4, 18),
MUX_GATE_CLR_SET_UPD(CLK_TOP_NPU_TOPS_SEL, "npu_tops_sel",
npu_tops_parents, 0x0c0, 0x0c4, 0x0c8, 16, 1, 23,
0x1C4, 19),
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_SEL, "dramc_sel",
sspxtp_parents, 0x0c0, 0x0c4, 0x0c8, 24, 1,
31, 0x1C4, 20, CLK_IS_CRITICAL),
/* CLK_CFG_13 */
MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel",
dramc_md32_parents, 0x0d0, 0x0d4, 0x0d8, 0,
2, 7, 0x1C4, 21, CLK_IS_CRITICAL),
MUX_GATE_CLR_SET_UPD_FLAGS(
CLK_TOP_INFRA_F26M_SEL, "csw_infra_f26m_sel", sspxtp_parents,
0x0d0, 0x0d4, 0x0d8, 8, 1, 15, 0x1C4, 22, CLK_IS_CRITICAL),
MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_P0_SEL, "pextp_p0_sel",
sspxtp_parents, 0x0d0, 0x0d4, 0x0d8, 16, 1, 23,
0x1C4, 23),
MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_P1_SEL, "pextp_p1_sel",
sspxtp_parents, 0x0d0, 0x0d4, 0x0d8, 24, 1, 31,
0x1C4, 24),
/* CLK_CFG_14 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_P2_SEL, "pextp_p2_sel",
sspxtp_parents, 0x0e0, 0x0e4, 0x0e8, 0, 1, 7,
0x1C4, 25),
MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_P3_SEL, "pextp_p3_sel",
sspxtp_parents, 0x0e0, 0x0e4, 0x0e8, 8, 1, 15,
0x1C4, 26),
MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_XTP_GLB_P0_SEL, "da_xtp_glb_p0_sel",
da_xtp_glb_p0_parents, 0x0e0, 0x0e4, 0x0e8, 16, 1,
23, 0x1C4, 27),
MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_XTP_GLB_P1_SEL, "da_xtp_glb_p1_sel",
da_xtp_glb_p0_parents, 0x0e0, 0x0e4, 0x0e8, 24, 1,
31, 0x1C4, 28),
/* CLK_CFG_15 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_XTP_GLB_P2_SEL, "da_xtp_glb_p2_sel",
da_xtp_glb_p0_parents, 0x0f0, 0x0f4, 0x0f8, 0, 1,
7, 0x1C4, 29),
MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_XTP_GLB_P3_SEL, "da_xtp_glb_p3_sel",
da_xtp_glb_p0_parents, 0x0f0, 0x0f4, 0x0f8, 8, 1,
15, 0x1C4, 30),
MUX_GATE_CLR_SET_UPD(CLK_TOP_CKM_SEL, "ckm_sel", sspxtp_parents, 0x0F0,
0x0f4, 0x0f8, 16, 1, 23, 0x1c8, 0),
MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_SEL, "da_sel", sspxtp_parents, 0x0f0,
0x0f4, 0x0f8, 24, 1, 31, 0x1C8, 1),
/* CLK_CFG_16 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_SEL, "pextp_sel", sspxtp_parents,
0x0100, 0x104, 0x108, 0, 1, 7, 0x1c8, 2),
MUX_GATE_CLR_SET_UPD(CLK_TOP_TOPS_P2_26M_SEL, "tops_p2_26m_sel",
sspxtp_parents, 0x0100, 0x104, 0x108, 8, 1, 15,
0x1C8, 3),
MUX_GATE_CLR_SET_UPD(CLK_TOP_MCUSYS_BACKUP_625M_SEL,
"mcusys_backup_625m_sel",
mcusys_backup_625m_parents, 0x0100, 0x104, 0x108,
16, 1, 23, 0x1C8, 4),
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_SYNC_250M_SEL,
"netsys_sync_250m_sel", pcie_mbist_250m_parents,
0x0100, 0x104, 0x108, 24, 1, 31, 0x1c8, 5),
/* CLK_CFG_17 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_MACSEC_SEL, "macsec_sel", macsec_parents,
0x0110, 0x114, 0x118, 0, 2, 7, 0x1c8, 6),
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_TOPS_400M_SEL,
"netsys_tops_400m_sel", netsys_tops_400m_parents,
0x0110, 0x114, 0x118, 8, 1, 15, 0x1c8, 7),
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_PPEFB_250M_SEL,
"netsys_ppefb_250m_sel", pcie_mbist_250m_parents,
0x0110, 0x114, 0x118, 16, 1, 23, 0x1c8, 8),
MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_WARP_SEL, "netsys_warp_sel",
netsys_parents, 0x0110, 0x114, 0x118, 24, 2, 31,
0x1C8, 9),
/* CLK_CFG_18 */
MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_MII_SEL, "eth_mii_sel",
eth_mii_parents, 0x0120, 0x124, 0x128, 0, 1, 7,
0x1c8, 10),
MUX_GATE_CLR_SET_UPD(CLK_TOP_NPU_SEL, "ck_npu_sel", netsys_2x_parents,
0x0120, 0x124, 0x128, 8, 2, 15, 0x1c8, 11),
};
static const struct mtk_composite top_aud_divs[] = {
DIV_GATE(CLK_TOP_AUD_I2S_M, "aud_i2s_m", "aud_sel", 0x0420, 0, 0x0420,
8, 8),
};
static int clk_mt7988_topckgen_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
int r;
void __iomem *base;
int nr = ARRAY_SIZE(top_fixed_clks) + ARRAY_SIZE(top_divs) +
ARRAY_SIZE(top_muxes) + ARRAY_SIZE(top_aud_divs);
base = of_iomap(node, 0);
if (!base) {
pr_err("%s(): ioremap failed\n", __func__);
return -ENOMEM;
}
clk_data = mtk_alloc_clk_data(nr);
if (!clk_data)
return -ENOMEM;
mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
clk_data);
mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes), node,
&mt7988_clk_lock, clk_data);
mtk_clk_register_composites(top_aud_divs, ARRAY_SIZE(top_aud_divs),
base, &mt7988_clk_lock, clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r) {
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
goto free_topckgen_data;
}
return r;
free_topckgen_data:
mtk_free_clk_data(clk_data);
return r;
}
static const char *const mcu_bus_div_parents[] = { "top_xtal", "ccipll2_b",
"net1pll_d4" };
static const char *const mcu_arm_div_parents[] = { "top_xtal", "arm_b",
"net1pll_d4" };
static struct mtk_composite mcu_muxes[] = {
/* bus_pll_divider_cfg */
MUX_GATE_FLAGS(CLK_MCU_BUS_DIV_SEL, "mcu_bus_div_sel",
mcu_bus_div_parents, 0x7C0, 9, 2, -1, CLK_IS_CRITICAL),
/* mp2_pll_divider_cfg */
MUX_GATE_FLAGS(CLK_MCU_ARM_DIV_SEL, "mcu_arm_div_sel",
mcu_arm_div_parents, 0x7A8, 9, 2, -1, CLK_IS_CRITICAL),
};
static int clk_mt7988_mcusys_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
int r;
void __iomem *base;
int nr = ARRAY_SIZE(mcu_muxes);
base = of_iomap(node, 0);
if (!base) {
pr_err("%s(): ioremap failed\n", __func__);
return -ENOMEM;
}
clk_data = mtk_alloc_clk_data(nr);
if (!clk_data)
return -ENOMEM;
mtk_clk_register_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), base,
&mt7988_clk_lock, clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r) {
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
goto free_mcusys_data;
}
return r;
free_mcusys_data:
mtk_free_clk_data(clk_data);
return r;
}
static const struct of_device_id of_match_clk_mt7988_topckgen[] = {
{
.compatible = "mediatek,mt7988-topckgen",
},
{}
};
static struct platform_driver clk_mt7988_topckgen_drv = {
.probe = clk_mt7988_topckgen_probe,
.driver = {
.name = "clk-mt7988-topckgen",
.of_match_table = of_match_clk_mt7988_topckgen,
},
};
builtin_platform_driver(clk_mt7988_topckgen_drv);
static const struct of_device_id of_match_clk_mt7988_mcusys[] = {
{
.compatible = "mediatek,mt7988-mcusys",
},
{}
};
static struct platform_driver clk_mt7988_mcusys_drv = {
.probe = clk_mt7988_mcusys_probe,
.driver = {
.name = "clk-mt7988-mcusys",
.of_match_table = of_match_clk_mt7988_mcusys,
},
};
builtin_platform_driver(clk_mt7988_mcusys_drv);

View file

@ -0,0 +1,262 @@
// SPDX-License-Identifier: GPL-2.0+
#include <linux/bitfield.h>
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/nvmem-consumer.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/pinctrl/consumer.h>
#include <linux/phy.h>
#define MEDAITEK_2P5GE_PHY_DMB_FW "mediatek/mediatek-2p5ge-phy-dmb.bin"
#define MEDIATEK_2P5GE_PHY_PMB_FW "mediatek/mediatek-2p5ge-phy-pmb.bin"
#define MD32_EN_CFG 0x18
#define MD32_EN BIT(0)
#define BASE100T_STATUS_EXTEND 0x10
#define BASE1000T_STATUS_EXTEND 0x11
#define EXTEND_CTRL_AND_STATUS 0x16
#define PHY_AUX_CTRL_STATUS 0x1d
#define PHY_AUX_DPX_MASK GENMASK(5, 5)
#define PHY_AUX_SPEED_MASK GENMASK(4, 2)
/* Registers on MDIO_MMD_VEND1 */
#define MTK_PHY_LINK_STATUS_MISC 0xa2
#define MTK_PHY_FDX_ENABLE BIT(5)
/* Registers on MDIO_MMD_VEND2 */
#define MTK_PHY_LED0_ON_CTRL 0x24
#define MTK_PHY_LED0_ON_LINK1000 BIT(0)
#define MTK_PHY_LED0_ON_LINK100 BIT(1)
#define MTK_PHY_LED0_ON_LINK10 BIT(2)
#define MTK_PHY_LED0_ON_LINK2500 BIT(7)
#define MTK_PHY_LED0_POLARITY BIT(14)
#define MTK_PHY_LED1_ON_CTRL 0x26
#define MTK_PHY_LED1_ON_FDX BIT(4)
#define MTK_PHY_LED1_ON_HDX BIT(5)
#define MTK_PHY_LED1_POLARITY BIT(14)
enum {
PHY_AUX_SPD_10 = 0,
PHY_AUX_SPD_100,
PHY_AUX_SPD_1000,
PHY_AUX_SPD_2500,
};
static int mt798x_2p5ge_phy_config_init(struct phy_device *phydev)
{
int ret;
int i;
const struct firmware *fw;
struct device *dev = &phydev->mdio.dev;
struct device_node *np;
void __iomem *dmb_addr;
void __iomem *pmb_addr;
void __iomem *mcucsr_base;
u16 reg;
struct pinctrl *pinctrl;
np = of_find_compatible_node(NULL, NULL, "mediatek,2p5gphy-fw");
if (!np)
return -ENOENT;
dmb_addr = of_iomap(np, 0);
if (!dmb_addr)
return -ENOMEM;
pmb_addr = of_iomap(np, 1);
if (!pmb_addr)
return -ENOMEM;
mcucsr_base = of_iomap(np, 2);
if (!mcucsr_base)
return -ENOMEM;
ret = request_firmware(&fw, MEDAITEK_2P5GE_PHY_DMB_FW, dev);
if (ret) {
dev_err(dev, "failed to load firmware: %s, ret: %d\n",
MEDAITEK_2P5GE_PHY_DMB_FW, ret);
return ret;
}
for (i = 0; i < fw->size - 1; i += 4)
writel(*((uint32_t *)(fw->data + i)), dmb_addr + i);
release_firmware(fw);
ret = request_firmware(&fw, MEDIATEK_2P5GE_PHY_PMB_FW, dev);
if (ret) {
dev_err(dev, "failed to load firmware: %s, ret: %d\n",
MEDIATEK_2P5GE_PHY_PMB_FW, ret);
return ret;
}
for (i = 0; i < fw->size - 1; i += 4)
writel(*((uint32_t *)(fw->data + i)), pmb_addr + i);
release_firmware(fw);
reg = readw(mcucsr_base + MD32_EN_CFG);
writew(reg | MD32_EN, mcucsr_base + MD32_EN_CFG);
dev_dbg(dev, "Firmware loading/trigger ok.\n");
/* Setup LED */
phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
MTK_PHY_LED0_POLARITY);
phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
MTK_PHY_LED0_ON_LINK10 |
MTK_PHY_LED0_ON_LINK100 |
MTK_PHY_LED0_ON_LINK1000 |
MTK_PHY_LED0_ON_LINK2500);
phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL,
MTK_PHY_LED1_ON_FDX | MTK_PHY_LED1_ON_HDX);
pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "i2p5gbe-led");
if (IS_ERR(pinctrl)) {
dev_err(&phydev->mdio.dev, "Fail to set LED pins!\n");
return PTR_ERR(pinctrl);
}
return 0;
}
static int mt798x_2p5ge_phy_config_aneg(struct phy_device *phydev)
{
bool changed = false;
u32 adv;
int ret;
if (phydev->autoneg == AUTONEG_DISABLE) {
/* Configure half duplex with genphy_setup_forced,
* because genphy_c45_pma_setup_forced does not support.
*/
return phydev->duplex != DUPLEX_FULL
? genphy_setup_forced(phydev)
: genphy_c45_pma_setup_forced(phydev);
}
ret = genphy_c45_an_config_aneg(phydev);
if (ret < 0)
return ret;
if (ret > 0)
changed = true;
adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
ret = phy_modify_changed(phydev, MII_CTRL1000,
ADVERTISE_1000FULL | ADVERTISE_1000HALF,
adv);
if (ret < 0)
return ret;
if (ret > 0)
changed = true;
return genphy_c45_check_and_restart_aneg(phydev, changed);
}
static int mt798x_2p5ge_phy_get_features(struct phy_device *phydev)
{
int ret;
ret = genphy_read_abilities(phydev);
if (ret)
return ret;
/* We don't support HDX at MAC layer on mt798x.
* So mask phy's HDX capabilities, too.
*/
linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
phydev->supported);
linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
phydev->supported);
linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
phydev->supported);
linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
phydev->supported);
linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported);
return 0;
}
static int mt798x_2p5ge_phy_read_status(struct phy_device *phydev)
{
int ret;
ret = genphy_update_link(phydev);
if (ret)
return ret;
phydev->speed = SPEED_UNKNOWN;
phydev->duplex = DUPLEX_UNKNOWN;
phydev->pause = 0;
phydev->asym_pause = 0;
if (!phydev->link)
return 0;
if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) {
ret = genphy_c45_read_lpa(phydev);
if (ret < 0)
return ret;
/* Read the link partner's 1G advertisement */
ret = phy_read(phydev, MII_STAT1000);
if (ret < 0)
return ret;
mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, ret);
} else if (phydev->autoneg == AUTONEG_DISABLE) {
linkmode_zero(phydev->lp_advertising);
}
ret = phy_read(phydev, PHY_AUX_CTRL_STATUS);
if (ret < 0)
return ret;
switch (FIELD_GET(PHY_AUX_SPEED_MASK, ret)) {
case PHY_AUX_SPD_10:
phydev->speed = SPEED_10;
break;
case PHY_AUX_SPD_100:
phydev->speed = SPEED_100;
break;
case PHY_AUX_SPD_1000:
phydev->speed = SPEED_1000;
break;
case PHY_AUX_SPD_2500:
phydev->speed = SPEED_2500;
phydev->duplex = DUPLEX_FULL; /* 2.5G must be FDX */
break;
}
ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LINK_STATUS_MISC);
if (ret < 0)
return ret;
phydev->duplex = (ret & MTK_PHY_FDX_ENABLE) ? DUPLEX_FULL : DUPLEX_HALF;
return 0;
}
static struct phy_driver mtk_gephy_driver[] = {
{
PHY_ID_MATCH_EXACT(0x00339c11),
.name = "MediaTek MT798x 2.5GbE PHY",
.config_init = mt798x_2p5ge_phy_config_init,
.config_aneg = mt798x_2p5ge_phy_config_aneg,
.get_features = mt798x_2p5ge_phy_get_features,
.read_status = mt798x_2p5ge_phy_read_status,
},
};
module_phy_driver(mtk_gephy_driver);
static struct mdio_device_id __maybe_unused mtk_2p5ge_phy_tbl[] = {
{ PHY_ID_MATCH_VENDOR(0x00339c00) },
{ }
};
MODULE_DESCRIPTION("MediaTek 2.5Gb Ethernet PHY driver");
MODULE_AUTHOR("SkyLake Huang <SkyLake.Huang@mediatek.com>");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(mdio, mtk_2p5ge_phy_tbl);
MODULE_FIRMWARE(MEDAITEK_2P5GE_PHY_DMB_FW);
MODULE_FIRMWARE(MEDIATEK_2P5GE_PHY_PMB_FW);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,276 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
/*
* Copyright (c) 2023 MediaTek Inc.
* Author: Sam Shih <sam.shih@mediatek.com>
* Author: Xiufeng Li <Xiufeng.Li@mediatek.com>
*/
#ifndef _DT_BINDINGS_CLK_MT7988_H
#define _DT_BINDINGS_CLK_MT7988_H
/* APMIXEDSYS */
#define CLK_APMIXED_NETSYSPLL 0
#define CLK_APMIXED_MPLL 1
#define CLK_APMIXED_MMPLL 2
#define CLK_APMIXED_APLL2 3
#define CLK_APMIXED_NET1PLL 4
#define CLK_APMIXED_NET2PLL 5
#define CLK_APMIXED_WEDMCUPLL 6
#define CLK_APMIXED_SGMPLL 7
#define CLK_APMIXED_ARM_B 8
#define CLK_APMIXED_CCIPLL2_B 9
#define CLK_APMIXED_USXGMIIPLL 10
#define CLK_APMIXED_MSDCPLL 11
/* TOPCKGEN */
#define CLK_TOP_XTAL 0
#define CLK_TOP_XTAL_D2 1
#define CLK_TOP_RTC_32K 2
#define CLK_TOP_RTC_32P7K 3
#define CLK_TOP_MPLL_D2 4
#define CLK_TOP_MPLL_D3_D2 5
#define CLK_TOP_MPLL_D4 6
#define CLK_TOP_MPLL_D8 7
#define CLK_TOP_MPLL_D8_D2 8
#define CLK_TOP_MMPLL_D2 9
#define CLK_TOP_MMPLL_D3_D5 10
#define CLK_TOP_MMPLL_D4 11
#define CLK_TOP_MMPLL_D6_D2 12
#define CLK_TOP_MMPLL_D8 13
#define CLK_TOP_APLL2_D4 14
#define CLK_TOP_NET1PLL_D4 15
#define CLK_TOP_NET1PLL_D5 16
#define CLK_TOP_NET1PLL_D5_D2 17
#define CLK_TOP_NET1PLL_D5_D4 18
#define CLK_TOP_NET1PLL_D8 19
#define CLK_TOP_NET1PLL_D8_D2 20
#define CLK_TOP_NET1PLL_D8_D4 21
#define CLK_TOP_NET1PLL_D8_D8 22
#define CLK_TOP_NET1PLL_D8_D16 23
#define CLK_TOP_NET2PLL_D2 24
#define CLK_TOP_NET2PLL_D4 25
#define CLK_TOP_NET2PLL_D4_D4 26
#define CLK_TOP_NET2PLL_D4_D8 27
#define CLK_TOP_NET2PLL_D6 28
#define CLK_TOP_NET2PLL_D8 29
#define CLK_TOP_NETSYS_SEL 30
#define CLK_TOP_NETSYS_500M_SEL 31
#define CLK_TOP_NETSYS_2X_SEL 32
#define CLK_TOP_NETSYS_GSW_SEL 33
#define CLK_TOP_ETH_GMII_SEL 34
#define CLK_TOP_NETSYS_MCU_SEL 35
#define CLK_TOP_NETSYS_PAO_2X_SEL 36
#define CLK_TOP_EIP197_SEL 37
#define CLK_TOP_AXI_INFRA_SEL 38
#define CLK_TOP_UART_SEL 39
#define CLK_TOP_EMMC_250M_SEL 40
#define CLK_TOP_EMMC_400M_SEL 41
#define CLK_TOP_SPI_SEL 42
#define CLK_TOP_SPIM_MST_SEL 43
#define CLK_TOP_NFI1X_SEL 44
#define CLK_TOP_SPINFI_SEL 45
#define CLK_TOP_PWM_SEL 46
#define CLK_TOP_I2C_SEL 47
#define CLK_TOP_PCIE_MBIST_250M_SEL 48
#define CLK_TOP_PEXTP_TL_SEL 49
#define CLK_TOP_PEXTP_TL_P1_SEL 50
#define CLK_TOP_PEXTP_TL_P2_SEL 51
#define CLK_TOP_PEXTP_TL_P3_SEL 52
#define CLK_TOP_USB_SYS_SEL 53
#define CLK_TOP_USB_SYS_P1_SEL 54
#define CLK_TOP_USB_XHCI_SEL 55
#define CLK_TOP_USB_XHCI_P1_SEL 56
#define CLK_TOP_USB_FRMCNT_SEL 57
#define CLK_TOP_USB_FRMCNT_P1_SEL 58
#define CLK_TOP_AUD_SEL 59
#define CLK_TOP_A1SYS_SEL 60
#define CLK_TOP_AUD_L_SEL 61
#define CLK_TOP_A_TUNER_SEL 62
#define CLK_TOP_SSPXTP_SEL 63
#define CLK_TOP_USB_PHY_SEL 64
#define CLK_TOP_USXGMII_SBUS_0_SEL 65
#define CLK_TOP_USXGMII_SBUS_1_SEL 66
#define CLK_TOP_SGM_0_SEL 67
#define CLK_TOP_SGM_SBUS_0_SEL 68
#define CLK_TOP_SGM_1_SEL 69
#define CLK_TOP_SGM_SBUS_1_SEL 70
#define CLK_TOP_XFI_PHY_0_XTAL_SEL 71
#define CLK_TOP_XFI_PHY_1_XTAL_SEL 72
#define CLK_TOP_SYSAXI_SEL 73
#define CLK_TOP_SYSAPB_SEL 74
#define CLK_TOP_ETH_REFCK_50M_SEL 75
#define CLK_TOP_ETH_SYS_200M_SEL 76
#define CLK_TOP_ETH_SYS_SEL 77
#define CLK_TOP_ETH_XGMII_SEL 78
#define CLK_TOP_BUS_TOPS_SEL 79
#define CLK_TOP_NPU_TOPS_SEL 80
#define CLK_TOP_DRAMC_SEL 81
#define CLK_TOP_DRAMC_MD32_SEL 82
#define CLK_TOP_INFRA_F26M_SEL 83
#define CLK_TOP_PEXTP_P0_SEL 84
#define CLK_TOP_PEXTP_P1_SEL 85
#define CLK_TOP_PEXTP_P2_SEL 86
#define CLK_TOP_PEXTP_P3_SEL 87
#define CLK_TOP_DA_XTP_GLB_P0_SEL 88
#define CLK_TOP_DA_XTP_GLB_P1_SEL 89
#define CLK_TOP_DA_XTP_GLB_P2_SEL 90
#define CLK_TOP_DA_XTP_GLB_P3_SEL 91
#define CLK_TOP_CKM_SEL 92
#define CLK_TOP_DA_SEL 93
#define CLK_TOP_PEXTP_SEL 94
#define CLK_TOP_TOPS_P2_26M_SEL 95
#define CLK_TOP_MCUSYS_BACKUP_625M_SEL 96
#define CLK_TOP_NETSYS_SYNC_250M_SEL 97
#define CLK_TOP_MACSEC_SEL 98
#define CLK_TOP_NETSYS_TOPS_400M_SEL 99
#define CLK_TOP_NETSYS_PPEFB_250M_SEL 100
#define CLK_TOP_NETSYS_WARP_SEL 101
#define CLK_TOP_ETH_MII_SEL 102
#define CLK_TOP_NPU_SEL 103
#define CLK_TOP_AUD_I2S_M 104
/* MCUSYS */
#define CLK_MCU_BUS_DIV_SEL 0
#define CLK_MCU_ARM_DIV_SEL 1
/* INFRACFG_AO */
#define CLK_INFRA_MUX_UART0_SEL 0
#define CLK_INFRA_MUX_UART1_SEL 1
#define CLK_INFRA_MUX_UART2_SEL 2
#define CLK_INFRA_MUX_SPI0_SEL 3
#define CLK_INFRA_MUX_SPI1_SEL 4
#define CLK_INFRA_MUX_SPI2_SEL 5
#define CLK_INFRA_PWM_SEL 6
#define CLK_INFRA_PWM_CK1_SEL 7
#define CLK_INFRA_PWM_CK2_SEL 8
#define CLK_INFRA_PWM_CK3_SEL 9
#define CLK_INFRA_PWM_CK4_SEL 10
#define CLK_INFRA_PWM_CK5_SEL 11
#define CLK_INFRA_PWM_CK6_SEL 12
#define CLK_INFRA_PWM_CK7_SEL 13
#define CLK_INFRA_PWM_CK8_SEL 14
#define CLK_INFRA_PCIE_GFMUX_TL_O_P0_SEL 15
#define CLK_INFRA_PCIE_GFMUX_TL_O_P1_SEL 16
#define CLK_INFRA_PCIE_GFMUX_TL_O_P2_SEL 17
#define CLK_INFRA_PCIE_GFMUX_TL_O_P3_SEL 18
/* INFRACFG */
#define CLK_INFRA_PCIE_PERI_26M_CK_P0 19
#define CLK_INFRA_PCIE_PERI_26M_CK_P1 20
#define CLK_INFRA_PCIE_PERI_26M_CK_P2 21
#define CLK_INFRA_PCIE_PERI_26M_CK_P3 22
#define CLK_INFRA_66M_GPT_BCK 23
#define CLK_INFRA_66M_PWM_HCK 24
#define CLK_INFRA_66M_PWM_BCK 25
#define CLK_INFRA_66M_PWM_CK1 26
#define CLK_INFRA_66M_PWM_CK2 27
#define CLK_INFRA_66M_PWM_CK3 28
#define CLK_INFRA_66M_PWM_CK4 29
#define CLK_INFRA_66M_PWM_CK5 30
#define CLK_INFRA_66M_PWM_CK6 31
#define CLK_INFRA_66M_PWM_CK7 32
#define CLK_INFRA_66M_PWM_CK8 33
#define CLK_INFRA_133M_CQDMA_BCK 34
#define CLK_INFRA_66M_AUD_SLV_BCK 35
#define CLK_INFRA_AUD_26M 36
#define CLK_INFRA_AUD_L 37
#define CLK_INFRA_AUD_AUD 38
#define CLK_INFRA_AUD_EG2 39
#define CLK_INFRA_DRAMC_F26M 40
#define CLK_INFRA_133M_DBG_ACKM 41
#define CLK_INFRA_66M_AP_DMA_BCK 42
#define CLK_INFRA_66M_SEJ_BCK 43
#define CLK_INFRA_PRE_CK_SEJ_F13M 44
#define CLK_INFRA_26M_THERM_SYSTEM 45
#define CLK_INFRA_I2C_BCK 46
#define CLK_INFRA_52M_UART0_CK 47
#define CLK_INFRA_52M_UART1_CK 48
#define CLK_INFRA_52M_UART2_CK 49
#define CLK_INFRA_NFI 50
#define CLK_INFRA_SPINFI 51
#define CLK_INFRA_66M_NFI_HCK 52
#define CLK_INFRA_104M_SPI0 53
#define CLK_INFRA_104M_SPI1 54
#define CLK_INFRA_104M_SPI2_BCK 55
#define CLK_INFRA_66M_SPI0_HCK 56
#define CLK_INFRA_66M_SPI1_HCK 57
#define CLK_INFRA_66M_SPI2_HCK 58
#define CLK_INFRA_66M_FLASHIF_AXI 59
#define CLK_INFRA_RTC 60
#define CLK_INFRA_26M_ADC_BCK 61
#define CLK_INFRA_RC_ADC 62
#define CLK_INFRA_MSDC400 63
#define CLK_INFRA_MSDC2_HCK 64
#define CLK_INFRA_133M_MSDC_0_HCK 65
#define CLK_INFRA_66M_MSDC_0_HCK 66
#define CLK_INFRA_133M_CPUM_BCK 67
#define CLK_INFRA_BIST2FPC 68
#define CLK_INFRA_I2C_X16W_MCK_CK_P1 69
#define CLK_INFRA_I2C_X16W_PCK_CK_P1 70
#define CLK_INFRA_133M_USB_HCK 71
#define CLK_INFRA_133M_USB_HCK_CK_P1 72
#define CLK_INFRA_66M_USB_HCK 73
#define CLK_INFRA_66M_USB_HCK_CK_P1 74
#define CLK_INFRA_USB_SYS 75
#define CLK_INFRA_USB_SYS_CK_P1 76
#define CLK_INFRA_USB_REF 77
#define CLK_INFRA_USB_CK_P1 78
#define CLK_INFRA_USB_FRMCNT 79
#define CLK_INFRA_USB_FRMCNT_CK_P1 80
#define CLK_INFRA_USB_PIPE 81
#define CLK_INFRA_USB_PIPE_CK_P1 82
#define CLK_INFRA_USB_UTMI 83
#define CLK_INFRA_USB_UTMI_CK_P1 84
#define CLK_INFRA_USB_XHCI 85
#define CLK_INFRA_USB_XHCI_CK_P1 86
#define CLK_INFRA_PCIE_GFMUX_TL_P0 87
#define CLK_INFRA_PCIE_GFMUX_TL_P1 88
#define CLK_INFRA_PCIE_GFMUX_TL_P2 89
#define CLK_INFRA_PCIE_GFMUX_TL_P3 90
#define CLK_INFRA_PCIE_PIPE_P0 91
#define CLK_INFRA_PCIE_PIPE_P1 92
#define CLK_INFRA_PCIE_PIPE_P2 93
#define CLK_INFRA_PCIE_PIPE_P3 94
#define CLK_INFRA_133M_PCIE_CK_P0 95
#define CLK_INFRA_133M_PCIE_CK_P1 96
#define CLK_INFRA_133M_PCIE_CK_P2 97
#define CLK_INFRA_133M_PCIE_CK_P3 98
/* ETHDMA */
#define CLK_ETHDMA_XGP1_EN 0
#define CLK_ETHDMA_XGP2_EN 1
#define CLK_ETHDMA_XGP3_EN 2
#define CLK_ETHDMA_FE_EN 3
#define CLK_ETHDMA_GP2_EN 4
#define CLK_ETHDMA_GP1_EN 5
#define CLK_ETHDMA_GP3_EN 6
#define CLK_ETHDMA_ESW_EN 7
#define CLK_ETHDMA_CRYPT0_EN 8
#define CLK_ETHDMA_NR_CLK 9
/* SGMIISYS_0 */
#define CLK_SGM0_TX_EN 0
#define CLK_SGM0_RX_EN 1
#define CLK_SGMII0_NR_CLK 2
/* SGMIISYS_1 */
#define CLK_SGM1_TX_EN 0
#define CLK_SGM1_RX_EN 1
#define CLK_SGMII1_NR_CLK 2
/* ETHWARP */
#define CLK_ETHWARP_WOCPU2_EN 0
#define CLK_ETHWARP_WOCPU1_EN 1
#define CLK_ETHWARP_WOCPU0_EN 2
#define CLK_ETHWARP_NR_CLK 3
#endif /* _DT_BINDINGS_CLK_MT7988_H */

Some files were not shown because too many files have changed in this diff Show more