diff --git a/.github/update.log b/.github/update.log index 17d3d0d1ef..a669d580c4 100644 --- a/.github/update.log +++ b/.github/update.log @@ -1179,3 +1179,4 @@ Update On Sat Nov 8 19:37:24 CET 2025 Update On Sun Nov 9 19:36:09 CET 2025 Update On Mon Nov 10 19:41:15 CET 2025 Update On Tue Nov 11 19:39:14 CET 2025 +Update On Wed Nov 12 19:37:25 CET 2025 diff --git a/clash-nyanpasu/frontend/nyanpasu/src/components/proxies/utils.ts b/clash-nyanpasu/frontend/nyanpasu/src/components/proxies/utils.ts index 02505d60ec..ba20acc7fa 100644 --- a/clash-nyanpasu/frontend/nyanpasu/src/components/proxies/utils.ts +++ b/clash-nyanpasu/frontend/nyanpasu/src/components/proxies/utils.ts @@ -10,7 +10,7 @@ export const filterDelay = (history?: ProxyItemHistory[]): number => { export enum SortType { Default = 'default', - Dealy = 'delay', + Delay = 'delay', Name = 'name', } @@ -21,7 +21,7 @@ export const nodeSortingFn = ( let sortedList = selectedGroup.all?.slice() switch (type) { - case SortType.Dealy: { + case SortType.Delay: { sortedList = sortedList?.sort((a, b) => { const delayA = filterDelay(a.history) const delayB = filterDelay(b.history) diff --git a/clash-nyanpasu/manifest/version.json b/clash-nyanpasu/manifest/version.json index d462568789..ab9a20a2a3 100644 --- a/clash-nyanpasu/manifest/version.json +++ b/clash-nyanpasu/manifest/version.json @@ -2,7 +2,7 @@ "manifest_version": 1, "latest": { "mihomo": "v1.19.16", - "mihomo_alpha": "alpha-2f545ef", + "mihomo_alpha": "alpha-0b3159b", "clash_rs": "v0.9.2", "clash_premium": "2023-09-05-gdcc8d87", "clash_rs_alpha": "0.9.2-alpha+sha.87c7b2c" @@ -10,25 +10,25 @@ "arch_template": { "mihomo": { "windows-i386": "mihomo-windows-386-{}.zip", - "windows-x86_64": "mihomo-windows-amd64-compatible-{}.zip", + "windows-x86_64": "mihomo-windows-amd64-v1-{}.zip", "windows-arm64": "mihomo-windows-arm64-{}.zip", "linux-aarch64": "mihomo-linux-arm64-{}.gz", - "linux-amd64": "mihomo-linux-amd64-compatible-{}.gz", + "linux-amd64": "mihomo-linux-amd64-v1-{}.gz", "linux-i386": "mihomo-linux-386-{}.gz", "darwin-arm64": "mihomo-darwin-arm64-{}.gz", - "darwin-x64": "mihomo-darwin-amd64-compatible-{}.gz", + "darwin-x64": "mihomo-darwin-amd64-v1-{}.gz", "linux-armv7": "mihomo-linux-armv5-{}.gz", "linux-armv7hf": "mihomo-linux-armv7-{}.gz" }, "mihomo_alpha": { "windows-i386": "mihomo-windows-386-{}.zip", - "windows-x86_64": "mihomo-windows-amd64-compatible-{}.zip", + "windows-x86_64": "mihomo-windows-amd64-v1-{}.zip", "windows-arm64": "mihomo-windows-arm64-{}.zip", "linux-aarch64": "mihomo-linux-arm64-{}.gz", - "linux-amd64": "mihomo-linux-amd64-compatible-{}.gz", + "linux-amd64": "mihomo-linux-amd64-v1-{}.gz", "linux-i386": "mihomo-linux-386-{}.gz", "darwin-arm64": "mihomo-darwin-arm64-{}.gz", - "darwin-x64": "mihomo-darwin-amd64-compatible-{}.gz", + "darwin-x64": "mihomo-darwin-amd64-v1-{}.gz", "linux-armv7": "mihomo-linux-armv5-{}.gz", "linux-armv7hf": "mihomo-linux-armv7-{}.gz" }, @@ -69,5 +69,5 @@ "linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf" } }, - "updated_at": "2025-11-10T22:21:23.620Z" + "updated_at": "2025-11-11T22:21:17.993Z" } diff --git a/clash-nyanpasu/scripts/utils/manifest.ts b/clash-nyanpasu/scripts/utils/manifest.ts index 627e31704f..69ef4d9abc 100644 --- a/clash-nyanpasu/scripts/utils/manifest.ts +++ b/clash-nyanpasu/scripts/utils/manifest.ts @@ -27,13 +27,13 @@ export const resolveMihomo = async (): LatestVersionResolver => { const archMapping: ArchMapping = { [SupportedArch.WindowsX86_32]: 'mihomo-windows-386-{}.zip', - [SupportedArch.WindowsX86_64]: 'mihomo-windows-amd64-compatible-{}.zip', + [SupportedArch.WindowsX86_64]: 'mihomo-windows-amd64-v1-{}.zip', [SupportedArch.WindowsArm64]: 'mihomo-windows-arm64-{}.zip', [SupportedArch.LinuxAarch64]: 'mihomo-linux-arm64-{}.gz', - [SupportedArch.LinuxAmd64]: 'mihomo-linux-amd64-compatible-{}.gz', + [SupportedArch.LinuxAmd64]: 'mihomo-linux-amd64-v1-{}.gz', [SupportedArch.LinuxI386]: 'mihomo-linux-386-{}.gz', [SupportedArch.DarwinArm64]: 'mihomo-darwin-arm64-{}.gz', - [SupportedArch.DarwinX64]: 'mihomo-darwin-amd64-compatible-{}.gz', + [SupportedArch.DarwinX64]: 'mihomo-darwin-amd64-v1-{}.gz', [SupportedArch.LinuxArmv7]: 'mihomo-linux-armv5-{}.gz', [SupportedArch.LinuxArmv7hf]: 'mihomo-linux-armv7-{}.gz', } satisfies ArchMapping @@ -57,13 +57,13 @@ export const resolveMihomoAlpha = async (): LatestVersionResolver => { const archMapping: ArchMapping = { [SupportedArch.WindowsX86_32]: 'mihomo-windows-386-{}.zip', - [SupportedArch.WindowsX86_64]: 'mihomo-windows-amd64-compatible-{}.zip', + [SupportedArch.WindowsX86_64]: 'mihomo-windows-amd64-v1-{}.zip', [SupportedArch.WindowsArm64]: 'mihomo-windows-arm64-{}.zip', [SupportedArch.LinuxAarch64]: 'mihomo-linux-arm64-{}.gz', - [SupportedArch.LinuxAmd64]: 'mihomo-linux-amd64-compatible-{}.gz', + [SupportedArch.LinuxAmd64]: 'mihomo-linux-amd64-v1-{}.gz', [SupportedArch.LinuxI386]: 'mihomo-linux-386-{}.gz', [SupportedArch.DarwinArm64]: 'mihomo-darwin-arm64-{}.gz', - [SupportedArch.DarwinX64]: 'mihomo-darwin-amd64-compatible-{}.gz', + [SupportedArch.DarwinX64]: 'mihomo-darwin-amd64-v1-{}.gz', [SupportedArch.LinuxArmv7]: 'mihomo-linux-armv5-{}.gz', [SupportedArch.LinuxArmv7hf]: 'mihomo-linux-armv7-{}.gz', } satisfies ArchMapping diff --git a/echo/pkg/metric_reader/reader.go b/echo/pkg/metric_reader/reader.go index 4d95639052..3ba2e882af 100644 --- a/echo/pkg/metric_reader/reader.go +++ b/echo/pkg/metric_reader/reader.go @@ -10,6 +10,7 @@ import ( "github.com/pkg/errors" dto "github.com/prometheus/client_model/go" "github.com/prometheus/common/expfmt" + "github.com/prometheus/common/model" "go.uber.org/zap" ) @@ -71,7 +72,8 @@ func (r *readerImpl) fetchMetrics(ctx context.Context) (map[string]*dto.MetricFa if err != nil { return nil, errors.Wrap(err, "failed to read response body") } - - var parser expfmt.TextParser + // Use LegacyValidation for backward compatibility with older Prometheus metrics + // This prevents the "Invalid name validation scheme requested: unset" panic + parser := expfmt.NewTextParser(model.LegacyValidation) return parser.TextToMetricFamilies(strings.NewReader(string(body))) } diff --git a/echo/pkg/xray/server.go b/echo/pkg/xray/server.go index 33422d7d66..5d99b8169e 100644 --- a/echo/pkg/xray/server.go +++ b/echo/pkg/xray/server.go @@ -89,26 +89,18 @@ func (xs *XrayServer) Setup() error { return err } xs.instance = instance - if xs.cfg.SyncTrafficEndPoint != "" { // find api port and server, hard code api Tag to `api` - var grpcEndPoint string var proxyTags []string for _, inbound := range xs.cfg.XRayConfig.InboundConfigs { - if inbound.Tag == XrayAPITag { - grpcEndPoint = fmt.Sprintf("%s:%d", inbound.ListenOn.String(), inbound.PortList.Range[0].From) - } if InProxyTags(inbound.Tag) { proxyTags = append(proxyTags, inbound.Tag) } } - if grpcEndPoint == "" { - return errors.New("can't find api port in config") - } if len(proxyTags) == 0 { return errors.New("can't find proxy tag in config") } - xs.up = NewUserPool(grpcEndPoint, xs.cfg.SyncTrafficEndPoint, xs.cfg.GetMetricURL(), proxyTags) + xs.up = NewUserPool(xs.cfg.XRayConfig.API.Listen, xs.cfg.SyncTrafficEndPoint, xs.cfg.GetMetricURL(), proxyTags) } return nil } diff --git a/echo/pkg/xray/services.go b/echo/pkg/xray/services.go index 08826faca6..4e08527658 100644 --- a/echo/pkg/xray/services.go +++ b/echo/pkg/xray/services.go @@ -6,7 +6,6 @@ import ( proxy "github.com/xtls/xray-core/app/proxyman/command" "github.com/xtls/xray-core/common/serial" - "github.com/xtls/xray-core/proxy/shadowsocks" "go.uber.org/zap" ) @@ -15,18 +14,6 @@ func getEmailAndTrafficType(input string) (string, string) { return s[1], s[len(s)-1] } -func mappingCipher(in string) shadowsocks.CipherType { - switch in { - case "aes-128-gcm": - return shadowsocks.CipherType_AES_128_GCM - case "aes-256-gcm": - return shadowsocks.CipherType_AES_256_GCM - case "chacha20-ietf-poly1305": - return shadowsocks.CipherType_CHACHA20_POLY1305 - } - return shadowsocks.CipherType_UNKNOWN -} - // AddInboundUser add user to inbound by tag func AddInboundUser(ctx context.Context, c proxy.HandlerServiceClient, tag string, user *User) error { _, err := c.AlterInbound(ctx, &proxy.AlterInboundRequest{ @@ -35,8 +22,11 @@ func AddInboundUser(ctx context.Context, c proxy.HandlerServiceClient, tag strin &proxy.AddUserOperation{User: user.ToXrayUser()}), }) if err != nil { + if strings.Contains(err.Error(), "already exists") { + zap.S().Named("xray").Infof("User %s already exists", user.GetEmail()) + return nil + } zap.S().Named("xray").Errorf("Failed to Add User: %s To Server Tag: %s", user.GetEmail(), tag) - return err } user.running = true zap.S().Named("xray").Infof("Add User: %s To Server Tag: %s", user.GetEmail(), tag) diff --git a/echo/pkg/xray/user.go b/echo/pkg/xray/user.go index 2ae50fbd73..e912b68d66 100644 --- a/echo/pkg/xray/user.go +++ b/echo/pkg/xray/user.go @@ -13,7 +13,7 @@ import ( stats "github.com/xtls/xray-core/app/stats/command" "github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/serial" - "github.com/xtls/xray-core/proxy/shadowsocks" + "github.com/xtls/xray-core/proxy/shadowsocks_2022" "github.com/xtls/xray-core/proxy/trojan" "go.uber.org/zap" "google.golang.org/grpc" @@ -97,7 +97,8 @@ func (u *User) ToXrayUser() *protocol.User { case ProtocolTrojan: account = serial.ToTypedMessage(&trojan.Account{Password: u.Password}) case ProtocolSS: - account = serial.ToTypedMessage(&shadowsocks.Account{CipherType: mappingCipher(u.Method), Password: u.Password}) + memoryAccount := &shadowsocks_2022.MemoryAccount{Key: u.Password} + account = serial.ToTypedMessage(memoryAccount.ToProto()) default: zap.S().DPanicf("unknown protocol %s", u.Protocol) return nil @@ -297,8 +298,10 @@ func (up *UserPool) syncUserConfigsFromServer(ctx context.Context, proxyTag stri } func (up *UserPool) Start(ctx context.Context) error { - conn, err := grpc.DialContext( - context.Background(), up.grpcEndPoint, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()) + conn, err := grpc.NewClient( + up.grpcEndPoint, + grpc.WithTransportCredentials(insecure.NewCredentials()), + ) if err != nil { return err } diff --git a/filebrowser/.github/workflows/main.yaml b/filebrowser/.github/workflows/main.yaml index 99d3bc647a..b14c0b4969 100644 --- a/filebrowser/.github/workflows/main.yaml +++ b/filebrowser/.github/workflows/main.yaml @@ -13,11 +13,11 @@ jobs: lint-frontend: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: pnpm/action-setup@v4 with: package_json_file: "frontend/package.json" - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version: "22.x" cache: "pnpm" @@ -26,10 +26,10 @@ jobs: lint-backend: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 + - uses: actions/checkout@v5 + - uses: actions/setup-go@v6 with: - go-version: '1.24' + go-version: '1.25' - run: make lint-backend lint: runs-on: ubuntu-latest @@ -41,11 +41,11 @@ jobs: test-frontend: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: pnpm/action-setup@v4 with: package_json_file: "frontend/package.json" - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version: "22.x" cache: "pnpm" @@ -54,10 +54,10 @@ jobs: test-backend: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 + - uses: actions/checkout@v5 + - uses: actions/setup-go@v6 with: - go-version: '1.24' + go-version: '1.25' - run: make test-backend test: runs-on: ubuntu-latest @@ -71,16 +71,16 @@ jobs: needs: [lint, test] if: startsWith(github.event.ref, 'refs/tags/v') steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 0 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: - go-version: '1.23' + go-version: '1.25' - uses: pnpm/action-setup@v4 with: package_json_file: "frontend/package.json" - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: node-version: "22.x" cache: "pnpm" diff --git a/filebrowser/.github/workflows/site-pr.yml b/filebrowser/.github/workflows/site-pr.yml index c3075c9393..9bc3db17f8 100644 --- a/filebrowser/.github/workflows/site-pr.yml +++ b/filebrowser/.github/workflows/site-pr.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v5 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 diff --git a/filebrowser/.github/workflows/site-publish.yml b/filebrowser/.github/workflows/site-publish.yml index e3618a9976..d41c00872d 100644 --- a/filebrowser/.github/workflows/site-publish.yml +++ b/filebrowser/.github/workflows/site-publish.yml @@ -15,7 +15,7 @@ jobs: timeout-minutes: 5 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 diff --git a/filebrowser/frontend/assets.go b/filebrowser/frontend/assets.go index 01c523f0d4..7955822f2a 100644 --- a/filebrowser/frontend/assets.go +++ b/filebrowser/frontend/assets.go @@ -1,5 +1,4 @@ //go:build !dev -// +build !dev package frontend diff --git a/filebrowser/frontend/assets_dev.go b/filebrowser/frontend/assets_dev.go index 292cd1d0ca..01938ebe00 100644 --- a/filebrowser/frontend/assets_dev.go +++ b/filebrowser/frontend/assets_dev.go @@ -1,5 +1,4 @@ //go:build dev -// +build dev package frontend diff --git a/filebrowser/frontend/package.json b/filebrowser/frontend/package.json index de25129914..befb3f3131 100644 --- a/filebrowser/frontend/package.json +++ b/filebrowser/frontend/package.json @@ -75,5 +75,5 @@ "vite-plugin-compression2": "^1.0.0", "vue-tsc": "^2.2.0" }, - "packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0" + "packageManager": "pnpm@9.15.9+sha512.68046141893c66fad01c079231128e9afb89ef87e2691d69e4d40eee228988295fd4682181bae55b58418c3a253bde65a505ec7c5f9403ece5cc3cd37dcf2531" } diff --git a/filebrowser/frontend/pnpm-lock.yaml b/filebrowser/frontend/pnpm-lock.yaml index 1482e30cd1..ae9b474bee 100644 --- a/filebrowser/frontend/pnpm-lock.yaml +++ b/filebrowser/frontend/pnpm-lock.yaml @@ -10,25 +10,25 @@ importers: dependencies: '@chenfengyuan/vue-number-input': specifier: ^2.0.1 - version: 2.0.1(vue@3.5.17(typescript@5.6.3)) + version: 2.0.1(vue@3.5.24(typescript@5.6.3)) '@vueuse/core': specifier: ^12.5.0 - version: 12.5.0(typescript@5.6.3) + version: 12.8.2(typescript@5.6.3) '@vueuse/integrations': specifier: ^12.5.0 - version: 12.5.0(focus-trap@7.6.2)(jwt-decode@4.0.0)(typescript@5.6.3) + version: 12.8.2(focus-trap@7.6.2)(jwt-decode@4.0.0)(typescript@5.6.3) ace-builds: specifier: ^1.43.2 - version: 1.43.2 + version: 1.43.4 core-js: specifier: ^3.44.0 - version: 3.44.0 + version: 3.46.0 dayjs: specifier: ^1.11.13 - version: 1.11.13 + version: 1.11.19 dompurify: specifier: ^3.2.6 - version: 3.2.6 + version: 3.3.0 epubjs: specifier: ^0.3.93 version: 0.3.93 @@ -37,7 +37,7 @@ importers: version: 10.1.6 js-base64: specifier: ^3.7.7 - version: 3.7.7 + version: 3.7.8 jwt-decode: specifier: ^4.0.0 version: 4.0.0 @@ -46,7 +46,7 @@ importers: version: 4.17.21 marked: specifier: ^15.0.6 - version: 15.0.6 + version: 15.0.12 material-icons: specifier: ^1.13.14 version: 1.13.14 @@ -55,13 +55,13 @@ importers: version: 8.0.1 pinia: specifier: ^2.3.1 - version: 2.3.1(typescript@5.6.3)(vue@3.5.17(typescript@5.6.3)) + version: 2.3.1(typescript@5.6.3)(vue@3.5.24(typescript@5.6.3)) pretty-bytes: specifier: ^6.1.1 version: 6.1.1 qrcode.vue: specifier: ^3.6.0 - version: 3.6.0(vue@3.5.17(typescript@5.6.3)) + version: 3.6.0(vue@3.5.24(typescript@5.6.3)) tus-js-client: specifier: ^4.3.1 version: 4.3.1 @@ -70,41 +70,41 @@ importers: version: 3.1.0 video.js: specifier: ^8.23.3 - version: 8.23.3 + version: 8.23.4 videojs-hotkeys: specifier: ^0.2.28 version: 0.2.30 videojs-mobile-ui: specifier: ^1.1.1 - version: 1.1.1(video.js@8.23.3) + version: 1.1.1(video.js@8.23.4) vue: specifier: ^3.5.17 - version: 3.5.17(typescript@5.6.3) + version: 3.5.24(typescript@5.6.3) vue-final-modal: specifier: ^4.5.5 - version: 4.5.5(@vueuse/core@12.5.0(typescript@5.6.3))(@vueuse/integrations@12.5.0(focus-trap@7.6.2)(jwt-decode@4.0.0)(typescript@5.6.3))(focus-trap@7.6.2)(vue@3.5.17(typescript@5.6.3)) + version: 4.5.5(@vueuse/core@12.8.2(typescript@5.6.3))(@vueuse/integrations@12.8.2(focus-trap@7.6.2)(jwt-decode@4.0.0)(typescript@5.6.3))(focus-trap@7.6.2)(vue@3.5.24(typescript@5.6.3)) vue-i18n: specifier: ^11.1.10 - version: 11.1.10(vue@3.5.17(typescript@5.6.3)) + version: 11.1.12(vue@3.5.24(typescript@5.6.3)) vue-lazyload: specifier: ^3.0.0 version: 3.0.0 vue-reader: specifier: ^1.2.17 - version: 1.2.17(vue@3.5.17(typescript@5.6.3)) + version: 1.3.3 vue-router: specifier: ^4.5.1 - version: 4.5.1(vue@3.5.17(typescript@5.6.3)) + version: 4.6.3(vue@3.5.24(typescript@5.6.3)) vue-toastification: specifier: ^2.0.0-rc.5 - version: 2.0.0-rc.5(vue@3.5.17(typescript@5.6.3)) + version: 2.0.0-rc.5(vue@3.5.24(typescript@5.6.3)) devDependencies: '@intlify/unplugin-vue-i18n': specifier: ^6.0.8 - version: 6.0.8(@vue/compiler-dom@3.5.17)(eslint@9.31.0)(rollup@4.52.5)(typescript@5.6.3)(vue-i18n@11.1.10(vue@3.5.17(typescript@5.6.3)))(vue@3.5.17(typescript@5.6.3)) + version: 6.0.8(@vue/compiler-dom@3.5.24)(eslint@9.39.1)(rollup@4.52.5)(typescript@5.6.3)(vue-i18n@11.1.12(vue@3.5.24(typescript@5.6.3)))(vue@3.5.24(typescript@5.6.3)) '@playwright/test': specifier: ^1.54.1 - version: 1.54.1 + version: 1.56.1 '@tsconfig/node22': specifier: ^22.0.2 version: 22.0.2 @@ -113,43 +113,43 @@ importers: version: 4.17.12 '@types/node': specifier: ^22.10.10 - version: 22.10.10 + version: 22.19.1 '@typescript-eslint/eslint-plugin': specifier: ^8.37.0 - version: 8.37.0(@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.6.3))(eslint@9.31.0)(typescript@5.6.3) + version: 8.46.4(@typescript-eslint/parser@8.37.0(eslint@9.39.1)(typescript@5.6.3))(eslint@9.39.1)(typescript@5.6.3) '@vitejs/plugin-legacy': specifier: ^6.0.0 - version: 6.0.0(terser@5.43.1)(vite@6.4.1(@types/node@22.10.10)(terser@5.43.1)(yaml@2.7.0)) + version: 6.1.1(terser@5.44.1)(vite@6.4.1(@types/node@22.19.1)(terser@5.44.1)(yaml@2.7.0)) '@vitejs/plugin-vue': specifier: ^5.0.4 - version: 5.2.1(vite@6.4.1(@types/node@22.10.10)(terser@5.43.1)(yaml@2.7.0))(vue@3.5.17(typescript@5.6.3)) + version: 5.2.4(vite@6.4.1(@types/node@22.19.1)(terser@5.44.1)(yaml@2.7.0))(vue@3.5.24(typescript@5.6.3)) '@vue/eslint-config-prettier': specifier: ^10.2.0 - version: 10.2.0(eslint@9.31.0)(prettier@3.6.2) + version: 10.2.0(eslint@9.39.1)(prettier@3.6.2) '@vue/eslint-config-typescript': specifier: ^14.6.0 - version: 14.6.0(eslint-plugin-vue@9.32.0(eslint@9.31.0))(eslint@9.31.0)(typescript@5.6.3) + version: 14.6.0(eslint-plugin-vue@9.33.0(eslint@9.39.1))(eslint@9.39.1)(typescript@5.6.3) '@vue/tsconfig': specifier: ^0.7.0 - version: 0.7.0(typescript@5.6.3)(vue@3.5.17(typescript@5.6.3)) + version: 0.7.0(typescript@5.6.3)(vue@3.5.24(typescript@5.6.3)) autoprefixer: specifier: ^10.4.21 - version: 10.4.21(postcss@8.5.6) + version: 10.4.22(postcss@8.5.6) concurrently: specifier: ^9.2.0 - version: 9.2.0 + version: 9.2.1 eslint: specifier: ^9.31.0 - version: 9.31.0 + version: 9.39.1 eslint-config-prettier: specifier: ^10.1.5 - version: 10.1.5(eslint@9.31.0) + version: 10.1.8(eslint@9.39.1) eslint-plugin-prettier: specifier: ^5.5.1 - version: 5.5.1(eslint-config-prettier@10.1.5(eslint@9.31.0))(eslint@9.31.0)(prettier@3.6.2) + version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.39.1))(eslint@9.39.1)(prettier@3.6.2) eslint-plugin-vue: specifier: ^9.24.0 - version: 9.32.0(eslint@9.31.0) + version: 9.33.0(eslint@9.39.1) jsdom: specifier: ^26.1.0 version: 26.1.0 @@ -161,182 +161,156 @@ importers: version: 3.6.2 terser: specifier: ^5.43.1 - version: 5.43.1 + version: 5.44.1 vite: specifier: ^6.4.1 - version: 6.4.1(@types/node@22.10.10)(terser@5.43.1)(yaml@2.7.0) + version: 6.4.1(@types/node@22.19.1)(terser@5.44.1)(yaml@2.7.0) vite-plugin-compression2: specifier: ^1.0.0 - version: 1.3.3(rollup@4.52.5)(vite@6.4.1(@types/node@22.10.10)(terser@5.43.1)(yaml@2.7.0)) + version: 1.4.0(rollup@4.52.5)(vite@6.4.1(@types/node@22.19.1)(terser@5.44.1)(yaml@2.7.0)) vue-tsc: specifier: ^2.2.0 - version: 2.2.0(typescript@5.6.3) + version: 2.2.12(typescript@5.6.3) packages: - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - '@asamuzakjp/css-color@2.8.3': resolution: {integrity: sha512-GIc76d9UI1hCvOATjZPyHFmE5qhRccp3/zGfMPapK3jBi+yocEzp6BBB0UnfRYP9NP4FANqUZYb0hnfs3TM3hw==} - '@babel/code-frame@7.26.2': - resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.26.2': - resolution: {integrity: sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==} + '@babel/compat-data@7.28.5': + resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} engines: {node: '>=6.9.0'} - '@babel/core@7.26.0': - resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==} + '@babel/core@7.28.5': + resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} engines: {node: '>=6.9.0'} - '@babel/generator@7.26.2': - resolution: {integrity: sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==} + '@babel/generator@7.28.5': + resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} engines: {node: '>=6.9.0'} - '@babel/helper-annotate-as-pure@7.25.9': - resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} + '@babel/helper-annotate-as-pure@7.27.3': + resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} engines: {node: '>=6.9.0'} - '@babel/helper-builder-binary-assignment-operator-visitor@7.25.9': - resolution: {integrity: sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g==} + '@babel/helper-compilation-targets@7.27.2': + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.25.9': - resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-create-class-features-plugin@7.25.9': - resolution: {integrity: sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==} + '@babel/helper-create-class-features-plugin@7.28.5': + resolution: {integrity: sha512-q3WC4JfdODypvxArsJQROfupPBq9+lMwjKq7C33GhbFYJsufD0yd/ziwD+hJucLeWsnFPWZjsU2DNFqBPE7jwQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-create-regexp-features-plugin@7.25.9': - resolution: {integrity: sha512-ORPNZ3h6ZRkOyAa/SaHU+XsLZr0UQzRwuDQ0cczIA17nAzZ+85G5cVkOJIj7QavLZGSe8QXUmNFxSZzjcZF9bw==} + '@babel/helper-create-regexp-features-plugin@7.28.5': + resolution: {integrity: sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-define-polyfill-provider@0.6.3': - resolution: {integrity: sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==} + '@babel/helper-define-polyfill-provider@0.6.5': + resolution: {integrity: sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - '@babel/helper-member-expression-to-functions@7.25.9': - resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==} + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.25.9': - resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} + '@babel/helper-member-expression-to-functions@7.28.5': + resolution: {integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.26.0': - resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.28.3': + resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-optimise-call-expression@7.25.9': - resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==} + '@babel/helper-optimise-call-expression@7.27.1': + resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} engines: {node: '>=6.9.0'} - '@babel/helper-plugin-utils@7.25.9': - resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==} + '@babel/helper-plugin-utils@7.27.1': + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} engines: {node: '>=6.9.0'} - '@babel/helper-remap-async-to-generator@7.25.9': - resolution: {integrity: sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==} + '@babel/helper-remap-async-to-generator@7.27.1': + resolution: {integrity: sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-replace-supers@7.25.9': - resolution: {integrity: sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ==} + '@babel/helper-replace-supers@7.27.1': + resolution: {integrity: sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-simple-access@7.25.9': - resolution: {integrity: sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==} - engines: {node: '>=6.9.0'} - - '@babel/helper-skip-transparent-expression-wrappers@7.25.9': - resolution: {integrity: sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-string-parser@7.25.9': - resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==} engines: {node: '>=6.9.0'} '@babel/helper-string-parser@7.27.1': resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.25.9': - resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.27.1': - resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.25.9': - resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} + '@babel/helper-wrap-function@7.28.3': + resolution: {integrity: sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g==} engines: {node: '>=6.9.0'} - '@babel/helper-wrap-function@7.25.9': - resolution: {integrity: sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==} + '@babel/helpers@7.28.4': + resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.26.0': - resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.26.2': - resolution: {integrity: sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==} + '@babel/parser@7.28.5': + resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/parser@7.26.7': - resolution: {integrity: sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/parser@7.28.0': - resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9': - resolution: {integrity: sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==} + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5': + resolution: {integrity: sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9': - resolution: {integrity: sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==} + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1': + resolution: {integrity: sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9': - resolution: {integrity: sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==} + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1': + resolution: {integrity: sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9': - resolution: {integrity: sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==} + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1': + resolution: {integrity: sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.13.0 - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9': - resolution: {integrity: sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==} + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.3': + resolution: {integrity: sha512-b6YTX108evsvE4YgWyQ921ZAFFQm3Bn+CA3+ZXlNVnPhx+UfsVURoPjfGAPCjBgrqo30yX/C2nZGX96DxvR9Iw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -347,14 +321,14 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-import-assertions@7.26.0': - resolution: {integrity: sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==} + '@babel/plugin-syntax-import-assertions@7.27.1': + resolution: {integrity: sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-import-attributes@7.26.0': - resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} + '@babel/plugin-syntax-import-attributes@7.27.1': + resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -365,308 +339,314 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-transform-arrow-functions@7.25.9': - resolution: {integrity: sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==} + '@babel/plugin-transform-arrow-functions@7.27.1': + resolution: {integrity: sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-async-generator-functions@7.25.9': - resolution: {integrity: sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw==} + '@babel/plugin-transform-async-generator-functions@7.28.0': + resolution: {integrity: sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-async-to-generator@7.25.9': - resolution: {integrity: sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==} + '@babel/plugin-transform-async-to-generator@7.27.1': + resolution: {integrity: sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoped-functions@7.25.9': - resolution: {integrity: sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==} + '@babel/plugin-transform-block-scoped-functions@7.27.1': + resolution: {integrity: sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoping@7.25.9': - resolution: {integrity: sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==} + '@babel/plugin-transform-block-scoping@7.28.5': + resolution: {integrity: sha512-45DmULpySVvmq9Pj3X9B+62Xe+DJGov27QravQJU1LLcapR6/10i+gYVAucGGJpHBp5mYxIMK4nDAT/QDLr47g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-class-properties@7.25.9': - resolution: {integrity: sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==} + '@babel/plugin-transform-class-properties@7.27.1': + resolution: {integrity: sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-class-static-block@7.26.0': - resolution: {integrity: sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==} + '@babel/plugin-transform-class-static-block@7.28.3': + resolution: {integrity: sha512-LtPXlBbRoc4Njl/oh1CeD/3jC+atytbnf/UqLoqTDcEYGUPj022+rvfkbDYieUrSj3CaV4yHDByPE+T2HwfsJg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.12.0 - '@babel/plugin-transform-classes@7.25.9': - resolution: {integrity: sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==} + '@babel/plugin-transform-classes@7.28.4': + resolution: {integrity: sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-computed-properties@7.25.9': - resolution: {integrity: sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==} + '@babel/plugin-transform-computed-properties@7.27.1': + resolution: {integrity: sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-destructuring@7.25.9': - resolution: {integrity: sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==} + '@babel/plugin-transform-destructuring@7.28.5': + resolution: {integrity: sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-dotall-regex@7.25.9': - resolution: {integrity: sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==} + '@babel/plugin-transform-dotall-regex@7.27.1': + resolution: {integrity: sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-duplicate-keys@7.25.9': - resolution: {integrity: sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==} + '@babel/plugin-transform-duplicate-keys@7.27.1': + resolution: {integrity: sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9': - resolution: {integrity: sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==} + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1': + resolution: {integrity: sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-transform-dynamic-import@7.25.9': - resolution: {integrity: sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==} + '@babel/plugin-transform-dynamic-import@7.27.1': + resolution: {integrity: sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-exponentiation-operator@7.25.9': - resolution: {integrity: sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA==} + '@babel/plugin-transform-explicit-resource-management@7.28.0': + resolution: {integrity: sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-export-namespace-from@7.25.9': - resolution: {integrity: sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==} + '@babel/plugin-transform-exponentiation-operator@7.28.5': + resolution: {integrity: sha512-D4WIMaFtwa2NizOp+dnoFjRez/ClKiC2BqqImwKd1X28nqBtZEyCYJ2ozQrrzlxAFrcrjxo39S6khe9RNDlGzw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-for-of@7.25.9': - resolution: {integrity: sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==} + '@babel/plugin-transform-export-namespace-from@7.27.1': + resolution: {integrity: sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-function-name@7.25.9': - resolution: {integrity: sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==} + '@babel/plugin-transform-for-of@7.27.1': + resolution: {integrity: sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-json-strings@7.25.9': - resolution: {integrity: sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==} + '@babel/plugin-transform-function-name@7.27.1': + resolution: {integrity: sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-literals@7.25.9': - resolution: {integrity: sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==} + '@babel/plugin-transform-json-strings@7.27.1': + resolution: {integrity: sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-logical-assignment-operators@7.25.9': - resolution: {integrity: sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==} + '@babel/plugin-transform-literals@7.27.1': + resolution: {integrity: sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-member-expression-literals@7.25.9': - resolution: {integrity: sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==} + '@babel/plugin-transform-logical-assignment-operators@7.28.5': + resolution: {integrity: sha512-axUuqnUTBuXyHGcJEVVh9pORaN6wC5bYfE7FGzPiaWa3syib9m7g+/IT/4VgCOe2Upef43PHzeAvcrVek6QuuA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-amd@7.25.9': - resolution: {integrity: sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==} + '@babel/plugin-transform-member-expression-literals@7.27.1': + resolution: {integrity: sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-commonjs@7.25.9': - resolution: {integrity: sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==} + '@babel/plugin-transform-modules-amd@7.27.1': + resolution: {integrity: sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-systemjs@7.25.9': - resolution: {integrity: sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==} + '@babel/plugin-transform-modules-commonjs@7.27.1': + resolution: {integrity: sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-umd@7.25.9': - resolution: {integrity: sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==} + '@babel/plugin-transform-modules-systemjs@7.28.5': + resolution: {integrity: sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-named-capturing-groups-regex@7.25.9': - resolution: {integrity: sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==} + '@babel/plugin-transform-modules-umd@7.27.1': + resolution: {integrity: sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-named-capturing-groups-regex@7.27.1': + resolution: {integrity: sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-transform-new-target@7.25.9': - resolution: {integrity: sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==} + '@babel/plugin-transform-new-target@7.27.1': + resolution: {integrity: sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-nullish-coalescing-operator@7.25.9': - resolution: {integrity: sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog==} + '@babel/plugin-transform-nullish-coalescing-operator@7.27.1': + resolution: {integrity: sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-numeric-separator@7.25.9': - resolution: {integrity: sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==} + '@babel/plugin-transform-numeric-separator@7.27.1': + resolution: {integrity: sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-object-rest-spread@7.25.9': - resolution: {integrity: sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==} + '@babel/plugin-transform-object-rest-spread@7.28.4': + resolution: {integrity: sha512-373KA2HQzKhQCYiRVIRr+3MjpCObqzDlyrM6u4I201wL8Mp2wHf7uB8GhDwis03k2ti8Zr65Zyyqs1xOxUF/Ew==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-object-super@7.25.9': - resolution: {integrity: sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==} + '@babel/plugin-transform-object-super@7.27.1': + resolution: {integrity: sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-optional-catch-binding@7.25.9': - resolution: {integrity: sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==} + '@babel/plugin-transform-optional-catch-binding@7.27.1': + resolution: {integrity: sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-optional-chaining@7.25.9': - resolution: {integrity: sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==} + '@babel/plugin-transform-optional-chaining@7.28.5': + resolution: {integrity: sha512-N6fut9IZlPnjPwgiQkXNhb+cT8wQKFlJNqcZkWlcTqkcqx6/kU4ynGmLFoa4LViBSirn05YAwk+sQBbPfxtYzQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-parameters@7.25.9': - resolution: {integrity: sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==} + '@babel/plugin-transform-parameters@7.27.7': + resolution: {integrity: sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-private-methods@7.25.9': - resolution: {integrity: sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==} + '@babel/plugin-transform-private-methods@7.27.1': + resolution: {integrity: sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-private-property-in-object@7.25.9': - resolution: {integrity: sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==} + '@babel/plugin-transform-private-property-in-object@7.27.1': + resolution: {integrity: sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-property-literals@7.25.9': - resolution: {integrity: sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==} + '@babel/plugin-transform-property-literals@7.27.1': + resolution: {integrity: sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-regenerator@7.25.9': - resolution: {integrity: sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==} + '@babel/plugin-transform-regenerator@7.28.4': + resolution: {integrity: sha512-+ZEdQlBoRg9m2NnzvEeLgtvBMO4tkFBw5SQIUgLICgTrumLoU7lr+Oghi6km2PFj+dbUt2u1oby2w3BDO9YQnA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-regexp-modifiers@7.26.0': - resolution: {integrity: sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==} + '@babel/plugin-transform-regexp-modifiers@7.27.1': + resolution: {integrity: sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-transform-reserved-words@7.25.9': - resolution: {integrity: sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==} + '@babel/plugin-transform-reserved-words@7.27.1': + resolution: {integrity: sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-shorthand-properties@7.25.9': - resolution: {integrity: sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==} + '@babel/plugin-transform-shorthand-properties@7.27.1': + resolution: {integrity: sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-spread@7.25.9': - resolution: {integrity: sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==} + '@babel/plugin-transform-spread@7.27.1': + resolution: {integrity: sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-sticky-regex@7.25.9': - resolution: {integrity: sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==} + '@babel/plugin-transform-sticky-regex@7.27.1': + resolution: {integrity: sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-template-literals@7.25.9': - resolution: {integrity: sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==} + '@babel/plugin-transform-template-literals@7.27.1': + resolution: {integrity: sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-typeof-symbol@7.25.9': - resolution: {integrity: sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==} + '@babel/plugin-transform-typeof-symbol@7.27.1': + resolution: {integrity: sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-escapes@7.25.9': - resolution: {integrity: sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==} + '@babel/plugin-transform-unicode-escapes@7.27.1': + resolution: {integrity: sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-property-regex@7.25.9': - resolution: {integrity: sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==} + '@babel/plugin-transform-unicode-property-regex@7.27.1': + resolution: {integrity: sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-regex@7.25.9': - resolution: {integrity: sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==} + '@babel/plugin-transform-unicode-regex@7.27.1': + resolution: {integrity: sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-sets-regex@7.25.9': - resolution: {integrity: sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==} + '@babel/plugin-transform-unicode-sets-regex@7.27.1': + resolution: {integrity: sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/preset-env@7.26.0': - resolution: {integrity: sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==} + '@babel/preset-env@7.28.5': + resolution: {integrity: sha512-S36mOoi1Sb6Fz98fBfE+UZSpYw5mJm0NUHtIKrOuNcqeFauy1J6dIvXm2KRVKobOSaGq4t/hBXdN4HGU3wL9Wg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -676,32 +656,20 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 - '@babel/runtime@7.26.0': - resolution: {integrity: sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==} + '@babel/runtime@7.28.4': + resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} engines: {node: '>=6.9.0'} - '@babel/runtime@7.26.7': - resolution: {integrity: sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==} + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} - '@babel/template@7.25.9': - resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} + '@babel/traverse@7.28.5': + resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.25.9': - resolution: {integrity: sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.26.0': - resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.26.7': - resolution: {integrity: sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.28.1': - resolution: {integrity: sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==} + '@babel/types@7.28.5': + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} '@chenfengyuan/vue-number-input@2.0.1': @@ -899,60 +867,56 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/eslint-utils@4.7.0': - resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} + '@eslint-community/eslint-utils@4.9.0': + resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.12.1': - resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.21.0': - resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} + '@eslint/config-array@0.21.1': + resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/config-helpers@0.3.0': - resolution: {integrity: sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==} + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/core@0.15.1': - resolution: {integrity: sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==} + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/eslintrc@3.3.1': resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.31.0': - resolution: {integrity: sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw==} + '@eslint/js@9.39.1': + resolution: {integrity: sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/object-schema@2.1.6': - resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/plugin-kit@0.3.3': - resolution: {integrity: sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag==} + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} - '@humanfs/node@0.16.6': - resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + '@humanfs/node@0.16.7': + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} engines: {node: '>=18.18.0'} '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - '@humanwhocodes/retry@0.3.1': - resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} - engines: {node: '>=18.18'} - '@humanwhocodes/retry@0.4.3': resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} @@ -969,20 +933,20 @@ packages: vue-i18n: optional: true - '@intlify/core-base@11.1.10': - resolution: {integrity: sha512-JhRb40hD93Vk0BgMgDc/xMIFtdXPHoytzeK6VafBNOj6bb6oUZrGamXkBKecMsmGvDQQaPRGG2zpa25VCw8pyw==} + '@intlify/core-base@11.1.12': + resolution: {integrity: sha512-whh0trqRsSqVLNEUCwU59pyJZYpU8AmSWl8M3Jz2Mv5ESPP6kFh4juas2NpZ1iCvy7GlNRffUD1xr84gceimjg==} engines: {node: '>= 16'} - '@intlify/message-compiler@11.1.10': - resolution: {integrity: sha512-TABl3c8tSLWbcD+jkQTyBhrnW251dzqW39MPgEUCsd69Ua3ceoimsbIzvkcPzzZvt1QDxNkenMht+5//V3JvLQ==} + '@intlify/message-compiler@11.1.12': + resolution: {integrity: sha512-Fv9iQSJoJaXl4ZGkOCN1LDM3trzze0AS2zRz2EHLiwenwL6t0Ki9KySYlyr27yVOj5aVz0e55JePO+kELIvfdQ==} engines: {node: '>= 16'} '@intlify/message-compiler@11.1.2': resolution: {integrity: sha512-T/xbNDzi+Yv0Qn2Dfz2CWCAJiwNgU5d95EhhAEf4YmOgjCKktpfpiUSmLcBvK1CtLpPQ85AMMQk/2NCcXnNj1g==} engines: {node: '>= 16'} - '@intlify/shared@11.1.10': - resolution: {integrity: sha512-6ZW/f3Zzjxfa1Wh0tYQI5pLKUtU+SY7l70pEG+0yd0zjcsYcK0EBt6Fz30Dy0tZhEqemziQQy2aNU3GJzyrMUA==} + '@intlify/shared@11.1.12': + resolution: {integrity: sha512-Om86EjuQtA69hdNj3GQec9ZC0L0vPSAnXzB3gP/gyJ7+mA7t06d9aOAiqMZ+xEOsumGP4eEBlfl8zF2LOTzf2A==} engines: {node: '>= 16'} '@intlify/shared@11.1.2': @@ -1024,30 +988,24 @@ packages: vue-i18n: optional: true - '@jridgewell/gen-mapping@0.3.5': - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} - '@jridgewell/gen-mapping@0.3.8': - resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} - engines: {node: '>=6.0.0'} + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} - '@jridgewell/set-array@1.2.1': - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} + '@jridgewell/source-map@0.3.11': + resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==} - '@jridgewell/source-map@0.3.6': - resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - '@jridgewell/sourcemap-codec@1.5.0': - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - - '@jridgewell/trace-mapping@0.3.25': - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -1061,17 +1019,17 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@pkgr/core@0.2.7': - resolution: {integrity: sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==} + '@pkgr/core@0.2.9': + resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@playwright/test@1.54.1': - resolution: {integrity: sha512-FS8hQ12acieG2dYSksmLOF7BNxnVf2afRJdCuM1eMSxj6QTSE6G4InGF7oApGgDb65MX7AwMVlIkpru0yZA4Xw==} + '@playwright/test@1.56.1': + resolution: {integrity: sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==} engines: {node: '>=18'} hasBin: true - '@rollup/pluginutils@5.1.3': - resolution: {integrity: sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==} + '@rollup/pluginutils@5.1.4': + resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} engines: {node: '>=14.0.0'} peerDependencies: rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 @@ -1079,8 +1037,8 @@ packages: rollup: optional: true - '@rollup/pluginutils@5.1.4': - resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==} + '@rollup/pluginutils@5.3.0': + resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} engines: {node: '>=14.0.0'} peerDependencies: rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 @@ -1201,12 +1159,6 @@ packages: '@tsconfig/node22@22.0.2': resolution: {integrity: sha512-Kmwj4u8sDRDrMYRoN9FDEcXD8UpBSaPQQ24Gz+Gamqfm7xxn+GBR7ge/Z7pK8OXNGyUzbSwJj+TH6B+DS/epyA==} - '@types/estree@1.0.6': - resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - - '@types/estree@1.0.7': - resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} - '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} @@ -1223,14 +1175,14 @@ packages: '@types/lodash@4.17.13': resolution: {integrity: sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==} - '@types/node@22.10.10': - resolution: {integrity: sha512-X47y/mPNzxviAGY5TcYPtYL8JsY3kAq2n8fMmKoRCxq/c4v4pyGNCzM2R6+M5/umG4ZfHuT+sgqDYqWc9rJ6ww==} + '@types/node@22.19.1': + resolution: {integrity: sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==} '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} - '@types/web-bluetooth@0.0.20': - resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} + '@types/web-bluetooth@0.0.21': + resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==} '@typescript-eslint/eslint-plugin@8.37.0': resolution: {integrity: sha512-jsuVWeIkb6ggzB+wPCsR4e6loj+rM72ohW6IBn2C+5NCvfUVY8s33iFPySSVXqtm5Hu29Ne/9bnA0JmyLmgenA==} @@ -1240,6 +1192,14 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/eslint-plugin@8.46.4': + resolution: {integrity: sha512-R48VhmTJqplNyDxCyqqVkFSZIx1qX6PzwqgcXn1olLrzxcSBDlOsbtcnQuQhNtnNiJ4Xe5gREI1foajYaYU2Vg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.46.4 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/parser@8.37.0': resolution: {integrity: sha512-kVIaQE9vrN9RLCQMQ3iyRlVJpTiDUY6woHGb30JDkfJErqrQEmtdWH3gV0PBAfGZgQXoqzXOO0T3K6ioApbbAA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1253,6 +1213,12 @@ packages: peerDependencies: typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/project-service@8.46.4': + resolution: {integrity: sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/scope-manager@8.21.0': resolution: {integrity: sha512-G3IBKz0/0IPfdeGRMbp+4rbjfSSdnGkXsM/pFZA8zM9t9klXDnB/YnKOBQ0GoPmoROa4bCq2NeHgJa5ydsQ4mA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1261,12 +1227,22 @@ packages: resolution: {integrity: sha512-0vGq0yiU1gbjKob2q691ybTg9JX6ShiVXAAfm2jGf3q0hdP6/BruaFjL/ManAR/lj05AvYCH+5bbVo0VtzmjOA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.46.4': + resolution: {integrity: sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/tsconfig-utils@8.37.0': resolution: {integrity: sha512-1/YHvAVTimMM9mmlPvTec9NP4bobA1RkDbMydxG8omqwJJLEW/Iy2C4adsAESIXU3WGLXFHSZUU+C9EoFWl4Zg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/tsconfig-utils@8.46.4': + resolution: {integrity: sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/type-utils@8.37.0': resolution: {integrity: sha512-SPkXWIkVZxhgwSwVq9rqj/4VFo7MnWwVaRNznfQDc/xPYHjXnPfLWn+4L6FF1cAz6e7dsqBeMawgl7QjUMj4Ow==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1274,6 +1250,13 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/type-utils@8.46.4': + resolution: {integrity: sha512-V4QC8h3fdT5Wro6vANk6eojqfbv5bpwHuMsBcJUJkqs2z5XnYhJzyz9Y02eUmF9u3PgXEUiOt4w4KHR3P+z0PQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/types@8.21.0': resolution: {integrity: sha512-PAL6LUuQwotLW2a8VsySDBwYMm129vFm4tMVlylzdoTybTHaAi0oBp7Ac6LhSrHHOdLM3efH+nAR6hAWoMF89A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1282,6 +1265,10 @@ packages: resolution: {integrity: sha512-ax0nv7PUF9NOVPs+lmQ7yIE7IQmAf8LGcXbMvHX5Gm+YJUYNAl340XkGnrimxZ0elXyoQJuN5sbg6C4evKA4SQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.46.4': + resolution: {integrity: sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@8.21.0': resolution: {integrity: sha512-x+aeKh/AjAArSauz0GiQZsjT8ciadNMHdkUSwBB9Z6PrKc/4knM4g3UfHml6oDJmKC88a6//cdxnO/+P2LkMcg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1294,6 +1281,12 @@ packages: peerDependencies: typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/typescript-estree@8.46.4': + resolution: {integrity: sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/utils@8.37.0': resolution: {integrity: sha512-TSFvkIW6gGjN2p6zbXo20FzCABbyUAuq6tBvNRGsKdsSQ6a7rnV6ADfZ7f4iI3lIiXc4F4WWvtUfDw9CJ9pO5A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1301,6 +1294,13 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/utils@8.46.4': + resolution: {integrity: sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/visitor-keys@8.21.0': resolution: {integrity: sha512-BkLMNpdV6prozk8LlyK/SOoWLmUFi+ZD+pcqti9ILCbVvHGk1ui1g4jJOc2WDLaeExz2qWwojxlPce5PljcT3w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1309,8 +1309,12 @@ packages: resolution: {integrity: sha512-YzfhzcTnZVPiLfP/oeKtDp2evwvHLMe0LOy7oe+hb9KKIumLNohYS9Hgp1ifwpu42YWxhZE8yieggz6JpqO/1w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@videojs/http-streaming@3.17.0': - resolution: {integrity: sha512-Ch1P3tvvIEezeZXyK11UfWgp4cWKX4vIhZ30baN/lRinqdbakZ5hiAI3pGjRy3d+q/Epyc8Csz5xMdKNNGYpcw==} + '@typescript-eslint/visitor-keys@8.46.4': + resolution: {integrity: sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@videojs/http-streaming@3.17.2': + resolution: {integrity: sha512-VBQ3W4wnKnVKb/limLdtSD2rAd5cmHN70xoMf4OmuDd0t2kfJX04G+sfw6u2j8oOm2BXYM9E1f4acHruqKnM1g==} engines: {node: '>=8', npm: '>=5'} peerDependencies: video.js: ^8.19.0 @@ -1322,46 +1326,40 @@ packages: '@videojs/xhr@2.7.0': resolution: {integrity: sha512-giab+EVRanChIupZK7gXjHy90y3nncA2phIOyG3Ne5fvpiMJzvqYwiTOnEVW2S4CoYcuKJkomat7bMXA/UoUZQ==} - '@vitejs/plugin-legacy@6.0.0': - resolution: {integrity: sha512-pWt9cWaGJAKYw+67VLpN8hSP+G+yAQnrf5Pqh/NzSDKFl/4KpxTtwb5OLQezHoZOxghahO/ha3IpvblBbX/t6A==} + '@vitejs/plugin-legacy@6.1.1': + resolution: {integrity: sha512-BvusL+mYZ0q5qS5Rq3D70QxZBmhyiHRaXLtYJHH5AEsAmdSqJR4xe5KwMi1H3w8/9lVJwhkLYqFQ9vmWYWy6kA==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} peerDependencies: terser: ^5.16.0 vite: ^6.0.0 - '@vitejs/plugin-vue@5.2.1': - resolution: {integrity: sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==} + '@vitejs/plugin-vue@5.2.4': + resolution: {integrity: sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==} engines: {node: ^18.0.0 || >=20.0.0} peerDependencies: vite: ^5.0.0 || ^6.0.0 vue: ^3.2.25 - '@volar/language-core@2.4.11': - resolution: {integrity: sha512-lN2C1+ByfW9/JRPpqScuZt/4OrUUse57GLI6TbLgTIqBVemdl1wNcZ1qYGEo2+Gw8coYLgCy7SuKqn6IrQcQgg==} + '@volar/language-core@2.4.15': + resolution: {integrity: sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==} - '@volar/source-map@2.4.11': - resolution: {integrity: sha512-ZQpmafIGvaZMn/8iuvCFGrW3smeqkq/IIh9F1SdSx9aUl0J4Iurzd6/FhmjNO5g2ejF3rT45dKskgXWiofqlZQ==} + '@volar/source-map@2.4.15': + resolution: {integrity: sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg==} - '@volar/typescript@2.4.11': - resolution: {integrity: sha512-2DT+Tdh88Spp5PyPbqhyoYavYCPDsqbHLFwcUI9K1NlY1YgUJvujGdrqUp0zWxnW7KWNTr3xSpMuv2WnaTKDAw==} + '@volar/typescript@2.4.15': + resolution: {integrity: sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg==} - '@vue/compiler-core@3.5.13': - resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==} + '@vue/compiler-core@3.5.24': + resolution: {integrity: sha512-eDl5H57AOpNakGNAkFDH+y7kTqrQpJkZFXhWZQGyx/5Wh7B1uQYvcWkvZi11BDhscPgj8N7XV3oRwiPnx1Vrig==} - '@vue/compiler-core@3.5.17': - resolution: {integrity: sha512-Xe+AittLbAyV0pabcN7cP7/BenRBNcteM4aSDCtRvGw0d9OL+HG1u/XHLY/kt1q4fyMeZYXyIYrsHuPSiDPosA==} + '@vue/compiler-dom@3.5.24': + resolution: {integrity: sha512-1QHGAvs53gXkWdd3ZMGYuvQFXHW4ksKWPG8HP8/2BscrbZ0brw183q2oNWjMrSWImYLHxHrx1ItBQr50I/q2zw==} - '@vue/compiler-dom@3.5.13': - resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==} + '@vue/compiler-sfc@3.5.24': + resolution: {integrity: sha512-8EG5YPRgmTB+YxYBM3VXy8zHD9SWHUJLIGPhDovo3Z8VOgvP+O7UP5vl0J4BBPWYD9vxtBabzW1EuEZ+Cqs14g==} - '@vue/compiler-dom@3.5.17': - resolution: {integrity: sha512-+2UgfLKoaNLhgfhV5Ihnk6wB4ljyW1/7wUIog2puUqajiC29Lp5R/IKDdkebh9jTbTogTbsgB+OY9cEWzG95JQ==} - - '@vue/compiler-sfc@3.5.17': - resolution: {integrity: sha512-rQQxbRJMgTqwRugtjw0cnyQv9cP4/4BxWfTdRBkqsTfLOHWykLzbOc3C4GGzAmdMDxhzU/1Ija5bTjMVrddqww==} - - '@vue/compiler-ssr@3.5.17': - resolution: {integrity: sha512-hkDbA0Q20ZzGgpj5uZjb9rBzQtIHLS78mMilwrlpWk2Ep37DYntUz0PonQ6kr113vfOEdM+zTBuJDaceNIW0tQ==} + '@vue/compiler-ssr@3.5.24': + resolution: {integrity: sha512-trOvMWNBMQ/odMRHW7Ae1CdfYx+7MuiQu62Jtu36gMLXcaoqKvAyh+P73sYG9ll+6jLB6QPovqoKGGZROzkFFg==} '@vue/compiler-vue2@2.7.16': resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} @@ -1386,33 +1384,30 @@ packages: typescript: optional: true - '@vue/language-core@2.2.0': - resolution: {integrity: sha512-O1ZZFaaBGkKbsRfnVH1ifOK1/1BUkyK+3SQsfnh6PmMmD4qJcTU8godCeA96jjDRTL6zgnK7YzCHfaUlH2r0Mw==} + '@vue/language-core@2.2.12': + resolution: {integrity: sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA==} peerDependencies: typescript: '*' peerDependenciesMeta: typescript: optional: true - '@vue/reactivity@3.5.17': - resolution: {integrity: sha512-l/rmw2STIscWi7SNJp708FK4Kofs97zc/5aEPQh4bOsReD/8ICuBcEmS7KGwDj5ODQLYWVN2lNibKJL1z5b+Lw==} + '@vue/reactivity@3.5.24': + resolution: {integrity: sha512-BM8kBhtlkkbnyl4q+HiF5R5BL0ycDPfihowulm02q3WYp2vxgPcJuZO866qa/0u3idbMntKEtVNuAUp5bw4teg==} - '@vue/runtime-core@3.5.17': - resolution: {integrity: sha512-QQLXa20dHg1R0ri4bjKeGFKEkJA7MMBxrKo2G+gJikmumRS7PTD4BOU9FKrDQWMKowz7frJJGqBffYMgQYS96Q==} + '@vue/runtime-core@3.5.24': + resolution: {integrity: sha512-RYP/byyKDgNIqfX/gNb2PB55dJmM97jc9wyF3jK7QUInYKypK2exmZMNwnjueWwGceEkP6NChd3D2ZVEp9undQ==} - '@vue/runtime-dom@3.5.17': - resolution: {integrity: sha512-8El0M60TcwZ1QMz4/os2MdlQECgGoVHPuLnQBU3m9h3gdNRW9xRmI8iLS4t/22OQlOE6aJvNNlBiCzPHur4H9g==} + '@vue/runtime-dom@3.5.24': + resolution: {integrity: sha512-Z8ANhr/i0XIluonHVjbUkjvn+CyrxbXRIxR7wn7+X7xlcb7dJsfITZbkVOeJZdP8VZwfrWRsWdShH6pngMxRjw==} - '@vue/server-renderer@3.5.17': - resolution: {integrity: sha512-BOHhm8HalujY6lmC3DbqF6uXN/K00uWiEeF22LfEsm9Q93XeJ/plHTepGwf6tqFcF7GA5oGSSAAUock3VvzaCA==} + '@vue/server-renderer@3.5.24': + resolution: {integrity: sha512-Yh2j2Y4G/0/4z/xJ1Bad4mxaAk++C2v4kaa8oSYTMJBJ00/ndPuxCnWeot0/7/qafQFLh5pr6xeV6SdMcE/G1w==} peerDependencies: - vue: 3.5.17 + vue: 3.5.24 - '@vue/shared@3.5.13': - resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==} - - '@vue/shared@3.5.17': - resolution: {integrity: sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg==} + '@vue/shared@3.5.24': + resolution: {integrity: sha512-9cwHL2EsJBdi8NY22pngYYWzkTDhld6fAD6jlaeloNGciNSJL6bLpbxVgXl96X00Jtc6YWQv96YA/0sxex/k1A==} '@vue/tsconfig@0.7.0': resolution: {integrity: sha512-ku2uNz5MaZ9IerPPUyOHzyjhXoX2kVJaVf7hL315DC17vS6IiZRmmCPfggNbU16QTvM80+uYYy3eYJB59WCtvg==} @@ -1425,11 +1420,11 @@ packages: vue: optional: true - '@vueuse/core@12.5.0': - resolution: {integrity: sha512-GVyH1iYqNANwcahAx8JBm6awaNgvR/SwZ1fjr10b8l1HIgDp82ngNbfzJUgOgWEoxjL+URAggnlilAEXwCOZtg==} + '@vueuse/core@12.8.2': + resolution: {integrity: sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==} - '@vueuse/integrations@12.5.0': - resolution: {integrity: sha512-HYLt8M6mjUfcoUOzyBcX2RjpfapIwHPBmQJtTmXOQW845Y/Osu9VuTJ5kPvnmWJ6IUa05WpblfOwZ+P0G4iZsQ==} + '@vueuse/integrations@12.8.2': + resolution: {integrity: sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g==} peerDependencies: async-validator: ^4 axios: ^1 @@ -1469,34 +1464,29 @@ packages: universal-cookie: optional: true - '@vueuse/metadata@12.5.0': - resolution: {integrity: sha512-Ui7Lo2a7AxrMAXRF+fAp9QsXuwTeeZ8fIB9wsLHqzq9MQk+2gMYE2IGJW48VMJ8ecvCB3z3GsGLKLbSasQ5Qlg==} + '@vueuse/metadata@12.8.2': + resolution: {integrity: sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==} - '@vueuse/shared@12.5.0': - resolution: {integrity: sha512-vMpcL1lStUU6O+kdj6YdHDixh0odjPAUM15uJ9f7MY781jcYkIwFA4iv2EfoIPO6vBmvutI1HxxAwmf0cx5ISQ==} + '@vueuse/shared@12.8.2': + resolution: {integrity: sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==} '@xmldom/xmldom@0.7.13': resolution: {integrity: sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g==} engines: {node: '>=10.0.0'} deprecated: this version is no longer supported, please update to at least 0.8.* - '@xmldom/xmldom@0.8.10': - resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==} + '@xmldom/xmldom@0.8.11': + resolution: {integrity: sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==} engines: {node: '>=10.0.0'} - ace-builds@1.43.2: - resolution: {integrity: sha512-3wzJUJX0RpMc03jo0V8Q3bSb/cKPnS7Nqqw8fVHsCCHweKMiTIxT3fP46EhjmVy6MCuxwP801ere+RW245phGw==} + ace-builds@1.43.4: + resolution: {integrity: sha512-8hAxVfo2ImICd69BWlZwZlxe9rxDGDjuUhh+WeWgGDvfBCE+r3lkynkQvIovDz4jcMi8O7bsEaFygaDT+h9sBA==} acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.14.0: - resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} - engines: {node: '>=0.4.0'} - hasBin: true - acorn@8.15.0: resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} engines: {node: '>=0.4.0'} @@ -1512,8 +1502,8 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - alien-signals@0.4.14: - resolution: {integrity: sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q==} + alien-signals@1.0.13: + resolution: {integrity: sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==} ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} @@ -1526,39 +1516,43 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - autoprefixer@10.4.21: - resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==} + autoprefixer@10.4.22: + resolution: {integrity: sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==} engines: {node: ^10 || ^12 || >=14} hasBin: true peerDependencies: postcss: ^8.1.0 - babel-plugin-polyfill-corejs2@0.4.12: - resolution: {integrity: sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==} + babel-plugin-polyfill-corejs2@0.4.14: + resolution: {integrity: sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-plugin-polyfill-corejs3@0.10.6: - resolution: {integrity: sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==} + babel-plugin-polyfill-corejs3@0.13.0: + resolution: {integrity: sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-plugin-polyfill-regenerator@0.6.3: - resolution: {integrity: sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==} + babel-plugin-polyfill-regenerator@0.6.5: + resolution: {integrity: sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + baseline-browser-mapping@2.8.26: + resolution: {integrity: sha512-73lC1ugzwoaWCLJ1LvOgrR5xsMLTqSKIEoMHVtL9E/HNk0PXtTM76ZIm84856/SF7Nv8mPZxKoBsgpm0tR1u1Q==} + hasBin: true + boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} @@ -1571,13 +1565,8 @@ packages: peerDependencies: browserslist: '*' - browserslist@4.24.2: - resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - - browserslist@4.25.1: - resolution: {integrity: sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==} + browserslist@4.28.0: + resolution: {integrity: sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -1588,11 +1577,8 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caniuse-lite@1.0.30001685: - resolution: {integrity: sha512-e/kJN1EMyHQzgcMEEgoo+YTCO1NGCmIYHk5Qk8jT6AazWemS5QFKJ5ShCJlH3GZrNIdZofcNCEwZqbMjjKzmnA==} - - caniuse-lite@1.0.30001727: - resolution: {integrity: sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==} + caniuse-lite@1.0.30001754: + resolution: {integrity: sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==} chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} @@ -1618,8 +1604,8 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - concurrently@9.2.0: - resolution: {integrity: sha512-IsB/fiXTupmagMW4MNp2lx2cdSN2FfZq78vF90LBB+zZHArbIQZjQtzXCiXnvTxCZSvXanTqFLWBjw2UkLx1SQ==} + concurrently@9.2.1: + resolution: {integrity: sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==} engines: {node: '>=18'} hasBin: true @@ -1629,11 +1615,11 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - core-js-compat@3.39.0: - resolution: {integrity: sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==} + core-js-compat@3.46.0: + resolution: {integrity: sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==} - core-js@3.44.0: - resolution: {integrity: sha512-aFCtd4l6GvAXwVEh3XbbVqJGHDJt0OZRa+5ePGx3LLwi12WfexqQxcsohb2wgsa/92xtl19Hd66G/L+TaAxDMw==} + core-js@3.46.0: + resolution: {integrity: sha512-vDMm9B0xnqqZ8uSBpZ8sNtRtOdmfShrvT6h2TuQGLs0Is+cR0DYbj/KWP6ALVNbWPpqA/qPLoOuppJN07humpA==} core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -1665,14 +1651,14 @@ packages: resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} engines: {node: '>=18'} - dayjs@1.11.13: - resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + dayjs@1.11.19: + resolution: {integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==} de-indent@1.0.2: resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} - debug@4.3.7: - resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -1680,8 +1666,8 @@ packages: supports-color: optional: true - debug@4.4.0: - resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -1698,14 +1684,11 @@ packages: dom-walk@0.1.2: resolution: {integrity: sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==} - dompurify@3.2.6: - resolution: {integrity: sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==} + dompurify@3.3.0: + resolution: {integrity: sha512-r+f6MYR1gGN1eJv0TVQbhA7if/U7P87cdPl3HN5rikqaBSBxLiCb/b9O+2eG0cxz0ghyU+mU1QkbsOwERMYlWQ==} - electron-to-chromium@1.5.183: - resolution: {integrity: sha512-vCrDBYjQCAEefWGjlK3EpoSKfKbT10pR4XXPdn65q7snuNOZnthoVpBfZPykmDapOKfoD+MMIPG8ZjKyyc9oHA==} - - electron-to-chromium@1.5.67: - resolution: {integrity: sha512-nz88NNBsD7kQSAGGJyp8hS6xSPtWwqNogA0mjtc2nUYeEf3nURK9qpV18TuBdDmEDgVWotS8Wkzf+V52dSQ/LQ==} + electron-to-chromium@1.5.250: + resolution: {integrity: sha512-/5UMj9IiGDMOFBnN4i7/Ry5onJrAGSbOGo3s9FEKmwobGq6xw832ccET0CE3CkkMBZ8GJSlUIesZofpyurqDXw==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -1746,14 +1729,14 @@ packages: engines: {node: '>=6.0'} hasBin: true - eslint-config-prettier@10.1.5: - resolution: {integrity: sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==} + eslint-config-prettier@10.1.8: + resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} hasBin: true peerDependencies: eslint: '>=7.0.0' - eslint-plugin-prettier@5.5.1: - resolution: {integrity: sha512-dobTkHT6XaEVOo8IO90Q4DOSxnm3Y151QxPJlM/vKC0bVy+d6cVWQZLlFiuZPP0wS6vZwSKeJgKkcS+KfMBlRw==} + eslint-plugin-prettier@5.5.4: + resolution: {integrity: sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: '@types/eslint': '>=8.0.0' @@ -1766,8 +1749,8 @@ packages: eslint-config-prettier: optional: true - eslint-plugin-vue@9.32.0: - resolution: {integrity: sha512-b/Y05HYmnB/32wqVcjxjHZzNpwxj1onBOvqW89W+V+XNG1dRuaFbNd3vT9CLbr2LXjEoq+3vn8DanWf7XU22Ug==} + eslint-plugin-vue@9.33.0: + resolution: {integrity: sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw==} engines: {node: ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 @@ -1776,10 +1759,6 @@ packages: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint-scope@8.2.0: - resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint-scope@8.4.0: resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1788,16 +1767,12 @@ packages: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint-visitor-keys@4.2.0: - resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint-visitor-keys@4.2.1: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.31.0: - resolution: {integrity: sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==} + eslint@9.39.1: + resolution: {integrity: sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -1810,10 +1785,6 @@ packages: resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==} engines: {node: '>=0.10'} - espree@10.3.0: - resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - espree@10.4.0: resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1900,14 +1871,14 @@ packages: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} - flatted@3.3.2: - resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} focus-trap@7.6.2: resolution: {integrity: sha512-9FhUxK1hVju2+AiQIDJ5Dd//9R2n2RAfJ0qfhF4IHGHgcoEUTMpbTeG/zbEuwaiYXfuAH6XE0/aCyxDdRM+W5w==} - fraction.js@4.3.7: - resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + fraction.js@5.3.4: + resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} @@ -1941,10 +1912,6 @@ packages: global@4.4.0: resolution: {integrity: sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==} - globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - globals@13.24.0: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} engines: {node: '>=8'} @@ -1998,8 +1965,8 @@ packages: immediate@3.0.6: resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} - import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} imurmurhash@0.1.4: @@ -2009,8 +1976,8 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - is-core-module@2.15.1: - resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} engines: {node: '>= 0.4'} is-extglob@2.1.1: @@ -2045,8 +2012,8 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - js-base64@3.7.7: - resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==} + js-base64@3.7.8: + resolution: {integrity: sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==} js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -2064,8 +2031,8 @@ packages: canvas: optional: true - jsesc@3.0.2: - resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} hasBin: true @@ -2159,14 +2126,11 @@ packages: m3u8-parser@7.2.0: resolution: {integrity: sha512-CRatFqpjVtMiMaKXxNvuI3I++vUumIXVVT/JpCpdU/FynV/ceVw1qpPyyBNindL+JlPMSesx+WX1QJaZEJSaMQ==} - magic-string@0.30.14: - resolution: {integrity: sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - magic-string@0.30.17: - resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} - - marked@15.0.6: - resolution: {integrity: sha512-Y07CUOE+HQXbVDCGl3LXggqJDbXDP2pArc2C1N1RRMN0ONiShoSsIInMd5Gsxupe7fKLpgimTV+HOJ9r7bA+pg==} + marked@15.0.12: + resolution: {integrity: sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==} engines: {node: '>= 18'} hasBin: true @@ -2188,8 +2152,8 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} - min-document@2.19.0: - resolution: {integrity: sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==} + min-document@2.19.2: + resolution: {integrity: sha512-8S5I8db/uZN8r9HSLFVWPdJCvYOejMcEC82VIzNUc6Zkklf/d1gg2psfE79/vyhWOj4+J8MtwmoOz3TmvaGu5A==} minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -2227,11 +2191,8 @@ packages: next-tick@1.1.0: resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} - node-releases@2.0.18: - resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} - - node-releases@2.0.19: - resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + node-releases@2.0.27: + resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} normalize-range@0.1.2: resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} @@ -2318,13 +2279,13 @@ packages: pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} - playwright-core@1.54.1: - resolution: {integrity: sha512-Nbjs2zjj0htNhzgiy5wu+3w09YetDx5pkrpI/kZotDlDUaYk0HVA5xrBVPdow4SAUIlhgKcJeJg4GRKW6xHusA==} + playwright-core@1.56.1: + resolution: {integrity: sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==} engines: {node: '>=18'} hasBin: true - playwright@1.54.1: - resolution: {integrity: sha512-peWpSwIBmSLi6aW2auvrUtf2DqY16YYcCMO8rTVx486jKmDTJg7UAhyrraP98GB8BoPURZP8+nxO7TSd4cPr5g==} + playwright@1.56.1: + resolution: {integrity: sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==} engines: {node: '>=18'} hasBin: true @@ -2384,8 +2345,8 @@ packages: readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - regenerate-unicode-properties@10.2.0: - resolution: {integrity: sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==} + regenerate-unicode-properties@10.2.2: + resolution: {integrity: sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==} engines: {node: '>=4'} regenerate@1.4.2: @@ -2394,18 +2355,15 @@ packages: regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - regenerator-transform@0.15.2: - resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} - - regexpu-core@6.2.0: - resolution: {integrity: sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==} + regexpu-core@6.4.0: + resolution: {integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==} engines: {node: '>=4'} regjsgen@0.8.0: resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} - regjsparser@0.12.0: - resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==} + regjsparser@0.13.0: + resolution: {integrity: sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==} hasBin: true require-directory@2.1.1: @@ -2419,8 +2377,9 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} hasBin: true retry@0.12.0: @@ -2442,8 +2401,8 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - rxjs@7.8.1: - resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} @@ -2459,8 +2418,8 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.6.3: - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} engines: {node: '>=10'} hasBin: true @@ -2475,8 +2434,8 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - shell-quote@1.8.2: - resolution: {integrity: sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==} + shell-quote@1.8.3: + resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==} engines: {node: '>= 0.4'} signal-exit@3.0.7: @@ -2523,21 +2482,21 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - synckit@0.11.8: - resolution: {integrity: sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==} + synckit@0.11.11: + resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==} engines: {node: ^14.18.0 || >=16.0.0} systemjs@6.15.1: resolution: {integrity: sha512-Nk8c4lXvMB98MtbmjX7JwJRgJOL8fluecYCfCeYBznwmpOs8Bf15hLM6z4z71EDAhQVrQrI+wt1aLWSXZq+hXA==} - tabbable@6.2.0: - resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + tabbable@6.3.0: + resolution: {integrity: sha512-EIHvdY5bPLuWForiR/AN2Bxngzpuwn1is4asboytXtpTgsArc+WmSJKVLlhdh71u7jFcryDqB2A8lQvj78MkyQ==} tar-mini@0.2.0: resolution: {integrity: sha512-+qfUHz700DWnRutdUsxRRVZ38G1Qr27OetwaMYTdg8hcPxf46U0S1Zf76dQMWRBmusOt2ZCK5kbIaiLkoGO7WQ==} - terser@5.43.1: - resolution: {integrity: sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==} + terser@5.44.1: + resolution: {integrity: sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==} engines: {node: '>=10'} hasBin: true @@ -2568,12 +2527,6 @@ packages: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true - ts-api-utils@2.0.0: - resolution: {integrity: sha512-xCt/TOAc+EOHS1XPnijD3/yzpH6qg2xppZO1YDqGoVsNXfQfzHpOdNuXwrwOU8u4ITXJyDCTyt8w5g1sZv9ynQ==} - engines: {node: '>=18.12'} - peerDependencies: - typescript: '>=4.8.4' - ts-api-utils@2.1.0: resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} engines: {node: '>=18.12'} @@ -2613,8 +2566,8 @@ packages: ufo@1.5.4: resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} - undici-types@6.20.0: - resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} unicode-canonical-property-names-ecmascript@2.0.1: resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} @@ -2624,26 +2577,20 @@ packages: resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} engines: {node: '>=4'} - unicode-match-property-value-ecmascript@2.2.0: - resolution: {integrity: sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==} + unicode-match-property-value-ecmascript@2.2.1: + resolution: {integrity: sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==} engines: {node: '>=4'} - unicode-property-aliases-ecmascript@2.1.0: - resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} + unicode-property-aliases-ecmascript@2.2.0: + resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==} engines: {node: '>=4'} unplugin@1.16.1: resolution: {integrity: sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==} engines: {node: '>=14.0.0'} - update-browserslist-db@1.1.1: - resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - - update-browserslist-db@1.1.3: - resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + update-browserslist-db@1.1.4: + resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -2660,8 +2607,8 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - video.js@8.23.3: - resolution: {integrity: sha512-Toe0VLlDZcUhiaWfcePS1OEdT3ATfktm0hk/PELfD7zUoPDHeT+cJf/wZmCy5M5eGVwtGUg25RWPCj1L/1XufA==} + video.js@8.23.4: + resolution: {integrity: sha512-qI0VTlYmKzEqRsz1Nppdfcaww4RSxZAq77z2oNSl3cNg2h6do5C8Ffl0KqWQ1OpD8desWXsCrde7tKJ9gGTEyQ==} videojs-contrib-quality-levels@4.1.0: resolution: {integrity: sha512-TfrXJJg1Bv4t6TOCMEVMwF/CoS8iENYsWNKip8zfhB5kTcegiFYezEA0eHAJPU64ZC8NQbxQgOwAsYU8VXbOWA==} @@ -2684,8 +2631,8 @@ packages: videojs-vtt.js@0.15.5: resolution: {integrity: sha512-yZbBxvA7QMYn15Lr/ZfhhLPrNpI/RmCSCqgIff57GC2gIrV5YfyzLfLyZMj0NnZSAz8syB4N0nHXpZg9MyrMOQ==} - vite-plugin-compression2@1.3.3: - resolution: {integrity: sha512-Mb+xi/C5b68awtF4fNwRBPtoZiyUHU3I0SaBOAGlerlR31kusq1si6qG31lsjJH8T7QNg/p3IJY2HY9O9SvsfQ==} + vite-plugin-compression2@1.4.0: + resolution: {integrity: sha512-UEk0Bq1IkkwqbDLoLOHZ8WTmN1QbvR28fvNl2liB88/6SG1oLrTVkxfjqW3pdla/rKQ6QXn+pJpv3GBbl+k56g==} peerDependencies: vite: ^2.0.0||^3.0.0||^4.0.0||^5.0.0 ||^6.0.0 @@ -2729,8 +2676,8 @@ packages: yaml: optional: true - vscode-uri@3.0.8: - resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} + vscode-uri@3.1.0: + resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} vue-demi@0.14.10: resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} @@ -2763,8 +2710,8 @@ packages: focus-trap: '>=7.2.0' vue: '>=3.2.0' - vue-i18n@11.1.10: - resolution: {integrity: sha512-C+IwnSg8QDSOAox0gdFYP5tsKLx5jNWxiawNoiNB/Tw4CReXmM1VJMXbduhbrEzAFLhreqzfDocuSVjGbxQrag==} + vue-i18n@11.1.12: + resolution: {integrity: sha512-BnstPj3KLHLrsqbVU2UOrPmr0+Mv11bsUZG0PyCOzsawCivk8W00GMXHeVUWIDOgNaScCuZah47CZFE+Wnl8mw==} engines: {node: '>= 16'} peerDependencies: vue: ^3.0.0 @@ -2772,33 +2719,27 @@ packages: vue-lazyload@3.0.0: resolution: {integrity: sha512-h2keL/Rj550dLgesgOtXJS9qOiSMmuJNeVlfNAYV1/IYwOQYaWk5mFJlwRxmZDK9YC5gECcFLYYj7z1lKSf9ug==} - vue-reader@1.2.17: - resolution: {integrity: sha512-VeTLTiGTAywj6Ipyr8No9AR177qGYsyl5asEm0Fd7bFjL4GtGiq8PH3iH+eVJKEfw1c0+9cCyw4tyJ62qDYtqw==} - peerDependencies: - '@vue/composition-api': ^1.0.0-rc.1 - vue: ^2.0.0 || >=3.0.0 - peerDependenciesMeta: - '@vue/composition-api': - optional: true + vue-reader@1.3.3: + resolution: {integrity: sha512-Rpd9szXrnlyK1TxBsy/5He8W077ALFxrDLzOiD6HIzsJNj4miKs6nDljj4HdSliKbZ7LYvUMOitW9TL+5J5Ecg==} - vue-router@4.5.1: - resolution: {integrity: sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==} + vue-router@4.6.3: + resolution: {integrity: sha512-ARBedLm9YlbvQomnmq91Os7ck6efydTSpRP3nuOKCvgJOHNrhRoJDSKtee8kcL1Vf7nz6U+PMBL+hTvR3bTVQg==} peerDependencies: - vue: ^3.2.0 + vue: ^3.5.0 vue-toastification@2.0.0-rc.5: resolution: {integrity: sha512-q73e5jy6gucEO/U+P48hqX+/qyXDozAGmaGgLFm5tXX4wJBcVsnGp4e/iJqlm9xzHETYOilUuwOUje2Qg1JdwA==} peerDependencies: vue: ^3.0.2 - vue-tsc@2.2.0: - resolution: {integrity: sha512-gtmM1sUuJ8aSb0KoAFmK9yMxb8TxjewmxqTJ1aKphD5Cbu0rULFY6+UQT51zW7SpUcenfPUuflKyVwyx9Qdnxg==} + vue-tsc@2.2.12: + resolution: {integrity: sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw==} hasBin: true peerDependencies: typescript: '>=5.0.0' - vue@3.5.17: - resolution: {integrity: sha512-LbHV3xPN9BeljML+Xctq4lbz2lVHCR6DtbpTf5XIO6gugpXUN49j2QQPcMj086r9+AkJ0FfUT8xjulKKBkkr9g==} + vue@3.5.24: + resolution: {integrity: sha512-uTHDOpVQTMjcGgrqFPSb8iO2m1DUvo+WbGqoXQz8Y1CeBYQ0FXf2z1gLRaBtHjlRz7zZUBHxjVB5VTLzYkvftg==} peerDependencies: typescript: '*' peerDependenciesMeta: @@ -2894,11 +2835,6 @@ packages: snapshots: - '@ampproject/remapping@2.3.0': - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - '@asamuzakjp/css-color@2.8.3': dependencies: '@csstools/css-calc': 2.1.1(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3) @@ -2907,692 +2843,663 @@ snapshots: '@csstools/css-tokenizer': 3.0.3 lru-cache: 10.4.3 - '@babel/code-frame@7.26.2': + '@babel/code-frame@7.27.1': dependencies: - '@babel/helper-validator-identifier': 7.25.9 + '@babel/helper-validator-identifier': 7.28.5 js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.26.2': {} + '@babel/compat-data@7.28.5': {} - '@babel/core@7.26.0': + '@babel/core@7.28.5': dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.2 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) - '@babel/helpers': 7.26.0 - '@babel/parser': 7.26.2 - '@babel/template': 7.25.9 - '@babel/traverse': 7.25.9 - '@babel/types': 7.26.0 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.5 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helpers': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 - debug: 4.3.7 + debug: 4.4.3 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/generator@7.26.2': + '@babel/generator@7.28.5': dependencies: - '@babel/parser': 7.26.2 - '@babel/types': 7.26.0 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 3.0.2 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 - '@babel/helper-annotate-as-pure@7.25.9': + '@babel/helper-annotate-as-pure@7.27.3': dependencies: - '@babel/types': 7.26.0 + '@babel/types': 7.28.5 - '@babel/helper-builder-binary-assignment-operator-visitor@7.25.9': + '@babel/helper-compilation-targets@7.27.2': dependencies: - '@babel/traverse': 7.25.9 - '@babel/types': 7.26.0 - transitivePeerDependencies: - - supports-color - - '@babel/helper-compilation-targets@7.25.9': - dependencies: - '@babel/compat-data': 7.26.2 - '@babel/helper-validator-option': 7.25.9 - browserslist: 4.24.2 + '@babel/compat-data': 7.28.5 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.28.0 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-create-class-features-plugin@7.25.9(@babel/core@7.26.0)': + '@babel/helper-create-class-features-plugin@7.28.5(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-annotate-as-pure': 7.25.9 - '@babel/helper-member-expression-to-functions': 7.25.9 - '@babel/helper-optimise-call-expression': 7.25.9 - '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.0) - '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 - '@babel/traverse': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.5) + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/traverse': 7.28.5 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/helper-create-regexp-features-plugin@7.25.9(@babel/core@7.26.0)': + '@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-annotate-as-pure': 7.25.9 - regexpu-core: 6.2.0 + '@babel/core': 7.28.5 + '@babel/helper-annotate-as-pure': 7.27.3 + regexpu-core: 6.4.0 semver: 6.3.1 - '@babel/helper-define-polyfill-provider@0.6.3(@babel/core@7.26.0)': + '@babel/helper-define-polyfill-provider@0.6.5(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-plugin-utils': 7.25.9 - debug: 4.3.7 + '@babel/core': 7.28.5 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-plugin-utils': 7.27.1 + debug: 4.4.3 lodash.debounce: 4.0.8 - resolve: 1.22.8 + resolve: 1.22.11 transitivePeerDependencies: - supports-color - '@babel/helper-member-expression-to-functions@7.25.9': + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-member-expression-to-functions@7.28.5': dependencies: - '@babel/traverse': 7.25.9 - '@babel/types': 7.26.0 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/helper-module-imports@7.25.9': + '@babel/helper-module-imports@7.27.1': dependencies: - '@babel/traverse': 7.25.9 - '@babel/types': 7.26.0 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0)': + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-module-imports': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/helper-optimise-call-expression@7.25.9': + '@babel/helper-optimise-call-expression@7.27.1': dependencies: - '@babel/types': 7.26.0 + '@babel/types': 7.28.5 - '@babel/helper-plugin-utils@7.25.9': {} + '@babel/helper-plugin-utils@7.27.1': {} - '@babel/helper-remap-async-to-generator@7.25.9(@babel/core@7.26.0)': + '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-annotate-as-pure': 7.25.9 - '@babel/helper-wrap-function': 7.25.9 - '@babel/traverse': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-wrap-function': 7.28.3 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/helper-replace-supers@7.25.9(@babel/core@7.26.0)': + '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-member-expression-to-functions': 7.25.9 - '@babel/helper-optimise-call-expression': 7.25.9 - '@babel/traverse': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/helper-simple-access@7.25.9': + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': dependencies: - '@babel/traverse': 7.25.9 - '@babel/types': 7.26.0 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/helper-skip-transparent-expression-wrappers@7.25.9': - dependencies: - '@babel/traverse': 7.25.9 - '@babel/types': 7.26.0 - transitivePeerDependencies: - - supports-color - - '@babel/helper-string-parser@7.25.9': {} - '@babel/helper-string-parser@7.27.1': {} - '@babel/helper-validator-identifier@7.25.9': {} + '@babel/helper-validator-identifier@7.28.5': {} - '@babel/helper-validator-identifier@7.27.1': {} + '@babel/helper-validator-option@7.27.1': {} - '@babel/helper-validator-option@7.25.9': {} - - '@babel/helper-wrap-function@7.25.9': + '@babel/helper-wrap-function@7.28.3': dependencies: - '@babel/template': 7.25.9 - '@babel/traverse': 7.25.9 - '@babel/types': 7.26.0 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/helpers@7.26.0': + '@babel/helpers@7.28.4': dependencies: - '@babel/template': 7.25.9 - '@babel/types': 7.26.0 + '@babel/template': 7.27.2 + '@babel/types': 7.28.5 - '@babel/parser@7.26.2': + '@babel/parser@7.28.5': dependencies: - '@babel/types': 7.26.0 + '@babel/types': 7.28.5 - '@babel/parser@7.26.7': + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.28.5)': dependencies: - '@babel/types': 7.26.7 - - '@babel/parser@7.28.0': - dependencies: - '@babel/types': 7.28.1 - - '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/traverse': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 - '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.0) + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-transform-optional-chaining': 7.28.5(@babel/core@7.28.5) transitivePeerDependencies: - supports-color - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.3(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/traverse': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.0)': + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 + '@babel/core': 7.28.5 - '@babel/plugin-syntax-import-assertions@7.26.0(@babel/core@7.26.0)': + '@babel/plugin-syntax-import-assertions@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.0)': + '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.26.0)': + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-arrow-functions@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-async-generator-functions@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-async-generator-functions@7.28.0(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.0) - '@babel/traverse': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.5) + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-async-to-generator@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-module-imports': 7.25.9 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.0) + '@babel/core': 7.28.5 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.5) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-block-scoped-functions@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-block-scoping@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-block-scoping@7.28.5(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-class-properties@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-class-static-block@7.26.0(@babel/core@7.26.0)': + '@babel/plugin-transform-class-static-block@7.28.3(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-classes@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-classes@7.28.4(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-annotate-as-pure': 7.25.9 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.0) - '@babel/traverse': 7.25.9 - globals: 11.12.0 + '@babel/core': 7.28.5 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-globals': 7.28.0 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.5) + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-computed-properties@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-computed-properties@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/template': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/template': 7.27.2 - '@babel/plugin-transform-destructuring@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-transform-dotall-regex@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-transform-duplicate-keys@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-transform-dynamic-import@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-transform-exponentiation-operator@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-builder-binary-assignment-operator-visitor': 7.25.9 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-export-namespace-from@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-dotall-regex@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-for-of@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-explicit-resource-management@7.28.0(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.5) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-function-name@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-exponentiation-operator@7.28.5(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/traverse': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-json-strings@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-transform-literals@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-transform-logical-assignment-operators@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-transform-member-expression-literals@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-transform-modules-amd@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-commonjs@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-json-strings@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-simple-access': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-literals@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-logical-assignment-operators@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-systemjs@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-modules-umd@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-modules-systemjs@7.28.5(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-named-capturing-groups-regex@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-transform-new-target@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-transform-nullish-coalescing-operator@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-transform-numeric-separator@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-transform-object-rest-spread@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.0) - - '@babel/plugin-transform-object-super@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.0) + '@babel/core': 7.28.5 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-optional-catch-binding@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-optional-chaining@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-nullish-coalescing-operator@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-numeric-separator@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-object-rest-spread@7.28.4(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.5) + '@babel/traverse': 7.28.5 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-parameters@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-transform-private-methods@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.5) transitivePeerDependencies: - supports-color - '@babel/plugin-transform-private-property-in-object@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-optional-catch-binding@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-annotate-as-pure': 7.25.9 - '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-optional-chaining@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-property-literals@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-regenerator@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-private-methods@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - regenerator-transform: 0.15.2 - - '@babel/plugin-transform-regexp-modifiers@7.26.0(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-transform-reserved-words@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-transform-shorthand-properties@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - - '@babel/plugin-transform-spread@7.25.9(@babel/core@7.26.0)': - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/plugin-transform-sticky-regex@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-template-literals@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-typeof-symbol@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-regenerator@7.28.4(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-unicode-escapes@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-regexp-modifiers@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-unicode-property-regex@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-unicode-regex@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-unicode-sets-regex@7.25.9(@babel/core@7.26.0)': + '@babel/plugin-transform-spread@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0) - '@babel/helper-plugin-utils': 7.25.9 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color - '@babel/preset-env@7.26.0(@babel/core@7.26.0)': + '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/compat-data': 7.26.2 - '@babel/core': 7.26.0 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/helper-validator-option': 7.25.9 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.0) - '@babel/plugin-syntax-import-assertions': 7.26.0(@babel/core@7.26.0) - '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.0) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.26.0) - '@babel/plugin-transform-arrow-functions': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-async-generator-functions': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-async-to-generator': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-block-scoped-functions': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-block-scoping': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-class-properties': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-class-static-block': 7.26.0(@babel/core@7.26.0) - '@babel/plugin-transform-classes': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-computed-properties': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-destructuring': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-dotall-regex': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-duplicate-keys': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-dynamic-import': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-exponentiation-operator': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-export-namespace-from': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-for-of': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-function-name': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-json-strings': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-literals': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-logical-assignment-operators': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-member-expression-literals': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-modules-amd': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-modules-commonjs': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-modules-systemjs': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-modules-umd': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-new-target': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-nullish-coalescing-operator': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-numeric-separator': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-object-rest-spread': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-object-super': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-optional-catch-binding': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-private-methods': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-private-property-in-object': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-property-literals': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-regenerator': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-regexp-modifiers': 7.26.0(@babel/core@7.26.0) - '@babel/plugin-transform-reserved-words': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-shorthand-properties': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-spread': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-sticky-regex': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-template-literals': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-typeof-symbol': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-unicode-escapes': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-unicode-property-regex': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-unicode-regex': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-transform-unicode-sets-regex': 7.25.9(@babel/core@7.26.0) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.26.0) - babel-plugin-polyfill-corejs2: 0.4.12(@babel/core@7.26.0) - babel-plugin-polyfill-corejs3: 0.10.6(@babel/core@7.26.0) - babel-plugin-polyfill-regenerator: 0.6.3(@babel/core@7.26.0) - core-js-compat: 3.39.0 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-unicode-property-regex@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-unicode-sets-regex@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/preset-env@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/compat-data': 7.28.5 + '@babel/core': 7.28.5 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.28.3(@babel/core@7.28.5) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.5) + '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.28.5) + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-async-generator-functions': 7.28.0(@babel/core@7.28.5) + '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-block-scoping': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-class-static-block': 7.28.3(@babel/core@7.28.5) + '@babel/plugin-transform-classes': 7.28.4(@babel/core@7.28.5) + '@babel/plugin-transform-computed-properties': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-dotall-regex': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-explicit-resource-management': 7.28.0(@babel/core@7.28.5) + '@babel/plugin-transform-exponentiation-operator': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-json-strings': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-logical-assignment-operators': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-modules-systemjs': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-object-rest-spread': 7.28.4(@babel/core@7.28.5) + '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-optional-chaining': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.5) + '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-regenerator': 7.28.4(@babel/core@7.28.5) + '@babel/plugin-transform-regexp-modifiers': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-spread': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-unicode-property-regex': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-unicode-sets-regex': 7.27.1(@babel/core@7.28.5) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.28.5) + babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.5) + babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.5) + babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.5) + core-js-compat: 3.46.0 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.26.0)': + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.28.5)': dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - '@babel/types': 7.26.0 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/types': 7.28.5 esutils: 2.0.3 - '@babel/runtime@7.26.0': - dependencies: - regenerator-runtime: 0.14.1 + '@babel/runtime@7.28.4': {} - '@babel/runtime@7.26.7': + '@babel/template@7.27.2': dependencies: - regenerator-runtime: 0.14.1 + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 - '@babel/template@7.25.9': + '@babel/traverse@7.28.5': dependencies: - '@babel/code-frame': 7.26.2 - '@babel/parser': 7.26.2 - '@babel/types': 7.26.0 - - '@babel/traverse@7.25.9': - dependencies: - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.2 - '@babel/parser': 7.26.2 - '@babel/template': 7.25.9 - '@babel/types': 7.26.0 - debug: 4.3.7 - globals: 11.12.0 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.5 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.5 + '@babel/template': 7.27.2 + '@babel/types': 7.28.5 + debug: 4.4.3 transitivePeerDependencies: - supports-color - '@babel/types@7.26.0': - dependencies: - '@babel/helper-string-parser': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - - '@babel/types@7.26.7': - dependencies: - '@babel/helper-string-parser': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - - '@babel/types@7.28.1': + '@babel/types@7.28.5': dependencies: '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 - '@chenfengyuan/vue-number-input@2.0.1(vue@3.5.17(typescript@5.6.3))': + '@chenfengyuan/vue-number-input@2.0.1(vue@3.5.24(typescript@5.6.3))': dependencies: - vue: 3.5.17(typescript@5.6.3) + vue: 3.5.24(typescript@5.6.3) '@csstools/color-helpers@5.0.1': {} @@ -3692,73 +3599,73 @@ snapshots: '@esbuild/win32-x64@0.25.11': optional: true - '@eslint-community/eslint-utils@4.4.1(eslint@9.31.0)': + '@eslint-community/eslint-utils@4.4.1(eslint@9.39.1)': dependencies: - eslint: 9.31.0 + eslint: 9.39.1 eslint-visitor-keys: 3.4.3 - '@eslint-community/eslint-utils@4.7.0(eslint@9.31.0)': + '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1)': dependencies: - eslint: 9.31.0 + eslint: 9.39.1 eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.12.1': {} + '@eslint-community/regexpp@4.12.2': {} - '@eslint/config-array@0.21.0': + '@eslint/config-array@0.21.1': dependencies: - '@eslint/object-schema': 2.1.6 - debug: 4.4.0 + '@eslint/object-schema': 2.1.7 + debug: 4.4.3 minimatch: 3.1.2 transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.3.0': {} + '@eslint/config-helpers@0.4.2': + dependencies: + '@eslint/core': 0.17.0 - '@eslint/core@0.15.1': + '@eslint/core@0.17.0': dependencies: '@types/json-schema': 7.0.15 '@eslint/eslintrc@3.3.1': dependencies: ajv: 6.12.6 - debug: 4.4.0 + debug: 4.4.3 espree: 10.4.0 globals: 14.0.0 ignore: 5.3.2 - import-fresh: 3.3.0 + import-fresh: 3.3.1 js-yaml: 4.1.0 minimatch: 3.1.2 strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color - '@eslint/js@9.31.0': {} + '@eslint/js@9.39.1': {} - '@eslint/object-schema@2.1.6': {} + '@eslint/object-schema@2.1.7': {} - '@eslint/plugin-kit@0.3.3': + '@eslint/plugin-kit@0.4.1': dependencies: - '@eslint/core': 0.15.1 + '@eslint/core': 0.17.0 levn: 0.4.1 '@humanfs/core@0.19.1': {} - '@humanfs/node@0.16.6': + '@humanfs/node@0.16.7': dependencies: '@humanfs/core': 0.19.1 - '@humanwhocodes/retry': 0.3.1 + '@humanwhocodes/retry': 0.4.3 '@humanwhocodes/module-importer@1.0.1': {} - '@humanwhocodes/retry@0.3.1': {} - '@humanwhocodes/retry@0.4.3': {} - '@intlify/bundle-utils@10.0.1(vue-i18n@11.1.10(vue@3.5.17(typescript@5.6.3)))': + '@intlify/bundle-utils@10.0.1(vue-i18n@11.1.12(vue@3.5.24(typescript@5.6.3)))': dependencies: '@intlify/message-compiler': 11.1.2 '@intlify/shared': 11.1.7 - acorn: 8.14.0 + acorn: 8.15.0 escodegen: 2.1.0 estree-walker: 2.0.2 jsonc-eslint-parser: 2.4.0 @@ -3766,16 +3673,16 @@ snapshots: source-map-js: 1.2.1 yaml-eslint-parser: 1.2.3 optionalDependencies: - vue-i18n: 11.1.10(vue@3.5.17(typescript@5.6.3)) + vue-i18n: 11.1.12(vue@3.5.24(typescript@5.6.3)) - '@intlify/core-base@11.1.10': + '@intlify/core-base@11.1.12': dependencies: - '@intlify/message-compiler': 11.1.10 - '@intlify/shared': 11.1.10 + '@intlify/message-compiler': 11.1.12 + '@intlify/shared': 11.1.12 - '@intlify/message-compiler@11.1.10': + '@intlify/message-compiler@11.1.12': dependencies: - '@intlify/shared': 11.1.10 + '@intlify/shared': 11.1.12 source-map-js: 1.2.1 '@intlify/message-compiler@11.1.2': @@ -3783,18 +3690,18 @@ snapshots: '@intlify/shared': 11.1.2 source-map-js: 1.2.1 - '@intlify/shared@11.1.10': {} + '@intlify/shared@11.1.12': {} '@intlify/shared@11.1.2': {} '@intlify/shared@11.1.7': {} - '@intlify/unplugin-vue-i18n@6.0.8(@vue/compiler-dom@3.5.17)(eslint@9.31.0)(rollup@4.52.5)(typescript@5.6.3)(vue-i18n@11.1.10(vue@3.5.17(typescript@5.6.3)))(vue@3.5.17(typescript@5.6.3))': + '@intlify/unplugin-vue-i18n@6.0.8(@vue/compiler-dom@3.5.24)(eslint@9.39.1)(rollup@4.52.5)(typescript@5.6.3)(vue-i18n@11.1.12(vue@3.5.24(typescript@5.6.3)))(vue@3.5.24(typescript@5.6.3))': dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.31.0) - '@intlify/bundle-utils': 10.0.1(vue-i18n@11.1.10(vue@3.5.17(typescript@5.6.3))) + '@eslint-community/eslint-utils': 4.4.1(eslint@9.39.1) + '@intlify/bundle-utils': 10.0.1(vue-i18n@11.1.12(vue@3.5.24(typescript@5.6.3))) '@intlify/shared': 11.1.7 - '@intlify/vue-i18n-extensions': 8.0.0(@intlify/shared@11.1.7)(@vue/compiler-dom@3.5.17)(vue-i18n@11.1.10(vue@3.5.17(typescript@5.6.3)))(vue@3.5.17(typescript@5.6.3)) + '@intlify/vue-i18n-extensions': 8.0.0(@intlify/shared@11.1.7)(@vue/compiler-dom@3.5.24)(vue-i18n@11.1.12(vue@3.5.24(typescript@5.6.3)))(vue@3.5.24(typescript@5.6.3)) '@rollup/pluginutils': 5.1.4(rollup@4.52.5) '@typescript-eslint/scope-manager': 8.21.0 '@typescript-eslint/typescript-estree': 8.21.0(typescript@5.6.3) @@ -3806,9 +3713,9 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 unplugin: 1.16.1 - vue: 3.5.17(typescript@5.6.3) + vue: 3.5.24(typescript@5.6.3) optionalDependencies: - vue-i18n: 11.1.10(vue@3.5.17(typescript@5.6.3)) + vue-i18n: 11.1.12(vue@3.5.24(typescript@5.6.3)) transitivePeerDependencies: - '@vue/compiler-dom' - eslint @@ -3816,42 +3723,38 @@ snapshots: - supports-color - typescript - '@intlify/vue-i18n-extensions@8.0.0(@intlify/shared@11.1.7)(@vue/compiler-dom@3.5.17)(vue-i18n@11.1.10(vue@3.5.17(typescript@5.6.3)))(vue@3.5.17(typescript@5.6.3))': + '@intlify/vue-i18n-extensions@8.0.0(@intlify/shared@11.1.7)(@vue/compiler-dom@3.5.24)(vue-i18n@11.1.12(vue@3.5.24(typescript@5.6.3)))(vue@3.5.24(typescript@5.6.3))': dependencies: - '@babel/parser': 7.26.7 + '@babel/parser': 7.28.5 optionalDependencies: '@intlify/shared': 11.1.7 - '@vue/compiler-dom': 3.5.17 - vue: 3.5.17(typescript@5.6.3) - vue-i18n: 11.1.10(vue@3.5.17(typescript@5.6.3)) + '@vue/compiler-dom': 3.5.24 + vue: 3.5.24(typescript@5.6.3) + vue-i18n: 11.1.12(vue@3.5.24(typescript@5.6.3)) - '@jridgewell/gen-mapping@0.3.5': + '@jridgewell/gen-mapping@0.3.13': dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 - '@jridgewell/gen-mapping@0.3.8': + '@jridgewell/remapping@2.3.5': dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 '@jridgewell/resolve-uri@3.1.2': {} - '@jridgewell/set-array@1.2.1': {} - - '@jridgewell/source-map@0.3.6': + '@jridgewell/source-map@0.3.11': dependencies: - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 - '@jridgewell/sourcemap-codec@1.5.0': {} + '@jridgewell/sourcemap-codec@1.5.5': {} - '@jridgewell/trace-mapping@0.3.25': + '@jridgewell/trace-mapping@0.3.31': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.5 '@nodelib/fs.scandir@2.1.5': dependencies: @@ -3865,23 +3768,23 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.18.0 - '@pkgr/core@0.2.7': {} + '@pkgr/core@0.2.9': {} - '@playwright/test@1.54.1': + '@playwright/test@1.56.1': dependencies: - playwright: 1.54.1 + playwright: 1.56.1 - '@rollup/pluginutils@5.1.3(rollup@4.52.5)': + '@rollup/pluginutils@5.1.4(rollup@4.52.5)': dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.8 estree-walker: 2.0.2 picomatch: 4.0.3 optionalDependencies: rollup: 4.52.5 - '@rollup/pluginutils@5.1.4(rollup@4.52.5)': + '@rollup/pluginutils@5.3.0(rollup@4.52.5)': dependencies: - '@types/estree': 1.0.7 + '@types/estree': 1.0.8 estree-walker: 2.0.2 picomatch: 4.0.3 optionalDependencies: @@ -3955,10 +3858,6 @@ snapshots: '@tsconfig/node22@22.0.2': {} - '@types/estree@1.0.6': {} - - '@types/estree@1.0.7': {} - '@types/estree@1.0.8': {} '@types/json-schema@7.0.15': {} @@ -3973,24 +3872,24 @@ snapshots: '@types/lodash@4.17.13': {} - '@types/node@22.10.10': + '@types/node@22.19.1': dependencies: - undici-types: 6.20.0 + undici-types: 6.21.0 '@types/trusted-types@2.0.7': optional: true - '@types/web-bluetooth@0.0.20': {} + '@types/web-bluetooth@0.0.21': {} - '@typescript-eslint/eslint-plugin@8.37.0(@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.6.3))(eslint@9.31.0)(typescript@5.6.3)': + '@typescript-eslint/eslint-plugin@8.37.0(@typescript-eslint/parser@8.37.0(eslint@9.39.1)(typescript@5.6.3))(eslint@9.39.1)(typescript@5.6.3)': dependencies: - '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.37.0(eslint@9.31.0)(typescript@5.6.3) + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.37.0(eslint@9.39.1)(typescript@5.6.3) '@typescript-eslint/scope-manager': 8.37.0 - '@typescript-eslint/type-utils': 8.37.0(eslint@9.31.0)(typescript@5.6.3) - '@typescript-eslint/utils': 8.37.0(eslint@9.31.0)(typescript@5.6.3) + '@typescript-eslint/type-utils': 8.37.0(eslint@9.39.1)(typescript@5.6.3) + '@typescript-eslint/utils': 8.37.0(eslint@9.39.1)(typescript@5.6.3) '@typescript-eslint/visitor-keys': 8.37.0 - eslint: 9.31.0 + eslint: 9.39.1 graphemer: 1.4.0 ignore: 7.0.5 natural-compare: 1.4.0 @@ -3999,14 +3898,31 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.6.3)': + '@typescript-eslint/eslint-plugin@8.46.4(@typescript-eslint/parser@8.37.0(eslint@9.39.1)(typescript@5.6.3))(eslint@9.39.1)(typescript@5.6.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.37.0(eslint@9.39.1)(typescript@5.6.3) + '@typescript-eslint/scope-manager': 8.46.4 + '@typescript-eslint/type-utils': 8.46.4(eslint@9.39.1)(typescript@5.6.3) + '@typescript-eslint/utils': 8.46.4(eslint@9.39.1)(typescript@5.6.3) + '@typescript-eslint/visitor-keys': 8.46.4 + eslint: 9.39.1 + graphemer: 1.4.0 + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.1.0(typescript@5.6.3) + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.37.0(eslint@9.39.1)(typescript@5.6.3)': dependencies: '@typescript-eslint/scope-manager': 8.37.0 '@typescript-eslint/types': 8.37.0 '@typescript-eslint/typescript-estree': 8.37.0(typescript@5.6.3) '@typescript-eslint/visitor-keys': 8.37.0 - debug: 4.4.0 - eslint: 9.31.0 + debug: 4.4.3 + eslint: 9.39.1 typescript: 5.6.3 transitivePeerDependencies: - supports-color @@ -4015,7 +3931,16 @@ snapshots: dependencies: '@typescript-eslint/tsconfig-utils': 8.37.0(typescript@5.6.3) '@typescript-eslint/types': 8.37.0 - debug: 4.4.0 + debug: 4.4.3 + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.46.4(typescript@5.6.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.46.4(typescript@5.6.3) + '@typescript-eslint/types': 8.46.4 + debug: 4.4.3 typescript: 5.6.3 transitivePeerDependencies: - supports-color @@ -4030,17 +3955,38 @@ snapshots: '@typescript-eslint/types': 8.37.0 '@typescript-eslint/visitor-keys': 8.37.0 + '@typescript-eslint/scope-manager@8.46.4': + dependencies: + '@typescript-eslint/types': 8.46.4 + '@typescript-eslint/visitor-keys': 8.46.4 + '@typescript-eslint/tsconfig-utils@8.37.0(typescript@5.6.3)': dependencies: typescript: 5.6.3 - '@typescript-eslint/type-utils@8.37.0(eslint@9.31.0)(typescript@5.6.3)': + '@typescript-eslint/tsconfig-utils@8.46.4(typescript@5.6.3)': + dependencies: + typescript: 5.6.3 + + '@typescript-eslint/type-utils@8.37.0(eslint@9.39.1)(typescript@5.6.3)': dependencies: '@typescript-eslint/types': 8.37.0 '@typescript-eslint/typescript-estree': 8.37.0(typescript@5.6.3) - '@typescript-eslint/utils': 8.37.0(eslint@9.31.0)(typescript@5.6.3) - debug: 4.4.0 - eslint: 9.31.0 + '@typescript-eslint/utils': 8.37.0(eslint@9.39.1)(typescript@5.6.3) + debug: 4.4.3 + eslint: 9.39.1 + ts-api-utils: 2.1.0(typescript@5.6.3) + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/type-utils@8.46.4(eslint@9.39.1)(typescript@5.6.3)': + dependencies: + '@typescript-eslint/types': 8.46.4 + '@typescript-eslint/typescript-estree': 8.46.4(typescript@5.6.3) + '@typescript-eslint/utils': 8.46.4(eslint@9.39.1)(typescript@5.6.3) + debug: 4.4.3 + eslint: 9.39.1 ts-api-utils: 2.1.0(typescript@5.6.3) typescript: 5.6.3 transitivePeerDependencies: @@ -4050,6 +3996,8 @@ snapshots: '@typescript-eslint/types@8.37.0': {} + '@typescript-eslint/types@8.46.4': {} + '@typescript-eslint/typescript-estree@8.21.0(typescript@5.6.3)': dependencies: '@typescript-eslint/types': 8.21.0 @@ -4058,8 +4006,8 @@ snapshots: fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 - semver: 7.6.3 - ts-api-utils: 2.0.0(typescript@5.6.3) + semver: 7.7.3 + ts-api-utils: 2.1.0(typescript@5.6.3) typescript: 5.6.3 transitivePeerDependencies: - supports-color @@ -4070,23 +4018,50 @@ snapshots: '@typescript-eslint/tsconfig-utils': 8.37.0(typescript@5.6.3) '@typescript-eslint/types': 8.37.0 '@typescript-eslint/visitor-keys': 8.37.0 - debug: 4.4.0 + debug: 4.4.3 fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 - semver: 7.6.3 + semver: 7.7.3 ts-api-utils: 2.1.0(typescript@5.6.3) typescript: 5.6.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.37.0(eslint@9.31.0)(typescript@5.6.3)': + '@typescript-eslint/typescript-estree@8.46.4(typescript@5.6.3)': dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0) + '@typescript-eslint/project-service': 8.46.4(typescript@5.6.3) + '@typescript-eslint/tsconfig-utils': 8.46.4(typescript@5.6.3) + '@typescript-eslint/types': 8.46.4 + '@typescript-eslint/visitor-keys': 8.46.4 + debug: 4.4.3 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.3 + ts-api-utils: 2.1.0(typescript@5.6.3) + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.37.0(eslint@9.39.1)(typescript@5.6.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) '@typescript-eslint/scope-manager': 8.37.0 '@typescript-eslint/types': 8.37.0 '@typescript-eslint/typescript-estree': 8.37.0(typescript@5.6.3) - eslint: 9.31.0 + eslint: 9.39.1 + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.46.4(eslint@9.39.1)(typescript@5.6.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + '@typescript-eslint/scope-manager': 8.46.4 + '@typescript-eslint/types': 8.46.4 + '@typescript-eslint/typescript-estree': 8.46.4(typescript@5.6.3) + eslint: 9.39.1 typescript: 5.6.3 transitivePeerDependencies: - supports-color @@ -4094,109 +4069,101 @@ snapshots: '@typescript-eslint/visitor-keys@8.21.0': dependencies: '@typescript-eslint/types': 8.21.0 - eslint-visitor-keys: 4.2.0 + eslint-visitor-keys: 4.2.1 '@typescript-eslint/visitor-keys@8.37.0': dependencies: '@typescript-eslint/types': 8.37.0 eslint-visitor-keys: 4.2.1 - '@videojs/http-streaming@3.17.0(video.js@8.23.3)': + '@typescript-eslint/visitor-keys@8.46.4': dependencies: - '@babel/runtime': 7.26.7 + '@typescript-eslint/types': 8.46.4 + eslint-visitor-keys: 4.2.1 + + '@videojs/http-streaming@3.17.2(video.js@8.23.4)': + dependencies: + '@babel/runtime': 7.28.4 '@videojs/vhs-utils': 4.1.1 aes-decrypter: 4.0.2 global: 4.4.0 m3u8-parser: 7.2.0 mpd-parser: 1.3.1 mux.js: 7.1.0 - video.js: 8.23.3 + video.js: 8.23.4 '@videojs/vhs-utils@4.1.1': dependencies: - '@babel/runtime': 7.26.7 + '@babel/runtime': 7.28.4 global: 4.4.0 '@videojs/xhr@2.7.0': dependencies: - '@babel/runtime': 7.26.7 + '@babel/runtime': 7.28.4 global: 4.4.0 is-function: 1.0.2 - '@vitejs/plugin-legacy@6.0.0(terser@5.43.1)(vite@6.4.1(@types/node@22.10.10)(terser@5.43.1)(yaml@2.7.0))': + '@vitejs/plugin-legacy@6.1.1(terser@5.44.1)(vite@6.4.1(@types/node@22.19.1)(terser@5.44.1)(yaml@2.7.0))': dependencies: - '@babel/core': 7.26.0 - '@babel/preset-env': 7.26.0(@babel/core@7.26.0) - browserslist: 4.24.2 - browserslist-to-esbuild: 2.1.1(browserslist@4.24.2) - core-js: 3.44.0 - magic-string: 0.30.14 + '@babel/core': 7.28.5 + '@babel/preset-env': 7.28.5(@babel/core@7.28.5) + browserslist: 4.28.0 + browserslist-to-esbuild: 2.1.1(browserslist@4.28.0) + core-js: 3.46.0 + magic-string: 0.30.21 regenerator-runtime: 0.14.1 systemjs: 6.15.1 - terser: 5.43.1 - vite: 6.4.1(@types/node@22.10.10)(terser@5.43.1)(yaml@2.7.0) + terser: 5.44.1 + vite: 6.4.1(@types/node@22.19.1)(terser@5.44.1)(yaml@2.7.0) transitivePeerDependencies: - supports-color - '@vitejs/plugin-vue@5.2.1(vite@6.4.1(@types/node@22.10.10)(terser@5.43.1)(yaml@2.7.0))(vue@3.5.17(typescript@5.6.3))': + '@vitejs/plugin-vue@5.2.4(vite@6.4.1(@types/node@22.19.1)(terser@5.44.1)(yaml@2.7.0))(vue@3.5.24(typescript@5.6.3))': dependencies: - vite: 6.4.1(@types/node@22.10.10)(terser@5.43.1)(yaml@2.7.0) - vue: 3.5.17(typescript@5.6.3) + vite: 6.4.1(@types/node@22.19.1)(terser@5.44.1)(yaml@2.7.0) + vue: 3.5.24(typescript@5.6.3) - '@volar/language-core@2.4.11': + '@volar/language-core@2.4.15': dependencies: - '@volar/source-map': 2.4.11 + '@volar/source-map': 2.4.15 - '@volar/source-map@2.4.11': {} + '@volar/source-map@2.4.15': {} - '@volar/typescript@2.4.11': + '@volar/typescript@2.4.15': dependencies: - '@volar/language-core': 2.4.11 + '@volar/language-core': 2.4.15 path-browserify: 1.0.1 - vscode-uri: 3.0.8 + vscode-uri: 3.1.0 - '@vue/compiler-core@3.5.13': + '@vue/compiler-core@3.5.24': dependencies: - '@babel/parser': 7.26.2 - '@vue/shared': 3.5.13 + '@babel/parser': 7.28.5 + '@vue/shared': 3.5.24 entities: 4.5.0 estree-walker: 2.0.2 source-map-js: 1.2.1 - '@vue/compiler-core@3.5.17': + '@vue/compiler-dom@3.5.24': dependencies: - '@babel/parser': 7.28.0 - '@vue/shared': 3.5.17 - entities: 4.5.0 + '@vue/compiler-core': 3.5.24 + '@vue/shared': 3.5.24 + + '@vue/compiler-sfc@3.5.24': + dependencies: + '@babel/parser': 7.28.5 + '@vue/compiler-core': 3.5.24 + '@vue/compiler-dom': 3.5.24 + '@vue/compiler-ssr': 3.5.24 + '@vue/shared': 3.5.24 estree-walker: 2.0.2 - source-map-js: 1.2.1 - - '@vue/compiler-dom@3.5.13': - dependencies: - '@vue/compiler-core': 3.5.13 - '@vue/shared': 3.5.13 - - '@vue/compiler-dom@3.5.17': - dependencies: - '@vue/compiler-core': 3.5.17 - '@vue/shared': 3.5.17 - - '@vue/compiler-sfc@3.5.17': - dependencies: - '@babel/parser': 7.28.0 - '@vue/compiler-core': 3.5.17 - '@vue/compiler-dom': 3.5.17 - '@vue/compiler-ssr': 3.5.17 - '@vue/shared': 3.5.17 - estree-walker: 2.0.2 - magic-string: 0.30.17 + magic-string: 0.30.21 postcss: 8.5.6 source-map-js: 1.2.1 - '@vue/compiler-ssr@3.5.17': + '@vue/compiler-ssr@3.5.24': dependencies: - '@vue/compiler-dom': 3.5.17 - '@vue/shared': 3.5.17 + '@vue/compiler-dom': 3.5.24 + '@vue/shared': 3.5.24 '@vue/compiler-vue2@2.7.16': dependencies: @@ -4205,121 +4172,113 @@ snapshots: '@vue/devtools-api@6.6.4': {} - '@vue/eslint-config-prettier@10.2.0(eslint@9.31.0)(prettier@3.6.2)': + '@vue/eslint-config-prettier@10.2.0(eslint@9.39.1)(prettier@3.6.2)': dependencies: - eslint: 9.31.0 - eslint-config-prettier: 10.1.5(eslint@9.31.0) - eslint-plugin-prettier: 5.5.1(eslint-config-prettier@10.1.5(eslint@9.31.0))(eslint@9.31.0)(prettier@3.6.2) + eslint: 9.39.1 + eslint-config-prettier: 10.1.8(eslint@9.39.1) + eslint-plugin-prettier: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.39.1))(eslint@9.39.1)(prettier@3.6.2) prettier: 3.6.2 transitivePeerDependencies: - '@types/eslint' - '@vue/eslint-config-typescript@14.6.0(eslint-plugin-vue@9.32.0(eslint@9.31.0))(eslint@9.31.0)(typescript@5.6.3)': + '@vue/eslint-config-typescript@14.6.0(eslint-plugin-vue@9.33.0(eslint@9.39.1))(eslint@9.39.1)(typescript@5.6.3)': dependencies: - '@typescript-eslint/utils': 8.37.0(eslint@9.31.0)(typescript@5.6.3) - eslint: 9.31.0 - eslint-plugin-vue: 9.32.0(eslint@9.31.0) + '@typescript-eslint/utils': 8.37.0(eslint@9.39.1)(typescript@5.6.3) + eslint: 9.39.1 + eslint-plugin-vue: 9.33.0(eslint@9.39.1) fast-glob: 3.3.3 - typescript-eslint: 8.37.0(eslint@9.31.0)(typescript@5.6.3) - vue-eslint-parser: 10.2.0(eslint@9.31.0) + typescript-eslint: 8.37.0(eslint@9.39.1)(typescript@5.6.3) + vue-eslint-parser: 10.2.0(eslint@9.39.1) optionalDependencies: typescript: 5.6.3 transitivePeerDependencies: - supports-color - '@vue/language-core@2.2.0(typescript@5.6.3)': + '@vue/language-core@2.2.12(typescript@5.6.3)': dependencies: - '@volar/language-core': 2.4.11 - '@vue/compiler-dom': 3.5.13 + '@volar/language-core': 2.4.15 + '@vue/compiler-dom': 3.5.24 '@vue/compiler-vue2': 2.7.16 - '@vue/shared': 3.5.13 - alien-signals: 0.4.14 + '@vue/shared': 3.5.24 + alien-signals: 1.0.13 minimatch: 9.0.5 muggle-string: 0.4.1 path-browserify: 1.0.1 optionalDependencies: typescript: 5.6.3 - '@vue/reactivity@3.5.17': + '@vue/reactivity@3.5.24': dependencies: - '@vue/shared': 3.5.17 + '@vue/shared': 3.5.24 - '@vue/runtime-core@3.5.17': + '@vue/runtime-core@3.5.24': dependencies: - '@vue/reactivity': 3.5.17 - '@vue/shared': 3.5.17 + '@vue/reactivity': 3.5.24 + '@vue/shared': 3.5.24 - '@vue/runtime-dom@3.5.17': + '@vue/runtime-dom@3.5.24': dependencies: - '@vue/reactivity': 3.5.17 - '@vue/runtime-core': 3.5.17 - '@vue/shared': 3.5.17 + '@vue/reactivity': 3.5.24 + '@vue/runtime-core': 3.5.24 + '@vue/shared': 3.5.24 csstype: 3.1.3 - '@vue/server-renderer@3.5.17(vue@3.5.17(typescript@5.6.3))': + '@vue/server-renderer@3.5.24(vue@3.5.24(typescript@5.6.3))': dependencies: - '@vue/compiler-ssr': 3.5.17 - '@vue/shared': 3.5.17 - vue: 3.5.17(typescript@5.6.3) + '@vue/compiler-ssr': 3.5.24 + '@vue/shared': 3.5.24 + vue: 3.5.24(typescript@5.6.3) - '@vue/shared@3.5.13': {} + '@vue/shared@3.5.24': {} - '@vue/shared@3.5.17': {} - - '@vue/tsconfig@0.7.0(typescript@5.6.3)(vue@3.5.17(typescript@5.6.3))': + '@vue/tsconfig@0.7.0(typescript@5.6.3)(vue@3.5.24(typescript@5.6.3))': optionalDependencies: typescript: 5.6.3 - vue: 3.5.17(typescript@5.6.3) + vue: 3.5.24(typescript@5.6.3) - '@vueuse/core@12.5.0(typescript@5.6.3)': + '@vueuse/core@12.8.2(typescript@5.6.3)': dependencies: - '@types/web-bluetooth': 0.0.20 - '@vueuse/metadata': 12.5.0 - '@vueuse/shared': 12.5.0(typescript@5.6.3) - vue: 3.5.17(typescript@5.6.3) + '@types/web-bluetooth': 0.0.21 + '@vueuse/metadata': 12.8.2 + '@vueuse/shared': 12.8.2(typescript@5.6.3) + vue: 3.5.24(typescript@5.6.3) transitivePeerDependencies: - typescript - '@vueuse/integrations@12.5.0(focus-trap@7.6.2)(jwt-decode@4.0.0)(typescript@5.6.3)': + '@vueuse/integrations@12.8.2(focus-trap@7.6.2)(jwt-decode@4.0.0)(typescript@5.6.3)': dependencies: - '@vueuse/core': 12.5.0(typescript@5.6.3) - '@vueuse/shared': 12.5.0(typescript@5.6.3) - vue: 3.5.17(typescript@5.6.3) + '@vueuse/core': 12.8.2(typescript@5.6.3) + '@vueuse/shared': 12.8.2(typescript@5.6.3) + vue: 3.5.24(typescript@5.6.3) optionalDependencies: focus-trap: 7.6.2 jwt-decode: 4.0.0 transitivePeerDependencies: - typescript - '@vueuse/metadata@12.5.0': {} + '@vueuse/metadata@12.8.2': {} - '@vueuse/shared@12.5.0(typescript@5.6.3)': + '@vueuse/shared@12.8.2(typescript@5.6.3)': dependencies: - vue: 3.5.17(typescript@5.6.3) + vue: 3.5.24(typescript@5.6.3) transitivePeerDependencies: - typescript '@xmldom/xmldom@0.7.13': {} - '@xmldom/xmldom@0.8.10': {} + '@xmldom/xmldom@0.8.11': {} - ace-builds@1.43.2: {} - - acorn-jsx@5.3.2(acorn@8.14.0): - dependencies: - acorn: 8.14.0 + ace-builds@1.43.4: {} acorn-jsx@5.3.2(acorn@8.15.0): dependencies: acorn: 8.15.0 - acorn@8.14.0: {} - acorn@8.15.0: {} aes-decrypter@4.0.2: dependencies: - '@babel/runtime': 7.26.7 + '@babel/runtime': 7.28.4 '@videojs/vhs-utils': 4.1.1 global: 4.4.0 pkcs7: 1.0.4 @@ -4333,7 +4292,7 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - alien-signals@0.4.14: {} + alien-signals@1.0.13: {} ansi-regex@5.0.1: {} @@ -4343,50 +4302,52 @@ snapshots: argparse@2.0.1: {} - autoprefixer@10.4.21(postcss@8.5.6): + autoprefixer@10.4.22(postcss@8.5.6): dependencies: - browserslist: 4.25.1 - caniuse-lite: 1.0.30001727 - fraction.js: 4.3.7 + browserslist: 4.28.0 + caniuse-lite: 1.0.30001754 + fraction.js: 5.3.4 normalize-range: 0.1.2 picocolors: 1.1.1 postcss: 8.5.6 postcss-value-parser: 4.2.0 - babel-plugin-polyfill-corejs2@0.4.12(@babel/core@7.26.0): + babel-plugin-polyfill-corejs2@0.4.14(@babel/core@7.28.5): dependencies: - '@babel/compat-data': 7.26.2 - '@babel/core': 7.26.0 - '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.0) + '@babel/compat-data': 7.28.5 + '@babel/core': 7.28.5 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.5) semver: 6.3.1 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-corejs3@0.10.6(@babel/core@7.26.0): + babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.28.5): dependencies: - '@babel/core': 7.26.0 - '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.0) - core-js-compat: 3.39.0 + '@babel/core': 7.28.5 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.5) + core-js-compat: 3.46.0 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-regenerator@0.6.3(@babel/core@7.26.0): + babel-plugin-polyfill-regenerator@0.6.5(@babel/core@7.28.5): dependencies: - '@babel/core': 7.26.0 - '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.0) + '@babel/core': 7.28.5 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.5) transitivePeerDependencies: - supports-color balanced-match@1.0.2: {} + baseline-browser-mapping@2.8.26: {} + boolbase@1.0.0: {} - brace-expansion@1.1.11: + brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - brace-expansion@2.0.1: + brace-expansion@2.0.2: dependencies: balanced-match: 1.0.2 @@ -4394,32 +4355,24 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist-to-esbuild@2.1.1(browserslist@4.24.2): + browserslist-to-esbuild@2.1.1(browserslist@4.28.0): dependencies: - browserslist: 4.24.2 + browserslist: 4.28.0 meow: 13.2.0 - browserslist@4.24.2: + browserslist@4.28.0: dependencies: - caniuse-lite: 1.0.30001685 - electron-to-chromium: 1.5.67 - node-releases: 2.0.18 - update-browserslist-db: 1.1.1(browserslist@4.24.2) - - browserslist@4.25.1: - dependencies: - caniuse-lite: 1.0.30001727 - electron-to-chromium: 1.5.183 - node-releases: 2.0.19 - update-browserslist-db: 1.1.3(browserslist@4.25.1) + baseline-browser-mapping: 2.8.26 + caniuse-lite: 1.0.30001754 + electron-to-chromium: 1.5.250 + node-releases: 2.0.27 + update-browserslist-db: 1.1.4(browserslist@4.28.0) buffer-from@1.1.2: {} callsites@3.1.0: {} - caniuse-lite@1.0.30001685: {} - - caniuse-lite@1.0.30001727: {} + caniuse-lite@1.0.30001754: {} chalk@4.1.2: dependencies: @@ -4447,12 +4400,11 @@ snapshots: concat-map@0.0.1: {} - concurrently@9.2.0: + concurrently@9.2.1: dependencies: chalk: 4.1.2 - lodash: 4.17.21 - rxjs: 7.8.1 - shell-quote: 1.8.2 + rxjs: 7.8.2 + shell-quote: 1.8.3 supports-color: 8.1.1 tree-kill: 1.2.2 yargs: 17.7.2 @@ -4461,11 +4413,11 @@ snapshots: convert-source-map@2.0.0: {} - core-js-compat@3.39.0: + core-js-compat@3.46.0: dependencies: - browserslist: 4.24.2 + browserslist: 4.28.0 - core-js@3.44.0: {} + core-js@3.46.0: {} core-util-is@1.0.3: {} @@ -4496,15 +4448,15 @@ snapshots: whatwg-mimetype: 4.0.0 whatwg-url: 14.2.0 - dayjs@1.11.13: {} + dayjs@1.11.19: {} de-indent@1.0.2: {} - debug@4.3.7: + debug@4.4.0: dependencies: ms: 2.1.3 - debug@4.4.0: + debug@4.4.3: dependencies: ms: 2.1.3 @@ -4514,13 +4466,11 @@ snapshots: dom-walk@0.1.2: {} - dompurify@3.2.6: + dompurify@3.3.0: optionalDependencies: '@types/trusted-types': 2.0.7 - electron-to-chromium@1.5.183: {} - - electron-to-chromium@1.5.67: {} + electron-to-chromium@1.5.250: {} emoji-regex@8.0.0: {} @@ -4530,7 +4480,7 @@ snapshots: dependencies: '@types/localforage': 0.0.34 '@xmldom/xmldom': 0.7.13 - core-js: 3.44.0 + core-js: 3.46.0 event-emitter: 0.3.5 jszip: 3.10.1 localforage: 1.10.0 @@ -4597,29 +4547,29 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-config-prettier@10.1.5(eslint@9.31.0): + eslint-config-prettier@10.1.8(eslint@9.39.1): dependencies: - eslint: 9.31.0 + eslint: 9.39.1 - eslint-plugin-prettier@5.5.1(eslint-config-prettier@10.1.5(eslint@9.31.0))(eslint@9.31.0)(prettier@3.6.2): + eslint-plugin-prettier@5.5.4(eslint-config-prettier@10.1.8(eslint@9.39.1))(eslint@9.39.1)(prettier@3.6.2): dependencies: - eslint: 9.31.0 + eslint: 9.39.1 prettier: 3.6.2 prettier-linter-helpers: 1.0.0 - synckit: 0.11.8 + synckit: 0.11.11 optionalDependencies: - eslint-config-prettier: 10.1.5(eslint@9.31.0) + eslint-config-prettier: 10.1.8(eslint@9.39.1) - eslint-plugin-vue@9.32.0(eslint@9.31.0): + eslint-plugin-vue@9.33.0(eslint@9.39.1): dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.31.0) - eslint: 9.31.0 + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + eslint: 9.39.1 globals: 13.24.0 natural-compare: 1.4.0 nth-check: 2.1.1 postcss-selector-parser: 6.1.2 - semver: 7.6.3 - vue-eslint-parser: 9.4.3(eslint@9.31.0) + semver: 7.7.3 + vue-eslint-parser: 9.4.3(eslint@9.39.1) xml-name-validator: 4.0.0 transitivePeerDependencies: - supports-color @@ -4629,11 +4579,6 @@ snapshots: esrecurse: 4.3.0 estraverse: 5.3.0 - eslint-scope@8.2.0: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - eslint-scope@8.4.0: dependencies: esrecurse: 4.3.0 @@ -4641,29 +4586,26 @@ snapshots: eslint-visitor-keys@3.4.3: {} - eslint-visitor-keys@4.2.0: {} - eslint-visitor-keys@4.2.1: {} - eslint@9.31.0: + eslint@9.39.1: dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.31.0) - '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.21.0 - '@eslint/config-helpers': 0.3.0 - '@eslint/core': 0.15.1 + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.21.1 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.31.0 - '@eslint/plugin-kit': 0.3.3 - '@humanfs/node': 0.16.6 + '@eslint/js': 9.39.1 + '@eslint/plugin-kit': 0.4.1 + '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 - '@types/estree': 1.0.7 - '@types/json-schema': 7.0.15 + '@types/estree': 1.0.8 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.0 + debug: 4.4.3 escape-string-regexp: 4.0.0 eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 @@ -4692,12 +4634,6 @@ snapshots: event-emitter: 0.3.5 type: 2.7.3 - espree@10.3.0: - dependencies: - acorn: 8.14.0 - acorn-jsx: 5.3.2(acorn@8.14.0) - eslint-visitor-keys: 4.2.0 - espree@10.4.0: dependencies: acorn: 8.15.0 @@ -4706,8 +4642,8 @@ snapshots: espree@9.6.1: dependencies: - acorn: 8.14.0 - acorn-jsx: 5.3.2(acorn@8.14.0) + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) eslint-visitor-keys: 3.4.3 esprima@4.0.1: {} @@ -4776,16 +4712,16 @@ snapshots: flat-cache@4.0.1: dependencies: - flatted: 3.3.2 + flatted: 3.3.3 keyv: 4.5.4 - flatted@3.3.2: {} + flatted@3.3.3: {} focus-trap@7.6.2: dependencies: - tabbable: 6.2.0 + tabbable: 6.3.0 - fraction.js@4.3.7: {} + fraction.js@5.3.4: {} fsevents@2.3.2: optional: true @@ -4809,11 +4745,9 @@ snapshots: global@4.4.0: dependencies: - min-document: 2.19.0 + min-document: 2.19.2 process: 0.11.10 - globals@11.12.0: {} - globals@13.24.0: dependencies: type-fest: 0.20.2 @@ -4839,14 +4773,14 @@ snapshots: http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.3 - debug: 4.4.0 + debug: 4.4.3 transitivePeerDependencies: - supports-color https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.3 - debug: 4.4.0 + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -4860,7 +4794,7 @@ snapshots: immediate@3.0.6: {} - import-fresh@3.3.0: + import-fresh@3.3.1: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 @@ -4869,7 +4803,7 @@ snapshots: inherits@2.0.4: {} - is-core-module@2.15.1: + is-core-module@2.16.1: dependencies: hasown: 2.0.2 @@ -4893,7 +4827,7 @@ snapshots: isexe@2.0.0: {} - js-base64@3.7.7: {} + js-base64@3.7.8: {} js-tokens@4.0.0: {} @@ -4928,7 +4862,7 @@ snapshots: - supports-color - utf-8-validate - jsesc@3.0.2: {} + jsesc@3.1.0: {} json-buffer@3.0.1: {} @@ -4940,10 +4874,10 @@ snapshots: jsonc-eslint-parser@2.4.0: dependencies: - acorn: 8.14.0 + acorn: 8.15.0 eslint-visitor-keys: 3.4.3 espree: 9.6.1 - semver: 7.6.3 + semver: 7.7.3 jszip@3.10.1: dependencies: @@ -5021,19 +4955,15 @@ snapshots: m3u8-parser@7.2.0: dependencies: - '@babel/runtime': 7.26.7 + '@babel/runtime': 7.28.4 '@videojs/vhs-utils': 4.1.1 global: 4.4.0 - magic-string@0.30.14: + magic-string@0.30.21: dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.5 - magic-string@0.30.17: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 - - marked@15.0.6: {} + marked@15.0.12: {} marks-pane@1.0.9: {} @@ -5048,30 +4978,30 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 - min-document@2.19.0: + min-document@2.19.2: dependencies: dom-walk: 0.1.2 minimatch@3.1.2: dependencies: - brace-expansion: 1.1.11 + brace-expansion: 1.1.12 minimatch@9.0.5: dependencies: - brace-expansion: 2.0.1 + brace-expansion: 2.0.2 mlly@1.7.4: dependencies: - acorn: 8.14.0 + acorn: 8.15.0 pathe: 2.0.2 pkg-types: 1.3.1 ufo: 1.5.4 mpd-parser@1.3.1: dependencies: - '@babel/runtime': 7.26.7 + '@babel/runtime': 7.28.4 '@videojs/vhs-utils': 4.1.1 - '@xmldom/xmldom': 0.8.10 + '@xmldom/xmldom': 0.8.11 global: 4.4.0 ms@2.1.3: {} @@ -5080,7 +5010,7 @@ snapshots: mux.js@7.1.0: dependencies: - '@babel/runtime': 7.26.7 + '@babel/runtime': 7.28.4 global: 4.4.0 nanoid@3.3.11: {} @@ -5089,9 +5019,7 @@ snapshots: next-tick@1.1.0: {} - node-releases@2.0.18: {} - - node-releases@2.0.19: {} + node-releases@2.0.27: {} normalize-range@0.1.2: {} @@ -5150,11 +5078,11 @@ snapshots: picomatch@4.0.3: {} - pinia@2.3.1(typescript@5.6.3)(vue@3.5.17(typescript@5.6.3)): + pinia@2.3.1(typescript@5.6.3)(vue@3.5.24(typescript@5.6.3)): dependencies: '@vue/devtools-api': 6.6.4 - vue: 3.5.17(typescript@5.6.3) - vue-demi: 0.14.10(vue@3.5.17(typescript@5.6.3)) + vue: 3.5.24(typescript@5.6.3) + vue-demi: 0.14.10(vue@3.5.24(typescript@5.6.3)) optionalDependencies: typescript: 5.6.3 transitivePeerDependencies: @@ -5162,7 +5090,7 @@ snapshots: pkcs7@1.0.4: dependencies: - '@babel/runtime': 7.26.7 + '@babel/runtime': 7.28.4 pkg-types@1.3.1: dependencies: @@ -5170,11 +5098,11 @@ snapshots: mlly: 1.7.4 pathe: 2.0.2 - playwright-core@1.54.1: {} + playwright-core@1.56.1: {} - playwright@1.54.1: + playwright@1.56.1: dependencies: - playwright-core: 1.54.1 + playwright-core: 1.56.1 optionalDependencies: fsevents: 2.3.2 @@ -5213,9 +5141,9 @@ snapshots: punycode@2.3.1: {} - qrcode.vue@3.6.0(vue@3.5.17(typescript@5.6.3)): + qrcode.vue@3.6.0(vue@3.5.24(typescript@5.6.3)): dependencies: - vue: 3.5.17(typescript@5.6.3) + vue: 3.5.24(typescript@5.6.3) querystringify@2.2.0: {} @@ -5231,7 +5159,7 @@ snapshots: string_decoder: 1.1.1 util-deprecate: 1.0.2 - regenerate-unicode-properties@10.2.0: + regenerate-unicode-properties@10.2.2: dependencies: regenerate: 1.4.2 @@ -5239,24 +5167,20 @@ snapshots: regenerator-runtime@0.14.1: {} - regenerator-transform@0.15.2: - dependencies: - '@babel/runtime': 7.26.0 - - regexpu-core@6.2.0: + regexpu-core@6.4.0: dependencies: regenerate: 1.4.2 - regenerate-unicode-properties: 10.2.0 + regenerate-unicode-properties: 10.2.2 regjsgen: 0.8.0 - regjsparser: 0.12.0 + regjsparser: 0.13.0 unicode-match-property-ecmascript: 2.0.0 - unicode-match-property-value-ecmascript: 2.2.0 + unicode-match-property-value-ecmascript: 2.2.1 regjsgen@0.8.0: {} - regjsparser@0.12.0: + regjsparser@0.13.0: dependencies: - jsesc: 3.0.2 + jsesc: 3.1.0 require-directory@2.1.1: {} @@ -5264,9 +5188,9 @@ snapshots: resolve-from@4.0.0: {} - resolve@1.22.8: + resolve@1.22.11: dependencies: - is-core-module: 2.15.1 + is-core-module: 2.16.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 @@ -5308,7 +5232,7 @@ snapshots: dependencies: queue-microtask: 1.2.3 - rxjs@7.8.1: + rxjs@7.8.2: dependencies: tslib: 2.8.1 @@ -5322,7 +5246,7 @@ snapshots: semver@6.3.1: {} - semver@7.6.3: {} + semver@7.7.3: {} setimmediate@1.0.5: {} @@ -5332,7 +5256,7 @@ snapshots: shebang-regex@3.0.0: {} - shell-quote@1.8.2: {} + shell-quote@1.8.3: {} signal-exit@3.0.7: {} @@ -5373,20 +5297,20 @@ snapshots: symbol-tree@3.2.4: {} - synckit@0.11.8: + synckit@0.11.11: dependencies: - '@pkgr/core': 0.2.7 + '@pkgr/core': 0.2.9 systemjs@6.15.1: {} - tabbable@6.2.0: {} + tabbable@6.3.0: {} tar-mini@0.2.0: {} - terser@5.43.1: + terser@5.44.1: dependencies: - '@jridgewell/source-map': 0.3.6 - acorn: 8.14.0 + '@jridgewell/source-map': 0.3.11 + acorn: 8.15.0 commander: 2.20.3 source-map-support: 0.5.21 @@ -5415,10 +5339,6 @@ snapshots: tree-kill@1.2.2: {} - ts-api-utils@2.0.0(typescript@5.6.3): - dependencies: - typescript: 5.6.3 - ts-api-utils@2.1.0(typescript@5.6.3): dependencies: typescript: 5.6.3 @@ -5430,7 +5350,7 @@ snapshots: buffer-from: 1.1.2 combine-errors: 3.0.3 is-stream: 2.0.1 - js-base64: 3.7.7 + js-base64: 3.7.8 lodash.throttle: 4.1.1 proper-lockfile: 4.1.2 url-parse: 1.5.10 @@ -5443,13 +5363,13 @@ snapshots: type@2.7.3: {} - typescript-eslint@8.37.0(eslint@9.31.0)(typescript@5.6.3): + typescript-eslint@8.37.0(eslint@9.39.1)(typescript@5.6.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.37.0(@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.6.3))(eslint@9.31.0)(typescript@5.6.3) - '@typescript-eslint/parser': 8.37.0(eslint@9.31.0)(typescript@5.6.3) + '@typescript-eslint/eslint-plugin': 8.37.0(@typescript-eslint/parser@8.37.0(eslint@9.39.1)(typescript@5.6.3))(eslint@9.39.1)(typescript@5.6.3) + '@typescript-eslint/parser': 8.37.0(eslint@9.39.1)(typescript@5.6.3) '@typescript-eslint/typescript-estree': 8.37.0(typescript@5.6.3) - '@typescript-eslint/utils': 8.37.0(eslint@9.31.0)(typescript@5.6.3) - eslint: 9.31.0 + '@typescript-eslint/utils': 8.37.0(eslint@9.39.1)(typescript@5.6.3) + eslint: 9.39.1 typescript: 5.6.3 transitivePeerDependencies: - supports-color @@ -5458,33 +5378,27 @@ snapshots: ufo@1.5.4: {} - undici-types@6.20.0: {} + undici-types@6.21.0: {} unicode-canonical-property-names-ecmascript@2.0.1: {} unicode-match-property-ecmascript@2.0.0: dependencies: unicode-canonical-property-names-ecmascript: 2.0.1 - unicode-property-aliases-ecmascript: 2.1.0 + unicode-property-aliases-ecmascript: 2.2.0 - unicode-match-property-value-ecmascript@2.2.0: {} + unicode-match-property-value-ecmascript@2.2.1: {} - unicode-property-aliases-ecmascript@2.1.0: {} + unicode-property-aliases-ecmascript@2.2.0: {} unplugin@1.16.1: dependencies: - acorn: 8.14.0 + acorn: 8.15.0 webpack-virtual-modules: 0.6.2 - update-browserslist-db@1.1.1(browserslist@4.24.2): + update-browserslist-db@1.1.4(browserslist@4.28.0): dependencies: - browserslist: 4.24.2 - escalade: 3.2.0 - picocolors: 1.1.1 - - update-browserslist-db@1.1.3(browserslist@4.25.1): - dependencies: - browserslist: 4.25.1 + browserslist: 4.28.0 escalade: 3.2.0 picocolors: 1.1.1 @@ -5503,10 +5417,10 @@ snapshots: util-deprecate@1.0.2: {} - video.js@8.23.3: + video.js@8.23.4: dependencies: - '@babel/runtime': 7.26.7 - '@videojs/http-streaming': 3.17.0(video.js@8.23.3) + '@babel/runtime': 7.28.4 + '@videojs/http-streaming': 3.17.2(video.js@8.23.4) '@videojs/vhs-utils': 4.1.1 '@videojs/xhr': 2.7.0 aes-decrypter: 4.0.2 @@ -5514,37 +5428,37 @@ snapshots: m3u8-parser: 7.2.0 mpd-parser: 1.3.1 mux.js: 7.1.0 - videojs-contrib-quality-levels: 4.1.0(video.js@8.23.3) + videojs-contrib-quality-levels: 4.1.0(video.js@8.23.4) videojs-font: 4.2.0 videojs-vtt.js: 0.15.5 - videojs-contrib-quality-levels@4.1.0(video.js@8.23.3): + videojs-contrib-quality-levels@4.1.0(video.js@8.23.4): dependencies: global: 4.4.0 - video.js: 8.23.3 + video.js: 8.23.4 videojs-font@4.2.0: {} videojs-hotkeys@0.2.30: {} - videojs-mobile-ui@1.1.1(video.js@8.23.3): + videojs-mobile-ui@1.1.1(video.js@8.23.4): dependencies: global: 4.4.0 - video.js: 8.23.3 + video.js: 8.23.4 videojs-vtt.js@0.15.5: dependencies: global: 4.4.0 - vite-plugin-compression2@1.3.3(rollup@4.52.5)(vite@6.4.1(@types/node@22.10.10)(terser@5.43.1)(yaml@2.7.0)): + vite-plugin-compression2@1.4.0(rollup@4.52.5)(vite@6.4.1(@types/node@22.19.1)(terser@5.44.1)(yaml@2.7.0)): dependencies: - '@rollup/pluginutils': 5.1.3(rollup@4.52.5) + '@rollup/pluginutils': 5.3.0(rollup@4.52.5) tar-mini: 0.2.0 - vite: 6.4.1(@types/node@22.10.10)(terser@5.43.1)(yaml@2.7.0) + vite: 6.4.1(@types/node@22.19.1)(terser@5.44.1)(yaml@2.7.0) transitivePeerDependencies: - rollup - vite@6.4.1(@types/node@22.10.10)(terser@5.43.1)(yaml@2.7.0): + vite@6.4.1(@types/node@22.19.1)(terser@5.44.1)(yaml@2.7.0): dependencies: esbuild: 0.25.11 fdir: 6.5.0(picomatch@4.0.3) @@ -5553,86 +5467,84 @@ snapshots: rollup: 4.52.5 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 22.10.10 + '@types/node': 22.19.1 fsevents: 2.3.3 - terser: 5.43.1 + terser: 5.44.1 yaml: 2.7.0 - vscode-uri@3.0.8: {} + vscode-uri@3.1.0: {} - vue-demi@0.14.10(vue@3.5.17(typescript@5.6.3)): + vue-demi@0.14.10(vue@3.5.24(typescript@5.6.3)): dependencies: - vue: 3.5.17(typescript@5.6.3) + vue: 3.5.24(typescript@5.6.3) - vue-eslint-parser@10.2.0(eslint@9.31.0): + vue-eslint-parser@10.2.0(eslint@9.39.1): dependencies: - debug: 4.4.0 - eslint: 9.31.0 - eslint-scope: 8.2.0 - eslint-visitor-keys: 4.2.0 - espree: 10.3.0 + debug: 4.4.3 + eslint: 9.39.1 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 esquery: 1.6.0 - semver: 7.6.3 + semver: 7.7.3 transitivePeerDependencies: - supports-color - vue-eslint-parser@9.4.3(eslint@9.31.0): + vue-eslint-parser@9.4.3(eslint@9.39.1): dependencies: - debug: 4.3.7 - eslint: 9.31.0 + debug: 4.4.3 + eslint: 9.39.1 eslint-scope: 7.2.2 eslint-visitor-keys: 3.4.3 espree: 9.6.1 esquery: 1.6.0 lodash: 4.17.21 - semver: 7.6.3 + semver: 7.7.3 transitivePeerDependencies: - supports-color - vue-final-modal@4.5.5(@vueuse/core@12.5.0(typescript@5.6.3))(@vueuse/integrations@12.5.0(focus-trap@7.6.2)(jwt-decode@4.0.0)(typescript@5.6.3))(focus-trap@7.6.2)(vue@3.5.17(typescript@5.6.3)): + vue-final-modal@4.5.5(@vueuse/core@12.8.2(typescript@5.6.3))(@vueuse/integrations@12.8.2(focus-trap@7.6.2)(jwt-decode@4.0.0)(typescript@5.6.3))(focus-trap@7.6.2)(vue@3.5.24(typescript@5.6.3)): dependencies: - '@vueuse/core': 12.5.0(typescript@5.6.3) - '@vueuse/integrations': 12.5.0(focus-trap@7.6.2)(jwt-decode@4.0.0)(typescript@5.6.3) + '@vueuse/core': 12.8.2(typescript@5.6.3) + '@vueuse/integrations': 12.8.2(focus-trap@7.6.2)(jwt-decode@4.0.0)(typescript@5.6.3) focus-trap: 7.6.2 - vue: 3.5.17(typescript@5.6.3) + vue: 3.5.24(typescript@5.6.3) - vue-i18n@11.1.10(vue@3.5.17(typescript@5.6.3)): + vue-i18n@11.1.12(vue@3.5.24(typescript@5.6.3)): dependencies: - '@intlify/core-base': 11.1.10 - '@intlify/shared': 11.1.10 + '@intlify/core-base': 11.1.12 + '@intlify/shared': 11.1.12 '@vue/devtools-api': 6.6.4 - vue: 3.5.17(typescript@5.6.3) + vue: 3.5.24(typescript@5.6.3) vue-lazyload@3.0.0: {} - vue-reader@1.2.17(vue@3.5.17(typescript@5.6.3)): + vue-reader@1.3.3: dependencies: epubjs: 0.3.93 - vue: 3.5.17(typescript@5.6.3) - vue-demi: 0.14.10(vue@3.5.17(typescript@5.6.3)) - vue-router@4.5.1(vue@3.5.17(typescript@5.6.3)): + vue-router@4.6.3(vue@3.5.24(typescript@5.6.3)): dependencies: '@vue/devtools-api': 6.6.4 - vue: 3.5.17(typescript@5.6.3) + vue: 3.5.24(typescript@5.6.3) - vue-toastification@2.0.0-rc.5(vue@3.5.17(typescript@5.6.3)): + vue-toastification@2.0.0-rc.5(vue@3.5.24(typescript@5.6.3)): dependencies: - vue: 3.5.17(typescript@5.6.3) + vue: 3.5.24(typescript@5.6.3) - vue-tsc@2.2.0(typescript@5.6.3): + vue-tsc@2.2.12(typescript@5.6.3): dependencies: - '@volar/typescript': 2.4.11 - '@vue/language-core': 2.2.0(typescript@5.6.3) + '@volar/typescript': 2.4.15 + '@vue/language-core': 2.2.12(typescript@5.6.3) typescript: 5.6.3 - vue@3.5.17(typescript@5.6.3): + vue@3.5.24(typescript@5.6.3): dependencies: - '@vue/compiler-dom': 3.5.17 - '@vue/compiler-sfc': 3.5.17 - '@vue/runtime-dom': 3.5.17 - '@vue/server-renderer': 3.5.17(vue@3.5.17(typescript@5.6.3)) - '@vue/shared': 3.5.17 + '@vue/compiler-dom': 3.5.24 + '@vue/compiler-sfc': 3.5.24 + '@vue/runtime-dom': 3.5.24 + '@vue/server-renderer': 3.5.24(vue@3.5.24(typescript@5.6.3)) + '@vue/shared': 3.5.24 optionalDependencies: typescript: 5.6.3 diff --git a/filebrowser/go.mod b/filebrowser/go.mod index cf005b556d..d7fedced8c 100644 --- a/filebrowser/go.mod +++ b/filebrowser/go.mod @@ -1,10 +1,10 @@ module github.com/filebrowser/filebrowser/v2 -go 1.24 +go 1.25 require ( github.com/asdine/storm/v3 v3.2.1 - github.com/asticode/go-astisub v0.34.0 + github.com/asticode/go-astisub v0.38.0 github.com/disintegration/imaging v1.6.2 github.com/dsoprea/go-exif/v3 v3.0.1 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 @@ -12,22 +12,22 @@ require ( github.com/gorilla/mux v1.8.1 github.com/gorilla/websocket v1.5.3 github.com/jellydator/ttlcache/v3 v3.4.0 - github.com/maruel/natural v1.1.1 + github.com/maruel/natural v1.2.1 github.com/marusama/semaphore/v2 v2.5.0 - github.com/mholt/archives v0.1.3 + github.com/mholt/archives v0.1.5 github.com/mitchellh/go-homedir v1.1.0 github.com/pelletier/go-toml/v2 v2.2.4 github.com/shirou/gopsutil/v3 v3.24.5 - github.com/spf13/afero v1.14.0 - github.com/spf13/cobra v1.9.1 - github.com/spf13/pflag v1.0.6 - github.com/spf13/viper v1.20.1 - github.com/stretchr/testify v1.10.0 + github.com/spf13/afero v1.15.0 + github.com/spf13/cobra v1.10.1 + github.com/spf13/pflag v1.0.10 + github.com/spf13/viper v1.21.0 + github.com/stretchr/testify v1.11.1 github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce - go.etcd.io/bbolt v1.4.2 - golang.org/x/crypto v0.40.0 - golang.org/x/image v0.29.0 - golang.org/x/text v0.27.0 + go.etcd.io/bbolt v1.4.3 + golang.org/x/crypto v0.44.0 + golang.org/x/image v0.33.0 + golang.org/x/text v0.31.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/yaml.v2 v2.4.0 ) @@ -56,22 +56,22 @@ require ( github.com/klauspost/pgzip v1.2.6 // indirect github.com/mikelolasagasti/xz v1.0.1 // indirect github.com/minio/minlz v1.0.1 // indirect - github.com/nwaples/rardecode/v2 v2.1.1 // indirect + github.com/nwaples/rardecode/v2 v2.2.0 // indirect github.com/pierrec/lz4/v4 v4.1.22 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect - github.com/sagikazarmark/locafero v0.9.0 // indirect - github.com/sorairolake/lzip-go v0.3.7 // indirect - github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/cast v1.9.2 // indirect + github.com/sagikazarmark/locafero v0.11.0 // indirect + github.com/sorairolake/lzip-go v0.3.8 // indirect + github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect + github.com/spf13/cast v1.10.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/ulikunitz/xz v0.5.12 // indirect + github.com/ulikunitz/xz v0.5.15 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect - go.uber.org/multierr v1.11.0 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect - golang.org/x/net v0.42.0 // indirect - golang.org/x/sync v0.16.0 // indirect - golang.org/x/sys v0.34.0 // indirect + golang.org/x/net v0.46.0 // indirect + golang.org/x/sync v0.18.0 // indirect + golang.org/x/sys v0.38.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/filebrowser/go.sum b/filebrowser/go.sum index a9ccaa5b46..92d28b3054 100644 --- a/filebrowser/go.sum +++ b/filebrowser/go.sum @@ -31,8 +31,8 @@ github.com/asticode/go-astikit v0.20.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xbl github.com/asticode/go-astikit v0.30.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xblP7fCWbgwipF0= github.com/asticode/go-astikit v0.56.0 h1:DmD2p7YnvxiPdF0h+dRmos3bsejNEXbycENsY5JfBqw= github.com/asticode/go-astikit v0.56.0/go.mod h1:fV43j20UZYfXzP9oBn33udkvCvDvCDhzjVqoLFuuYZE= -github.com/asticode/go-astisub v0.34.0 h1:owKNj0A9pc7YVW/rNy2MJZ1mf0L8DTdklZVfyZDhTWI= -github.com/asticode/go-astisub v0.34.0/go.mod h1:WTkuSzFB+Bp7wezuSf2Oxulj5A8zu2zLRVFf6bIFQK8= +github.com/asticode/go-astisub v0.38.0 h1:Qh3IO8Cotn0wwok5maid7xqsIJTwn2DtABT1UajKJaI= +github.com/asticode/go-astisub v0.38.0/go.mod h1:WTkuSzFB+Bp7wezuSf2Oxulj5A8zu2zLRVFf6bIFQK8= github.com/asticode/go-astits v1.8.0/go.mod h1:DkOWmBNQpnr9mv24KfZjq4JawCFX1FCqjLVGvO0DygQ= github.com/asticode/go-astits v1.13.0 h1:XOgkaadfZODnyZRR5Y0/DWkA9vrkLLPLeeOvDwfKZ1c= github.com/asticode/go-astits v1.13.0/go.mod h1:QSHmknZ51pf6KJdHKZHJTLlMegIrhega3LPWz3ND/iI= @@ -113,9 +113,8 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -167,20 +166,20 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo= -github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg= +github.com/maruel/natural v1.2.1 h1:G/y4pwtTA07lbQsMefvsmEO0VN0NfqpxprxXDM4R/4o= +github.com/maruel/natural v1.2.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg= github.com/marusama/semaphore/v2 v2.5.0 h1:o/1QJD9DBYOWRnDhPwDVAXQn6mQYD0gZaS1Tpx6DJGM= github.com/marusama/semaphore/v2 v2.5.0/go.mod h1:z9nMiNUekt/LTpTUQdpp+4sJeYqUGpwMHfW0Z8V8fnQ= -github.com/mholt/archives v0.1.3 h1:aEAaOtNra78G+TvV5ohmXrJOAzf++dIlYeDW3N9q458= -github.com/mholt/archives v0.1.3/go.mod h1:LUCGp++/IbV/I0Xq4SzcIR6uwgeh2yjnQWamjRQfLTU= +github.com/mholt/archives v0.1.5 h1:Fh2hl1j7VEhc6DZs2DLMgiBNChUux154a1G+2esNvzQ= +github.com/mholt/archives v0.1.5/go.mod h1:3TPMmBLPsgszL+1As5zECTuKwKvIfj6YcwWPpeTAXF4= github.com/mikelolasagasti/xz v1.0.1 h1:Q2F2jX0RYJUG3+WsM+FJknv+6eVjsjXNDV0KJXZzkD0= github.com/mikelolasagasti/xz v1.0.1/go.mod h1:muAirjiOUxPRXwm9HdDtB3uoRPrGnL85XHtokL9Hcgc= github.com/minio/minlz v1.0.1 h1:OUZUzXcib8diiX+JYxyRLIdomyZYzHct6EShOKtQY2A= github.com/minio/minlz v1.0.1/go.mod h1:qT0aEB35q79LLornSzeDH75LBf3aH1MV+jB5w9Wasec= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/nwaples/rardecode/v2 v2.1.1 h1:OJaYalXdliBUXPmC8CZGQ7oZDxzX1/5mQmgn0/GASew= -github.com/nwaples/rardecode/v2 v2.1.1/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw= +github.com/nwaples/rardecode/v2 v2.2.0 h1:4ufPGHiNe1rYJxYfehALLjup4Ls3ck42CWwjKiOqu0A= +github.com/nwaples/rardecode/v2 v2.2.0/go.mod h1:7uz379lSxPe6j9nvzxUZ+n7mnJNgjsRNb6IbvGVHRmw= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= @@ -193,28 +192,29 @@ github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= -github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= -github.com/sagikazarmark/locafero v0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k= -github.com/sagikazarmark/locafero v0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk= +github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= +github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= -github.com/sorairolake/lzip-go v0.3.7 h1:vP2uiD/NoklLyzYMdgOWkZME0ulkSfVTTE4MNRKCwNs= -github.com/sorairolake/lzip-go v0.3.7/go.mod h1:THOHr0FlNVCw2eOIEE9shFJAG1QxQg/pf2XUPAmNIqg= -github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= -github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= -github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= -github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE= -github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= -github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= -github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= -github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= +github.com/sorairolake/lzip-go v0.3.8 h1:j5Q2313INdTA80ureWYRhX+1K78mUXfMoPZCw/ivWik= +github.com/sorairolake/lzip-go v0.3.8/go.mod h1:JcBqGMV0frlxwrsE9sMWXDjqn3EeVf0/54YPsw66qkU= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= +github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= +github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= +github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -225,15 +225,15 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce h1:fb190+cK2Xz/dvi9Hv8eCYJYvIGUTN2/KLq1pT6CjEc= github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= -github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= +github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= @@ -242,16 +242,16 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/bbolt v1.4.2 h1:IrUHp260R8c+zYx/Tm8QZr04CX+qWS5PGfPdevhdm1I= -go.etcd.io/bbolt v1.4.2/go.mod h1:Is8rSHO/b4f3XigBC0lL0+4FwAQv3HXEEIgFMuKHceM= +go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo= +go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= go4.org v0.0.0-20230225012048-214862532bf5 h1:nifaUDeh+rPaBCMPMQHZmvJf+QdpLFnuQPwx+LxVmtc= go4.org v0.0.0-20230225012048-214862532bf5/go.mod h1:F57wTi5Lrj6WLyswp5EYV1ncrEbFGHD4hhz6S1ZYeaU= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -260,8 +260,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= -golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= +golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU= +golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -273,8 +273,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.29.0 h1:HcdsyR4Gsuys/Axh0rDEmlBmB68rW1U9BUdB3UVHsas= -golang.org/x/image v0.29.0/go.mod h1:RVJROnf3SLK8d26OW91j4FrIHGbsJ8QnbEocVTOWQDA= +golang.org/x/image v0.33.0 h1:LXRZRnv1+zGd5XBUVRFmYEphyyKJjQjCRiOuAP3sZfQ= +golang.org/x/image v0.33.0/go.mod h1:DD3OsTYT9chzuzTQt+zMcOlBHgfoKQb1gry8p76Y1sc= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -313,8 +313,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= +golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -327,8 +327,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -354,8 +354,8 @@ golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= -golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -366,8 +366,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= -golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -432,8 +432,6 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= -google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/filebrowser/http/headers.go b/filebrowser/http/headers.go index 10fb0316ed..a768a46cfb 100644 --- a/filebrowser/http/headers.go +++ b/filebrowser/http/headers.go @@ -1,5 +1,4 @@ //go:build !dev -// +build !dev package http diff --git a/filebrowser/http/headers_dev.go b/filebrowser/http/headers_dev.go index 214366253f..8ef7824f86 100644 --- a/filebrowser/http/headers_dev.go +++ b/filebrowser/http/headers_dev.go @@ -1,5 +1,4 @@ //go:build dev -// +build dev package http diff --git a/filebrowser/renovate.json b/filebrowser/renovate.json new file mode 100644 index 0000000000..a1aad25e78 --- /dev/null +++ b/filebrowser/renovate.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended", + "group:allNonMajor", + "group:allDigest", + ":disableDependencyDashboard" + ], + "postUpdateOptions": [ + "gomodUpdateImportPaths", + "gomodTidy" + ] +} diff --git a/filebrowser/tools/go.mod b/filebrowser/tools/go.mod index fb417176d3..8c900fb13b 100644 --- a/filebrowser/tools/go.mod +++ b/filebrowser/tools/go.mod @@ -1,55 +1,61 @@ module github.com/filebrowser/filebrowser/v2/tools -go 1.24 +go 1.25 require ( - github.com/golangci/golangci-lint/v2 v2.1.6 - golang.org/x/tools v0.32.0 + github.com/golangci/golangci-lint/v2 v2.6.1 + golang.org/x/tools v0.38.0 ) require ( 4d63.com/gocheckcompilerdirectives v1.3.0 // indirect 4d63.com/gochecknoglobals v0.2.2 // indirect - github.com/4meepo/tagalign v1.4.2 // indirect - github.com/Abirdcfly/dupword v0.1.3 // indirect - github.com/Antonboom/errname v1.1.0 // indirect - github.com/Antonboom/nilnil v1.1.0 // indirect - github.com/Antonboom/testifylint v1.6.1 // indirect + codeberg.org/chavacava/garif v0.2.0 // indirect + dev.gaijin.team/go/exhaustruct/v4 v4.0.0 // indirect + dev.gaijin.team/go/golib v0.6.0 // indirect + github.com/4meepo/tagalign v1.4.3 // indirect + github.com/Abirdcfly/dupword v0.1.7 // indirect + github.com/AdminBenni/iota-mixing v1.0.0 // indirect + github.com/AlwxSin/noinlineerr v1.0.5 // indirect + github.com/Antonboom/errname v1.1.1 // indirect + github.com/Antonboom/nilnil v1.1.1 // indirect + github.com/Antonboom/testifylint v1.6.4 // indirect github.com/BurntSushi/toml v1.5.0 // indirect - github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect - github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 // indirect - github.com/Masterminds/semver/v3 v3.3.1 // indirect + github.com/Djarvur/go-err113 v0.1.1 // indirect + github.com/Masterminds/semver/v3 v3.4.0 // indirect + github.com/MirrexOne/unqueryvet v1.2.1 // indirect github.com/OpenPeeDeeP/depguard/v2 v2.2.1 // indirect - github.com/alecthomas/chroma/v2 v2.17.2 // indirect + github.com/alecthomas/chroma/v2 v2.20.0 // indirect github.com/alecthomas/go-check-sumtype v0.3.1 // indirect github.com/alexkohler/nakedret/v2 v2.0.6 // indirect github.com/alexkohler/prealloc v1.0.0 // indirect + github.com/alfatraining/structtag v1.0.0 // indirect github.com/alingse/asasalint v0.0.11 // indirect github.com/alingse/nilnesserr v0.2.0 // indirect - github.com/ashanbrown/forbidigo v1.6.0 // indirect - github.com/ashanbrown/makezero v1.2.0 // indirect + github.com/ashanbrown/forbidigo/v2 v2.3.0 // indirect + github.com/ashanbrown/makezero/v2 v2.1.0 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bkielbasa/cyclop v1.2.3 // indirect github.com/blizzy78/varnamelen v0.8.0 // indirect github.com/bombsimon/wsl/v4 v4.7.0 // indirect + github.com/bombsimon/wsl/v5 v5.3.0 // indirect github.com/breml/bidichk v0.3.3 // indirect github.com/breml/errchkjson v0.4.1 // indirect github.com/butuzov/ireturn v0.4.0 // indirect github.com/butuzov/mirror v1.3.0 // indirect - github.com/catenacyber/perfsprint v0.9.1 // indirect - github.com/ccojocar/zxcvbn-go v1.0.2 // indirect + github.com/catenacyber/perfsprint v0.10.0 // indirect + github.com/ccojocar/zxcvbn-go v1.0.4 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/charithe/durationcheck v0.0.10 // indirect + github.com/charithe/durationcheck v0.0.11 // indirect github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect github.com/charmbracelet/lipgloss v1.1.0 // indirect github.com/charmbracelet/x/ansi v0.8.0 // indirect github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect github.com/charmbracelet/x/term v0.2.1 // indirect - github.com/chavacava/garif v0.1.0 // indirect github.com/ckaznocha/intrange v0.3.1 // indirect github.com/curioswitch/go-reassign v0.3.0 // indirect - github.com/daixiang0/gci v0.13.6 // indirect + github.com/daixiang0/gci v0.13.7 // indirect github.com/dave/dst v0.27.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/denis-tingaikin/go-header v0.5.0 // indirect @@ -60,8 +66,8 @@ require ( github.com/firefart/nonamedreturns v1.0.6 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect - github.com/ghostiam/protogetter v0.3.15 // indirect - github.com/go-critic/go-critic v0.13.0 // indirect + github.com/ghostiam/protogetter v0.3.17 // indirect + github.com/go-critic/go-critic v0.14.2 // indirect github.com/go-toolsmith/astcast v1.1.0 // indirect github.com/go-toolsmith/astcopy v1.1.0 // indirect github.com/go-toolsmith/astequal v1.2.0 // indirect @@ -72,48 +78,52 @@ require ( github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/go-xmlfmt/xmlfmt v1.1.3 // indirect github.com/gobwas/glob v0.2.3 // indirect - github.com/gofrs/flock v0.12.1 // indirect + github.com/godoc-lint/godoc-lint v0.10.1 // indirect + github.com/gofrs/flock v0.13.0 // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/golangci/asciicheck v0.5.0 // indirect github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 // indirect - github.com/golangci/go-printf-func-name v0.1.0 // indirect + github.com/golangci/go-printf-func-name v0.1.1 // indirect github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d // indirect github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 // indirect - github.com/golangci/misspell v0.6.0 // indirect - github.com/golangci/plugin-module-register v0.1.1 // indirect + github.com/golangci/misspell v0.7.0 // indirect + github.com/golangci/plugin-module-register v0.1.2 // indirect github.com/golangci/revgrep v0.8.0 // indirect + github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e // indirect github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e // indirect github.com/google/go-cmp v0.7.0 // indirect - github.com/gordonklaus/ineffassign v0.1.0 // indirect + github.com/gordonklaus/ineffassign v0.2.0 // indirect github.com/gostaticanalysis/analysisutil v0.7.1 // indirect github.com/gostaticanalysis/comment v1.5.0 // indirect github.com/gostaticanalysis/forcetypeassert v0.2.0 // indirect - github.com/gostaticanalysis/nilerr v0.1.1 // indirect + github.com/gostaticanalysis/nilerr v0.1.2 // indirect github.com/hashicorp/go-immutable-radix/v2 v2.1.0 // indirect github.com/hashicorp/go-version v1.7.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/jgautheron/goconst v1.8.1 // indirect + github.com/jgautheron/goconst v1.8.2 // indirect github.com/jingyugao/rowserrcheck v1.1.1 // indirect - github.com/jjti/go-spancheck v0.6.4 // indirect + github.com/jjti/go-spancheck v0.6.5 // indirect github.com/julz/importas v0.2.0 // indirect - github.com/karamaru-alpha/copyloopvar v1.2.1 // indirect + github.com/karamaru-alpha/copyloopvar v1.2.2 // indirect github.com/kisielk/errcheck v1.9.0 // indirect github.com/kkHAIKE/contextcheck v1.1.6 // indirect - github.com/kulti/thelper v0.6.3 // indirect - github.com/kunwardeep/paralleltest v1.0.14 // indirect + github.com/kulti/thelper v0.7.1 // indirect + github.com/kunwardeep/paralleltest v1.0.15 // indirect github.com/lasiar/canonicalheader v1.1.2 // indirect - github.com/ldez/exptostd v0.4.3 // indirect - github.com/ldez/gomoddirectives v0.6.1 // indirect - github.com/ldez/grignotin v0.9.0 // indirect - github.com/ldez/tagliatelle v0.7.1 // indirect - github.com/ldez/usetesting v0.4.3 // indirect + github.com/ldez/exptostd v0.4.5 // indirect + github.com/ldez/gomoddirectives v0.7.1 // indirect + github.com/ldez/grignotin v0.10.1 // indirect + github.com/ldez/tagliatelle v0.7.2 // indirect + github.com/ldez/usetesting v0.5.0 // indirect github.com/leonklingele/grouper v1.1.2 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/macabu/inamedparam v0.2.0 // indirect github.com/magiconair/properties v1.8.6 // indirect - github.com/manuelarte/funcorder v0.2.1 // indirect + github.com/manuelarte/embeddedstructfieldcheck v0.4.0 // indirect + github.com/manuelarte/funcorder v0.5.0 // indirect github.com/maratori/testableexamples v1.0.0 // indirect github.com/maratori/testpackage v1.1.1 // indirect github.com/matoous/godox v1.1.0 // indirect @@ -121,7 +131,7 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/mgechev/revive v1.9.0 // indirect + github.com/mgechev/revive v1.12.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moricho/tparallel v0.3.2 // indirect @@ -129,8 +139,7 @@ require ( github.com/nakabonne/nestif v0.3.1 // indirect github.com/nishanths/exhaustive v0.12.0 // indirect github.com/nishanths/predeclared v0.2.2 // indirect - github.com/nunnatsa/ginkgolinter v0.19.1 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/nunnatsa/ginkgolinter v0.21.2 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect @@ -139,8 +148,8 @@ require ( github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect - github.com/quasilyte/go-ruleguard v0.4.4 // indirect - github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect + github.com/quasilyte/go-ruleguard v0.4.5 // indirect + github.com/quasilyte/go-ruleguard/dsl v0.3.23 // indirect github.com/quasilyte/gogrep v0.5.0 // indirect github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect @@ -150,27 +159,26 @@ require ( github.com/ryancurrah/gomodguard v1.4.1 // indirect github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect - github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect + github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect - github.com/sashamelentyev/usestdlibvars v1.28.0 // indirect - github.com/securego/gosec/v2 v2.22.3 // indirect + github.com/sashamelentyev/usestdlibvars v1.29.0 // indirect + github.com/securego/gosec/v2 v2.22.10 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/sivchari/containedctx v1.0.3 // indirect - github.com/sonatard/noctx v0.1.0 // indirect + github.com/sonatard/noctx v0.4.0 // indirect github.com/sourcegraph/go-diff v0.7.0 // indirect github.com/spf13/afero v1.14.0 // indirect github.com/spf13/cast v1.5.0 // indirect - github.com/spf13/cobra v1.9.1 // indirect + github.com/spf13/cobra v1.10.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/spf13/pflag v1.0.6 // indirect + github.com/spf13/pflag v1.0.10 // indirect github.com/spf13/viper v1.12.0 // indirect github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect github.com/stbenjam/no-sprintf-host-port v0.2.0 // indirect github.com/stretchr/objx v0.5.2 // indirect - github.com/stretchr/testify v1.10.0 // indirect + github.com/stretchr/testify v1.11.1 // indirect github.com/subosito/gotenv v1.4.1 // indirect - github.com/tdakkota/asciicheck v0.4.1 // indirect - github.com/tetafro/godot v1.5.1 // indirect + github.com/tetafro/godot v1.5.4 // indirect github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 // indirect github.com/timonwong/loggercheck v0.11.0 // indirect github.com/tomarrell/wrapcheck/v2 v2.11.0 // indirect @@ -178,30 +186,31 @@ require ( github.com/ultraware/funlen v0.2.0 // indirect github.com/ultraware/whitespace v0.2.0 // indirect github.com/uudashr/gocognit v1.2.0 // indirect - github.com/uudashr/iface v1.3.1 // indirect + github.com/uudashr/iface v1.4.1 // indirect github.com/xen0n/gosmopolitan v1.3.0 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/yagipy/maintidx v1.0.0 // indirect github.com/yeya24/promlinter v0.3.0 // indirect github.com/ykadowak/zerologlint v0.1.5 // indirect gitlab.com/bosi/decorder v0.4.2 // indirect - go-simpler.org/musttag v0.13.1 // indirect - go-simpler.org/sloglint v0.11.0 // indirect - go.augendre.info/fatcontext v0.8.0 // indirect - go.uber.org/atomic v1.7.0 // indirect + go-simpler.org/musttag v0.14.0 // indirect + go-simpler.org/sloglint v0.11.1 // indirect + go.augendre.info/arangolint v0.3.1 // indirect + go.augendre.info/fatcontext v0.9.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.24.0 // indirect - golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect - golang.org/x/mod v0.24.0 // indirect - golang.org/x/sync v0.13.0 // indirect - golang.org/x/sys v0.32.0 // indirect - golang.org/x/text v0.24.0 // indirect - google.golang.org/protobuf v1.36.6 // indirect + go.uber.org/multierr v1.10.0 // indirect + go.uber.org/zap v1.27.0 // indirect + golang.org/x/exp/typeparams v0.0.0-20251023183803-a4bb9ffd2546 // indirect + golang.org/x/mod v0.29.0 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/sys v0.37.0 // indirect + golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 // indirect + golang.org/x/text v0.30.0 // indirect + google.golang.org/protobuf v1.36.8 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect honnef.co/go/tools v0.6.1 // indirect - mvdan.cc/gofumpt v0.8.0 // indirect - mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 // indirect + mvdan.cc/gofumpt v0.9.2 // indirect + mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15 // indirect ) diff --git a/filebrowser/tools/go.sum b/filebrowser/tools/go.sum index ae8c484aff..f2e0157b29 100644 --- a/filebrowser/tools/go.sum +++ b/filebrowser/tools/go.sum @@ -34,37 +34,47 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +codeberg.org/chavacava/garif v0.2.0 h1:F0tVjhYbuOCnvNcU3YSpO6b3Waw6Bimy4K0mM8y6MfY= +codeberg.org/chavacava/garif v0.2.0/go.mod h1:P2BPbVbT4QcvLZrORc2T29szK3xEOlnl0GiPTJmEqBQ= +dev.gaijin.team/go/exhaustruct/v4 v4.0.0 h1:873r7aNneqoBB3IaFIzhvt2RFYTuHgmMjoKfwODoI1Y= +dev.gaijin.team/go/exhaustruct/v4 v4.0.0/go.mod h1:aZ/k2o4Y05aMJtiux15x8iXaumE88YdiB0Ai4fXOzPI= +dev.gaijin.team/go/golib v0.6.0 h1:v6nnznFTs4bppib/NyU1PQxobwDHwCXXl15P7DV5Zgo= +dev.gaijin.team/go/golib v0.6.0/go.mod h1:uY1mShx8Z/aNHWDyAkZTkX+uCi5PdX7KsG1eDQa2AVE= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/4meepo/tagalign v1.4.2 h1:0hcLHPGMjDyM1gHG58cS73aQF8J4TdVR96TZViorO9E= -github.com/4meepo/tagalign v1.4.2/go.mod h1:+p4aMyFM+ra7nb41CnFG6aSDXqRxU/w1VQqScKqDARI= -github.com/Abirdcfly/dupword v0.1.3 h1:9Pa1NuAsZvpFPi9Pqkd93I7LIYRURj+A//dFd5tgBeE= -github.com/Abirdcfly/dupword v0.1.3/go.mod h1:8VbB2t7e10KRNdwTVoxdBaxla6avbhGzb8sCTygUMhw= -github.com/Antonboom/errname v1.1.0 h1:A+ucvdpMwlo/myWrkHEUEBWc/xuXdud23S8tmTb/oAE= -github.com/Antonboom/errname v1.1.0/go.mod h1:O1NMrzgUcVBGIfi3xlVuvX8Q/VP/73sseCaAppfjqZw= -github.com/Antonboom/nilnil v1.1.0 h1:jGxJxjgYS3VUUtOTNk8Z1icwT5ESpLH/426fjmQG+ng= -github.com/Antonboom/nilnil v1.1.0/go.mod h1:b7sAlogQjFa1wV8jUW3o4PMzDVFLbTux+xnQdvzdcIE= -github.com/Antonboom/testifylint v1.6.1 h1:6ZSytkFWatT8mwZlmRCHkWz1gPi+q6UBSbieji2Gj/o= -github.com/Antonboom/testifylint v1.6.1/go.mod h1:k+nEkathI2NFjKO6HvwmSrbzUcQ6FAnbZV+ZRrnXPLI= +github.com/4meepo/tagalign v1.4.3 h1:Bnu7jGWwbfpAie2vyl63Zup5KuRv21olsPIha53BJr8= +github.com/4meepo/tagalign v1.4.3/go.mod h1:00WwRjiuSbrRJnSVeGWPLp2epS5Q/l4UEy0apLLS37c= +github.com/Abirdcfly/dupword v0.1.7 h1:2j8sInznrje4I0CMisSL6ipEBkeJUJAmK1/lfoNGWrQ= +github.com/Abirdcfly/dupword v0.1.7/go.mod h1:K0DkBeOebJ4VyOICFdppB23Q0YMOgVafM0zYW0n9lF4= +github.com/AdminBenni/iota-mixing v1.0.0 h1:Os6lpjG2dp/AE5fYBPAA1zfa2qMdCAWwPMCgpwKq7wo= +github.com/AdminBenni/iota-mixing v1.0.0/go.mod h1:i4+tpAaB+qMVIV9OK3m4/DAynOd5bQFaOu+2AhtBCNY= +github.com/AlwxSin/noinlineerr v1.0.5 h1:RUjt63wk1AYWTXtVXbSqemlbVTb23JOSRiNsshj7TbY= +github.com/AlwxSin/noinlineerr v1.0.5/go.mod h1:+QgkkoYrMH7RHvcdxdlI7vYYEdgeoFOVjU9sUhw/rQc= +github.com/Antonboom/errname v1.1.1 h1:bllB7mlIbTVzO9jmSWVWLjxTEbGBVQ1Ff/ClQgtPw9Q= +github.com/Antonboom/errname v1.1.1/go.mod h1:gjhe24xoxXp0ScLtHzjiXp0Exi1RFLKJb0bVBtWKCWQ= +github.com/Antonboom/nilnil v1.1.1 h1:9Mdr6BYd8WHCDngQnNVV0b554xyisFioEKi30sksufQ= +github.com/Antonboom/nilnil v1.1.1/go.mod h1:yCyAmSw3doopbOWhJlVci+HuyNRuHJKIv6V2oYQa8II= +github.com/Antonboom/testifylint v1.6.4 h1:gs9fUEy+egzxkEbq9P4cpcMB6/G0DYdMeiFS87UiqmQ= +github.com/Antonboom/testifylint v1.6.4/go.mod h1:YO33FROXX2OoUfwjz8g+gUxQXio5i9qpVy7nXGbxDD4= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= -github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1 h1:Sz1JIXEcSfhz7fUi7xHnhpIE0thVASYjvosApmHuD2k= -github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.1/go.mod h1:n/LSCXNuIYqVfBlVXyHfMQkZDdp1/mmxfSjADd3z1Zg= -github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= -github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Djarvur/go-err113 v0.1.1 h1:eHfopDqXRwAi+YmCUas75ZE0+hoBHJ2GQNLYRSxao4g= +github.com/Djarvur/go-err113 v0.1.1/go.mod h1:IaWJdYFLg76t2ihfflPZnM1LIQszWOsFDh2hhhAVF6k= +github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= +github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/MirrexOne/unqueryvet v1.2.1 h1:M+zdXMq84g+E1YOLa7g7ExN3dWfZQrdDSTCM7gC+m/A= +github.com/MirrexOne/unqueryvet v1.2.1/go.mod h1:IWwCwMQlSWjAIteW0t+28Q5vouyktfujzYznSIWiuOg= github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4= github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= -github.com/alecthomas/chroma/v2 v2.17.2 h1:Rm81SCZ2mPoH+Q8ZCc/9YvzPUN/E7HgPiPJD8SLV6GI= -github.com/alecthomas/chroma/v2 v2.17.2/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk= +github.com/alecthomas/chroma/v2 v2.20.0 h1:sfIHpxPyR07/Oylvmcai3X/exDlE8+FA820NTz+9sGw= +github.com/alecthomas/chroma/v2 v2.20.0/go.mod h1:e7tViK0xh/Nf4BYHl00ycY6rV7b8iXBksI9E359yNmA= github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU= github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E= -github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= -github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= +github.com/alecthomas/repr v0.5.1 h1:E3G4t2QbHTSNpPKBgMTln5KLkZHLOcU7r37J4pXBuIg= +github.com/alecthomas/repr v0.5.1/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -74,18 +84,18 @@ github.com/alexkohler/nakedret/v2 v2.0.6 h1:ME3Qef1/KIKr3kWX3nti3hhgNxw6aqN5pZmQ github.com/alexkohler/nakedret/v2 v2.0.6/go.mod h1:l3RKju/IzOMQHmsEvXwkqMDzHHvurNQfAgE1eVmT40Q= github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= +github.com/alfatraining/structtag v1.0.0 h1:2qmcUqNcCoyVJ0up879K614L9PazjBSFruTB0GOFjCc= +github.com/alfatraining/structtag v1.0.0/go.mod h1:p3Xi5SwzTi+Ryj64DqjLWz7XurHxbGsq6y3ubePJPus= github.com/alingse/asasalint v0.0.11 h1:SFwnQXJ49Kx/1GghOFz1XGqHYKp21Kq1nHad/0WQRnw= github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= github.com/alingse/nilnesserr v0.2.0 h1:raLem5KG7EFVb4UIDAXgrv3N2JIaffeKNtcEXkEWd/w= github.com/alingse/nilnesserr v0.2.0/go.mod h1:1xJPrXonEtX7wyTq8Dytns5P2hNzoWymVUIaKm4HNFg= -github.com/ashanbrown/forbidigo v1.6.0 h1:D3aewfM37Yb3pxHujIPSpTf6oQk9sc9WZi8gerOIVIY= -github.com/ashanbrown/forbidigo v1.6.0/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= -github.com/ashanbrown/makezero v1.2.0 h1:/2Lp1bypdmK9wDIq7uWBlDF1iMUpIIS4A+pF6C9IEUU= -github.com/ashanbrown/makezero v1.2.0/go.mod h1:dxlPhHbDMC6N6xICzFBSK+4njQDdK8euNO0qjQMtGY4= +github.com/ashanbrown/forbidigo/v2 v2.3.0 h1:OZZDOchCgsX5gvToVtEBoV2UWbFfI6RKQTir2UZzSxo= +github.com/ashanbrown/forbidigo/v2 v2.3.0/go.mod h1:5p6VmsG5/1xx3E785W9fouMxIOkvY2rRV9nMdWadd6c= +github.com/ashanbrown/makezero/v2 v2.1.0 h1:snuKYMbqosNokUKm+R6/+vOPs8yVAi46La7Ck6QYSaE= +github.com/ashanbrown/makezero/v2 v2.1.0/go.mod h1:aEGT/9q3S8DHeE57C88z2a6xydvgx8J5hgXIGWgo0MY= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -96,6 +106,8 @@ github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= github.com/bombsimon/wsl/v4 v4.7.0 h1:1Ilm9JBPRczjyUs6hvOPKvd7VL1Q++PL8M0SXBDf+jQ= github.com/bombsimon/wsl/v4 v4.7.0/go.mod h1:uV/+6BkffuzSAVYD+yGyld1AChO7/EuLrCF/8xTiapg= +github.com/bombsimon/wsl/v5 v5.3.0 h1:nZWREJFL6U3vgW/B1lfDOigl+tEF6qgs6dGGbFeR0UM= +github.com/bombsimon/wsl/v5 v5.3.0/go.mod h1:Gp8lD04z27wm3FANIUPZycXp+8huVsn0oxc+n4qfV9I= github.com/breml/bidichk v0.3.3 h1:WSM67ztRusf1sMoqH6/c4OBCUlRVTKq+CbSeo0R17sE= github.com/breml/bidichk v0.3.3/go.mod h1:ISbsut8OnjB367j5NseXEGGgO/th206dVa427kR8YTE= github.com/breml/errchkjson v0.4.1 h1:keFSS8D7A2T0haP9kzZTi7o26r7kE3vymjZNeNDRDwg= @@ -104,17 +116,17 @@ github.com/butuzov/ireturn v0.4.0 h1:+s76bF/PfeKEdbG8b54aCocxXmi0wvYdOVsWxVO7n8E github.com/butuzov/ireturn v0.4.0/go.mod h1:ghI0FrCmap8pDWZwfPisFD1vEc56VKH4NpQUxDHta70= github.com/butuzov/mirror v1.3.0 h1:HdWCXzmwlQHdVhwvsfBb2Au0r3HyINry3bDWLYXiKoc= github.com/butuzov/mirror v1.3.0/go.mod h1:AEij0Z8YMALaq4yQj9CPPVYOyJQyiexpQEQgihajRfI= -github.com/catenacyber/perfsprint v0.9.1 h1:5LlTp4RwTooQjJCvGEFV6XksZvWE7wCOUvjD2z0vls0= -github.com/catenacyber/perfsprint v0.9.1/go.mod h1:q//VWC2fWbcdSLEY1R3l8n0zQCDPdE4IjZwyY1HMunM= -github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg= -github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= +github.com/catenacyber/perfsprint v0.10.0 h1:AZj1mYyxbxLRqmnYOeguZXEQwWOgQGm2wzLI5d7Hl/0= +github.com/catenacyber/perfsprint v0.10.0/go.mod h1:DJTGsi/Zufpuus6XPGJyKOTMELe347o6akPvWG9Zcsc= +github.com/ccojocar/zxcvbn-go v1.0.4 h1:FWnCIRMXPj43ukfX000kvBZvV6raSxakYr1nzyNrUcc= +github.com/ccojocar/zxcvbn-go v1.0.4/go.mod h1:3GxGX+rHmueTUMvm5ium7irpyjmm7ikxYFOSJB21Das= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= -github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= +github.com/charithe/durationcheck v0.0.11 h1:g1/EX1eIiKS57NTWsYtHDZ/APfeXKhye1DidBcABctk= +github.com/charithe/durationcheck v0.0.11/go.mod h1:x5iZaixRNl8ctbM+3B2RrPG5t856TxRyVQEnbIEM2X4= github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= @@ -125,8 +137,6 @@ github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0G github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= -github.com/chavacava/garif v0.1.0 h1:2JHa3hbYf5D9dsgseMKAmc/MZ109otzgNFk5s87H9Pc= -github.com/chavacava/garif v0.1.0/go.mod h1:XMyYCkEL58DF0oyW4qDjjnPWONs2HBqYKI+UIPD+Gww= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -137,8 +147,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/curioswitch/go-reassign v0.3.0 h1:dh3kpQHuADL3cobV/sSGETA8DOv457dwl+fbBAhrQPs= github.com/curioswitch/go-reassign v0.3.0/go.mod h1:nApPCCTtqLJN/s8HfItCcKV0jIPwluBOvZP+dsJGA88= -github.com/daixiang0/gci v0.13.6 h1:RKuEOSkGpSadkGbvZ6hJ4ddItT3cVZ9Vn9Rybk6xjl8= -github.com/daixiang0/gci v0.13.6/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk= +github.com/daixiang0/gci v0.13.7 h1:+0bG5eK9vlI08J+J/NWGbWPTNiXPG4WhNLJOkSxWITQ= +github.com/daixiang0/gci v0.13.7/go.mod h1:812WVN6JLFY9S6Tv76twqmNqevN0pa3SX3nih0brVzQ= github.com/dave/dst v0.27.3 h1:P1HPoMza3cMEquVf9kKy8yXsFirry4zEnWOdYPOoIzY= github.com/dave/dst v0.27.3/go.mod h1:jHh6EOibnHgcUW3WjKHisiooEkYwqpHLBSX1iOBhEyc= github.com/dave/jennifer v1.7.1 h1:B4jJJDHelWcDhlRQxWeo0Npa/pYKBLrirAQoTN45txo= @@ -168,10 +178,10 @@ github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwV github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= -github.com/ghostiam/protogetter v0.3.15 h1:1KF5sXel0HE48zh1/vn0Loiw25A9ApyseLzQuif1mLY= -github.com/ghostiam/protogetter v0.3.15/go.mod h1:WZ0nw9pfzsgxuRsPOFQomgDVSWtDLJRfQJEhsGbmQMA= -github.com/go-critic/go-critic v0.13.0 h1:kJzM7wzltQasSUXtYyTl6UaPVySO6GkaR1thFnJ6afY= -github.com/go-critic/go-critic v0.13.0/go.mod h1:M/YeuJ3vOCQDnP2SU+ZhjgRzwzcBW87JqLpMJLrZDLI= +github.com/ghostiam/protogetter v0.3.17 h1:sjGPErP9o7i2Ym+z3LsQzBdLCNaqbYy2iJQPxGXg04Q= +github.com/ghostiam/protogetter v0.3.17/go.mod h1:AivIX1eKA/TcUmzZdzbl+Tb8tjIe8FcyG6JFyemQAH4= +github.com/go-critic/go-critic v0.14.2 h1:PMvP5f+LdR8p6B29npvChUXbD1vrNlKDf60NJtgMBOo= +github.com/go-critic/go-critic v0.14.2/go.mod h1:xwntfW6SYAd7h1OqDzmN6hBX/JxsEKl5up/Y2bsxgVQ= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -181,8 +191,8 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -213,8 +223,10 @@ github.com/go-xmlfmt/xmlfmt v1.1.3 h1:t8Ey3Uy7jDSEisW2K3somuMKIpzktkWptA0iFCnRUW github.com/go-xmlfmt/xmlfmt v1.1.3/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= -github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= +github.com/godoc-lint/godoc-lint v0.10.1 h1:ZPUVzlDtJfA+P688JfPJPkI/SuzcBr/753yGIk5bOPA= +github.com/godoc-lint/godoc-lint v0.10.1/go.mod h1:KleLcHu/CGSvkjUH2RvZyoK1MBC7pDQg4NxMYLcBBsw= +github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= +github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -245,22 +257,26 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golangci/asciicheck v0.5.0 h1:jczN/BorERZwK8oiFBOGvlGPknhvq0bjnysTj4nUfo0= +github.com/golangci/asciicheck v0.5.0/go.mod h1:5RMNAInbNFw2krqN6ibBxN/zfRFa9S6tA1nPdM0l8qQ= github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32 h1:WUvBfQL6EW/40l6OmeSBYQJNSif4O11+bmWEz+C7FYw= github.com/golangci/dupl v0.0.0-20250308024227-f665c8d69b32/go.mod h1:NUw9Zr2Sy7+HxzdjIULge71wI6yEg1lWQr7Evcu8K0E= -github.com/golangci/go-printf-func-name v0.1.0 h1:dVokQP+NMTO7jwO4bwsRwLWeudOVUPPyAKJuzv8pEJU= -github.com/golangci/go-printf-func-name v0.1.0/go.mod h1:wqhWFH5mUdJQhweRnldEywnR5021wTdZSNgwYceV14s= +github.com/golangci/go-printf-func-name v0.1.1 h1:hIYTFJqAGp1iwoIfsNTpoq1xZAarogrvjO9AfiW3B4U= +github.com/golangci/go-printf-func-name v0.1.1/go.mod h1:Es64MpWEZbh0UBtTAICOZiB+miW53w/K9Or/4QogJss= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d h1:viFft9sS/dxoYY0aiOTsLKO2aZQAPT4nlQCsimGcSGE= github.com/golangci/gofmt v0.0.0-20250106114630-d62b90e6713d/go.mod h1:ivJ9QDg0XucIkmwhzCDsqcnxxlDStoTl89jDMIoNxKY= -github.com/golangci/golangci-lint/v2 v2.1.6 h1:LXqShFfAGM5BDzEOWD2SL1IzJAgUOqES/HRBsfKjI+w= -github.com/golangci/golangci-lint/v2 v2.1.6/go.mod h1:EPj+fgv4TeeBq3TcqaKZb3vkiV5dP4hHHKhXhEhzci8= +github.com/golangci/golangci-lint/v2 v2.6.1 h1:yTYVG6BJ4eG9QE815BAQDrC2xBbTB8lW11jg+YQ0b1c= +github.com/golangci/golangci-lint/v2 v2.6.1/go.mod h1:zlg/a5aw46LvRBHZ3OOwwsCtkjWTrn3wm5qowoteCRg= github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95 h1:AkK+w9FZBXlU/xUmBtSJN1+tAI4FIvy5WtnUnY8e4p8= github.com/golangci/golines v0.0.0-20250217134842-442fd0091d95/go.mod h1:k9mmcyWKSTMcPPvQUCfRWWQ9VHJ1U9Dc0R7kaXAgtnQ= -github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs= -github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo= -github.com/golangci/plugin-module-register v0.1.1 h1:TCmesur25LnyJkpsVrupv1Cdzo+2f7zX0H6Jkw1Ol6c= -github.com/golangci/plugin-module-register v0.1.1/go.mod h1:TTpqoB6KkwOJMV8u7+NyXMrkwwESJLOkfl9TxR1DGFc= +github.com/golangci/misspell v0.7.0 h1:4GOHr/T1lTW0hhR4tgaaV1WS/lJ+ncvYCoFKmqJsj0c= +github.com/golangci/misspell v0.7.0/go.mod h1:WZyyI2P3hxPY2UVHs3cS8YcllAeyfquQcKfdeE9AFVg= +github.com/golangci/plugin-module-register v0.1.2 h1:e5WM6PO6NIAEcij3B053CohVp3HIYbzSuP53UAYgOpg= +github.com/golangci/plugin-module-register v0.1.2/go.mod h1:1+QGTsKBvAIvPvoY/os+G5eoqxWn70HYDm2uvUyGuVw= github.com/golangci/revgrep v0.8.0 h1:EZBctwbVd0aMeRnNUsFogoyayvKHyxlV3CdUA46FX2s= github.com/golangci/revgrep v0.8.0/go.mod h1:U4R/s9dlXZsg8uJmaR1GrloUr14D7qDl8gi2iPXJH8k= +github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e h1:ai0EfmVYE2bRA5htgAG9r7s3tHsfjIhN98WshBTJ9jM= +github.com/golangci/swaggoswag v0.0.0-20250504205917-77f2aca3143e/go.mod h1:Vrn4B5oR9qRwM+f54koyeH3yzphlecwERs0el27Fr/s= github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e h1:gD6P7NEo7Eqtt0ssnqSJNNndxe69DOQ24A5h7+i3KpM= github.com/golangci/unconvert v0.0.0-20250410112200-a129a6e6413e/go.mod h1:h+wZwLjUTJnm/P2rwlbJdRPZXOzaT36/FwnPnY2inzc= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -275,7 +291,6 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= @@ -289,23 +304,22 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= -github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 h1:EEHtgt9IwisQ2AZ4pIsMjahcegHh6rmhqxzIRQIyepY= +github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s= -github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= +github.com/gordonklaus/ineffassign v0.2.0 h1:Uths4KnmwxNJNzq87fwQQDDnbNb7De00VOk9Nu0TySs= +github.com/gordonklaus/ineffassign v0.2.0/go.mod h1:TIpymnagPSexySzs7F9FnO1XFTy8IT3a59vmZp5Y9Lw= github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= -github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= github.com/gostaticanalysis/comment v1.5.0 h1:X82FLl+TswsUMpMh17srGRuKaaXprTaytmEpgnKIDu8= github.com/gostaticanalysis/comment v1.5.0/go.mod h1:V6eb3gpCv9GNVqb6amXzEUX3jXLVK/AdA+IrAMSqvEc= github.com/gostaticanalysis/forcetypeassert v0.2.0 h1:uSnWrrUEYDr86OCxWa4/Tp2jeYDlogZiZHzGkWFefTk= github.com/gostaticanalysis/forcetypeassert v0.2.0/go.mod h1:M5iPavzE9pPqWyeiVXSFghQjljW1+l/Uke3PXHS6ILY= -github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= -github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= +github.com/gostaticanalysis/nilerr v0.1.2 h1:S6nk8a9N8g062nsx63kUkF6AzbHGw7zzyHMcpu52xQU= +github.com/gostaticanalysis/nilerr v0.1.2/go.mod h1:A19UHhoY3y8ahoL7YKz6sdjDtduwTSI4CsymaC2htPA= github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/gostaticanalysis/testutil v0.5.0 h1:Dq4wT1DdTwTGCQQv3rl3IvD5Ld0E6HiY+3Zh0sUGqw8= github.com/gostaticanalysis/testutil v0.5.0/go.mod h1:OLQSbuM6zw2EvCcXTz1lVq5unyoNft372msDY0nY5Hs= @@ -327,12 +341,12 @@ github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSo github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jgautheron/goconst v1.8.1 h1:PPqCYp3K/xlOj5JmIe6O1Mj6r1DbkdbLtR3AJuZo414= -github.com/jgautheron/goconst v1.8.1/go.mod h1:A0oxgBCHy55NQn6sYpO7UdnA9p+h7cPtoOZUmvNIako= +github.com/jgautheron/goconst v1.8.2 h1:y0XF7X8CikZ93fSNT6WBTb/NElBu9IjaY7CCYQrCMX4= +github.com/jgautheron/goconst v1.8.2/go.mod h1:A0oxgBCHy55NQn6sYpO7UdnA9p+h7cPtoOZUmvNIako= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= -github.com/jjti/go-spancheck v0.6.4 h1:Tl7gQpYf4/TMU7AT84MN83/6PutY21Nb9fuQjFTpRRc= -github.com/jjti/go-spancheck v0.6.4/go.mod h1:yAEYdKJ2lRkDA8g7X+oKUHXOWVAXSBJRv04OhF+QUjk= +github.com/jjti/go-spancheck v0.6.5 h1:lmi7pKxa37oKYIMScialXUK6hP3iY5F1gu+mLBPgYB8= +github.com/jjti/go-spancheck v0.6.5/go.mod h1:aEogkeatBrbYsyW6y5TgDfihCulDYciL1B7rG2vSsrU= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -344,8 +358,8 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julz/importas v0.2.0 h1:y+MJN/UdL63QbFJHws9BVC5RpA2iq0kpjrFajTGivjQ= github.com/julz/importas v0.2.0/go.mod h1:pThlt589EnCYtMnmhmRYY/qn9lCf/frPOK+WMx3xiJY= -github.com/karamaru-alpha/copyloopvar v1.2.1 h1:wmZaZYIjnJ0b5UoKDjUHrikcV0zuPyyxI4SVplLd2CI= -github.com/karamaru-alpha/copyloopvar v1.2.1/go.mod h1:nFmMlFNlClC2BPvNaHMdkirmTJxVCY0lhxBtlfOypMM= +github.com/karamaru-alpha/copyloopvar v1.2.2 h1:yfNQvP9YaGQR7VaWLYcfZUlRP2eo2vhExWKxD/fP6q0= +github.com/karamaru-alpha/copyloopvar v1.2.2/go.mod h1:oY4rGZqZ879JkJMtX3RRkcXRkmUvH0x35ykgaKgsgJY= github.com/kisielk/errcheck v1.9.0 h1:9xt1zI9EBfcYBvdU1nVrzMzzUPUtPKs9bVSIM3TAb3M= github.com/kisielk/errcheck v1.9.0/go.mod h1:kQxWMMVZgIkDq7U8xtG/n2juOjbLgZtedi0D+/VL/i8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -361,22 +375,22 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= -github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= -github.com/kunwardeep/paralleltest v1.0.14 h1:wAkMoMeGX/kGfhQBPODT/BL8XhK23ol/nuQ3SwFaUw8= -github.com/kunwardeep/paralleltest v1.0.14/go.mod h1:di4moFqtfz3ToSKxhNjhOZL+696QtJGCFe132CbBLGk= +github.com/kulti/thelper v0.7.1 h1:fI8QITAoFVLx+y+vSyuLBP+rcVIB8jKooNSCT2EiI98= +github.com/kulti/thelper v0.7.1/go.mod h1:NsMjfQEy6sd+9Kfw8kCP61W1I0nerGSYSFnGaxQkcbs= +github.com/kunwardeep/paralleltest v1.0.15 h1:ZMk4Qt306tHIgKISHWFJAO1IDQJLc6uDyJMLyncOb6w= +github.com/kunwardeep/paralleltest v1.0.15/go.mod h1:di4moFqtfz3ToSKxhNjhOZL+696QtJGCFe132CbBLGk= github.com/lasiar/canonicalheader v1.1.2 h1:vZ5uqwvDbyJCnMhmFYimgMZnJMjwljN5VGY0VKbMXb4= github.com/lasiar/canonicalheader v1.1.2/go.mod h1:qJCeLFS0G/QlLQ506T+Fk/fWMa2VmBUiEI2cuMK4djI= -github.com/ldez/exptostd v0.4.3 h1:Ag1aGiq2epGePuRJhez2mzOpZ8sI9Gimcb4Sb3+pk9Y= -github.com/ldez/exptostd v0.4.3/go.mod h1:iZBRYaUmcW5jwCR3KROEZ1KivQQp6PHXbDPk9hqJKCQ= -github.com/ldez/gomoddirectives v0.6.1 h1:Z+PxGAY+217f/bSGjNZr/b2KTXcyYLgiWI6geMBN2Qc= -github.com/ldez/gomoddirectives v0.6.1/go.mod h1:cVBiu3AHR9V31em9u2kwfMKD43ayN5/XDgr+cdaFaKs= -github.com/ldez/grignotin v0.9.0 h1:MgOEmjZIVNn6p5wPaGp/0OKWyvq42KnzAt/DAb8O4Ow= -github.com/ldez/grignotin v0.9.0/go.mod h1:uaVTr0SoZ1KBii33c47O1M8Jp3OP3YDwhZCmzT9GHEk= -github.com/ldez/tagliatelle v0.7.1 h1:bTgKjjc2sQcsgPiT902+aadvMjCeMHrY7ly2XKFORIk= -github.com/ldez/tagliatelle v0.7.1/go.mod h1:3zjxUpsNB2aEZScWiZTHrAXOl1x25t3cRmzfK1mlo2I= -github.com/ldez/usetesting v0.4.3 h1:pJpN0x3fMupdTf/IapYjnkhiY1nSTN+pox1/GyBRw3k= -github.com/ldez/usetesting v0.4.3/go.mod h1:eEs46T3PpQ+9RgN9VjpY6qWdiw2/QmfiDeWmdZdrjIQ= +github.com/ldez/exptostd v0.4.5 h1:kv2ZGUVI6VwRfp/+bcQ6Nbx0ghFWcGIKInkG/oFn1aQ= +github.com/ldez/exptostd v0.4.5/go.mod h1:QRjHRMXJrCTIm9WxVNH6VW7oN7KrGSht69bIRwvdFsM= +github.com/ldez/gomoddirectives v0.7.1 h1:FaULkvUIG36hj6chpwa+FdCNGZBsD7/fO+p7CCsM6pE= +github.com/ldez/gomoddirectives v0.7.1/go.mod h1:auDNtakWJR1rC+YX7ar+HmveqXATBAyEK1KYpsIRW/8= +github.com/ldez/grignotin v0.10.1 h1:keYi9rYsgbvqAZGI1liek5c+jv9UUjbvdj3Tbn5fn4o= +github.com/ldez/grignotin v0.10.1/go.mod h1:UlDbXFCARrXbWGNGP3S5vsysNXAPhnSuBufpTEbwOas= +github.com/ldez/tagliatelle v0.7.2 h1:KuOlL70/fu9paxuxbeqlicJnCspCRjH0x8FW+NfgYUk= +github.com/ldez/tagliatelle v0.7.2/go.mod h1:PtGgm163ZplJfZMZ2sf5nhUT170rSuPgBimoyYtdaSI= +github.com/ldez/usetesting v0.5.0 h1:3/QtzZObBKLy1F4F8jLuKJiKBjjVFi1IavpoWbmqLwc= +github.com/ldez/usetesting v0.5.0/go.mod h1:Spnb4Qppf8JTuRgblLrEWb7IE6rDmUpGvxY3iRrzvDQ= github.com/leonklingele/grouper v1.1.2 h1:o1ARBDLOmmasUaNDesWqWCIFH3u7hoFlM84YrjT3mIY= github.com/leonklingele/grouper v1.1.2/go.mod h1:6D0M/HVkhs2yRKRFZUoGjeDy7EZTfFBE9gl4kjmIGkA= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= @@ -385,8 +399,10 @@ github.com/macabu/inamedparam v0.2.0 h1:VyPYpOc10nkhI2qeNUdh3Zket4fcZjEWe35poddB github.com/macabu/inamedparam v0.2.0/go.mod h1:+Pee9/YfGe5LJ62pYXqB89lJ+0k5bsR8Wgz/C0Zlq3U= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/manuelarte/funcorder v0.2.1 h1:7QJsw3qhljoZ5rH0xapIvjw31EcQeFbF31/7kQ/xS34= -github.com/manuelarte/funcorder v0.2.1/go.mod h1:BQQ0yW57+PF9ZpjpeJDKOffEsQbxDFKW8F8zSMe/Zd0= +github.com/manuelarte/embeddedstructfieldcheck v0.4.0 h1:3mAIyaGRtjK6EO9E73JlXLtiy7ha80b2ZVGyacxgfww= +github.com/manuelarte/embeddedstructfieldcheck v0.4.0/go.mod h1:z8dFSyXqp+fC6NLDSljRJeNQJJDWnY7RoWFzV3PC6UM= +github.com/manuelarte/funcorder v0.5.0 h1:llMuHXXbg7tD0i/LNw8vGnkDTHFpTnWqKPI85Rknc+8= +github.com/manuelarte/funcorder v0.5.0/go.mod h1:Yt3CiUQthSBMBxjShjdXMexmzpP8YGvGLjrxJNkO2hA= github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= @@ -399,13 +415,12 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mgechev/revive v1.9.0 h1:8LaA62XIKrb8lM6VsBSQ92slt/o92z5+hTw3CmrvSrM= -github.com/mgechev/revive v1.9.0/go.mod h1:LAPq3+MgOf7GcL5PlWIkHb0PT7XH4NuC2LdWymhb9Mo= +github.com/mgechev/revive v1.12.0 h1:Q+/kkbbwerrVYPv9d9efaPGmAO/NsxwW/nE6ahpQaCU= +github.com/mgechev/revive v1.12.0/go.mod h1:VXsY2LsTigk8XU9BpZauVLjVrhICMOV3k1lpB3CXrp8= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -427,14 +442,12 @@ github.com/nishanths/exhaustive v0.12.0 h1:vIY9sALmw6T/yxiASewa4TQcFsVYZQQRUQJhK github.com/nishanths/exhaustive v0.12.0/go.mod h1:mEZ95wPIZW+x8kC4TgC+9YCUgiST7ecevsVDTgc2obs= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nunnatsa/ginkgolinter v0.19.1 h1:mjwbOlDQxZi9Cal+KfbEJTCz327OLNfwNvoZ70NJ+c4= -github.com/nunnatsa/ginkgolinter v0.19.1/go.mod h1:jkQ3naZDmxaZMXPWaS9rblH+i+GWXQCaS/JFIWcOH2s= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0= -github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= -github.com/onsi/gomega v1.36.3 h1:hID7cr8t3Wp26+cYnfcjR6HpJ00fdogN6dqZ1t6IylU= -github.com/onsi/gomega v1.36.3/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= +github.com/nunnatsa/ginkgolinter v0.21.2 h1:khzWfm2/Br8ZemX8QM1pl72LwM+rMeW6VUbQ4rzh0Po= +github.com/nunnatsa/ginkgolinter v0.21.2/go.mod h1:GItSI5fw7mCGLPmkvGYrr1kEetZe7B593jcyOpyabsY= +github.com/onsi/ginkgo/v2 v2.26.0 h1:1J4Wut1IlYZNEAWIV3ALrT9NfiaGW2cDCJQSFQMs/gE= +github.com/onsi/ginkgo/v2 v2.26.0/go.mod h1:qhEywmzWTBUY88kfO0BRvX4py7scov9yR+Az2oavUzw= +github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= +github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= @@ -448,7 +461,6 @@ github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0 github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -478,10 +490,10 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/quasilyte/go-ruleguard v0.4.4 h1:53DncefIeLX3qEpjzlS1lyUmQoUEeOWPFWqaTJq9eAQ= -github.com/quasilyte/go-ruleguard v0.4.4/go.mod h1:Vl05zJ538vcEEwu16V/Hdu7IYZWyKSwIy4c88Ro1kRE= -github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= -github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/go-ruleguard v0.4.5 h1:AGY0tiOT5hJX9BTdx/xBdoCubQUAE2grkqY2lSwvZcA= +github.com/quasilyte/go-ruleguard v0.4.5/go.mod h1:Vl05zJ538vcEEwu16V/Hdu7IYZWyKSwIy4c88Ro1kRE= +github.com/quasilyte/go-ruleguard/dsl v0.3.23 h1:lxjt5B6ZCiBeeNO8/oQsegE6fLeCzuMRoVWSkXC4uvY= +github.com/quasilyte/go-ruleguard/dsl v0.3.23/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU= @@ -503,14 +515,14 @@ github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9f github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0= github.com/sanposhiho/wastedassign/v2 v2.1.0/go.mod h1:+oSmSC+9bQ+VUAxA66nBb0Z7N8CK7mscKTDYC6aIek4= -github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw= -github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ= +github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU= github.com/sashamelentyev/interfacebloat v1.1.0 h1:xdRdJp0irL086OyW1H/RTZTr1h/tMEOsumirXcOJqAw= github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= -github.com/sashamelentyev/usestdlibvars v1.28.0 h1:jZnudE2zKCtYlGzLVreNp5pmCdOxXUzwsMDBkR21cyQ= -github.com/sashamelentyev/usestdlibvars v1.28.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= -github.com/securego/gosec/v2 v2.22.3 h1:mRrCNmRF2NgZp4RJ8oJ6yPJ7G4x6OCiAXHd8x4trLRc= -github.com/securego/gosec/v2 v2.22.3/go.mod h1:42M9Xs0v1WseinaB/BmNGO8AVqG8vRfhC2686ACY48k= +github.com/sashamelentyev/usestdlibvars v1.29.0 h1:8J0MoRrw4/NAXtjQqTHrbW9NN+3iMf7Knkq057v4XOQ= +github.com/sashamelentyev/usestdlibvars v1.29.0/go.mod h1:8PpnjHMk5VdeWlVb4wCdrB8PNbLqZ3wBZTZWkrpZZL8= +github.com/securego/gosec/v2 v2.22.10 h1:ntbBqdWXnu46DUOXn+R2SvPo3PiJCDugTCgTW2g4tQg= +github.com/securego/gosec/v2 v2.22.10/go.mod h1:9UNjK3tLpv/w2b0+7r82byV43wCJDNtEDQMeS+H/g2w= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= @@ -522,21 +534,22 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sivchari/containedctx v1.0.3 h1:x+etemjbsh2fB5ewm5FeLNi5bUjK0V8n0RB+Wwfd0XE= github.com/sivchari/containedctx v1.0.3/go.mod h1:c1RDvCbnJLtH4lLcYD/GqwiBSSf4F5Qk0xld2rBqzJ4= -github.com/sonatard/noctx v0.1.0 h1:JjqOc2WN16ISWAjAk8M5ej0RfExEXtkEyExl2hLW+OM= -github.com/sonatard/noctx v0.1.0/go.mod h1:0RvBxqY8D4j9cTTTWE8ylt2vqj2EPI8fHmrxHdsaZ2c= +github.com/sonatard/noctx v0.4.0 h1:7MC/5Gg4SQ4lhLYR6mvOP6mQVSxCrdyiExo7atBs27o= +github.com/sonatard/noctx v0.4.0/go.mod h1:64XdbzFb18XL4LporKXp8poqZtPKbCrqQ402CV+kJas= github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= -github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= +github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= github.com/ssgreg/nlreturn/v2 v2.2.1 h1:X4XDI7jstt3ySqGU86YGAURbxw3oTDPK9sPEi6YEwQ0= @@ -545,30 +558,22 @@ github.com/stbenjam/no-sprintf-host-port v0.2.0 h1:i8pxvGrt1+4G0czLr/WnmyH7zbZ8B github.com/stbenjam/no-sprintf-host-port v0.2.0/go.mod h1:eL0bQ9PasS0hsyTyfTjjG+E80QIyPnBVQbYZyv20Jfk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= -github.com/tdakkota/asciicheck v0.4.1 h1:bm0tbcmi0jezRA2b5kg4ozmMuGAFotKI3RZfrhfovg8= -github.com/tdakkota/asciicheck v0.4.1/go.mod h1:0k7M3rCfRXb0Z6bwgvkEIMleKH3kXNz9UqJ9Xuqopr8= github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= -github.com/tetafro/godot v1.5.1 h1:PZnjCol4+FqaEzvZg5+O8IY2P3hfY9JzRBNPv1pEDS4= -github.com/tetafro/godot v1.5.1/go.mod h1:cCdPtEndkmqqrhiCfkmxDodMQJ/f3L1BCNskCUZdTwk= +github.com/tetafro/godot v1.5.4 h1:u1ww+gqpRLiIA16yF2PV1CV1n/X3zhyezbNXC3E14Sg= +github.com/tetafro/godot v1.5.4/go.mod h1:eOkMrVQurDui411nBY2FA05EYH01r14LuWY/NrVDVcU= github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67 h1:9LPGD+jzxMlnk5r6+hJnar67cgpDIz/iyD+rfl5r2Vk= github.com/timakin/bodyclose v0.0.0-20241222091800-1db5c5ca4d67/go.mod h1:mkjARE7Yr8qU23YcGMSALbIxTQ9r9QBVahQOBRfU460= github.com/timonwong/loggercheck v0.11.0 h1:jdaMpYBl+Uq9mWPXv1r8jc5fC3gyXx4/WGwTnnNKn4M= @@ -583,8 +588,8 @@ github.com/ultraware/whitespace v0.2.0 h1:TYowo2m9Nfj1baEQBjuHzvMRbp19i+RCcRYrSW github.com/ultraware/whitespace v0.2.0/go.mod h1:XcP1RLD81eV4BW8UhQlpaR+SDc2givTvyI8a586WjW8= github.com/uudashr/gocognit v1.2.0 h1:3BU9aMr1xbhPlvJLSydKwdLN3tEUUrzPSSM8S4hDYRA= github.com/uudashr/gocognit v1.2.0/go.mod h1:k/DdKPI6XBZO1q7HgoV2juESI2/Ofj9AcHPZhBBdrTU= -github.com/uudashr/iface v1.3.1 h1:bA51vmVx1UIhiIsQFSNq6GZ6VPTk3WNMZgRiCe9R29U= -github.com/uudashr/iface v1.3.1/go.mod h1:4QvspiRd3JLPAEXBQ9AiZpLbJlrWWgRChOKDJEuQTdg= +github.com/uudashr/iface v1.4.1 h1:J16Xl1wyNX9ofhpHmQ9h9gk5rnv2A6lX/2+APLTo0zU= +github.com/uudashr/iface v1.4.1/go.mod h1:pbeBPlbuU2qkNDn0mmfrxP2X+wjPMIQAy+r1MBXSXtg= github.com/xen0n/gosmopolitan v1.3.0 h1:zAZI1zefvo7gcpbCOrPSHJZJYA9ZgLfJqtKzZ5pHqQM= github.com/xen0n/gosmopolitan v1.3.0/go.mod h1:rckfr5T6o4lBtM1ga7mLGKZmLxswUoH1zxHgNXOsEt4= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= @@ -606,27 +611,29 @@ gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8= go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= -go-simpler.org/musttag v0.13.1 h1:lw2sJyu7S1X8lc8zWUAdH42y+afdcCnHhWpnkWvd6vU= -go-simpler.org/musttag v0.13.1/go.mod h1:8r450ehpMLQgvpb6sg+hV5Ur47eH6olp/3yEanfG97k= -go-simpler.org/sloglint v0.11.0 h1:JlR1X4jkbeaffiyjLtymeqmGDKBDO1ikC6rjiuFAOco= -go-simpler.org/sloglint v0.11.0/go.mod h1:CFDO8R1i77dlciGfPEPvYke2ZMx4eyGiEIWkyeW2Pvw= -go.augendre.info/fatcontext v0.8.0 h1:2dfk6CQbDGeu1YocF59Za5Pia7ULeAM6friJ3LP7lmk= -go.augendre.info/fatcontext v0.8.0/go.mod h1:oVJfMgwngMsHO+KB2MdgzcO+RvtNdiCEOlWvSFtax/s= +go-simpler.org/musttag v0.14.0 h1:XGySZATqQYSEV3/YTy+iX+aofbZZllJaqwFWs+RTtSo= +go-simpler.org/musttag v0.14.0/go.mod h1:uP8EymctQjJ4Z1kUnjX0u2l60WfUdQxCwSNKzE1JEOE= +go-simpler.org/sloglint v0.11.1 h1:xRbPepLT/MHPTCA6TS/wNfZrDzkGvCCqUv4Bdwc3H7s= +go-simpler.org/sloglint v0.11.1/go.mod h1:2PowwiCOK8mjiF+0KGifVOT8ZsCNiFzvfyJeJOIt8MQ= +go.augendre.info/arangolint v0.3.1 h1:n2E6p8f+zfXSFLa2e2WqFPp4bfvcuRdd50y6cT65pSo= +go.augendre.info/arangolint v0.3.1/go.mod h1:6ZKzEzIZuBQwoSvlKT+qpUfIbBfFCE5gbAoTg0/117g= +go.augendre.info/fatcontext v0.9.0 h1:Gt5jGD4Zcj8CDMVzjOJITlSb9cEch54hjRRlN3qDojE= +go.augendre.info/fatcontext v0.9.0/go.mod h1:L94brOAT1OOUNue6ph/2HnwxoNlds9aXDF2FcUntbNw= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= -go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -650,8 +657,8 @@ golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWB golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac h1:TSSpLIG4v+p0rPv1pNOQtl1I8knsO4S9trOxNMOLVP4= -golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20251023183803-a4bb9ffd2546 h1:HDjDiATsGqvuqvkDvgJjD1IgPrVekcSXVVE21JwvzGE= +golang.org/x/exp/typeparams v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:4Mzdyp/6jzw9auFDJ3OMF5qksa7UvPnzKqTVGcb04ms= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -676,13 +683,11 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= -golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= +golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -717,14 +722,12 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= +golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -746,8 +749,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -794,19 +797,18 @@ golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 h1:LvzTn0GQhWuvKH/kVRS3R3bVAsdQWI7hvfLHGgh9+lU= +golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= @@ -817,13 +819,11 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -859,7 +859,6 @@ golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -869,22 +868,21 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= -golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= +golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= +golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= +golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= +golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= +golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM= +golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -964,8 +962,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= -google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= +google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -994,10 +992,10 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.6.1 h1:R094WgE8K4JirYjBaOpz/AvTyUu/3wbmAoskKN/pxTI= honnef.co/go/tools v0.6.1/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4= -mvdan.cc/gofumpt v0.8.0 h1:nZUCeC2ViFaerTcYKstMmfysj6uhQrA2vJe+2vwGU6k= -mvdan.cc/gofumpt v0.8.0/go.mod h1:vEYnSzyGPmjvFkqJWtXkh79UwPWP9/HMxQdGEXZHjpg= -mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 h1:WjUu4yQoT5BHT1w8Zu56SP8367OuBV5jvo+4Ulppyf8= -mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4/go.mod h1:rthT7OuvRbaGcd5ginj6dA2oLE7YNlta9qhBNNdCaLE= +mvdan.cc/gofumpt v0.9.2 h1:zsEMWL8SVKGHNztrx6uZrXdp7AX8r421Vvp23sz7ik4= +mvdan.cc/gofumpt v0.9.2/go.mod h1:iB7Hn+ai8lPvofHd9ZFGVg2GOr8sBUw1QUWjNbmIL/s= +mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15 h1:ssMzja7PDPJV8FStj7hq9IKiuiKhgz9ErWw+m68e7DI= +mvdan.cc/unparam v0.0.0-20251027182757-5beb8c8f8f15/go.mod h1:4M5MMXl2kW6fivUT6yRGpLLPNfuGtU2Z0cPvFquGDYU= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/filebrowser/tools/yarn.lock b/filebrowser/tools/yarn.lock index 451f399b2c..ac478ea49c 100644 --- a/filebrowser/tools/yarn.lock +++ b/filebrowser/tools/yarn.lock @@ -3,25 +3,18 @@ "@babel/code-frame@^7.0.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431" - integrity sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA== + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" + integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== dependencies: - "@babel/highlight" "^7.16.0" - -"@babel/helper-validator-identifier@^7.15.7": - version "7.15.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" - integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== - -"@babel/highlight@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a" - integrity sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g== - dependencies: - "@babel/helper-validator-identifier" "^7.15.7" - chalk "^2.0.0" + "@babel/helper-validator-identifier" "^7.27.1" js-tokens "^4.0.0" + picocolors "^1.1.1" + +"@babel/helper-validator-identifier@^7.27.1": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" + integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== "@commitlint/cli@^15.0.0": version "15.0.0" @@ -179,14 +172,14 @@ integrity sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q== "@types/minimist@^1.2.0": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" - integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== + version "1.2.5" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.5.tgz#ec10755e871497bcd83efe927e43ec46e8c0747e" + integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag== "@types/normalize-package-data@^2.4.0": - version "2.4.1" - resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" - integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== + version "2.4.4" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" + integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== "@types/parse-json@^4.0.0": version "4.0.0" @@ -204,7 +197,7 @@ JSONStream@^1.0.4: add-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" - integrity sha1-anmQQ3ynNtXhKI25K9MmbV9csqo= + integrity sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ== ansi-regex@^5.0.1: version "5.0.1" @@ -233,12 +226,12 @@ arg@^4.1.0: array-ify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" - integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4= + integrity sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng== arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== balanced-match@^1.0.0: version "1.0.2" @@ -277,7 +270,7 @@ camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -chalk@^2.0.0, chalk@^2.4.2: +chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -320,7 +313,7 @@ color-convert@^2.0.1: color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== color-name@~1.1.4: version "1.1.4" @@ -338,7 +331,7 @@ compare-func@^2.0.0: concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== concat-stream@^2.0.0: version "2.0.0" @@ -377,7 +370,16 @@ conventional-changelog-config-spec@2.1.0: resolved "https://registry.yarnpkg.com/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.0.tgz#874a635287ef8b581fd8558532bf655d4fb59f2d" integrity sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ== -conventional-changelog-conventionalcommits@4.6.1, conventional-changelog-conventionalcommits@^4.3.1, conventional-changelog-conventionalcommits@^4.5.0: +conventional-changelog-conventionalcommits@4.6.3, conventional-changelog-conventionalcommits@^4.5.0: + version "4.6.3" + resolved "https://registry.yarnpkg.com/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.3.tgz#0765490f56424b46f6cb4db9135902d6e5a36dc2" + integrity sha512-LTTQV4fwOM4oLPad317V/QNQ1FY4Hju5qeBIM1uTHbrnCE+Eg4CdRZ3gO2pUeR+tzWdp80M2j3qFFEDWVqOV4g== + dependencies: + compare-func "^2.0.0" + lodash "^4.17.15" + q "^1.5.1" + +conventional-changelog-conventionalcommits@^4.3.1: version "4.6.1" resolved "https://registry.yarnpkg.com/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.1.tgz#f4c0921937050674e578dc7875f908351ccf4014" integrity sha512-lzWJpPZhbM1R0PIzkwzGBCnAkH5RKJzJfFQZcl/D+2lsJxAwGnDKBqn/F4C1RD31GJNn8NuKWQzAZDAVXPp2Mw== @@ -448,13 +450,13 @@ conventional-changelog-preset-loader@^2.3.4: integrity sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g== conventional-changelog-writer@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-5.0.0.tgz#c4042f3f1542f2f41d7d2e0d6cad23aba8df8eec" - integrity sha512-HnDh9QHLNWfL6E1uHz6krZEQOgm8hN7z/m7tT16xwd802fwgMN0Wqd7AQYVkhpsjDUx/99oo+nGgvKF657XP5g== + version "5.0.1" + resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-5.0.1.tgz#e0757072f045fe03d91da6343c843029e702f359" + integrity sha512-5WsuKUfxW7suLblAbFnxAcrvf6r+0b7GvNaWUwUIk0bXMnENP/PEieGKVUQrjPqwPT4o3EPAASBXiY6iHooLOQ== dependencies: conventional-commits-filter "^2.0.7" dateformat "^3.0.0" - handlebars "^4.7.6" + handlebars "^4.7.7" json-stringify-safe "^5.0.1" lodash "^4.17.15" meow "^8.0.0" @@ -462,10 +464,10 @@ conventional-changelog-writer@^5.0.0: split "^1.0.0" through2 "^4.0.0" -conventional-changelog@3.1.24: - version "3.1.24" - resolved "https://registry.yarnpkg.com/conventional-changelog/-/conventional-changelog-3.1.24.tgz#ebd180b0fd1b2e1f0095c4b04fd088698348a464" - integrity sha512-ed6k8PO00UVvhExYohroVPXcOJ/K1N0/drJHx/faTH37OIZthlecuLIRX/T6uOp682CAoVoFpu+sSEaeuH6Asg== +conventional-changelog@3.1.25: + version "3.1.25" + resolved "https://registry.yarnpkg.com/conventional-changelog/-/conventional-changelog-3.1.25.tgz#3e227a37d15684f5aa1fb52222a6e9e2536ccaff" + integrity sha512-ryhi3fd1mKf3fSjbLXOfK2D06YwKNic1nC9mWqybBHdObPd8KJ2vjaXZfYj1U23t+V8T8n0d7gwnc9XbIdFbyQ== dependencies: conventional-changelog-angular "^5.0.12" conventional-changelog-atom "^2.0.8" @@ -487,7 +489,19 @@ conventional-commits-filter@^2.0.7: lodash.ismatch "^4.4.0" modify-values "^1.0.0" -conventional-commits-parser@^3.2.0, conventional-commits-parser@^3.2.2: +conventional-commits-parser@^3.2.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz#a7d3b77758a202a9b2293d2112a8d8052c740972" + integrity sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q== + dependencies: + JSONStream "^1.0.4" + is-text-path "^1.0.1" + lodash "^4.17.15" + meow "^8.0.0" + split2 "^3.0.0" + through2 "^4.0.0" + +conventional-commits-parser@^3.2.2: version "3.2.3" resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.2.3.tgz#fc43704698239451e3ef35fd1d8ed644f46bd86e" integrity sha512-YyRDR7On9H07ICFpRm/igcdjIqebXbvf4Cff+Pf0BrBys1i1EOzx9iFXNlAbdrLAR8jf7bkUYkDAr8pEy0q4Pw== @@ -554,9 +568,9 @@ dateformat@^3.0.0: integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== decamelize-keys@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" - integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= + version "1.1.1" + resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8" + integrity sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg== dependencies: decamelize "^1.1.0" map-obj "^1.0.0" @@ -564,7 +578,7 @@ decamelize-keys@^1.1.0: decamelize@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== detect-indent@^6.0.0: version "6.1.0" @@ -602,21 +616,21 @@ emoji-regex@^8.0.0: integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + version "1.3.4" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414" + integrity sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ== dependencies: is-arrayish "^0.2.1" escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== execa@^5.0.0: version "5.1.1" @@ -643,7 +657,7 @@ figures@^3.1.0: find-up@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== dependencies: locate-path "^2.0.0" @@ -670,13 +684,6 @@ find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" -fs-access@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/fs-access/-/fs-access-1.0.1.tgz#d6a87f262271cefebec30c553407fb995da8777a" - integrity sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o= - dependencies: - null-check "^1.0.0" - fs-extra@^10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1" @@ -686,10 +693,10 @@ fs-extra@^10.0.0: jsonfile "^6.0.1" universalify "^2.0.0" -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== get-caller-file@^2.0.5: version "2.0.5" @@ -711,7 +718,7 @@ get-stream@^6.0.0: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== -git-raw-commits@^2.0.0, git-raw-commits@^2.0.8: +git-raw-commits@^2.0.0: version "2.0.10" resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.10.tgz#e2255ed9563b1c9c3ea6bd05806410290297bbc1" integrity sha512-sHhX5lsbG9SOO6yXdlwgEMQ/ljIn7qMpAbJZCGfXX2fq5T8M5SrDnpYk9/4HswTildcIqatsWa91vty6VhWSaQ== @@ -722,10 +729,21 @@ git-raw-commits@^2.0.0, git-raw-commits@^2.0.8: split2 "^3.0.0" through2 "^4.0.0" +git-raw-commits@^2.0.8: + version "2.0.11" + resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.11.tgz#bc3576638071d18655e1cc60d7f524920008d723" + integrity sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A== + dependencies: + dargs "^7.0.0" + lodash "^4.17.15" + meow "^8.0.0" + split2 "^3.0.0" + through2 "^4.0.0" + git-remote-origin-url@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz#5282659dae2107145a11126112ad3216ec5fa65f" - integrity sha1-UoJlna4hBxRaERJhEq0yFuxfpl8= + integrity sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw== dependencies: gitconfiglocal "^1.0.0" pify "^2.3.0" @@ -741,7 +759,7 @@ git-semver-tags@^4.0.0, git-semver-tags@^4.1.1: gitconfiglocal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz#41d045f3851a5ea88f03f24ca1c6178114464b9b" - integrity sha1-QdBF84UaXqiPA/JMocYXgRRGS5s= + integrity sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ== dependencies: ini "^1.3.2" @@ -752,18 +770,23 @@ global-dirs@^0.1.1: dependencies: ini "^1.3.4" -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: +graceful-fs@^4.1.2: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graceful-fs@^4.1.6, graceful-fs@^4.2.0: version "4.2.8" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== -handlebars@^4.7.6: - version "4.7.7" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" - integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== +handlebars@^4.7.7: + version "4.7.8" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" + integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== dependencies: minimist "^1.2.5" - neo-async "^2.6.0" + neo-async "^2.6.2" source-map "^0.6.1" wordwrap "^1.0.0" optionalDependencies: @@ -777,19 +800,19 @@ hard-rejection@^2.1.0: has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== dependencies: - function-bind "^1.1.1" + function-bind "^1.1.2" hosted-git-info@^2.1.4: version "2.8.9" @@ -797,9 +820,9 @@ hosted-git-info@^2.1.4: integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== hosted-git-info@^4.0.0, hosted-git-info@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.0.2.tgz#5e425507eede4fea846b7262f0838456c4209961" - integrity sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg== + version "4.1.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" + integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== dependencies: lru-cache "^6.0.0" @@ -834,14 +857,14 @@ ini@^1.3.2, ini@^1.3.4: is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== -is-core-module@^2.2.0, is-core-module@^2.5.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548" - integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw== +is-core-module@^2.16.1, is-core-module@^2.5.0: + version "2.16.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== dependencies: - has "^1.0.3" + hasown "^2.0.2" is-fullwidth-code-point@^3.0.0: version "3.0.0" @@ -856,7 +879,7 @@ is-obj@^2.0.0: is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= + integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== is-stream@^2.0.0: version "2.0.1" @@ -866,14 +889,14 @@ is-stream@^2.0.0: is-text-path@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-1.0.1.tgz#4e1aa0fb51bfbcb3e92688001397202c1775b66e" - integrity sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4= + integrity sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w== dependencies: text-extensions "^1.0.0" isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== isexe@^2.0.0: version "2.0.0" @@ -898,7 +921,7 @@ json-parse-even-better-errors@^2.3.0: json-stringify-safe@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== jsonfile@^6.0.1: version "6.1.0" @@ -912,7 +935,7 @@ jsonfile@^6.0.1: jsonparse@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" - integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= + integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== kind-of@^6.0.3: version "6.0.3" @@ -927,7 +950,7 @@ lines-and-columns@^1.1.6: load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= + integrity sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw== dependencies: graceful-fs "^4.1.2" parse-json "^4.0.0" @@ -937,7 +960,7 @@ load-json-file@^4.0.0: locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== dependencies: p-locate "^2.0.0" path-exists "^3.0.0" @@ -972,7 +995,7 @@ lodash.get@^4: lodash.ismatch@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" - integrity sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc= + integrity sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g== lodash@^4.17.15, lodash@^4.17.19: version "4.17.21" @@ -994,7 +1017,7 @@ make-error@^1, make-error@^1.1.1: map-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= + integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg== map-obj@^4.0.0: version "4.3.0" @@ -1050,16 +1073,16 @@ minimist-options@4.1.0: kind-of "^6.0.3" minimist@^1.2.5: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== modify-values@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== -neo-async@^2.6.0: +neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== @@ -1091,11 +1114,6 @@ npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -null-check@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd" - integrity sha1-l33/1xdgErnsMNKjnbXPcqBDnt0= - onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" @@ -1127,7 +1145,7 @@ p-limit@^3.0.2: p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== dependencies: p-limit "^1.1.0" @@ -1155,7 +1173,7 @@ p-locate@^5.0.0: p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== p-try@^2.0.0: version "2.2.0" @@ -1172,7 +1190,7 @@ parent-module@^1.0.0: parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== dependencies: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" @@ -1190,7 +1208,7 @@ parse-json@^5.0.0: path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== path-exists@^4.0.0: version "4.0.0" @@ -1202,7 +1220,7 @@ path-key@^3.0.0, path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-parse@^1.0.6: +path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== @@ -1219,15 +1237,20 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= + integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== process-nextick-args@~2.0.0: version "2.0.1" @@ -1237,7 +1260,7 @@ process-nextick-args@~2.0.0: q@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= + integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw== quick-lru@^4.0.1: version "4.0.1" @@ -1247,7 +1270,7 @@ quick-lru@^4.0.1: read-pkg-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" - integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc= + integrity sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw== dependencies: find-up "^2.0.0" read-pkg "^3.0.0" @@ -1264,7 +1287,7 @@ read-pkg-up@^7.0.1: read-pkg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" - integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= + integrity sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA== dependencies: load-json-file "^4.0.0" normalize-package-data "^2.3.2" @@ -1281,18 +1304,18 @@ read-pkg@^5.2.0: type-fest "^0.6.0" readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" util-deprecate "^1.0.1" readable-stream@~2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -1313,7 +1336,7 @@ redent@^3.0.0: require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== resolve-from@5.0.0, resolve-from@^5.0.0: version "5.0.0" @@ -1333,12 +1356,13 @@ resolve-global@1.0.0, resolve-global@^1.0.0: global-dirs "^0.1.1" resolve@^1.10.0: - version "1.20.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" - integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== + version "1.22.11" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.11.tgz#aad857ce1ffb8bfa9b0b1ac29f1156383f68c262" + integrity sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ== dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" + is-core-module "^2.16.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" @@ -1368,11 +1392,9 @@ semver@^6.0.0: integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== semver@^7.1.1, semver@^7.3.4: - version "7.5.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" - integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== - dependencies: - lru-cache "^6.0.0" + version "7.7.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" + integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== shebang-command@^2.0.0: version "2.0.0" @@ -1405,17 +1427,17 @@ source-map@^0.6.0, source-map@^0.6.1: integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== spdx-correct@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" - integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + version "3.2.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + version "2.5.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66" + integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== spdx-expression-parse@^3.0.0: version "3.0.1" @@ -1426,9 +1448,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.11" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95" - integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== + version "3.0.22" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz#abf5a08a6f5d7279559b669f47f0a43e8f3464ef" + integrity sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ== split2@^3.0.0: version "3.2.2" @@ -1445,21 +1467,20 @@ split@^1.0.0: through "2" standard-version@^9.3.2: - version "9.3.2" - resolved "https://registry.yarnpkg.com/standard-version/-/standard-version-9.3.2.tgz#28db8c1be66fd2d736f28f7c5de7619e64cd6dab" - integrity sha512-u1rfKP4o4ew7Yjbfycv80aNMN2feTiqseAhUhrrx2XtdQGmu7gucpziXe68Z4YfHVqlxVEzo4aUA0Iu3VQOTgQ== + version "9.5.0" + resolved "https://registry.yarnpkg.com/standard-version/-/standard-version-9.5.0.tgz#851d6dcddf5320d5079601832aeb185dbf497949" + integrity sha512-3zWJ/mmZQsOaO+fOlsa0+QK90pwhNd042qEcw6hKFNoLFs7peGyvPffpEBbK/DSGPbyOvli0mUIFv5A4qTjh2Q== dependencies: chalk "^2.4.2" - conventional-changelog "3.1.24" + conventional-changelog "3.1.25" conventional-changelog-config-spec "2.1.0" - conventional-changelog-conventionalcommits "4.6.1" + conventional-changelog-conventionalcommits "4.6.3" conventional-recommended-bump "6.1.0" detect-indent "^6.0.0" detect-newline "^3.1.0" dotgitignore "^2.1.0" figures "^3.1.0" find-up "^5.0.0" - fs-access "^1.0.1" git-semver-tags "^4.0.0" semver "^7.1.1" stringify-package "^1.0.1" @@ -1503,7 +1524,7 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== strip-final-newline@^2.0.0: version "2.0.0" @@ -1531,6 +1552,11 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + text-extensions@^1.0.0: version "1.9.0" resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" @@ -1554,7 +1580,7 @@ through2@^4.0.0: through@2, "through@>=2.2.7 <3": version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== trim-newlines@^3.0.0: version "3.0.1" @@ -1596,7 +1622,7 @@ type-fest@^0.8.1: typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== typescript@^4.4.3: version "4.5.4" @@ -1604,9 +1630,9 @@ typescript@^4.4.3: integrity sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg== uglify-js@^3.1.4: - version "3.14.5" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.14.5.tgz#cdabb7d4954231d80cb4a927654c4655e51f4859" - integrity sha512-qZukoSxOG0urUTvjc2ERMTcAy+BiFh3weWAkeurLwjrCba73poHmG3E36XEjd/JGukMzwTL7uCxZiAexj8ppvQ== + version "3.19.3" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.19.3.tgz#82315e9bbc6f2b25888858acd1fff8441035b77f" + integrity sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ== universalify@^2.0.0: version "2.0.0" @@ -1616,7 +1642,7 @@ universalify@^2.0.0: util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== validate-npm-package-license@^3.0.1: version "3.0.4" @@ -1636,7 +1662,7 @@ which@^2.0.1: wordwrap@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= + integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== wrap-ansi@^7.0.0: version "7.0.0" diff --git a/geoip/README.md b/geoip/README.md index 64b8f7bad2..852c97e765 100644 --- a/geoip/README.md +++ b/geoip/README.md @@ -228,7 +228,7 @@ rules: 点击查看在 mihomo 中的使用方法 ```yaml -geodata-mode: true +geodata-mode: false geox-url: mmdb: "https://cdn.jsdelivr.net/gh/Loyalsoldier/geoip@release/Country.mmdb" asn: "https://cdn.jsdelivr.net/gh/Loyalsoldier/geoip@release/GeoLite2-ASN.mmdb" diff --git a/lede/target/linux/airoha/Makefile b/lede/target/linux/airoha/Makefile index 61b7b87692..3803fda9da 100644 --- a/lede/target/linux/airoha/Makefile +++ b/lede/target/linux/airoha/Makefile @@ -3,10 +3,11 @@ include $(TOPDIR)/rules.mk ARCH:=arm BOARD:=airoha BOARDNAME:=Airoha ARM -SUBTARGETS:=en7523 an7581 +SUBTARGETS:=an7581 en7523 FEATURES:=dt squashfs nand ramdisk gpio -KERNEL_PATCHVER:=6.6 +KERNEL_PATCHVER:=6.12 +KERNEL_TESTING_PATCHVER:=6.6 include $(INCLUDE_DIR)/target.mk diff --git a/lede/target/linux/airoha/an7581/base-files/etc/board.d/02_network b/lede/target/linux/airoha/an7581/base-files/etc/board.d/02_network new file mode 100644 index 0000000000..0d79ef6a77 --- /dev/null +++ b/lede/target/linux/airoha/an7581/base-files/etc/board.d/02_network @@ -0,0 +1,28 @@ +# +# Copyright (c) 2015 The Linux Foundation. All rights reserved. +# Copyright (c) 2011-2015 OpenWrt.org +# + +. /lib/functions/uci-defaults.sh +. /lib/functions/system.sh + +an7581_setup_interfaces() +{ + local board="$1" + + case "$board" in + bell,xg-040g-md) + ucidef_set_interfaces_lan_wan "lan2 lan3 lan4" "eth1" + ;; + *) + echo "Unsupported hardware. Network interfaces not initialized" + ;; + esac +} + +board_config_update +board=$(board_name) +an7581_setup_interfaces $board +board_config_flush + +exit 0 diff --git a/lede/target/linux/airoha/an7581/base-files/lib/upgrade/platform.sh b/lede/target/linux/airoha/an7581/base-files/lib/upgrade/platform.sh new file mode 100644 index 0000000000..556caa19fe --- /dev/null +++ b/lede/target/linux/airoha/an7581/base-files/lib/upgrade/platform.sh @@ -0,0 +1,15 @@ +REQUIRE_IMAGE_METADATA=1 + +platform_do_upgrade() { + local board=$(board_name) + + case "$board" in + *) + nand_do_upgrade "$1" + ;; + esac +} + +platform_check_image() { + return 0 +} diff --git a/lede/target/linux/airoha/an7581/config-6.12 b/lede/target/linux/airoha/an7581/config-6.12 new file mode 100644 index 0000000000..77bd649276 --- /dev/null +++ b/lede/target/linux/airoha/an7581/config-6.12 @@ -0,0 +1,413 @@ +CONFIG_64BIT=y +CONFIG_AIROHA_CPU_PM_DOMAIN=y +CONFIG_AIROHA_SCU_SSR=y +CONFIG_AIROHA_THERMAL=y +CONFIG_AIROHA_WATCHDOG=y +CONFIG_AMPERE_ERRATUM_AC03_CPU_38=y +CONFIG_ARCH_AIROHA=y +CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y +CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y +CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_FORCE_MAX_ORDER=10 +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_PKEY_BITS=3 +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANTS_EXECMEM_LATE=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_ARCH_WANTS_THP_SWAP=y +CONFIG_ARM64=y +CONFIG_ARM64_4K_PAGES=y +CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y +CONFIG_ARM64_PA_BITS=48 +CONFIG_ARM64_PA_BITS_48=y +CONFIG_ARM64_PLATFORM_DEVICES=y +CONFIG_ARM64_TAGGED_ADDR_ABI=y +CONFIG_ARM64_VA_BITS=39 +CONFIG_ARM64_VA_BITS_39=y +CONFIG_ARM_AIROHA_SOC_CPUFREQ=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_PMU=y +CONFIG_ARM_PMUV3=y +CONFIG_ARM_PSCI_FW=y +CONFIG_ARM_SMCCC_SOC_ID=y +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BLK_PM=y +CONFIG_BLOCK_NOTIFIERS=y +CONFIG_BUFFER_HEAD=y +CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y +CONFIG_CC_HAVE_SHADOW_CALL_STACK=y +CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_EN7523=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +# CONFIG_COMPAT_32BIT_TIME is not set +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_MITIGATIONS=y +CONFIG_CPU_RMAP=y +CONFIG_CRC16=y +CONFIG_CRC_CCITT=y +CONFIG_CRYPTO_AUTHENC=y +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_DRBG_HMAC=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_ECHAINIV=y +CONFIG_CRYPTO_GENIV=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKS=64 +CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE=32 +CONFIG_CRYPTO_JITTERENTROPY_OSR=1 +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA3=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_MISC=y +CONFIG_DEV_COREDUMP=y +CONFIG_DMADEVICES=y +CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_NEED_SYNC=y +CONFIG_DMA_OF=y +CONFIG_DTC=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_EXT4_FS=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FRAME_POINTER=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FUNCTION_ALIGNMENT=4 +CONFIG_FUNCTION_ALIGNMENT_4B=y +CONFIG_FWNODE_MDIO=y +# CONFIG_FW_LOADER_USER_HELPER is not set +CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_DEVICES=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IOREMAP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GLOB=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_EN7523=y +CONFIG_GPIO_GENERIC=y +CONFIG_GRO_CELLS=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HOTPLUG_CORE_SYNC=y +CONFIG_HOTPLUG_CORE_SYNC_DEAD=y +CONFIG_HOTPLUG_CPU=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_AIROHA=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +# CONFIG_INET_ESP_OFFLOAD is not set +CONFIG_INET_IPCOMP=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_TUNNEL=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IO_URING=y +CONFIG_IPV6=y +CONFIG_IPV6_MULTIPLE_TABLES=y +# CONFIG_IPV6_SUBTREES is not set +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_COMMON=y +# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_MSI_LIB=y +CONFIG_IRQ_WORK=y +CONFIG_JBD2=y +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LRU_GEN_WALKS_MMU=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_MDIO_AIROHA is not set +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y +CONFIG_MEDIATEK_GE_SOC_PHY=y +CONFIG_MFD_SYSCON=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_CQHCI=y +CONFIG_MMC_MTK=y +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_MODULES_TREE_LOOKUP=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_MTK_BMT=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_FIT_FW=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTK_NET_PHYLIB=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NET_AIROHA=y +CONFIG_NET_AIROHA_FLOW_STATS=y +CONFIG_NET_AIROHA_NPU=y +CONFIG_NET_DEVLINK=y +CONFIG_NET_DSA=y +CONFIG_NET_DSA_MT7530=y +# CONFIG_NET_DSA_MT7530_MDIO is not set +CONFIG_NET_DSA_MT7530_MMIO=y +CONFIG_NET_DSA_TAG_MTK=y +CONFIG_NET_EGRESS=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_INGRESS=y +CONFIG_NET_SELFTESTS=y +# CONFIG_NET_VENDOR_3COM is not set +CONFIG_NET_VENDOR_AIROHA=y +# CONFIG_NET_VENDOR_MEDIATEK is not set +CONFIG_NET_XGRESS=y +CONFIG_NLS=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=4 +CONFIG_NVMEM=y +CONFIG_NVMEM_BLOCK=y +CONFIG_NVMEM_LAYOUTS=y +CONFIG_NVMEM_LAYOUT_ASCII_ENV=y +CONFIG_NVMEM_SYSFS=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_PADATA=y +CONFIG_PAGE_POOL=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PARTITION_PERCPU=y +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEASPM=y +# CONFIG_PCIEASPM_DEFAULT is not set +CONFIG_PCIEASPM_PERFORMANCE=y +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_MEDIATEK=y +CONFIG_PCIE_MEDIATEK_GEN3=y +CONFIG_PCIE_PME=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCS_AIROHA=y +CONFIG_PCS_AIROHA_AN7581=y +# CONFIG_PCS_AIROHA_AN7583 is not set +CONFIG_PERF_EVENTS=y +CONFIG_PER_VMA_LOCK=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_PHYLIB=y +CONFIG_PHYLIB_LEDS=y +CONFIG_PHYLINK=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PHY_AIROHA_PCIE=y +CONFIG_PHY_AIROHA_USB=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_AIROHA=y +# CONFIG_PINCTRL_MT2712 is not set +# CONFIG_PINCTRL_MT6765 is not set +# CONFIG_PINCTRL_MT6795 is not set +# CONFIG_PINCTRL_MT6797 is not set +# CONFIG_PINCTRL_MT7622 is not set +# CONFIG_PINCTRL_MT7981 is not set +# CONFIG_PINCTRL_MT7986 is not set +# CONFIG_PINCTRL_MT8173 is not set +# CONFIG_PINCTRL_MT8183 is not set +# CONFIG_PINCTRL_MT8186 is not set +# CONFIG_PINCTRL_MT8188 is not set +# CONFIG_PINCTRL_MT8516 is not set +CONFIG_PM=y +CONFIG_PM_CLK=y +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_PM_OPP=y +CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_SUPPLY=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RAS=y +CONFIG_RATIONAL=y +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_RELOCATABLE=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RFS_ACCEL=y +CONFIG_RODATA_FULL_DEFAULT_ENABLED=y +CONFIG_RPS=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_SERIAL_8250_AIROHA=y +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_NR_UARTS=5 +CONFIG_SERIAL_8250_RUNTIME_UARTS=5 +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SGL_ALLOC=y +CONFIG_SKB_EXTENSIONS=y +CONFIG_SMP=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SOC_BUS=y +CONFIG_SOFTIRQ_ON_OWN_STACK=y +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +# CONFIG_SPI_AIROHA_EN7523 is not set +CONFIG_SPI_AIROHA_SNFI=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPLIT_PMD_PTLOCKS=y +CONFIG_SPLIT_PTE_PTLOCKS=y +CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y +CONFIG_SWIOTLB=y +CONFIG_SWPHY=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_OF=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TOOLS_SUPPORT_RELR=y +CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +# CONFIG_UNMAP_KERNEL_AT_EL0 is not set +CONFIG_USER_STACKTRACE_SUPPORT=y +CONFIG_VDSO_GETRANDOM=y +CONFIG_VMAP_STACK=y +CONFIG_WANT_DEV_COREDUMP=y +CONFIG_WATCHDOG_CORE=y +# CONFIG_WLAN is not set +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_XFRM_AH=y +CONFIG_XFRM_ALGO=y +CONFIG_XFRM_ESP=y +CONFIG_XFRM_IPCOMP=y +CONFIG_XFRM_MIGRATE=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZONE_DMA32=y +CONFIG_ZSTD_COMMON=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y diff --git a/lede/target/linux/airoha/an7583/base-files/etc/board.d/02_network b/lede/target/linux/airoha/an7583/base-files/etc/board.d/02_network new file mode 100644 index 0000000000..077d193ed5 --- /dev/null +++ b/lede/target/linux/airoha/an7583/base-files/etc/board.d/02_network @@ -0,0 +1,28 @@ +# +# Copyright (c) 2015 The Linux Foundation. All rights reserved. +# Copyright (c) 2011-2015 OpenWrt.org +# + +. /lib/functions/uci-defaults.sh +. /lib/functions/system.sh + +an7583_setup_interfaces() +{ + local board="$1" + + case "$board" in + airoha,an7583-evb) + ucidef_set_interface_lan "lan1 lan2 lan3 lan4 eth1" + ;; + *) + echo "Unsupported hardware. Network interfaces not initialized" + ;; + esac +} + +board_config_update +board=$(board_name) +an7583_setup_interfaces $board +board_config_flush + +exit 0 diff --git a/lede/target/linux/airoha/an7583/config-6.12 b/lede/target/linux/airoha/an7583/config-6.12 new file mode 100644 index 0000000000..f3d4effeda --- /dev/null +++ b/lede/target/linux/airoha/an7583/config-6.12 @@ -0,0 +1,402 @@ +CONFIG_64BIT=y +CONFIG_AIROHA_CPU_PM_DOMAIN=y +CONFIG_AIROHA_SCU_SSR=y +CONFIG_AIROHA_THERMAL=y +CONFIG_AIROHA_WATCHDOG=y +CONFIG_AMPERE_ERRATUM_AC03_CPU_38=y +CONFIG_ARCH_AIROHA=y +CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y +CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y +CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_FORCE_MAX_ORDER=10 +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_ARCH_WANTS_THP_SWAP=y +CONFIG_ARM64=y +CONFIG_ARM64_4K_PAGES=y +CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y +CONFIG_ARM64_PA_BITS=48 +CONFIG_ARM64_PA_BITS_48=y +CONFIG_ARM64_PLATFORM_DEVICES=y +CONFIG_ARM64_TAGGED_ADDR_ABI=y +CONFIG_ARM64_VA_BITS=39 +CONFIG_ARM64_VA_BITS_39=y +# CONFIG_ARM64_VA_BITS_48 is not set +# CONFIG_ARM64_VA_BITS_52 is not set +CONFIG_ARM_AIROHA_SOC_CPUFREQ=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_DEBUG_WX is not set +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_PMU=y +CONFIG_ARM_PMUV3=y +CONFIG_ARM_PSCI_FW=y +CONFIG_ARM_SMCCC_SOC_ID=y +# CONFIG_ARM_SMMU is not set +# CONFIG_ARM_SMMU_V3 is not set +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BLK_PM=y +CONFIG_BUFFER_HEAD=y +CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y +CONFIG_CC_HAVE_SHADOW_CALL_STACK=y +CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_EN7523=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +# CONFIG_COMPAT_32BIT_TIME is not set +# CONFIG_COMPRESSED_INSTALL is not set +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_RMAP=y +CONFIG_CRC16=y +CONFIG_CRC_CCITT=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DEV_EIP93=y +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_DRBG_HMAC=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKS=64 +CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE=32 +CONFIG_CRYPTO_JITTERENTROPY_OSR=1 +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA3=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_MISC=y +CONFIG_DMADEVICES=y +CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_NEED_SYNC=y +CONFIG_DMA_OF=y +CONFIG_DMA_OPS_HELPERS=y +CONFIG_DTC=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EXT4_FS=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FRAME_POINTER=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FUNCTION_ALIGNMENT=4 +CONFIG_FUNCTION_ALIGNMENT_4B=y +CONFIG_FWNODE_MDIO=y +CONFIG_FW_CACHE=y +# CONFIG_FW_LOADER_USER_HELPER is not set +CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_DEVICES=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IOREMAP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GLOB=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_EN7523=y +CONFIG_GPIO_GENERIC=y +CONFIG_GRO_CELLS=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HOTPLUG_CORE_SYNC=y +CONFIG_HOTPLUG_CORE_SYNC_DEAD=y +CONFIG_HOTPLUG_CPU=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_AIROHA=y +# CONFIG_HISILICON_ERRATUM_162100801 is not set +# CONFIG_IDPF is not set +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +# CONFIG_INET_ESP_OFFLOAD is not set +CONFIG_INET_IPCOMP=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_TUNNEL=y +CONFIG_IO_URING=y +CONFIG_IPC_NS=y +CONFIG_IPV6=y +CONFIG_IPV6_MULTIPLE_TABLES=y +# CONFIG_IPV6_SUBTREES is not set +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_COMMON=y +# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_MSI_LIB=y +CONFIG_IRQ_WORK=y +CONFIG_JBD2=y +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LRU_GEN_WALKS_MMU=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_AIROHA=y +CONFIG_MDIO_DEVRES=y +# CONFIG_MEDIATEK_GE_SOC_PHY is not set +# CONFIG_MEMCG is not set +CONFIG_MFD_SYSCON=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_CQHCI=y +CONFIG_MMC_MTK=y +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_MODULES_TREE_LOOKUP=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_MTK_BMT=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_FIT_FW=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NET_AIROHA=y +CONFIG_NET_AIROHA_FLOW_STATS=y +CONFIG_NET_AIROHA_NPU=y +CONFIG_NET_DEVLINK=y +CONFIG_NET_DSA=y +CONFIG_NET_DSA_MT7530=y +CONFIG_NET_DSA_MT7530_MDIO=y +CONFIG_NET_DSA_MT7530_MMIO=y +CONFIG_NET_DSA_TAG_MTK=y +CONFIG_NET_FLOW_LIMIT=y +# CONFIG_NET_MEDIATEK_SOC is not set +CONFIG_NET_SELFTESTS=y +# CONFIG_NET_VENDOR_3COM is not set +CONFIG_NET_VENDOR_AIROHA=y +# CONFIG_NET_VENDOR_MEDIATEK is not set +CONFIG_NLS=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=4 +CONFIG_NVMEM=y +CONFIG_NVMEM_BLOCK=y +CONFIG_NVMEM_LAYOUTS=y +CONFIG_NVMEM_LAYOUT_ASCII_ENV=y +CONFIG_NVMEM_SYSFS=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_PAGE_POOL=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PARTITION_PERCPU=y +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEASPM=y +# CONFIG_PCIEASPM_DEFAULT is not set +CONFIG_PCIEASPM_PERFORMANCE=y +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_MEDIATEK=y +CONFIG_PCIE_MEDIATEK_GEN3=y +CONFIG_PCIE_PME=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +# CONFIG_PCS_AIROHA_AN7581 is not set +CONFIG_PCS_AIROHA_AN7583=y +CONFIG_PERF_EVENTS=y +CONFIG_PER_VMA_LOCK=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_PHYLIB=y +CONFIG_PHYLIB_LEDS=y +CONFIG_PHYLINK=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PHY_AIROHA_PCIE=y +# CONFIG_PHY_AIROHA_USB is not set +CONFIG_PINCTRL=y +CONFIG_PINCTRL_AIROHA=y +# CONFIG_PINCTRL_MT2712 is not set +# CONFIG_PINCTRL_MT6765 is not set +# CONFIG_PINCTRL_MT6795 is not set +# CONFIG_PINCTRL_MT6797 is not set +# CONFIG_PINCTRL_MT7622 is not set +# CONFIG_PINCTRL_MT7981 is not set +# CONFIG_PINCTRL_MT7986 is not set +# CONFIG_PINCTRL_MT8173 is not set +# CONFIG_PINCTRL_MT8183 is not set +# CONFIG_PINCTRL_MT8186 is not set +# CONFIG_PINCTRL_MT8188 is not set +# CONFIG_PINCTRL_MT8516 is not set +CONFIG_PM=y +CONFIG_PM_CLK=y +CONFIG_PM_OPP=y +CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_SUPPLY=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RAS=y +CONFIG_RATIONAL=y +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_RELOCATABLE=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RFS_ACCEL=y +CONFIG_RODATA_FULL_DEFAULT_ENABLED=y +CONFIG_RPS=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_SERIAL_8250_AIROHA=y +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_NR_UARTS=5 +CONFIG_SERIAL_8250_RUNTIME_UARTS=5 +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SGL_ALLOC=y +CONFIG_SKB_EXTENSIONS=y +CONFIG_SMP=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SOC_BUS=y +CONFIG_SOFTIRQ_ON_OWN_STACK=y +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +# CONFIG_SPI_AIROHA_EN7523 is not set +CONFIG_SPI_AIROHA_SNFI=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y +CONFIG_SWIOTLB=y +CONFIG_SWPHY=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +# CONFIG_TEST_FPU is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_OF=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +# CONFIG_UNMAP_KERNEL_AT_EL0 is not set +CONFIG_USER_STACKTRACE_SUPPORT=y +CONFIG_VDSO_GETRANDOM=y +CONFIG_VMAP_STACK=y +CONFIG_WATCHDOG_CORE=y +# CONFIG_WLAN is not set +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_XFRM_AH=y +CONFIG_XFRM_ALGO=y +CONFIG_XFRM_ESP=y +CONFIG_XFRM_IPCOMP=y +CONFIG_XFRM_MIGRATE=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZONE_DMA32=y +CONFIG_ZSTD_COMMON=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y diff --git a/lede/target/linux/airoha/an7583/config-6.6 b/lede/target/linux/airoha/an7583/config-6.6 new file mode 100644 index 0000000000..f3d4effeda --- /dev/null +++ b/lede/target/linux/airoha/an7583/config-6.6 @@ -0,0 +1,402 @@ +CONFIG_64BIT=y +CONFIG_AIROHA_CPU_PM_DOMAIN=y +CONFIG_AIROHA_SCU_SSR=y +CONFIG_AIROHA_THERMAL=y +CONFIG_AIROHA_WATCHDOG=y +CONFIG_AMPERE_ERRATUM_AC03_CPU_38=y +CONFIG_ARCH_AIROHA=y +CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y +CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y +CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_FORCE_MAX_ORDER=10 +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_ARCH_WANTS_THP_SWAP=y +CONFIG_ARM64=y +CONFIG_ARM64_4K_PAGES=y +CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y +CONFIG_ARM64_PA_BITS=48 +CONFIG_ARM64_PA_BITS_48=y +CONFIG_ARM64_PLATFORM_DEVICES=y +CONFIG_ARM64_TAGGED_ADDR_ABI=y +CONFIG_ARM64_VA_BITS=39 +CONFIG_ARM64_VA_BITS_39=y +# CONFIG_ARM64_VA_BITS_48 is not set +# CONFIG_ARM64_VA_BITS_52 is not set +CONFIG_ARM_AIROHA_SOC_CPUFREQ=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_DEBUG_WX is not set +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_PMU=y +CONFIG_ARM_PMUV3=y +CONFIG_ARM_PSCI_FW=y +CONFIG_ARM_SMCCC_SOC_ID=y +# CONFIG_ARM_SMMU is not set +# CONFIG_ARM_SMMU_V3 is not set +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BLK_PM=y +CONFIG_BUFFER_HEAD=y +CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y +CONFIG_CC_HAVE_SHADOW_CALL_STACK=y +CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_EN7523=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +# CONFIG_COMPAT_32BIT_TIME is not set +# CONFIG_COMPRESSED_INSTALL is not set +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_RMAP=y +CONFIG_CRC16=y +CONFIG_CRC_CCITT=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DEV_EIP93=y +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_DRBG_HMAC=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKS=64 +CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE=32 +CONFIG_CRYPTO_JITTERENTROPY_OSR=1 +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA3=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_MISC=y +CONFIG_DMADEVICES=y +CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_NEED_SYNC=y +CONFIG_DMA_OF=y +CONFIG_DMA_OPS_HELPERS=y +CONFIG_DTC=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EXT4_FS=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FRAME_POINTER=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FUNCTION_ALIGNMENT=4 +CONFIG_FUNCTION_ALIGNMENT_4B=y +CONFIG_FWNODE_MDIO=y +CONFIG_FW_CACHE=y +# CONFIG_FW_LOADER_USER_HELPER is not set +CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_DEVICES=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IOREMAP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GLOB=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_EN7523=y +CONFIG_GPIO_GENERIC=y +CONFIG_GRO_CELLS=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HOTPLUG_CORE_SYNC=y +CONFIG_HOTPLUG_CORE_SYNC_DEAD=y +CONFIG_HOTPLUG_CPU=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_AIROHA=y +# CONFIG_HISILICON_ERRATUM_162100801 is not set +# CONFIG_IDPF is not set +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +# CONFIG_INET_ESP_OFFLOAD is not set +CONFIG_INET_IPCOMP=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_TUNNEL=y +CONFIG_IO_URING=y +CONFIG_IPC_NS=y +CONFIG_IPV6=y +CONFIG_IPV6_MULTIPLE_TABLES=y +# CONFIG_IPV6_SUBTREES is not set +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_COMMON=y +# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_MSI_LIB=y +CONFIG_IRQ_WORK=y +CONFIG_JBD2=y +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LRU_GEN_WALKS_MMU=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_AIROHA=y +CONFIG_MDIO_DEVRES=y +# CONFIG_MEDIATEK_GE_SOC_PHY is not set +# CONFIG_MEMCG is not set +CONFIG_MFD_SYSCON=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_CQHCI=y +CONFIG_MMC_MTK=y +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_MODULES_TREE_LOOKUP=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_MTK_BMT=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_FIT_FW=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NET_AIROHA=y +CONFIG_NET_AIROHA_FLOW_STATS=y +CONFIG_NET_AIROHA_NPU=y +CONFIG_NET_DEVLINK=y +CONFIG_NET_DSA=y +CONFIG_NET_DSA_MT7530=y +CONFIG_NET_DSA_MT7530_MDIO=y +CONFIG_NET_DSA_MT7530_MMIO=y +CONFIG_NET_DSA_TAG_MTK=y +CONFIG_NET_FLOW_LIMIT=y +# CONFIG_NET_MEDIATEK_SOC is not set +CONFIG_NET_SELFTESTS=y +# CONFIG_NET_VENDOR_3COM is not set +CONFIG_NET_VENDOR_AIROHA=y +# CONFIG_NET_VENDOR_MEDIATEK is not set +CONFIG_NLS=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=4 +CONFIG_NVMEM=y +CONFIG_NVMEM_BLOCK=y +CONFIG_NVMEM_LAYOUTS=y +CONFIG_NVMEM_LAYOUT_ASCII_ENV=y +CONFIG_NVMEM_SYSFS=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_PAGE_POOL=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PARTITION_PERCPU=y +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEASPM=y +# CONFIG_PCIEASPM_DEFAULT is not set +CONFIG_PCIEASPM_PERFORMANCE=y +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_MEDIATEK=y +CONFIG_PCIE_MEDIATEK_GEN3=y +CONFIG_PCIE_PME=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +# CONFIG_PCS_AIROHA_AN7581 is not set +CONFIG_PCS_AIROHA_AN7583=y +CONFIG_PERF_EVENTS=y +CONFIG_PER_VMA_LOCK=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_PHYLIB=y +CONFIG_PHYLIB_LEDS=y +CONFIG_PHYLINK=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PHY_AIROHA_PCIE=y +# CONFIG_PHY_AIROHA_USB is not set +CONFIG_PINCTRL=y +CONFIG_PINCTRL_AIROHA=y +# CONFIG_PINCTRL_MT2712 is not set +# CONFIG_PINCTRL_MT6765 is not set +# CONFIG_PINCTRL_MT6795 is not set +# CONFIG_PINCTRL_MT6797 is not set +# CONFIG_PINCTRL_MT7622 is not set +# CONFIG_PINCTRL_MT7981 is not set +# CONFIG_PINCTRL_MT7986 is not set +# CONFIG_PINCTRL_MT8173 is not set +# CONFIG_PINCTRL_MT8183 is not set +# CONFIG_PINCTRL_MT8186 is not set +# CONFIG_PINCTRL_MT8188 is not set +# CONFIG_PINCTRL_MT8516 is not set +CONFIG_PM=y +CONFIG_PM_CLK=y +CONFIG_PM_OPP=y +CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_SUPPLY=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RAS=y +CONFIG_RATIONAL=y +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_RELOCATABLE=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RFS_ACCEL=y +CONFIG_RODATA_FULL_DEFAULT_ENABLED=y +CONFIG_RPS=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_SERIAL_8250_AIROHA=y +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_NR_UARTS=5 +CONFIG_SERIAL_8250_RUNTIME_UARTS=5 +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SGL_ALLOC=y +CONFIG_SKB_EXTENSIONS=y +CONFIG_SMP=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SOC_BUS=y +CONFIG_SOFTIRQ_ON_OWN_STACK=y +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +# CONFIG_SPI_AIROHA_EN7523 is not set +CONFIG_SPI_AIROHA_SNFI=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y +CONFIG_SWIOTLB=y +CONFIG_SWPHY=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +# CONFIG_TEST_FPU is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_OF=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +# CONFIG_UNMAP_KERNEL_AT_EL0 is not set +CONFIG_USER_STACKTRACE_SUPPORT=y +CONFIG_VDSO_GETRANDOM=y +CONFIG_VMAP_STACK=y +CONFIG_WATCHDOG_CORE=y +# CONFIG_WLAN is not set +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_XFRM_AH=y +CONFIG_XFRM_ALGO=y +CONFIG_XFRM_ESP=y +CONFIG_XFRM_IPCOMP=y +CONFIG_XFRM_MIGRATE=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZONE_DMA32=y +CONFIG_ZSTD_COMMON=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y diff --git a/lede/target/linux/airoha/an7583/target.mk b/lede/target/linux/airoha/an7583/target.mk new file mode 100644 index 0000000000..dacbe0928e --- /dev/null +++ b/lede/target/linux/airoha/an7583/target.mk @@ -0,0 +1,11 @@ +ARCH:=aarch64 +SUBTARGET:=an7583 +BOARDNAME:=AN7583 +CPU_TYPE:=cortex-a53 +KERNELNAME:=Image dtbs +FEATURES+=pwm source-only + +define Target/Description + Build firmware images for Airoha an7583 ARM based boards. +endef + diff --git a/lede/target/linux/airoha/dts/an7581-evb-emmc.dts b/lede/target/linux/airoha/dts/an7581-evb-emmc.dts index 26d446e2a1..25d9b87af0 100644 --- a/lede/target/linux/airoha/dts/an7581-evb-emmc.dts +++ b/lede/target/linux/airoha/dts/an7581-evb-emmc.dts @@ -57,6 +57,13 @@ }; }; + pcie2_rst_pins: pcie2-rst-pins { + conf { + pins = "pcie_reset2"; + drive-open-drain = <1>; + }; + }; + gswp1_led0_pins: gswp1-led0-pins { mux { function = "phy1_led0"; @@ -99,6 +106,17 @@ }; }; +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; + + mediatek,u3p-dis-msk = <0x1>; + phys = <&usb1_phy PHY_TYPE_USB2>; +}; + &mmc0 { pinctrl-names = "default", "state_uhs"; pinctrl-0 = <&mmc_pins>; @@ -156,6 +174,46 @@ status = "okay"; }; +&pcie2 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie2_rst_pins>; + status = "okay"; +}; + +&mdio { + as21xx_1: ethernet-phy@1d { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <0x1d>; + + firmware-name = "as21x1x_fw.bin"; + + reset-deassert-us = <1000000>; + reset-assert-us = <1000000>; + reset-gpios = <&en7581_pinctrl 31 GPIO_ACTIVE_LOW>; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <0>; + default-state = "keep"; + }; + + led@1 { + reg = <1>; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <1>; + default-state = "keep"; + }; + }; + }; +}; + ð { status = "okay"; }; @@ -164,6 +222,13 @@ status = "okay"; }; +&gdm4 { + status = "okay"; + + phy-handle = <&as21xx_1>; + phy-mode = "usxgmii"; +}; + &switch { pinctrl-names = "default"; pinctrl-0 = <&mdio_pins>; diff --git a/lede/target/linux/airoha/dts/an7581-xg-040g-md.dts b/lede/target/linux/airoha/dts/an7581-xg-040g-md.dts new file mode 100644 index 0000000000..11fe8b9973 --- /dev/null +++ b/lede/target/linux/airoha/dts/an7581-xg-040g-md.dts @@ -0,0 +1,265 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/dts-v1/; + +#include +#include +#include +#include "an7581.dtsi" + +/ { + model = "Nokia Bell XG-040G-MD"; + compatible = "bell,xg-040g-md", "airoha,an7581"; + + efuse-banks { + compatible = "airoha,an7581-efuses"; + #address-cells = <0x01>; + #size-cells = <0x00>; + + bank@0 { + reg = <0x00>; + }; + + bank@1 { + reg = <0x01>; + }; + }; + + aliases { + serial0 = &uart1; + }; + + chosen { + bootargs = "console=ttyS0,115200n8 loglevel=7 earlycon"; + stdout-path = "serial0:115200n8"; + bootargs-append = " ubi.mtd=rootfs,2048 rootfstype=squashfs loglevel=8 ubi.block=0,rootfs ro init=/etc/preinit"; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x2 0x00000000>; + }; + + leds { + compatible = "gpio-leds"; + + led-0 { + label = "pwr"; + color = <0x01>; + function = "power"; + gpios = <0x24 0x11 0x01>; + default-state = "on"; + }; + + led-2 { + label = "pon"; + color = <0x02>; + function = "status"; + gpios = <0x24 0x13 0x01>; + default-state = "off"; + }; + + led-3 { + label = "internet"; + color = <0x02>; + function = "status"; + gpios = <0x24 0x14 0x01>; + default-state = "on"; + }; + }; +}; + +&en7581_pinctrl { + gpio-ranges = <&en7581_pinctrl 0 13 47>; + + mdio_pins: mdio-pins { + mux { + function = "mdio"; + groups = "mdio"; + }; + + conf { + pins = "gpio2"; + output-high; + }; + }; + + pcie0_rst_pins: pcie0-rst-pins { + conf { + pins = "pcie_reset0"; + drive-open-drain = <1>; + }; + }; + + pcie1_rst_pins: pcie1-rst-pins { + conf { + pins = "pcie_reset1"; + drive-open-drain = <1>; + }; + }; + + gswp1_led0_pins: gswp1-led0-pins { + mux { + function = "phy1_led0"; + pins = "gpio33"; + }; + }; + + gswp2_led0_pins: gswp2-led0-pins { + mux { + function = "phy2_led0"; + pins = "gpio34"; + }; + }; + + gswp3_led0_pins: gswp3-led0-pins { + mux { + function = "phy3_led0"; + pins = "gpio35"; + }; + }; + + gswp4_led0_pins: gswp4-led0-pins { + mux { + function = "phy4_led0"; + pins = "gpio42"; + }; + }; + + pwm_gpio18_idx10_pins: pwm-gpio18-idx10-pins { + function = "pwm"; + pins = "gpio18"; + output-enable; + }; +}; + +&snfi { + status = "okay"; +}; + + +&spi_nand { + #address-cells = <1>; + #size-cells = <1>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bootloader"; + reg = <0x0 0x00080000>; + read-only; + }; + + partition@80000 { + label = "env"; + reg = <0x00080000 0x00080000>; + }; + + partition@100000 { + label = "ubi"; + reg = <0x00100000 0x00>; + }; + }; +}; + +&i2c0 { + status = "okay"; +}; + +&npu { + status = "okay"; +}; + +ð { + status = "okay"; +}; + +&gdm1 { + status = "okay"; +}; + +&gdm4 { + status = "okay"; + phy-handle = <&phy15>; + phy-mode = "2500base-x"; + label = "lan1"; +}; + +&switch { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + + ports { + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan3"; + }; + + port@4 { + status = "okay"; + label = "lan4"; + }; + }; + + mdio { + ethernet-phy@1 { + status = "okay"; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gswp2_led0_pins>; + + leds { + gsw-phy1-led0@0 { + reg = <0x00>; + function = LED_FUNCTION_LAN; + status = "okay"; + active-low; + }; + }; + }; + + ethernet-phy@2 { + status = "okay"; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gswp3_led0_pins>; + + leds { + gsw-phy2-led0@0 { + reg = <0x00>; + function = LED_FUNCTION_LAN; + status = "okay"; + active-low; + }; + }; + }; + + ethernet-phy@3 { + status = "okay"; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gswp4_led0_pins>; + + leds { + gsw-phy3-led0@0 { + reg = <0x00>; + function = LED_FUNCTION_LAN; + status = "okay"; + active-low; + }; + }; + }; + + phy15: ethernet-phy@f { + /* Airoha EN8811H */ + compatible = "ethernet-phy-id03a2.a411", "ethernet-phy-ieee802.3-c45"; + reg = <15>; + phy-mode = "2500base-x"; + phandle = <0x38>; + }; + }; +}; diff --git a/lede/target/linux/airoha/dts/an7581.dtsi b/lede/target/linux/airoha/dts/an7581.dtsi index 2637b24142..32bc6b5df7 100644 --- a/lede/target/linux/airoha/dts/an7581.dtsi +++ b/lede/target/linux/airoha/dts/an7581.dtsi @@ -3,6 +3,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -438,6 +441,48 @@ status = "disabled"; }; + pon_pcs: pcs@1fa08000 { + compatible = "airoha,an7581-pcs-pon"; + reg = <0x0 0x1fa08000 0x0 0x1000>, + <0x0 0x1fa80000 0x0 0x60>, + <0x0 0x1fa80a00 0x0 0x164>, + <0x0 0x1fa84000 0x0 0x450>, + <0x0 0x1fa85900 0x0 0x338>, + <0x0 0x1fa86000 0x0 0x300>, + <0x0 0x1fa8a000 0x0 0x1000>, + <0x0 0x1fa8b000 0x0 0x1000>; + reg-names = "xfi_mac", "hsgmii_an", "hsgmii_pcs", + "multi_sgmii", "usxgmii", + "hsgmii_rate_adp", "xfi_ana", "xfi_pma"; + + resets = <&scuclk EN7581_XPON_MAC_RST>, + <&scuclk EN7581_XPON_PHY_RST>; + reset-names = "mac", "phy"; + + airoha,scu = <&scuclk>; + }; + + eth_pcs: pcs@1fa09000 { + compatible = "airoha,an7581-pcs-eth"; + reg = <0x0 0x1fa09000 0x0 0x1000>, + <0x0 0x1fa70000 0x0 0x60>, + <0x0 0x1fa70a00 0x0 0x164>, + <0x0 0x1fa74000 0x0 0x450>, + <0x0 0x1fa75900 0x0 0x338>, + <0x0 0x1fa76000 0x0 0x300>, + <0x0 0x1fa7a000 0x0 0x1000>, + <0x0 0x1fa7b000 0x0 0x1000>; + reg-names = "xfi_mac", "hsgmii_an", "hsgmii_pcs", + "multi_sgmii", "usxgmii", + "hsgmii_rate_adp", "xfi_ana", "xfi_pma"; + + resets = <&scuclk EN7581_XSI_MAC_RST>, + <&scuclk EN7581_XSI_PHY_RST>; + reset-names = "mac", "phy"; + + airoha,scu = <&scuclk>; + }; + chip_scu: syscon@1fa20000 { compatible = "airoha,en7581-chip-scu", "syscon"; reg = <0x0 0x1fa20000 0x0 0x388>; @@ -448,8 +493,8 @@ reg = <0x0 0x1fbe3400 0x0 0xff>; }; - scuclk: clock-controller@1fa20000 { - compatible = "airoha,en7581-scu"; + scuclk: clock-controller@1fb00000 { + compatible = "airoha,en7581-scu", "syscon"; reg = <0x0 0x1fb00000 0x0 0x970>; #clock-cells = <1>; #reset-cells = <1>; @@ -461,6 +506,52 @@ interrupts = ; }; + usb0: usb@1fab0000 { + compatible = "mediatek,mtk-xhci"; + reg = <0x0 0x1fab0000 0x0 0x3e00>, + <0x0 0x1fab3e00 0x0 0x100>; + reg-names = "mac", "ippc"; + interrupts = ; + + phys = <&usb0_phy PHY_TYPE_USB2>, <&usb0_phy PHY_TYPE_USB3>; + + status = "disabled"; + }; + + usb0_phy: phy@1fac0000 { + compatible = "airoha,an7581-usb-phy"; + reg = <0x0 0x1fac0000 0x0 0x10000>; + + airoha,scu = <&scuclk>; + airoha,usb2-monitor-clk-sel = ; + airoha,serdes-port = ; + + #phy-cells = <1>; + }; + + usb1: usb@1fad0000 { + compatible = "mediatek,mtk-xhci"; + reg = <0x0 0x1fad0000 0x0 0x3e00>, + <0x0 0x1fad3e00 0x0 0x100>; + reg-names = "mac", "ippc"; + interrupts = ; + + phys = <&usb1_phy PHY_TYPE_USB2>, <&usb1_phy PHY_TYPE_USB3>; + + status = "disabled"; + }; + + usb1_phy: phy@1fae0000 { + compatible = "airoha,an7581-usb-phy"; + reg = <0x0 0x1fae0000 0x0 0x10000>; + + airoha,scu = <&scuclk>; + airoha,usb2-monitor-clk-sel = ; + airoha,serdes-port = ; + + #phy-cells = <1>; + }; + crypto@1e004000 { compatible = "inside-secure,safexcel-eip93ies"; reg = <0x0 0x1fb70000 0x0 0x1000>; @@ -676,6 +767,49 @@ }; }; + pcie2: pcie@1fc40000 { + compatible = "airoha,en7581-pcie"; + device_type = "pci"; + linux,pci-domain = <2>; + #address-cells = <3>; + #size-cells = <2>; + + reg = <0x0 0x1fc40000 0x0 0x1670>; + reg-names = "pcie-mac"; + + clocks = <&scuclk EN7523_CLK_PCIE>; + clock-names = "sys-ck"; + + phys = <&usb1_phy PHY_TYPE_USB3>; + phy-names = "pcie-phy"; + + ranges = <0x02000000 0 0x28000000 0x0 0x28000000 0 0x4000000>; + + resets = <&scuclk EN7581_PCIE0_RST>, + <&scuclk EN7581_PCIE1_RST>, + <&scuclk EN7581_PCIE2_RST>; + reset-names = "phy-lane0", "phy-lane1", "phy-lane2"; + + mediatek,pbus-csr = <&pbus_csr 0x10 0x14>; + + interrupts = ; + bus-range = <0x00 0xff>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + 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>; + + status = "disabled"; + + pcie_intc2: interrupt-controller { + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + }; + }; + npu: npu@1e900000 { compatible = "airoha,en7581-npu"; reg = <0x0 0x1e900000 0x0 0x313000>; @@ -753,6 +887,22 @@ pause; }; }; + + gdm2: ethernet@2 { + compatible = "airoha,eth-mac"; + reg = <2>; + pcs = <&pon_pcs>; + + status = "disabled"; + }; + + gdm4: ethernet@4 { + compatible = "airoha,eth-mac"; + reg = <4>; + pcs = <ð_pcs>; + + status = "disabled"; + }; }; switch: switch@1fb58000 { @@ -816,7 +966,7 @@ }; }; - mdio { + mdio: mdio { #address-cells = <1>; #size-cells = <0>; diff --git a/lede/target/linux/airoha/dts/an7583-evb-emmc.dts b/lede/target/linux/airoha/dts/an7583-evb-emmc.dts new file mode 100644 index 0000000000..6477832a20 --- /dev/null +++ b/lede/target/linux/airoha/dts/an7583-evb-emmc.dts @@ -0,0 +1,297 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/dts-v1/; + +#include +#include +#include +#include "an7583.dtsi" + +/ { + model = "Airoha AN7583 Evaluation Board"; + compatible = "airoha,an7583-evb", "airoha,an7583", "airoha,en7583"; + + aliases { + serial0 = &uart1; + }; + + chosen { + bootargs = "console=ttyS0,115200 earlycon"; + stdout-path = "serial0:115200n8"; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x2 0x00000000>; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + poll-interval = <100>; + + btn-reset { + label = "reset"; + linux,code = ; + gpios = <&an7583_pinctrl 0 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + compatible = "gpio-leds"; + + led-1 { + label = "pon"; + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&an7583_pinctrl 12 GPIO_ACTIVE_LOW>; + }; + + led-2 { + label = "internet"; + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&an7583_pinctrl 26 GPIO_ACTIVE_LOW>; + }; + + led-3 { + label = "wps"; + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&an7583_pinctrl 31 GPIO_ACTIVE_LOW>; + }; + + led-4 { + label = "los"; + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&an7583_pinctrl 27 GPIO_ACTIVE_LOW>; + }; + + led-5 { + label = "voip_hook"; + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&an7583_pinctrl 29 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&an7583_pinctrl { + gpio-ranges = <&an7583_pinctrl 0 2 53>; + + mdio0_pins: mdio0-pins { + conf { + pins = "mdio_0"; + output-high; + }; + }; + + pcie0_rst_pins: pcie0-rst-pins { + conf { + pins = "pcie_reset0"; + drive-open-drain = <1>; + }; + }; + + pcie1_rst_pins: pcie1-rst-pins { + conf { + pins = "pcie_reset1"; + drive-open-drain = <1>; + }; + }; + + gswp1_led0_pins: gswp1-led0-pins { + mux { + function = "phy1_led0"; + pins = "gpio1"; + }; + }; + + gswp2_led0_pins: gswp2-led0-pins { + mux { + function = "phy2_led0"; + pins = "gpio2"; + }; + }; + + gswp3_led0_pins: gswp3-led0-pins { + mux { + function = "phy3_led0"; + pins = "gpio3"; + }; + }; + + gswp4_led0_pins: gswp4-led0-pins { + mux { + function = "phy4_led0"; + pins = "gpio4"; + }; + }; + + mmc_pins: mmc-pins { + mux { + function = "emmc"; + groups = "emmc"; + }; + }; +}; + +&mmc0 { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc_pins>; + pinctrl-1 = <&mmc_pins>; + status = "okay"; + + #address-cells = <1>; + #size-cells = <0>; + + card@0 { + compatible = "mmc-card"; + reg = <0>; + + block { + compatible = "block-device"; + partitions { + block-partition-factory { + partname = "art"; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x40000 0x1e00>; + }; + + mac_factory_2c0000: mac@2c0000 { + reg = <0x2c0000 0x6>; + }; + + pon_mac_factory_2c0006: pon_mac@2c0006 { + reg = <0x2c0006 0x6>; + }; + + onu_type_factory_2e0000: onu_type@2e0000 { + reg = <0x2e0000 0x10>; + }; + + board_config_factory_2e0010: board_config@2e0010 { + reg = <0x2e0010 0x8>; + }; + }; + }; + }; + }; + }; +}; + +&i2c0 { + status = "okay"; +}; + +&i2c1 { + status = "okay"; +}; + +&mdio_0 { + pinctrl-names = "default"; + pinctrl-0 = <&mdio0_pins>; + + en8811: ethernet-phy@f { + reg = <0xf>; + + reset-gpios = <&an7583_pinctrl 28 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <20000>; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + function = LED_FUNCTION_LAN; + color = ; + function-enumerator = <0>; + default-state = "keep"; + }; + + led@1 { + reg = <1>; + function = LED_FUNCTION_LAN; + color = ; + function-enumerator = <1>; + default-state = "keep"; + }; + }; + }; +}; + +&npu { + status = "okay"; +}; + +ð { + status = "okay"; + nvmem-cells = <&mac_factory_2c0000>; + nvmem-cell-names = "mac"; +}; + +&gdm1 { + status = "okay"; +}; + +&gdm3 { + status = "okay"; + + phy-handle = <&en8811>; + phy-mode = "2500base-x"; +}; + +&switch { + status = "okay"; +}; + +&gsw_phy1 { + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gswp1_led0_pins>; + status = "okay"; +}; + +&gsw_phy1_led0 { + status = "okay"; + active-low; +}; + +&gsw_phy2 { + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gswp2_led0_pins>; + status = "okay"; +}; + +&gsw_phy2_led0 { + status = "okay"; + active-low; +}; + +&gsw_phy3 { + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gswp3_led0_pins>; + status = "okay"; +}; + +&gsw_phy3_led0 { + status = "okay"; + active-low; +}; + +&gsw_phy4 { + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gswp4_led0_pins>; + status = "okay"; +}; + +&gsw_phy4_led0 { + status = "okay"; + active-low; +}; diff --git a/lede/target/linux/airoha/dts/an7583-evb.dts b/lede/target/linux/airoha/dts/an7583-evb.dts new file mode 100644 index 0000000000..95ac20e727 --- /dev/null +++ b/lede/target/linux/airoha/dts/an7583-evb.dts @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/dts-v1/; + +#include +#include +#include +#include "an7583.dtsi" + +/ { + model = "Airoha AN7583 Evaluation Board"; + compatible = "airoha,an7583-evb", "airoha,an7583", "airoha,en7583"; + + aliases { + serial0 = &uart1; + }; + + chosen { + bootargs = "console=ttyS0,115200 earlycon"; + stdout-path = "serial0:115200n8"; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x2 0x00000000>; + }; +}; + +&an7583_pinctrl { + gpio-ranges = <&an7583_pinctrl 0 2 53>; + + mdio0_pins: mdio0-pins { + conf { + pins = "mdio_0"; + output-high; + }; + }; + + pcie0_rst_pins: pcie0-rst-pins { + conf { + pins = "pcie_reset0"; + drive-open-drain = <1>; + }; + }; + + pcie1_rst_pins: pcie1-rst-pins { + conf { + pins = "pcie_reset1"; + drive-open-drain = <1>; + }; + }; + + gswp1_led0_pins: gswp1-led0-pins { + mux { + function = "phy1_led0"; + pins = "gpio1"; + }; + }; +}; + +&snfi { + status = "okay"; +}; + + +&spi_nand { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + bl2@0 { + label = "bl2"; + reg = <0x0 0x20000>; + }; + + ubi@20000 { + label = "ubi"; + reg = <0x20000 0x0>; + }; + }; +}; + +&i2c0 { + status = "okay"; +}; + +&npu { + status = "okay"; +}; + +ð { + status = "okay"; +}; + +&gdm1 { + status = "okay"; +}; + +&switch { + status = "okay"; +}; + +&gsw_phy1 { + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gswp1_led0_pins>; + status = "okay"; +}; + +&gsw_phy1_led0 { + status = "okay"; + active-low; +}; + +&gsw_port2 { + status = "disabled"; +}; + +&gsw_port3 { + status = "disabled"; +}; + +&gsw_port4 { + status = "disabled"; +}; + +&gsw_phy2 { + status = "disabled"; +}; + +&gsw_phy3 { + status = "disabled"; +}; + +&gsw_phy4 { + status = "disabled"; +}; + +&mdio_0 { + pinctrl-names = "default"; + pinctrl-0 = <&mdio0_pins>; + + /* Present but not HW connected to GDM port */ + /* + * as21xx_0: ethernet-phy@1d { + * reg = <0x1d>; + * compatible = "ethernet-phy-ieee802.3-c45"; + * status = "disabled"; + * + * firmware-name = "as21x1x_fw.bin"; + * + * reset-deassert-us = <350000>; + * reset-assert-us = <200000>; + * reset-gpios = <&an7583_pinctrl 34 GPIO_ACTIVE_LOW>; + * + * leds { + * #address-cells = <1>; + * #size-cells = <0>; + * + * led@0 { + * reg = <0>; + * color = ; + * function = LED_FUNCTION_LAN; + * function-enumerator = <0>; + * default-state = "keep"; + * }; + * + * led@1 { + * reg = <1>; + * color = ; + * function = LED_FUNCTION_LAN; + * function-enumerator = <1>; + * default-state = "keep"; + * }; + * }; + * }; + */ + + as21xx_1: ethernet-phy@1f { + reg = <0x1f>; + compatible = "ethernet-phy-ieee802.3-c45"; + + firmware-name = "as21x1x_fw.bin"; + + reset-deassert-us = <350000>; + reset-assert-us = <200000>; + reset-gpios = <&an7583_pinctrl 35 GPIO_ACTIVE_LOW>; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <0>; + default-state = "keep"; + }; + + led@1 { + reg = <1>; + color = ; + function = LED_FUNCTION_LAN; + function-enumerator = <1>; + default-state = "keep"; + }; + }; + }; +}; + +/* GDM2 seems to be connected to PON */ +/* + *&gdm2 { + * status = "disabled"; + * + * phy-handle = <&as21xx_0>; + * phy-mode = "usxgmii"; + *}; + */ + +&gdm3 { + status = "okay"; + + phy-handle = <&as21xx_1>; + phy-mode = "usxgmii"; +}; diff --git a/lede/target/linux/airoha/dts/an7583.dtsi b/lede/target/linux/airoha/dts/an7583.dtsi new file mode 100644 index 0000000000..49a0616a39 --- /dev/null +++ b/lede/target/linux/airoha/dts/an7583.dtsi @@ -0,0 +1,844 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) + +#include +#include +#include +#include +#include +#include +#include + +/ { + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + atf@80000000 { + no-map; + reg = <0x0 0x80000000 0x0 0x200000>; + }; + + npu_binary: npu-binary@84000000 { + no-map; + reg = <0x0 0x84000000 0x0 0xa00000>; + }; + + qdma0_buf: qdma0-buf@87000000 { + no-map; + reg = <0x0 0x87000000 0x0 0x2000000>; + }; + + qdma1_buf: qdma1-buf@89000000 { + no-map; + reg = <0x0 0x89000000 0x0 0x1000000>; + }; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu-map { + cluster0 { + core0 { + cpu = <&cpu0>; + }; + + core1 { + cpu = <&cpu1>; + }; + }; + }; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x0>; + operating-points-v2 = <&cpu_opp_table>; + enable-method = "psci"; + clocks = <&cpufreq>; + clock-names = "cpu"; + power-domains = <&cpufreq>; + power-domain-names = "perf"; + next-level-cache = <&l2>; + #cooling-cells = <2>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a53"; + reg = <0x1>; + operating-points-v2 = <&cpu_opp_table>; + enable-method = "psci"; + clocks = <&cpufreq>; + clock-names = "cpu"; + power-domains = <&cpufreq>; + power-domain-names = "perf"; + next-level-cache = <&l2>; + #cooling-cells = <2>; + }; + + l2: l2-cache { + compatible = "cache"; + cache-size = <0x80000>; + cache-line-size = <64>; + cache-level = <2>; + cache-unified; + }; + }; + + cpufreq: cpufreq { + compatible = "airoha,en7581-cpufreq"; + + operating-points-v2 = <&cpu_smcc_opp_table>; + + #power-domain-cells = <0>; + #clock-cells = <0>; + }; + + cpu_opp_table: opp-table { + compatible = "operating-points-v2"; + opp-shared; + + opp-500000000 { + opp-hz = /bits/ 64 <500000000>; + required-opps = <&smcc_opp0>; + }; + + opp-550000000 { + opp-hz = /bits/ 64 <550000000>; + required-opps = <&smcc_opp1>; + }; + + opp-600000000 { + opp-hz = /bits/ 64 <600000000>; + required-opps = <&smcc_opp2>; + }; + + opp-650000000 { + opp-hz = /bits/ 64 <650000000>; + required-opps = <&smcc_opp3>; + }; + + opp-7000000000 { + opp-hz = /bits/ 64 <700000000>; + required-opps = <&smcc_opp4>; + }; + + opp-7500000000 { + opp-hz = /bits/ 64 <750000000>; + required-opps = <&smcc_opp5>; + }; + + opp-8000000000 { + opp-hz = /bits/ 64 <800000000>; + required-opps = <&smcc_opp6>; + }; + + opp-8500000000 { + opp-hz = /bits/ 64 <850000000>; + required-opps = <&smcc_opp7>; + }; + + opp-9000000000 { + opp-hz = /bits/ 64 <900000000>; + required-opps = <&smcc_opp8>; + }; + + opp-9500000000 { + opp-hz = /bits/ 64 <950000000>; + required-opps = <&smcc_opp9>; + }; + + opp-10000000000 { + opp-hz = /bits/ 64 <1000000000>; + required-opps = <&smcc_opp10>; + }; + + opp-10500000000 { + opp-hz = /bits/ 64 <1050000000>; + required-opps = <&smcc_opp11>; + }; + + opp-11000000000 { + opp-hz = /bits/ 64 <1100000000>; + required-opps = <&smcc_opp12>; + }; + + opp-11500000000 { + opp-hz = /bits/ 64 <1150000000>; + required-opps = <&smcc_opp13>; + }; + + opp-12000000000 { + opp-hz = /bits/ 64 <1200000000>; + required-opps = <&smcc_opp14>; + }; + }; + + cpu_smcc_opp_table: opp-table-cpu-smcc { + compatible = "operating-points-v2"; + + smcc_opp0: opp0 { + opp-level = <0>; + }; + + smcc_opp1: opp1 { + opp-level = <1>; + }; + + smcc_opp2: opp2 { + opp-level = <2>; + }; + + smcc_opp3: opp3 { + opp-level = <3>; + }; + + smcc_opp4: opp4 { + opp-level = <4>; + }; + + smcc_opp5: opp5 { + opp-level = <5>; + }; + + smcc_opp6: opp6 { + opp-level = <6>; + }; + + smcc_opp7: opp7 { + opp-level = <7>; + }; + + smcc_opp8: opp8 { + opp-level = <8>; + }; + + smcc_opp9: opp9 { + opp-level = <9>; + }; + + smcc_opp10: opp10 { + opp-level = <10>; + }; + + smcc_opp11: opp11 { + opp-level = <11>; + }; + + smcc_opp12: opp12 { + opp-level = <12>; + }; + + smcc_opp13: opp13 { + opp-level = <13>; + }; + + smcc_opp14: opp14 { + opp-level = <14>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupt-parent = <&gic>; + interrupts = , + , + , + ; + }; + + thermal-zones { + cpu_thermal: cpu-thermal { + polling-delay-passive = <10000>; + polling-delay = <5000>; + + thermal-sensors = <&thermal 0>; + + trips { + cpu_hot: cpu-hot { + temperature = <95000>; + hysteresis = <1000>; + type = "hot"; + }; + + cpu-critical { + temperature = <110000>; + hysteresis = <1000>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_hot>; + cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, + <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + }; + + clk25m: oscillator { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + clock-output-names = "clkxtal"; + }; + + sys_hclk: clk-oscillator-100mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <100000000>; + clock-output-names = "sys_hclk"; + }; + + vmmc_3v3: regulator-vmmc-3v3 { + compatible = "regulator-fixed"; + regulator-name = "vmmc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + sfp1: sfp1 { + compatible = "sff,sfp"; + }; + + sfp2: sfp2 { + compatible = "sff,sfp"; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gic: interrupt-controller@9000000 { + compatible = "arm,gic-v3"; + interrupt-controller; + #interrupt-cells = <3>; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x0 0x09000000 0x0 0x20000>, + <0x0 0x09080000 0x0 0x80000>, + <0x0 0x09400000 0x0 0x2000>, + <0x0 0x09500000 0x0 0x2000>, + <0x0 0x09600000 0x0 0x20000>; + interrupts = ; + }; + + chip_scu: syscon@1fa20000 { + compatible = "airoha,en7581-chip-scu", "syscon", "simple-mfd"; + reg = <0x0 0x1fa20000 0x0 0x388>; + + thermal: thermal { + compatible = "airoha,an7583-thermal"; + + #thermal-sensor-cells = <0>; + }; + }; + + pbus_csr: syscon@1fbe3400 { + compatible = "airoha,en7581-pbus-csr", "syscon"; + reg = <0x0 0x1fbe3400 0x0 0xff>; + }; + + scuclk: system-controller@1fa20000 { + compatible = "airoha,an7583-scu", "syscon"; + reg = <0x0 0x1fb00000 0x0 0x970>; + + #address-cells = <1>; + #size-cells = <0>; + + #clock-cells = <1>; + #reset-cells = <1>; + + airoha,chip-scu = <&chip_scu>; + + mdio_0: mdio-bus@c8 { + compatible = "airoha,an7583-mdio"; + reg = <0xc8>; + + clocks = <&scuclk AN7583_CLK_MDIO0>; + resets = <&scuclk AN7583_MDIO0>; + }; + + mdio_1: mdio-bus@cc { + compatible = "airoha,an7583-mdio"; + reg = <0xcc>; + + clocks = <&scuclk AN7583_CLK_MDIO1>; + resets = <&scuclk AN7583_MDIO1>; + }; + }; + + system-controller@1fbf0200 { + compatible = "syscon", "simple-mfd"; + reg = <0x0 0x1fbf0200 0x0 0xc0>; + + an7583_pinctrl: pinctrl { + compatible = "airoha,an7583-pinctrl"; + + interrupt-parent = <&gic>; + interrupts = ; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + }; + + i2cclock: i2cclock@0 { + #clock-cells = <0>; + compatible = "fixed-clock"; + + /* 20 MHz */ + clock-frequency = <20000000>; + }; + + i2c0: i2c0@1fbf8000 { + compatible = "airoha,an7581-i2c"; + reg = <0x0 0x1fbf8000 0x0 0x100>; + + clocks = <&i2cclock>; + + /* 100 kHz */ + clock-frequency = <100000>; + #address-cells = <1>; + #size-cells = <0>; + + status = "disable"; + }; + + i2c1: i2c1@1fbf8100 { + compatible = "airoha,an7581-i2c"; + reg = <0x0 0x1fbf8100 0x0 0x100>; + + clocks = <&i2cclock>; + + /* 100 kHz */ + clock-frequency = <100000>; + #address-cells = <1>; + #size-cells = <0>; + + status = "disable"; + }; + + mmc0: mmc@1fa0e000 { + compatible = "mediatek,mt7622-mmc"; + reg = <0x0 0x1fa0e000 0x0 0x1000>, + <0x0 0x1fa0c000 0x0 0x60>; + interrupts = ; + clocks = <&scuclk EN7581_CLK_EMMC>, <&clk25m>; + clock-names = "source", "hclk"; + bus-width = <4>; + max-frequency = <52000000>; + vmmc-supply = <&vmmc_3v3>; + disable-wp; + cap-mmc-highspeed; + non-removable; + + status = "disabled"; + }; + + snfi: spi@1fa10000 { + compatible = "airoha,en7581-snand"; + reg = <0x0 0x1fa10000 0x0 0x140>, + <0x0 0x1fa11000 0x0 0x160>; + + clocks = <&scuclk EN7523_CLK_SPI>; + clock-names = "spi"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + spi_nand: nand@0 { + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <50000000>; + spi-tx-bus-width = <1>; + spi-rx-bus-width = <2>; + }; + }; + + uart1: serial@1fbf0000 { + compatible = "ns16550"; + reg = <0x0 0x1fbf0000 0x0 0x30>; + reg-io-width = <4>; + reg-shift = <2>; + interrupts = ; + clock-frequency = <1843200>; + }; + + watchdog@1fbf0100 { + compatible = "airoha,en7581-wdt"; + reg = <0x0 0x1fbf0100 0x0 0x38>; + + clocks = <&sys_hclk>; + clock-names = "bus"; + }; + + uart2: serial@1fbf0300 { + compatible = "airoha,en7523-uart"; + reg = <0x0 0x1fbf0300 0x0 0x30>; + reg-io-width = <4>; + reg-shift = <2>; + interrupts = ; + clock-frequency = <7372800>; + + status = "disabled"; + }; + + hsuart3: serial@1fbe1000 { + compatible = "airoha,en7523-uart"; + reg = <0x0 0x1fbe1000 0x0 0x40>; + reg-io-width = <4>; + reg-shift = <2>; + interrupts = ; + clock-frequency = <7372800>; + + status = "disabled"; + }; + + uart4: serial@1fbf0600 { + compatible = "airoha,en7523-uart"; + reg = <0x0 0x1fbf0600 0x0 0x30>; + reg-io-width = <4>; + reg-shift = <2>; + interrupts = ; + clock-frequency = <7372800>; + + status = "disabled"; + }; + + uart5: serial@1fbf0700 { + compatible = "airoha,en7523-uart"; + reg = <0x0 0x1fbf0700 0x0 0x30>; + reg-io-width = <4>; + reg-shift = <2>; + interrupts = ; + clock-frequency = <7372800>; + + status = "disabled"; + }; + + crypto@1e004000 { + compatible = "inside-secure,safexcel-eip93ies"; + reg = <0x0 0x1fb70000 0x0 0x1000>; + + interrupts = ; + }; + + npu: npu@1e900000 { + compatible = "airoha,an7583-npu"; + reg = <0x0 0x1e900000 0x0 0x313000>; + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + memory-region = <&npu_binary>; + memory-region-names = "binary"; + + status = "disabled"; + }; + + pon_pcs: pcs@1fa08000 { + compatible = "airoha,an7583-pcs-pon"; + reg = <0x0 0x1fa08000 0x0 0x1000>, + <0x0 0x1fa80000 0x0 0x60>, + <0x0 0x1fa80a00 0x0 0x164>, + <0x0 0x1fa84000 0x0 0x450>, + <0x0 0x1fa85900 0x0 0x338>, + <0x0 0x1fa86000 0x0 0x300>, + <0x0 0x1fa8f000 0x0 0x1000>, + <0x0 0x1fa8e000 0x0 0x1000>; + reg-names = "xfi_mac", "hsgmii_an", "hsgmii_pcs", + "multi_sgmii", "usxgmii", + "hsgmii_rate_adp", "xfi_ana", "xfi_pma"; + + resets = <&scuclk AN7583_XPON_MAC_RST>, + <&scuclk AN7583_XPON_PHY_RST>, + <&scuclk AN7583_XPON_XFI_RST>; + reset-names = "mac", "phy", "xfi"; + + airoha,scu = <&scuclk>; + }; + + eth_pcs: pcs@1fa09000 { + compatible = "airoha,an7583-pcs-eth"; + reg = <0x0 0x1fa09000 0x0 0x1000>, + <0x0 0x1fa70000 0x0 0x60>, + <0x0 0x1fa70a00 0x0 0x164>, + <0x0 0x1fa74000 0x0 0x450>, + <0x0 0x1fa75900 0x0 0x338>, + <0x0 0x1fa76000 0x0 0x300>, + <0x0 0x1fa7f000 0x0 0x1000>, + <0x0 0x1fa7e000 0x0 0x1000>; + reg-names = "xfi_mac", "hsgmii_an", "hsgmii_pcs", + "multi_sgmii", "usxgmii", + "hsgmii_rate_adp", "xfi_ana", "xfi_pma"; + + resets = <&scuclk AN7583_XSI_MAC_RST>, + <&scuclk AN7583_XSI_PHY_RST>; + reset-names = "mac", "phy"; + + airoha,scu = <&scuclk>; + }; + + eth: ethernet@1fb50000 { + compatible = "airoha,an7583-eth"; + reg = <0 0x1fb50000 0 0x2600>, + <0 0x1fb54000 0 0x2000>, + <0 0x1fb56000 0 0x2000>; + reg-names = "fe", "qdma0", "qdma1"; + + resets = <&scuclk AN7583_FE_RST>, + <&scuclk AN7583_FE_PDMA_RST>, + <&scuclk AN7583_FE_QDMA_RST>, + <&scuclk AN7583_DUAL_HSI0_MAC_RST>, + <&scuclk AN7583_DUAL_HSI1_MAC_RST>, + <&scuclk AN7583_XFP_MAC_RST>; + reset-names = "fe", "pdma", "qdma", + "hsi0-mac", "hsi1-mac", + "xfp-mac"; + + interrupts = , + , + , + , + , + , + , + , + , + ; + + memory-region = <&qdma0_buf>, <&qdma1_buf>; + memory-region-names = "qdma0-buf", "qdma1-buf"; + + airoha,npu = <&npu>; + + status = "disabled"; + + #address-cells = <1>; + #size-cells = <0>; + + gdm1: ethernet@1 { + compatible = "airoha,eth-mac"; + reg = <1>; + phy-mode = "internal"; + status = "disabled"; + + fixed-link { + speed = <10000>; + full-duplex; + pause; + }; + }; + + gdm2: ethernet@2 { + compatible = "airoha,eth-mac"; + reg = <2>; + pcs = <&pon_pcs>; + + status = "disabled"; + }; + + gdm3: ethernet@3 { + compatible = "airoha,eth-mac"; + reg = <3>; + pcs = <ð_pcs>; + airoha,gdm-srcport = <0x16>; + + status = "disabled"; + }; + }; + + switch: switch@1fb58000 { + compatible = "airoha,an7583-switch"; + reg = <0 0x1fb58000 0 0x8000>; + resets = <&scuclk AN7583_GSW_RST>; + + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&gic>; + interrupts = ; + + status = "disabled"; + + #address-cells = <1>; + #size-cells = <1>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + gsw_port1: port@1 { + reg = <1>; + label = "lan1"; + phy-mode = "internal"; + phy-handle = <&gsw_phy1>; + }; + + gsw_port2: port@2 { + reg = <2>; + label = "lan2"; + phy-mode = "internal"; + phy-handle = <&gsw_phy2>; + }; + + gsw_port3: port@3 { + reg = <3>; + label = "lan3"; + phy-mode = "internal"; + phy-handle = <&gsw_phy3>; + }; + + gsw_port4: port@4 { + reg = <4>; + label = "lan4"; + phy-mode = "internal"; + phy-handle = <&gsw_phy4>; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gdm1>; + phy-mode = "internal"; + + fixed-link { + speed = <10000>; + full-duplex; + pause; + }; + }; + }; + + mdio: mdio { + #address-cells = <1>; + #size-cells = <0>; + + gsw_phy1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <9>; + phy-mode = "internal"; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + gsw_phy1_led0: gsw-phy1-led0@0 { + reg = <0>; + function = "phy1_led0"; + status = "disabled"; + }; + + gsw_phy1_led1: gsw-phy1-led1@1 { + reg = <1>; + function = "phy1_led1"; + status = "disabled"; + }; + }; + }; + + gsw_phy2: ethernet-phy@2 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <10>; + phy-mode = "internal"; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + gsw_phy2_led0: gsw-phy2-led0@0 { + reg = <0>; + function = "phy2_led0"; + status = "disabled"; + }; + + gsw_phy2_led1: gsw-phy2-led1@1 { + reg = <1>; + function = "phy1_led1"; + status = "disabled"; + }; + }; + }; + + gsw_phy3: ethernet-phy@3 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <11>; + phy-mode = "internal"; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + gsw_phy3_led0: gsw-phy3-led0@0 { + reg = <0>; + function = LED_FUNCTION_LAN; + status = "disabled"; + }; + + gsw_phy3_led1: gsw-phy3-led1@1 { + reg = <1>; + function = LED_FUNCTION_LAN; + status = "disabled"; + }; + }; + }; + + gsw_phy4: ethernet-phy@4 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <12>; + phy-mode = "internal"; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + gsw_phy4_led0: gsw-phy4-led0@0 { + reg = <0>; + function = LED_FUNCTION_LAN; + status = "disabled"; + }; + + gsw_phy4_led1: gsw-phy4-led1@1 { + reg = <1>; + function = LED_FUNCTION_LAN; + status = "disabled"; + }; + }; + }; + }; + }; + }; +}; diff --git a/lede/target/linux/airoha/dts/en7523.dtsi b/lede/target/linux/airoha/dts/en7523.dtsi index 024a89752a..c58cc7f467 100644 --- a/lede/target/linux/airoha/dts/en7523.dtsi +++ b/lede/target/linux/airoha/dts/en7523.dtsi @@ -4,6 +4,7 @@ #include #include #include +#include / { interrupt-parent = <&gic>; @@ -89,6 +90,7 @@ reg = <0x1fa20000 0x400>, <0x1fb00000 0x1000>; #clock-cells = <1>; + #reset-cells = <1>; }; gic: interrupt-controller@9000000 { @@ -203,17 +205,22 @@ }; spi_ctrl: spi_controller@1fa10000 { - compatible = "airoha,en7523-spi"; - reg = <0x1fa10000 0x140>; + compatible = "airoha,en7523-snand"; + reg = <0x1fa10000 0x140>, + <0x1fa11000 0x160>; + + clocks = <&scu EN7523_CLK_SPI>; + clock-names = "spi"; + #address-cells = <1>; #size-cells = <0>; - spi-rx-bus-width = <2>; - spi-tx-bus-width = <2>; nand: nand@0 { compatible = "spi-nand"; reg = <0>; - nand-ecc-engine = <&nand>; + spi-max-frequency = <50000000>; + spi-tx-bus-width = <1>; + spi-rx-bus-width = <2>; }; }; }; diff --git a/lede/target/linux/airoha/en7523/config-6.12 b/lede/target/linux/airoha/en7523/config-6.12 new file mode 100644 index 0000000000..f3d4effeda --- /dev/null +++ b/lede/target/linux/airoha/en7523/config-6.12 @@ -0,0 +1,402 @@ +CONFIG_64BIT=y +CONFIG_AIROHA_CPU_PM_DOMAIN=y +CONFIG_AIROHA_SCU_SSR=y +CONFIG_AIROHA_THERMAL=y +CONFIG_AIROHA_WATCHDOG=y +CONFIG_AMPERE_ERRATUM_AC03_CPU_38=y +CONFIG_ARCH_AIROHA=y +CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y +CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y +CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_FORCE_MAX_ORDER=10 +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_ARCH_WANTS_THP_SWAP=y +CONFIG_ARM64=y +CONFIG_ARM64_4K_PAGES=y +CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y +CONFIG_ARM64_PA_BITS=48 +CONFIG_ARM64_PA_BITS_48=y +CONFIG_ARM64_PLATFORM_DEVICES=y +CONFIG_ARM64_TAGGED_ADDR_ABI=y +CONFIG_ARM64_VA_BITS=39 +CONFIG_ARM64_VA_BITS_39=y +# CONFIG_ARM64_VA_BITS_48 is not set +# CONFIG_ARM64_VA_BITS_52 is not set +CONFIG_ARM_AIROHA_SOC_CPUFREQ=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_DEBUG_WX is not set +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_PMU=y +CONFIG_ARM_PMUV3=y +CONFIG_ARM_PSCI_FW=y +CONFIG_ARM_SMCCC_SOC_ID=y +# CONFIG_ARM_SMMU is not set +# CONFIG_ARM_SMMU_V3 is not set +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BLK_PM=y +CONFIG_BUFFER_HEAD=y +CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y +CONFIG_CC_HAVE_SHADOW_CALL_STACK=y +CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_EN7523=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +# CONFIG_COMPAT_32BIT_TIME is not set +# CONFIG_COMPRESSED_INSTALL is not set +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_RMAP=y +CONFIG_CRC16=y +CONFIG_CRC_CCITT=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DEV_EIP93=y +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_DRBG_HMAC=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKS=64 +CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE=32 +CONFIG_CRYPTO_JITTERENTROPY_OSR=1 +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA3=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_MISC=y +CONFIG_DMADEVICES=y +CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_NEED_SYNC=y +CONFIG_DMA_OF=y +CONFIG_DMA_OPS_HELPERS=y +CONFIG_DTC=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EXT4_FS=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FRAME_POINTER=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FUNCTION_ALIGNMENT=4 +CONFIG_FUNCTION_ALIGNMENT_4B=y +CONFIG_FWNODE_MDIO=y +CONFIG_FW_CACHE=y +# CONFIG_FW_LOADER_USER_HELPER is not set +CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_DEVICES=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IOREMAP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_PINCTRL_GROUPS=y +CONFIG_GENERIC_PINMUX_FUNCTIONS=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GLOB=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_EN7523=y +CONFIG_GPIO_GENERIC=y +CONFIG_GRO_CELLS=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HOTPLUG_CORE_SYNC=y +CONFIG_HOTPLUG_CORE_SYNC_DEAD=y +CONFIG_HOTPLUG_CPU=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_AIROHA=y +# CONFIG_HISILICON_ERRATUM_162100801 is not set +# CONFIG_IDPF is not set +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +# CONFIG_INET_ESP_OFFLOAD is not set +CONFIG_INET_IPCOMP=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_TUNNEL=y +CONFIG_IO_URING=y +CONFIG_IPC_NS=y +CONFIG_IPV6=y +CONFIG_IPV6_MULTIPLE_TABLES=y +# CONFIG_IPV6_SUBTREES is not set +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_COMMON=y +# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_MSI_LIB=y +CONFIG_IRQ_WORK=y +CONFIG_JBD2=y +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LRU_GEN_WALKS_MMU=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_AIROHA=y +CONFIG_MDIO_DEVRES=y +# CONFIG_MEDIATEK_GE_SOC_PHY is not set +# CONFIG_MEMCG is not set +CONFIG_MFD_SYSCON=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_CQHCI=y +CONFIG_MMC_MTK=y +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_MODULES_TREE_LOOKUP=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_MTK_BMT=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MTD_SPLIT_FIT_FW=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_BEB_LIMIT=20 +CONFIG_MTD_UBI_BLOCK=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NET_AIROHA=y +CONFIG_NET_AIROHA_FLOW_STATS=y +CONFIG_NET_AIROHA_NPU=y +CONFIG_NET_DEVLINK=y +CONFIG_NET_DSA=y +CONFIG_NET_DSA_MT7530=y +CONFIG_NET_DSA_MT7530_MDIO=y +CONFIG_NET_DSA_MT7530_MMIO=y +CONFIG_NET_DSA_TAG_MTK=y +CONFIG_NET_FLOW_LIMIT=y +# CONFIG_NET_MEDIATEK_SOC is not set +CONFIG_NET_SELFTESTS=y +# CONFIG_NET_VENDOR_3COM is not set +CONFIG_NET_VENDOR_AIROHA=y +# CONFIG_NET_VENDOR_MEDIATEK is not set +CONFIG_NLS=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=4 +CONFIG_NVMEM=y +CONFIG_NVMEM_BLOCK=y +CONFIG_NVMEM_LAYOUTS=y +CONFIG_NVMEM_LAYOUT_ASCII_ENV=y +CONFIG_NVMEM_SYSFS=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_PAGE_POOL=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PARTITION_PERCPU=y +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEASPM=y +# CONFIG_PCIEASPM_DEFAULT is not set +CONFIG_PCIEASPM_PERFORMANCE=y +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_MEDIATEK=y +CONFIG_PCIE_MEDIATEK_GEN3=y +CONFIG_PCIE_PME=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +# CONFIG_PCS_AIROHA_AN7581 is not set +CONFIG_PCS_AIROHA_AN7583=y +CONFIG_PERF_EVENTS=y +CONFIG_PER_VMA_LOCK=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_PHYLIB=y +CONFIG_PHYLIB_LEDS=y +CONFIG_PHYLINK=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PHY_AIROHA_PCIE=y +# CONFIG_PHY_AIROHA_USB is not set +CONFIG_PINCTRL=y +CONFIG_PINCTRL_AIROHA=y +# CONFIG_PINCTRL_MT2712 is not set +# CONFIG_PINCTRL_MT6765 is not set +# CONFIG_PINCTRL_MT6795 is not set +# CONFIG_PINCTRL_MT6797 is not set +# CONFIG_PINCTRL_MT7622 is not set +# CONFIG_PINCTRL_MT7981 is not set +# CONFIG_PINCTRL_MT7986 is not set +# CONFIG_PINCTRL_MT8173 is not set +# CONFIG_PINCTRL_MT8183 is not set +# CONFIG_PINCTRL_MT8186 is not set +# CONFIG_PINCTRL_MT8188 is not set +# CONFIG_PINCTRL_MT8516 is not set +CONFIG_PM=y +CONFIG_PM_CLK=y +CONFIG_PM_OPP=y +CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_SUPPLY=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RAS=y +CONFIG_RATIONAL=y +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_RELOCATABLE=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RFS_ACCEL=y +CONFIG_RODATA_FULL_DEFAULT_ENABLED=y +CONFIG_RPS=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_SERIAL_8250_AIROHA=y +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_NR_UARTS=5 +CONFIG_SERIAL_8250_RUNTIME_UARTS=5 +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SGL_ALLOC=y +CONFIG_SKB_EXTENSIONS=y +CONFIG_SMP=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SOC_BUS=y +CONFIG_SOFTIRQ_ON_OWN_STACK=y +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +# CONFIG_SPI_AIROHA_EN7523 is not set +CONFIG_SPI_AIROHA_SNFI=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y +CONFIG_SWIOTLB=y +CONFIG_SWPHY=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +# CONFIG_TEST_FPU is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_OF=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +# CONFIG_UNMAP_KERNEL_AT_EL0 is not set +CONFIG_USER_STACKTRACE_SUPPORT=y +CONFIG_VDSO_GETRANDOM=y +CONFIG_VMAP_STACK=y +CONFIG_WATCHDOG_CORE=y +# CONFIG_WLAN is not set +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_XFRM_AH=y +CONFIG_XFRM_ALGO=y +CONFIG_XFRM_ESP=y +CONFIG_XFRM_IPCOMP=y +CONFIG_XFRM_MIGRATE=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZONE_DMA32=y +CONFIG_ZSTD_COMMON=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y diff --git a/lede/target/linux/airoha/image/Makefile b/lede/target/linux/airoha/image/Makefile index dd5878bfe1..52fcaaad54 100644 --- a/lede/target/linux/airoha/image/Makefile +++ b/lede/target/linux/airoha/image/Makefile @@ -1,6 +1,10 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/image.mk +loadaddr-$(CONFIG_TARGET_airoha_an7581) := 0x80200000 +loadaddr-$(CONFIG_TARGET_airoha_an7583) := 0x80200000 +loadaddr-$(CONFIG_TARGET_airoha_en7523) := 0x80200000 + # default all platform image(fit) build define Device/Default PROFILES = Default $$(DEVICE_NAME) @@ -8,9 +12,11 @@ define Device/Default KERNEL = kernel-bin | lzma | \ fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb KERNEL_INITRAMFS = kernel-bin | lzma | \ - fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb with-initrd + fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtb + KERNEL_LOADADDR = $(loadaddr-y) FILESYSTEMS := squashfs - DEVICE_DTS_DIR := $(DTS_DIR) + DEVICE_DTS = $$(SOC)-$(lastword $(subst _, ,$(1))) + DEVICE_DTS_DIR := ../dts IMAGES := sysupgrade.bin IMAGE/sysupgrade.bin := append-kernel | pad-to 128k | append-rootfs | \ pad-rootfs | append-metadata diff --git a/lede/target/linux/airoha/image/an7581.mk b/lede/target/linux/airoha/image/an7581.mk index 78918879f7..3742ce659e 100644 --- a/lede/target/linux/airoha/image/an7581.mk +++ b/lede/target/linux/airoha/image/an7581.mk @@ -1,3 +1,17 @@ +define Build/an7581-emmc-bl2-bl31-uboot + head -c $$((0x800)) /dev/zero > $@ + cat $(STAGING_DIR_IMAGE)/an7581_$1-bl2.fip >> $@ + dd if=$(STAGING_DIR_IMAGE)/an7581_$1-bl31-u-boot.fip of=$@ bs=1 seek=$$((0x20000)) conv=notrunc +endef + +define Build/an7581-preloader + cat $(STAGING_DIR_IMAGE)/an7581_$1-bl2.fip >> $@ +endef + +define Build/an7581-bl31-uboot + cat $(STAGING_DIR_IMAGE)/an7581_$1-bl31-u-boot.fip >> $@ +endef + define Device/FitImageLzma KERNEL_SUFFIX := -uImage.itb KERNEL = kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(DEVICE_DTS).dtb @@ -10,10 +24,11 @@ define Device/airoha_an7581-evb DEVICE_MODEL := AN7581 Evaluation Board (SNAND) DEVICE_PACKAGES := kmod-leds-pwm kmod-i2c-an7581 kmod-pwm-airoha kmod-input-gpio-keys-polled DEVICE_DTS := an7581-evb - DEVICE_DTS_DIR := ../dts DEVICE_DTS_CONFIG := config@1 - KERNEL_LOADADDR := 0x80088000 IMAGE/sysupgrade.bin := append-kernel | pad-to 128k | append-rootfs | pad-rootfs | append-metadata + ARTIFACT/preloader.bin := an7581-preloader rfb + ARTIFACT/bl31-uboot.fip := an7581-bl31-uboot rfb + ARTIFACTS := preloader.bin bl31-uboot.fip endef TARGET_DEVICES += airoha_an7581-evb @@ -21,7 +36,31 @@ define Device/airoha_an7581-evb-emmc DEVICE_VENDOR := Airoha DEVICE_MODEL := AN7581 Evaluation Board (EMMC) DEVICE_DTS := an7581-evb-emmc - DEVICE_DTS_DIR := ../dts DEVICE_PACKAGES := kmod-i2c-an7581 + ARTIFACT/preloader.bin := an7581-preloader rfb + ARTIFACT/bl31-uboot.fip := an7581-bl31-uboot rfb + ARTIFACTS := preloader.bin bl31-uboot.fip endef TARGET_DEVICES += airoha_an7581-evb-emmc + +define Device/bell_xg-040g-md + $(call Device/FitImageLzma) + DEVICE_VENDOR := Nokia Bell + DEVICE_MODEL := Nokia Bell XG-040G-MD + DEVICE_DTS_CONFIG := config@1 + KERNEL_LOADADDR := 0x80088000 + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 128k + PAGESIZE := 2048 + KERNEL_SIZE := 10240k + IMAGE_SIZE := 261120k + KERNEL_IN_UBI := 1 + UBINIZE_OPTS := -m 2048 -p 128KiB -s 2048 + DEVICE_PACKAGES := airoha-en7581-npu-firmware kmod-phy-airoha-en8811h kmod-i2c-an7581 kmod-input-gpio-keys-polled + IMAGES += factory.bin sysupgrade.bin + IMAGE/factory.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-ubi + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + SOC := an7581 +endef +TARGET_DEVICES += bell_xg-040g-md + diff --git a/lede/target/linux/airoha/image/an7583.mk b/lede/target/linux/airoha/image/an7583.mk new file mode 100644 index 0000000000..bbc78c65ae --- /dev/null +++ b/lede/target/linux/airoha/image/an7583.mk @@ -0,0 +1,25 @@ +define Device/FitImageLzma + KERNEL_SUFFIX := -uImage.itb + KERNEL = kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(DEVICE_DTS).dtb + KERNEL_NAME := Image +endef + +define Device/airoha_an7583-evb + $(call Device/FitImageLzma) + DEVICE_VENDOR := Airoha + DEVICE_MODEL := AN7583 Evaluation Board (SNAND) + DEVICE_PACKAGES := kmod-phy-aeonsemi-as21xxx kmod-leds-pwm kmod-pwm-airoha kmod-input-gpio-keys-polled + DEVICE_DTS := an7583-evb + DEVICE_DTS_CONFIG := config@1 + KERNEL_LOADADDR := 0x80088000 + IMAGE/sysupgrade.bin := append-kernel | pad-to 128k | append-rootfs | pad-rootfs | append-metadata +endef +TARGET_DEVICES += airoha_an7583-evb + +define Device/airoha_an7583-evb-emmc + DEVICE_VENDOR := Airoha + DEVICE_MODEL := AN7583 Evaluation Board (EMMC) + DEVICE_DTS := an7583-evb-emmc + DEVICE_PACKAGES := kmod-phy-airoha-en8811h kmod-i2c-an7581 +endef +TARGET_DEVICES += airoha_an7583-evb-emmc diff --git a/lede/target/linux/airoha/image/en7523.mk b/lede/target/linux/airoha/image/en7523.mk index aca37a9923..9cbe7594df 100644 --- a/lede/target/linux/airoha/image/en7523.mk +++ b/lede/target/linux/airoha/image/en7523.mk @@ -1,5 +1,3 @@ -KERNEL_LOADADDR := 0x80208000 - define Target/Description Build firmware images for Airoha EN7523 ARM based boards. endef @@ -8,6 +6,5 @@ define Device/airoha_en7523-evb DEVICE_VENDOR := Airoha DEVICE_MODEL := EN7523 Evaluation Board DEVICE_DTS := en7523-evb - DEVICE_DTS_DIR := ../dts endef -TARGET_DEVICES += airoha_en7523-evb \ No newline at end of file +TARGET_DEVICES += airoha_en7523-evb diff --git a/lede/target/linux/airoha/patches-6.12/014-01-v6.13-net-airoha-fix-PSE-memory-configuration-in-airoha_fe.patch b/lede/target/linux/airoha/patches-6.12/014-01-v6.13-net-airoha-fix-PSE-memory-configuration-in-airoha_fe.patch new file mode 100644 index 0000000000..fb86423733 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/014-01-v6.13-net-airoha-fix-PSE-memory-configuration-in-airoha_fe.patch @@ -0,0 +1,40 @@ +From 8e38e08f2c560328a873c35aff1a0dbea6a7d084 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 1 Oct 2024 12:10:25 +0200 +Subject: [PATCH 2/2] net: airoha: fix PSE memory configuration in + airoha_fe_pse_ports_init() + +Align PSE memory configuration to vendor SDK. In particular, increase +initial value of PSE reserved memory in airoha_fe_pse_ports_init() +routine by the value used for the second Packet Processor Engine (PPE2) +and do not overwrite the default value. + +Introduced by commit 23020f049327 ("net: airoha: Introduce ethernet support +for EN7581 SoC") + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20241001-airoha-eth-pse-fix-v2-2-9a56cdffd074@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/airoha_eth.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mediatek/airoha_eth.c ++++ b/drivers/net/ethernet/mediatek/airoha_eth.c +@@ -1166,11 +1166,13 @@ static void airoha_fe_pse_ports_init(str + [FE_PSE_PORT_GDM4] = 2, + [FE_PSE_PORT_CDM5] = 2, + }; ++ u32 all_rsv; + int q; + ++ all_rsv = airoha_fe_get_pse_all_rsv(eth); + /* hw misses PPE2 oq rsv */ +- airoha_fe_set(eth, REG_FE_PSE_BUF_SET, +- PSE_RSV_PAGES * pse_port_num_queues[FE_PSE_PORT_PPE2]); ++ all_rsv += PSE_RSV_PAGES * pse_port_num_queues[FE_PSE_PORT_PPE2]; ++ airoha_fe_set(eth, REG_FE_PSE_BUF_SET, all_rsv); + + /* CMD1 */ + for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_CDM1]; q++) diff --git a/lede/target/linux/airoha/patches-6.12/014-02-v6.13-net-airoha-read-default-PSE-reserved-pages-value-bef.patch b/lede/target/linux/airoha/patches-6.12/014-02-v6.13-net-airoha-read-default-PSE-reserved-pages-value-bef.patch new file mode 100644 index 0000000000..a2e5c4fdd9 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/014-02-v6.13-net-airoha-read-default-PSE-reserved-pages-value-bef.patch @@ -0,0 +1,52 @@ +From 1f3e7ff4f296af1f4350f457d5bd82bc825e645a Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 1 Oct 2024 12:10:24 +0200 +Subject: [PATCH 1/2] net: airoha: read default PSE reserved pages value before + updating + +Store the default value for the number of PSE reserved pages in orig_val +at the beginning of airoha_fe_set_pse_oq_rsv routine, before updating it +with airoha_fe_set_pse_queue_rsv_pages(). +Introduce airoha_fe_get_pse_all_rsv utility routine. + +Introduced by commit 23020f049327 ("net: airoha: Introduce ethernet support +for EN7581 SoC") + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20241001-airoha-eth-pse-fix-v2-1-9a56cdffd074@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/airoha_eth.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/mediatek/airoha_eth.c ++++ b/drivers/net/ethernet/mediatek/airoha_eth.c +@@ -1116,17 +1116,23 @@ static void airoha_fe_set_pse_queue_rsv_ + PSE_CFG_WR_EN_MASK | PSE_CFG_OQRSV_SEL_MASK); + } + ++static u32 airoha_fe_get_pse_all_rsv(struct airoha_eth *eth) ++{ ++ u32 val = airoha_fe_rr(eth, REG_FE_PSE_BUF_SET); ++ ++ return FIELD_GET(PSE_ALLRSV_MASK, val); ++} ++ + static int airoha_fe_set_pse_oq_rsv(struct airoha_eth *eth, + u32 port, u32 queue, u32 val) + { +- u32 orig_val, tmp, all_rsv, fq_limit; ++ u32 orig_val = airoha_fe_get_pse_queue_rsv_pages(eth, port, queue); ++ u32 tmp, all_rsv, fq_limit; + + airoha_fe_set_pse_queue_rsv_pages(eth, port, queue, val); + + /* modify all rsv */ +- orig_val = airoha_fe_get_pse_queue_rsv_pages(eth, port, queue); +- tmp = airoha_fe_rr(eth, REG_FE_PSE_BUF_SET); +- all_rsv = FIELD_GET(PSE_ALLRSV_MASK, tmp); ++ all_rsv = airoha_fe_get_pse_all_rsv(eth); + all_rsv += (val - orig_val); + airoha_fe_rmw(eth, REG_FE_PSE_BUF_SET, PSE_ALLRSV_MASK, + FIELD_PREP(PSE_ALLRSV_MASK, all_rsv)); diff --git a/lede/target/linux/airoha/patches-6.12/016-v6.13-net-airoha-Fix-EGRESS_RATE_METER_EN_MASK-definition.patch b/lede/target/linux/airoha/patches-6.12/016-v6.13-net-airoha-Fix-EGRESS_RATE_METER_EN_MASK-definition.patch new file mode 100644 index 0000000000..d70cadf9d9 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/016-v6.13-net-airoha-Fix-EGRESS_RATE_METER_EN_MASK-definition.patch @@ -0,0 +1,33 @@ +From 2518b119639162251b6cc7195aec394930c1d867 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 9 Oct 2024 00:21:47 +0200 +Subject: [PATCH] net: airoha: Fix EGRESS_RATE_METER_EN_MASK definition + +Fix typo in EGRESS_RATE_METER_EN_MASK mask definition. This bus in not +introducing any user visible problem since, even if we are setting +EGRESS_RATE_METER_EN_MASK bit in REG_EGRESS_RATE_METER_CFG register, +egress QoS metering is not supported yet since we are missing some other +hw configurations (e.g token bucket rate, token bucket size). + +Introduced by commit 23020f049327 ("net: airoha: Introduce ethernet support +for EN7581 SoC") + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20241009-airoha-fixes-v2-1-18af63ec19bf@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/airoha_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mediatek/airoha_eth.c ++++ b/drivers/net/ethernet/mediatek/airoha_eth.c +@@ -554,7 +554,7 @@ + #define FWD_DSCP_LOW_THR_MASK GENMASK(17, 0) + + #define REG_EGRESS_RATE_METER_CFG 0x100c +-#define EGRESS_RATE_METER_EN_MASK BIT(29) ++#define EGRESS_RATE_METER_EN_MASK BIT(31) + #define EGRESS_RATE_METER_EQ_RATE_EN_MASK BIT(17) + #define EGRESS_RATE_METER_WINDOW_SZ_MASK GENMASK(16, 12) + #define EGRESS_RATE_METER_TIMESLICE_MASK GENMASK(10, 0) diff --git a/lede/target/linux/airoha/patches-6.12/017-v6.13-net-airoha-Implement-BQL-support.patch b/lede/target/linux/airoha/patches-6.12/017-v6.13-net-airoha-Implement-BQL-support.patch new file mode 100644 index 0000000000..7787207f43 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/017-v6.13-net-airoha-Implement-BQL-support.patch @@ -0,0 +1,42 @@ +From 1d304174106c93ce05f6088813ad7203b3eb381a Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Sat, 12 Oct 2024 11:01:11 +0200 +Subject: [PATCH] net: airoha: Implement BQL support + +Introduce BQL support in the airoha_eth driver reporting to the kernel +info about tx hw DMA queues in order to avoid bufferbloat and keep the +latency small. + +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20241012-en7581-bql-v2-1-4deb4efdb60b@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/airoha_eth.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mediatek/airoha_eth.c ++++ b/drivers/net/ethernet/mediatek/airoha_eth.c +@@ -1709,9 +1709,11 @@ static int airoha_qdma_tx_napi_poll(stru + WRITE_ONCE(desc->msg1, 0); + + if (skb) { ++ u16 queue = skb_get_queue_mapping(skb); + struct netdev_queue *txq; + +- txq = netdev_get_tx_queue(skb->dev, qid); ++ txq = netdev_get_tx_queue(skb->dev, queue); ++ netdev_tx_completed_queue(txq, 1, skb->len); + if (netif_tx_queue_stopped(txq) && + q->ndesc - q->queued >= q->free_thr) + netif_tx_wake_queue(txq); +@@ -2499,7 +2501,9 @@ static netdev_tx_t airoha_dev_xmit(struc + q->queued += i; + + skb_tx_timestamp(skb); +- if (!netdev_xmit_more()) ++ netdev_tx_sent_queue(txq, skb->len); ++ ++ if (netif_xmit_stopped(txq) || !netdev_xmit_more()) + airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid), + TX_RING_CPU_IDX_MASK, + FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head)); diff --git a/lede/target/linux/airoha/patches-6.12/029-02-spi-airoha-remove-unnecessary-restriction-length.patch b/lede/target/linux/airoha/patches-6.12/029-02-spi-airoha-remove-unnecessary-restriction-length.patch new file mode 100644 index 0000000000..e3b9f0ccbe --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/029-02-spi-airoha-remove-unnecessary-restriction-length.patch @@ -0,0 +1,31 @@ +From 4658f57ba7f60c3bd8e14c1ca7acf2090aee8436 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Tue, 12 Aug 2025 06:21:35 +0300 +Subject: [PATCH v6 02/13] spi: airoha: remove unnecessary restriction length + +The "length < 160" restriction is not needed because airoha_snand_write_data() +and airoha_snand_read_data() will properly handle data transfers above +SPI_MAX_TRANSFER_SIZE. + +Signed-off-by: Mikhail Kshevetskiy +Reviewed-by: AngeloGioacchino Del Regno +--- + drivers/spi/spi-airoha-snfi.c | 7 ------- + 1 file changed, 7 deletions(-) + +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -619,13 +619,6 @@ static int airoha_snand_adjust_op_size(s + + if (op->data.nbytes > max_len) + op->data.nbytes = max_len; +- } else { +- max_len = 1 + op->addr.nbytes + op->dummy.nbytes; +- if (max_len >= 160) +- return -EOPNOTSUPP; +- +- if (op->data.nbytes > 160 - max_len) +- op->data.nbytes = 160 - max_len; + } + + return 0; diff --git a/lede/target/linux/airoha/patches-6.12/029-04-spi-airoha-remove-unnecessary-switch-to-non-dma-m.patch b/lede/target/linux/airoha/patches-6.12/029-04-spi-airoha-remove-unnecessary-switch-to-non-dma-m.patch new file mode 100644 index 0000000000..626e5c0ad9 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/029-04-spi-airoha-remove-unnecessary-switch-to-non-dma-m.patch @@ -0,0 +1,29 @@ +From fb41a3e3bc357592b28a8abb504df99dad642588 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Mon, 11 Aug 2025 13:09:51 +0300 +Subject: [PATCH v6 04/13] spi: airoha: remove unnecessary switch to non-dma + mode + +The code switches to dma at the start of dirmap operation and returns +to non-dma at the end of dirmap operation, so an additional switch to +non-dma at the start of dirmap write is not required. + +Signed-off-by: Mikhail Kshevetskiy +Acked-by: Lorenzo Bianconi +Reviewed-by: AngeloGioacchino Del Regno +--- + drivers/spi/spi-airoha-snfi.c | 3 --- + 1 file changed, 3 deletions(-) + +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -815,9 +815,6 @@ static ssize_t airoha_snand_dirmap_write + int err; + + as_ctrl = spi_controller_get_devdata(spi->controller); +- err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL); +- if (err < 0) +- return err; + + memcpy(txrx_buf + offs, buf, len); + dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE, diff --git a/lede/target/linux/airoha/patches-6.12/029-07-spi-airoha-unify-dirmap-read-write-code.patch b/lede/target/linux/airoha/patches-6.12/029-07-spi-airoha-unify-dirmap-read-write-code.patch new file mode 100644 index 0000000000..4be20c5b55 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/029-07-spi-airoha-unify-dirmap-read-write-code.patch @@ -0,0 +1,135 @@ +From 995b1a65206ee28d5403db0518cb230f2ce429ef Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Mon, 11 Aug 2025 19:57:43 +0300 +Subject: [PATCH v6 07/13] spi: airoha: unify dirmap read/write code + +Makes dirmap writing looks similar to dirmap reading. Just a minor +refactoring, no behavior change is expected. + +Signed-off-by: Mikhail Kshevetskiy +--- + drivers/spi/spi-airoha-snfi.c | 50 ++++++++++++++++++++++------------- + 1 file changed, 32 insertions(+), 18 deletions(-) + +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -672,6 +672,8 @@ static ssize_t airoha_snand_dirmap_read( + u32 val, rd_mode; + int err; + ++ as_ctrl = spi_controller_get_devdata(spi->controller); ++ + switch (op->cmd.opcode) { + case SPI_NAND_OP_READ_FROM_CACHE_DUAL: + rd_mode = 1; +@@ -684,7 +686,6 @@ static ssize_t airoha_snand_dirmap_read( + break; + } + +- as_ctrl = spi_controller_get_devdata(spi->controller); + err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA); + if (err < 0) + return err; +@@ -748,7 +749,7 @@ static ssize_t airoha_snand_dirmap_read( + if (err) + goto error_dma_unmap; + +- /* trigger dma start read */ ++ /* trigger dma reading */ + err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, + SPI_NFI_RD_TRIG); + if (err) +@@ -806,37 +807,47 @@ error_dma_mode_off: + static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc, + u64 offs, size_t len, const void *buf) + { +- struct spi_mem_op *op = &desc->info.op_tmpl; + struct spi_device *spi = desc->mem->spi; + u8 *txrx_buf = spi_get_ctldata(spi); + struct airoha_snand_ctrl *as_ctrl; + dma_addr_t dma_addr; +- u32 wr_mode, val; ++ u32 wr_mode, val, opcode; + int err; + + as_ctrl = spi_controller_get_devdata(spi->controller); + ++ opcode = desc->info.op_tmpl.cmd.opcode; ++ switch (opcode) { ++ case SPI_NAND_OP_PROGRAM_LOAD_SINGLE: ++ case SPI_NAND_OP_PROGRAM_LOAD_RAMDOM_SINGLE: ++ wr_mode = 0; ++ break; ++ case SPI_NAND_OP_PROGRAM_LOAD_QUAD: ++ case SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD: ++ wr_mode = 2; ++ break; ++ default: ++ /* unknown opcode */ ++ return -EOPNOTSUPP; ++ } ++ + memcpy(txrx_buf + offs, buf, len); +- dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE, +- DMA_TO_DEVICE); +- err = dma_mapping_error(as_ctrl->dev, dma_addr); +- if (err) +- return err; + + err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA); + if (err < 0) +- goto error_dma_unmap; ++ return err; + + err = airoha_snand_nfi_config(as_ctrl); + if (err) +- goto error_dma_unmap; ++ goto error_dma_mode_off; + +- if (op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_QUAD || +- op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD) +- wr_mode = BIT(1); +- else +- wr_mode = 0; ++ dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE, ++ DMA_TO_DEVICE); ++ err = dma_mapping_error(as_ctrl->dev, dma_addr); ++ if (err) ++ goto error_dma_mode_off; + ++ /* set dma addr */ + err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR, + dma_addr); + if (err) +@@ -850,12 +861,13 @@ static ssize_t airoha_snand_dirmap_write + if (err) + goto error_dma_unmap; + ++ /* set write command */ + err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL1, +- FIELD_PREP(SPI_NFI_PG_LOAD_CMD, +- op->cmd.opcode)); ++ FIELD_PREP(SPI_NFI_PG_LOAD_CMD, opcode)); + if (err) + goto error_dma_unmap; + ++ /* set write mode */ + err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_MISC_CTL, + FIELD_PREP(SPI_NFI_DATA_READ_WR_MODE, wr_mode)); + if (err) +@@ -887,6 +899,7 @@ static ssize_t airoha_snand_dirmap_write + if (err) + goto error_dma_unmap; + ++ /* trigger dma writing */ + err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, + SPI_NFI_WR_TRIG); + if (err) +@@ -931,6 +944,7 @@ static ssize_t airoha_snand_dirmap_write + error_dma_unmap: + dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE, + DMA_TO_DEVICE); ++error_dma_mode_off: + airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL); + return err; + } diff --git a/lede/target/linux/airoha/patches-6.12/029-08-spi-airoha-support-of-dualio-quadio-flash-reading.patch b/lede/target/linux/airoha/patches-6.12/029-08-spi-airoha-support-of-dualio-quadio-flash-reading.patch new file mode 100644 index 0000000000..4e00e7c178 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/029-08-spi-airoha-support-of-dualio-quadio-flash-reading.patch @@ -0,0 +1,92 @@ +From baaba9b8d3d907575323cbb7fabeae23db2a542b Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Mon, 11 Aug 2025 20:52:34 +0300 +Subject: [PATCH v6 08/13] spi: airoha: support of dualio/quadio flash reading + commands + +Airoha snfi spi controller supports acceleration of DUAL/QUAD +operations, but does not supports DUAL_IO/QUAD_IO operations. +Luckily DUAL/QUAD operations do the same as DUAL_IO/QUAD_IO ones, +so we can issue corresponding DUAL/QUAD operation instead of +DUAL_IO/QUAD_IO one. + +Signed-off-by: Mikhail Kshevetskiy +Reviewed-by: AngeloGioacchino Del Regno +--- + drivers/spi/spi-airoha-snfi.c | 28 ++++++++++++++++++++++------ + 1 file changed, 22 insertions(+), 6 deletions(-) + +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -147,6 +147,8 @@ + #define SPI_NFI_CUS_SEC_SIZE_EN BIT(16) + + #define REG_SPI_NFI_RD_CTL2 0x0510 ++#define SPI_NFI_DATA_READ_CMD GENMASK(7, 0) ++ + #define REG_SPI_NFI_RD_CTL3 0x0514 + + #define REG_SPI_NFI_PG_CTL1 0x0524 +@@ -179,7 +181,9 @@ + #define SPI_NAND_OP_READ_FROM_CACHE_SINGLE 0x03 + #define SPI_NAND_OP_READ_FROM_CACHE_SINGLE_FAST 0x0b + #define SPI_NAND_OP_READ_FROM_CACHE_DUAL 0x3b ++#define SPI_NAND_OP_READ_FROM_CACHE_DUALIO 0xbb + #define SPI_NAND_OP_READ_FROM_CACHE_QUAD 0x6b ++#define SPI_NAND_OP_READ_FROM_CACHE_QUADIO 0xeb + #define SPI_NAND_OP_WRITE_ENABLE 0x06 + #define SPI_NAND_OP_WRITE_DISABLE 0x04 + #define SPI_NAND_OP_PROGRAM_LOAD_SINGLE 0x02 +@@ -664,26 +668,38 @@ static int airoha_snand_dirmap_create(st + static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc, + u64 offs, size_t len, void *buf) + { +- struct spi_mem_op *op = &desc->info.op_tmpl; + struct spi_device *spi = desc->mem->spi; + struct airoha_snand_ctrl *as_ctrl; + u8 *txrx_buf = spi_get_ctldata(spi); + dma_addr_t dma_addr; +- u32 val, rd_mode; ++ u32 val, rd_mode, opcode; + int err; + + as_ctrl = spi_controller_get_devdata(spi->controller); + +- switch (op->cmd.opcode) { ++ /* ++ * DUALIO and QUADIO opcodes are not supported by the spi controller, ++ * replace them with supported opcodes. ++ */ ++ opcode = desc->info.op_tmpl.cmd.opcode; ++ switch (opcode) { ++ case SPI_NAND_OP_READ_FROM_CACHE_SINGLE: ++ case SPI_NAND_OP_READ_FROM_CACHE_SINGLE_FAST: ++ rd_mode = 0; ++ break; + case SPI_NAND_OP_READ_FROM_CACHE_DUAL: ++ case SPI_NAND_OP_READ_FROM_CACHE_DUALIO: ++ opcode = SPI_NAND_OP_READ_FROM_CACHE_DUAL; + rd_mode = 1; + break; + case SPI_NAND_OP_READ_FROM_CACHE_QUAD: ++ case SPI_NAND_OP_READ_FROM_CACHE_QUADIO: ++ opcode = SPI_NAND_OP_READ_FROM_CACHE_QUAD; + rd_mode = 2; + break; + default: +- rd_mode = 0; +- break; ++ /* unknown opcode */ ++ return -EOPNOTSUPP; + } + + err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA); +@@ -717,7 +733,7 @@ static ssize_t airoha_snand_dirmap_read( + + /* set read command */ + err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL2, +- op->cmd.opcode); ++ FIELD_PREP(SPI_NFI_DATA_READ_CMD, opcode)); + if (err) + goto error_dma_unmap; + diff --git a/lede/target/linux/airoha/patches-6.12/029-09-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch b/lede/target/linux/airoha/patches-6.12/029-09-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch new file mode 100644 index 0000000000..7eef83d562 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/029-09-spi-airoha-buffer-must-be-0xff-ed-before-writing.patch @@ -0,0 +1,29 @@ +From 6ca9cd453cb5d8a6411791295771b4dbd1c623de Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Mon, 11 Aug 2025 21:18:04 +0300 +Subject: [PATCH v6 09/13] spi: airoha: buffer must be 0xff-ed before writing + +During writing, the entire flash page (including OOB) will be updated +with the values from the temporary buffer, so we need to fill the +untouched areas of the buffer with 0xff value to prevent accidental +data overwriting. + +Signed-off-by: Mikhail Kshevetskiy +--- + drivers/spi/spi-airoha-snfi.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -847,7 +847,11 @@ static ssize_t airoha_snand_dirmap_write + return -EOPNOTSUPP; + } + ++ if (offs > 0) ++ memset(txrx_buf, 0xff, offs); + memcpy(txrx_buf + offs, buf, len); ++ if (bytes > offs + len) ++ memset(txrx_buf + offs + len, 0xff, bytes - offs - len); + + err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA); + if (err < 0) diff --git a/lede/target/linux/airoha/patches-6.12/029-10-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG.patch b/lede/target/linux/airoha/patches-6.12/029-10-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG.patch new file mode 100644 index 0000000000..0a3ddc8be3 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/029-10-spi-airoha-avoid-setting-of-page-oob-sizes-in-REG.patch @@ -0,0 +1,62 @@ +From 4abbbc74306598159fe1dc545f929ae594bf4dd1 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Thu, 14 Aug 2025 18:00:32 +0300 +Subject: [PATCH v6 10/13] spi: airoha: avoid setting of page/oob sizes in + REG_SPI_NFI_PAGEFMT + +spi-airoha-snfi uses custom sector size in REG_SPI_NFI_SECCUS_SIZE +register, so setting of page/oob sizes in REG_SPI_NFI_PAGEFMT is not +required. + +Signed-off-by: Mikhail Kshevetskiy +--- + drivers/spi/spi-airoha-snfi.c | 38 ----------------------------------- + 1 file changed, 38 deletions(-) + +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -518,44 +518,6 @@ static int airoha_snand_nfi_config(struc + if (err) + return err; + +- /* page format */ +- switch (as_ctrl->nfi_cfg.spare_size) { +- case 26: +- val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x1); +- break; +- case 27: +- val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x2); +- break; +- case 28: +- val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x3); +- break; +- default: +- val = FIELD_PREP(SPI_NFI_SPARE_SIZE, 0x0); +- break; +- } +- +- err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_PAGEFMT, +- SPI_NFI_SPARE_SIZE, val); +- if (err) +- return err; +- +- switch (as_ctrl->nfi_cfg.page_size) { +- case 2048: +- val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x1); +- break; +- case 4096: +- val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x2); +- break; +- default: +- val = FIELD_PREP(SPI_NFI_PAGE_SIZE, 0x0); +- break; +- } +- +- err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_PAGEFMT, +- SPI_NFI_PAGE_SIZE, val); +- if (err) +- return err; +- + /* sec num */ + val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num); + err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, diff --git a/lede/target/linux/airoha/patches-6.12/029-11-spi-airoha-reduce-the-number-of-modification-of-R.patch b/lede/target/linux/airoha/patches-6.12/029-11-spi-airoha-reduce-the-number-of-modification-of-R.patch new file mode 100644 index 0000000000..2193994ed9 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/029-11-spi-airoha-reduce-the-number-of-modification-of-R.patch @@ -0,0 +1,197 @@ +From 0d8f58869192df0acdba286d233b57a4feeaf94b Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Thu, 14 Aug 2025 18:49:34 +0300 +Subject: [PATCH v6 11/13] spi: airoha: reduce the number of modification of + REG_SPI_NFI_CNFG and REG_SPI_NFI_SECCUS_SIZE registers + +This just reduce the number of modification of REG_SPI_NFI_CNFG and +REG_SPI_NFI_SECCUS_SIZE registers during dirmap operation. + +This patch is a necessary step to avoid reading flash page settings +from SNFI registers during driver startup. + +Signed-off-by: Mikhail Kshevetskiy +Reviewed-by: AngeloGioacchino Del Regno +--- + drivers/spi/spi-airoha-snfi.c | 135 +++++++++++++++++++++++++--------- + 1 file changed, 102 insertions(+), 33 deletions(-) + +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -668,7 +668,48 @@ static ssize_t airoha_snand_dirmap_read( + if (err < 0) + return err; + +- err = airoha_snand_nfi_config(as_ctrl); ++ /* NFI reset */ ++ err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, ++ SPI_NFI_FIFO_FLUSH | SPI_NFI_RST); ++ if (err) ++ goto error_dma_mode_off; ++ ++ /* NFI configure: ++ * - No AutoFDM (custom sector size (SECCUS) register will be used) ++ * - No SoC's hardware ECC (flash internal ECC will be used) ++ * - Use burst mode (faster, but requires 16 byte alignment for addresses) ++ * - Setup for reading (SPI_NFI_READ_MODE) ++ * - Setup reading command: FIELD_PREP(SPI_NFI_OPMODE, 6) ++ * - Use DMA instead of PIO for data reading ++ */ ++ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, ++ SPI_NFI_DMA_MODE | ++ SPI_NFI_READ_MODE | ++ SPI_NFI_DMA_BURST_EN | ++ SPI_NFI_HW_ECC_EN | ++ SPI_NFI_AUTO_FDM_EN | ++ SPI_NFI_OPMODE, ++ SPI_NFI_DMA_MODE | ++ SPI_NFI_READ_MODE | ++ SPI_NFI_DMA_BURST_EN | ++ FIELD_PREP(SPI_NFI_OPMODE, 6)); ++ if (err) ++ goto error_dma_mode_off; ++ ++ /* Set number of sector will be read */ ++ val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num); ++ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, ++ SPI_NFI_SEC_NUM, val); ++ if (err) ++ goto error_dma_mode_off; ++ ++ /* Set custom sector size */ ++ val = as_ctrl->nfi_cfg.sec_size; ++ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, ++ SPI_NFI_CUS_SEC_SIZE | ++ SPI_NFI_CUS_SEC_SIZE_EN, ++ FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) | ++ SPI_NFI_CUS_SEC_SIZE_EN); + if (err) + goto error_dma_mode_off; + +@@ -684,7 +725,14 @@ static ssize_t airoha_snand_dirmap_read( + if (err) + goto error_dma_unmap; + +- /* set cust sec size */ ++ /* ++ * Setup transfer length ++ * --------------------- ++ * The following rule MUST be met: ++ * transfer_length = ++ * = NFI_SNF_MISC_CTL2.read_data_byte_number = ++ * = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size ++ */ + val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num; + val = FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, val); + err = regmap_update_bits(as_ctrl->regmap_nfi, +@@ -711,18 +759,6 @@ static ssize_t airoha_snand_dirmap_read( + if (err) + goto error_dma_unmap; + +- /* set nfi read */ +- err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, +- SPI_NFI_OPMODE, +- FIELD_PREP(SPI_NFI_OPMODE, 6)); +- if (err) +- goto error_dma_unmap; +- +- err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, +- SPI_NFI_READ_MODE | SPI_NFI_DMA_MODE); +- if (err) +- goto error_dma_unmap; +- + err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x0); + if (err) + goto error_dma_unmap; +@@ -819,7 +855,48 @@ static ssize_t airoha_snand_dirmap_write + if (err < 0) + return err; + +- err = airoha_snand_nfi_config(as_ctrl); ++ /* NFI reset */ ++ err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, ++ SPI_NFI_FIFO_FLUSH | SPI_NFI_RST); ++ if (err) ++ goto error_dma_mode_off; ++ ++ /* ++ * NFI configure: ++ * - No AutoFDM (custom sector size (SECCUS) register will be used) ++ * - No SoC's hardware ECC (flash internal ECC will be used) ++ * - Use burst mode (faster, but requires 16 byte alignment for addresses) ++ * - Setup for writing (SPI_NFI_READ_MODE bit is cleared) ++ * - Setup writing command: FIELD_PREP(SPI_NFI_OPMODE, 3) ++ * - Use DMA instead of PIO for data writing ++ */ ++ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, ++ SPI_NFI_DMA_MODE | ++ SPI_NFI_READ_MODE | ++ SPI_NFI_DMA_BURST_EN | ++ SPI_NFI_HW_ECC_EN | ++ SPI_NFI_AUTO_FDM_EN | ++ SPI_NFI_OPMODE, ++ SPI_NFI_DMA_MODE | ++ SPI_NFI_DMA_BURST_EN | ++ FIELD_PREP(SPI_NFI_OPMODE, 3)); ++ if (err) ++ goto error_dma_mode_off; ++ ++ /* Set number of sector will be written */ ++ val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num); ++ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, ++ SPI_NFI_SEC_NUM, val); ++ if (err) ++ goto error_dma_mode_off; ++ ++ /* Set custom sector size */ ++ val = as_ctrl->nfi_cfg.sec_size; ++ err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, ++ SPI_NFI_CUS_SEC_SIZE | ++ SPI_NFI_CUS_SEC_SIZE_EN, ++ FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) | ++ SPI_NFI_CUS_SEC_SIZE_EN); + if (err) + goto error_dma_mode_off; + +@@ -835,8 +912,16 @@ static ssize_t airoha_snand_dirmap_write + if (err) + goto error_dma_unmap; + +- val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, +- as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num); ++ /* ++ * Setup transfer length ++ * --------------------- ++ * The following rule MUST be met: ++ * transfer_length = ++ * = NFI_SNF_MISC_CTL2.write_data_byte_number = ++ * = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size ++ */ ++ val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num; ++ val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, val); + err = regmap_update_bits(as_ctrl->regmap_nfi, + REG_SPI_NFI_SNF_MISC_CTL2, + SPI_NFI_PROG_LOAD_BYTE_NUM, val); +@@ -861,22 +946,6 @@ static ssize_t airoha_snand_dirmap_write + if (err) + goto error_dma_unmap; + +- err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, +- SPI_NFI_READ_MODE); +- if (err) +- goto error_dma_unmap; +- +- err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, +- SPI_NFI_OPMODE, +- FIELD_PREP(SPI_NFI_OPMODE, 3)); +- if (err) +- goto error_dma_unmap; +- +- err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, +- SPI_NFI_DMA_MODE); +- if (err) +- goto error_dma_unmap; +- + err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x80); + if (err) + goto error_dma_unmap; diff --git a/lede/target/linux/airoha/patches-6.12/029-12-spi-airoha-set-custom-sector-size-equal-to-flash-.patch b/lede/target/linux/airoha/patches-6.12/029-12-spi-airoha-set-custom-sector-size-equal-to-flash-.patch new file mode 100644 index 0000000000..d9f35366b4 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/029-12-spi-airoha-set-custom-sector-size-equal-to-flash-.patch @@ -0,0 +1,140 @@ +From 893ee23d650ca9ee36541b9a5ae0bc18be01a11f Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Thu, 14 Aug 2025 22:47:17 +0300 +Subject: [PATCH v6 12/13] spi: airoha: set custom sector size equal to flash + page size + +Set custom sector size equal to flash page size including oob. Thus we +will always read a single sector. The maximum custom sector size is +8187, so all possible flash sector sizes are supported. + +This patch is a necessary step to avoid reading flash page settings +from SNFI registers during driver startup. + +Signed-off-by: Mikhail Kshevetskiy +Reviewed-by: AngeloGioacchino Del Regno +--- + drivers/spi/spi-airoha-snfi.c | 35 +++++++++++++++++++---------------- + 1 file changed, 19 insertions(+), 16 deletions(-) + +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -519,7 +519,7 @@ static int airoha_snand_nfi_config(struc + return err; + + /* sec num */ +- val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num); ++ val = FIELD_PREP(SPI_NFI_SEC_NUM, 1); + err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, + SPI_NFI_SEC_NUM, val); + if (err) +@@ -532,7 +532,8 @@ static int airoha_snand_nfi_config(struc + return err; + + /* set cust sec size */ +- val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, as_ctrl->nfi_cfg.sec_size); ++ val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, ++ as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num); + return regmap_update_bits(as_ctrl->regmap_nfi, + REG_SPI_NFI_SECCUS_SIZE, + SPI_NFI_CUS_SEC_SIZE, val); +@@ -635,10 +636,13 @@ static ssize_t airoha_snand_dirmap_read( + u8 *txrx_buf = spi_get_ctldata(spi); + dma_addr_t dma_addr; + u32 val, rd_mode, opcode; ++ size_t bytes; + int err; + + as_ctrl = spi_controller_get_devdata(spi->controller); + ++ bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size; ++ + /* + * DUALIO and QUADIO opcodes are not supported by the spi controller, + * replace them with supported opcodes. +@@ -697,18 +701,17 @@ static ssize_t airoha_snand_dirmap_read( + goto error_dma_mode_off; + + /* Set number of sector will be read */ +- val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num); + err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, +- SPI_NFI_SEC_NUM, val); ++ SPI_NFI_SEC_NUM, ++ FIELD_PREP(SPI_NFI_SEC_NUM, 1)); + if (err) + goto error_dma_mode_off; + + /* Set custom sector size */ +- val = as_ctrl->nfi_cfg.sec_size; + err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, + SPI_NFI_CUS_SEC_SIZE | + SPI_NFI_CUS_SEC_SIZE_EN, +- FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) | ++ FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, bytes) | + SPI_NFI_CUS_SEC_SIZE_EN); + if (err) + goto error_dma_mode_off; +@@ -733,11 +736,10 @@ static ssize_t airoha_snand_dirmap_read( + * = NFI_SNF_MISC_CTL2.read_data_byte_number = + * = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size + */ +- val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num; +- val = FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, val); + err = regmap_update_bits(as_ctrl->regmap_nfi, + REG_SPI_NFI_SNF_MISC_CTL2, +- SPI_NFI_READ_DATA_BYTE_NUM, val); ++ SPI_NFI_READ_DATA_BYTE_NUM, ++ FIELD_PREP(SPI_NFI_READ_DATA_BYTE_NUM, bytes)); + if (err) + goto error_dma_unmap; + +@@ -826,10 +828,13 @@ static ssize_t airoha_snand_dirmap_write + struct airoha_snand_ctrl *as_ctrl; + dma_addr_t dma_addr; + u32 wr_mode, val, opcode; ++ size_t bytes; + int err; + + as_ctrl = spi_controller_get_devdata(spi->controller); + ++ bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size; ++ + opcode = desc->info.op_tmpl.cmd.opcode; + switch (opcode) { + case SPI_NAND_OP_PROGRAM_LOAD_SINGLE: +@@ -884,18 +889,17 @@ static ssize_t airoha_snand_dirmap_write + goto error_dma_mode_off; + + /* Set number of sector will be written */ +- val = FIELD_PREP(SPI_NFI_SEC_NUM, as_ctrl->nfi_cfg.sec_num); + err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, +- SPI_NFI_SEC_NUM, val); ++ SPI_NFI_SEC_NUM, ++ FIELD_PREP(SPI_NFI_SEC_NUM, 1)); + if (err) + goto error_dma_mode_off; + + /* Set custom sector size */ +- val = as_ctrl->nfi_cfg.sec_size; + err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, + SPI_NFI_CUS_SEC_SIZE | + SPI_NFI_CUS_SEC_SIZE_EN, +- FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, val) | ++ FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, bytes) | + SPI_NFI_CUS_SEC_SIZE_EN); + if (err) + goto error_dma_mode_off; +@@ -920,11 +924,10 @@ static ssize_t airoha_snand_dirmap_write + * = NFI_SNF_MISC_CTL2.write_data_byte_number = + * = NFI_CON.sector_number * NFI_SECCUS.custom_sector_size + */ +- val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num; +- val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, val); + err = regmap_update_bits(as_ctrl->regmap_nfi, + REG_SPI_NFI_SNF_MISC_CTL2, +- SPI_NFI_PROG_LOAD_BYTE_NUM, val); ++ SPI_NFI_PROG_LOAD_BYTE_NUM, ++ FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM, bytes)); + if (err) + goto error_dma_unmap; + diff --git a/lede/target/linux/airoha/patches-6.12/029-13-spi-airoha-avoid-reading-flash-page-settings-from.patch b/lede/target/linux/airoha/patches-6.12/029-13-spi-airoha-avoid-reading-flash-page-settings-from.patch new file mode 100644 index 0000000000..2efc56f356 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/029-13-spi-airoha-avoid-reading-flash-page-settings-from.patch @@ -0,0 +1,204 @@ +From 64a4d6e84145227211485067022cd4e5cf052e04 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Thu, 14 Aug 2025 23:56:24 +0300 +Subject: [PATCH v6 13/13] spi: airoha: avoid reading flash page settings from + SNFI registers during driver startup + +The spinand driver do 3 type of dirmap requests: + * read/write whole flash page without oob + (offs = 0, len = page_size) + * read/write whole flash page including oob + (offs = 0, len = page_size + oob_size) + * read/write oob area only + (offs = page_size, len = oob_size) + +The trick is: + * read/write a single "sector" + * set a custom sector size equal to offs + len. It's a bit safer to + rounded up "sector size" value 64. + * set the transfer length equal to custom sector size + +And it works! + +Thus we can remove a dirty hack that reads flash page settings from +SNFI registers during driver startup. Also airoha_snand_adjust_op_size() +function becomes unnecessary. + +Signed-off-by: Mikhail Kshevetskiy +--- + drivers/spi/spi-airoha-snfi.c | 115 ++-------------------------------- + 1 file changed, 5 insertions(+), 110 deletions(-) + +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -223,13 +223,6 @@ struct airoha_snand_ctrl { + struct regmap *regmap_ctrl; + struct regmap *regmap_nfi; + struct clk *spi_clk; +- +- struct { +- size_t page_size; +- size_t sec_size; +- u8 sec_num; +- u8 spare_size; +- } nfi_cfg; + }; + + static int airoha_snand_set_fifo_op(struct airoha_snand_ctrl *as_ctrl, +@@ -490,55 +483,6 @@ static int airoha_snand_nfi_init(struct + SPI_NFI_ALL_IRQ_EN, SPI_NFI_AHB_DONE_EN); + } + +-static int airoha_snand_nfi_config(struct airoha_snand_ctrl *as_ctrl) +-{ +- int err; +- u32 val; +- +- err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, +- SPI_NFI_FIFO_FLUSH | SPI_NFI_RST); +- if (err) +- return err; +- +- /* auto FDM */ +- err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, +- SPI_NFI_AUTO_FDM_EN); +- if (err) +- return err; +- +- /* HW ECC */ +- err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, +- SPI_NFI_HW_ECC_EN); +- if (err) +- return err; +- +- /* DMA Burst */ +- err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG, +- SPI_NFI_DMA_BURST_EN); +- if (err) +- return err; +- +- /* sec num */ +- val = FIELD_PREP(SPI_NFI_SEC_NUM, 1); +- err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, +- SPI_NFI_SEC_NUM, val); +- if (err) +- return err; +- +- /* enable cust sec size */ +- err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, +- SPI_NFI_CUS_SEC_SIZE_EN); +- if (err) +- return err; +- +- /* set cust sec size */ +- val = FIELD_PREP(SPI_NFI_CUS_SEC_SIZE, +- as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num); +- return regmap_update_bits(as_ctrl->regmap_nfi, +- REG_SPI_NFI_SECCUS_SIZE, +- SPI_NFI_CUS_SEC_SIZE, val); +-} +- + static bool airoha_snand_is_page_ops(const struct spi_mem_op *op) + { + if (op->addr.nbytes != 2) +@@ -571,26 +515,6 @@ static bool airoha_snand_is_page_ops(con + } + } + +-static int airoha_snand_adjust_op_size(struct spi_mem *mem, +- struct spi_mem_op *op) +-{ +- size_t max_len; +- +- if (airoha_snand_is_page_ops(op)) { +- struct airoha_snand_ctrl *as_ctrl; +- +- as_ctrl = spi_controller_get_devdata(mem->spi->controller); +- max_len = as_ctrl->nfi_cfg.sec_size; +- max_len += as_ctrl->nfi_cfg.spare_size; +- max_len *= as_ctrl->nfi_cfg.sec_num; +- +- if (op->data.nbytes > max_len) +- op->data.nbytes = max_len; +- } +- +- return 0; +-} +- + static bool airoha_snand_supports_op(struct spi_mem *mem, + const struct spi_mem_op *op) + { +@@ -641,7 +565,8 @@ static ssize_t airoha_snand_dirmap_read( + + as_ctrl = spi_controller_get_devdata(spi->controller); + +- bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size; ++ /* minimum oob size is 64 */ ++ bytes = round_up(offs + len, 64); + + /* + * DUALIO and QUADIO opcodes are not supported by the spi controller, +@@ -833,7 +758,8 @@ static ssize_t airoha_snand_dirmap_write + + as_ctrl = spi_controller_get_devdata(spi->controller); + +- bytes = as_ctrl->nfi_cfg.sec_num * as_ctrl->nfi_cfg.sec_size; ++ /* minimum oob size is 64 */ ++ bytes = round_up(offs + len, 64); + + opcode = desc->info.op_tmpl.cmd.opcode; + switch (opcode) { +@@ -1080,7 +1006,6 @@ static int airoha_snand_exec_op(struct s + } + + static const struct spi_controller_mem_ops airoha_snand_mem_ops = { +- .adjust_op_size = airoha_snand_adjust_op_size, + .supports_op = airoha_snand_supports_op, + .exec_op = airoha_snand_exec_op, + .dirmap_create = airoha_snand_dirmap_create, +@@ -1105,36 +1030,6 @@ static int airoha_snand_setup(struct spi + return 0; + } + +-static int airoha_snand_nfi_setup(struct airoha_snand_ctrl *as_ctrl) +-{ +- u32 val, sec_size, sec_num; +- int err; +- +- err = regmap_read(as_ctrl->regmap_nfi, REG_SPI_NFI_CON, &val); +- if (err) +- return err; +- +- sec_num = FIELD_GET(SPI_NFI_SEC_NUM, val); +- +- err = regmap_read(as_ctrl->regmap_nfi, REG_SPI_NFI_SECCUS_SIZE, &val); +- if (err) +- return err; +- +- sec_size = FIELD_GET(SPI_NFI_CUS_SEC_SIZE, val); +- +- /* init default value */ +- as_ctrl->nfi_cfg.sec_size = sec_size; +- as_ctrl->nfi_cfg.sec_num = sec_num; +- as_ctrl->nfi_cfg.page_size = round_down(sec_size * sec_num, 1024); +- as_ctrl->nfi_cfg.spare_size = 16; +- +- err = airoha_snand_nfi_init(as_ctrl); +- if (err) +- return err; +- +- return airoha_snand_nfi_config(as_ctrl); +-} +- + static const struct regmap_config spi_ctrl_regmap_config = { + .name = "ctrl", + .reg_bits = 32, +@@ -1208,7 +1103,7 @@ static int airoha_snand_probe(struct pla + ctrl->setup = airoha_snand_setup; + device_set_node(&ctrl->dev, dev_fwnode(dev)); + +- err = airoha_snand_nfi_setup(as_ctrl); ++ err = airoha_snand_nfi_init(as_ctrl); + if (err) + return err; + diff --git a/lede/target/linux/airoha/patches-6.12/029-14-spi-airoha-snfi-make-compatible-with-EN7523-SoC.patch b/lede/target/linux/airoha/patches-6.12/029-14-spi-airoha-snfi-make-compatible-with-EN7523-SoC.patch new file mode 100644 index 0000000000..5e0c59ef67 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/029-14-spi-airoha-snfi-make-compatible-with-EN7523-SoC.patch @@ -0,0 +1,27 @@ +From 12664d09a94bd0f50f31a3811447f70275ea9bb8 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Thu, 9 Oct 2025 19:49:18 +0300 +Subject: [PATCH 1/2] spi: airoha-snfi: make compatible with EN7523 SoC + +The driver is fully compatible with EN7523 based SoCs, so add +corresponding compatible string. + +This driver is better than en7523-spi because it supports DMA. +Measurements shows that DMA based flash reading is 4 times faster +than non-dma one. + +Signed-off-by: Mikhail Kshevetskiy +--- + drivers/spi/spi-airoha-snfi.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -1047,6 +1047,7 @@ static const struct regmap_config spi_nf + }; + + static const struct of_device_id airoha_snand_ids[] = { ++ { .compatible = "airoha,en7523-snand" }, + { .compatible = "airoha,en7581-snand" }, + { /* sentinel */ } + }; diff --git a/lede/target/linux/airoha/patches-6.12/029-15-spi-airoha-snfi-en7523-workaround-flash-damaging-if-.patch b/lede/target/linux/airoha/patches-6.12/029-15-spi-airoha-snfi-en7523-workaround-flash-damaging-if-.patch new file mode 100644 index 0000000000..0b8fc4c0b0 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/029-15-spi-airoha-snfi-en7523-workaround-flash-damaging-if-.patch @@ -0,0 +1,97 @@ +From 0299de52cbb2274345e12518298a8014adb56411 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Thu, 9 Oct 2025 19:33:23 +0300 +Subject: [PATCH 2/2] spi: airoha-snfi: en7523: workaround flash damaging if + UART_TXD was short to GND + +We found that some serial console may pull TX line to GROUND during board +boot time. Airoha uses TX line as one of it's BOOT pins. This will lead +to booting in RESERVED boot mode. + +It was found that some flashes operates incorrectly in RESERVED mode. +Micron and Skyhigh flashes are definitely affected by the issue, +Winbond flashes are NOT affected. + +Details: +-------- +DMA reading of odd pages on affected flashes operates incorrectly. Page +reading offset (start of the page) on hardware level is replaced by 0x10. +Thus results in incorrect data reading. Usage of UBI make things even +worse. Any attempt to access UBI leads to ubi damaging. As result OS loading +becomes impossible. + +Non-DMA reading is OK. + +This patch detects booting in reserved mode, turn off DMA and print big +fat warning. + +Signed-off-by: Mikhail Kshevetskiy +--- + drivers/spi/spi-airoha-snfi.c | 38 ++++++++++++++++++++++++++++++++--- + 1 file changed, 35 insertions(+), 3 deletions(-) + +--- a/drivers/spi/spi-airoha-snfi.c ++++ b/drivers/spi/spi-airoha-snfi.c +@@ -1013,6 +1013,11 @@ static const struct spi_controller_mem_o + .dirmap_write = airoha_snand_dirmap_write, + }; + ++static const struct spi_controller_mem_ops airoha_snand_nodma_mem_ops = { ++ .supports_op = airoha_snand_supports_op, ++ .exec_op = airoha_snand_exec_op, ++}; ++ + static int airoha_snand_setup(struct spi_device *spi) + { + struct airoha_snand_ctrl *as_ctrl; +@@ -1059,7 +1064,10 @@ static int airoha_snand_probe(struct pla + struct device *dev = &pdev->dev; + struct spi_controller *ctrl; + void __iomem *base; +- int err; ++ int err, dma_enabled; ++#if defined(CONFIG_ARM) ++ u32 sfc_strap; ++#endif + + ctrl = devm_spi_alloc_host(dev, sizeof(*as_ctrl)); + if (!ctrl) +@@ -1093,12 +1101,36 @@ static int airoha_snand_probe(struct pla + return dev_err_probe(dev, PTR_ERR(as_ctrl->spi_clk), + "unable to get spi clk\n"); + +- err = dma_set_mask(as_ctrl->dev, DMA_BIT_MASK(32)); ++ dma_enabled = 1; ++#if defined(CONFIG_ARM) ++ err = regmap_read(as_ctrl->regmap_ctrl, ++ REG_SPI_CTRL_SFC_STRAP, &sfc_strap); + if (err) + return err; + ++ if (!(sfc_strap & 0x04)) { ++ dma_enabled = 0; ++ printk(KERN_WARNING "\n" ++ "=== WARNING ======================================================\n" ++ "Detected booting in RESERVED mode (UART_TXD was short to GND).\n" ++ "This mode is known for incorrect DMA reading of some flashes.\n" ++ "Usage of DMA for flash operations will be disabled to prevent data\n" ++ "damage. Unplug your serial console and power cycle the board\n" ++ "to boot with full performance.\n" ++ "==================================================================\n\n"); ++ } ++#endif ++ ++ if (dma_enabled) { ++ err = dma_set_mask(as_ctrl->dev, DMA_BIT_MASK(32)); ++ if (err) ++ return err; ++ } ++ + ctrl->num_chipselect = 2; +- ctrl->mem_ops = &airoha_snand_mem_ops; ++ ctrl->mem_ops = dma_enabled ? ++ &airoha_snand_mem_ops : ++ &airoha_snand_nodma_mem_ops; + ctrl->bits_per_word_mask = SPI_BPW_MASK(8); + ctrl->mode_bits = SPI_RX_DUAL; + ctrl->setup = airoha_snand_setup; diff --git a/lede/target/linux/airoha/patches-6.12/030-v6.13-hwrng-airoha-add-support-for-Airoha-EN7581-TRNG.patch b/lede/target/linux/airoha/patches-6.12/030-v6.13-hwrng-airoha-add-support-for-Airoha-EN7581-TRNG.patch new file mode 100644 index 0000000000..e21fb5649e --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/030-v6.13-hwrng-airoha-add-support-for-Airoha-EN7581-TRNG.patch @@ -0,0 +1,306 @@ +From 5c5db81bff81a0fcd9ad998543d4241cbfe4742f Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 17 Oct 2024 14:44:38 +0200 +Subject: [PATCH 2/2] hwrng: airoha - add support for Airoha EN7581 TRNG + +Add support for Airoha TRNG. The Airoha SoC provide a True RNG module +that can output 4 bytes of raw data at times. + +The module makes use of various noise source to provide True Random +Number Generation. + +On probe the module is reset to operate Health Test and verify correct +execution of it. + +The module can also provide DRBG function but the execution mode is +mutually exclusive, running as TRNG doesn't permit to also run it as +DRBG. + +Signed-off-by: Christian Marangi +Reviewed-by: Martin Kaiser +Signed-off-by: Herbert Xu +--- + drivers/char/hw_random/Kconfig | 13 ++ + drivers/char/hw_random/Makefile | 1 + + drivers/char/hw_random/airoha-trng.c | 243 +++++++++++++++++++++++++++ + 3 files changed, 257 insertions(+) + create mode 100644 drivers/char/hw_random/airoha-trng.c + +--- a/drivers/char/hw_random/Kconfig ++++ b/drivers/char/hw_random/Kconfig +@@ -62,6 +62,19 @@ config HW_RANDOM_AMD + + If unsure, say Y. + ++config HW_RANDOM_AIROHA ++ tristate "Airoha True HW Random Number Generator support" ++ depends on ARCH_AIROHA || COMPILE_TEST ++ default HW_RANDOM ++ help ++ This driver provides kernel-side support for the True Random Number ++ Generator hardware found on Airoha SoC. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called airoha-rng. ++ ++ If unsure, say Y. ++ + config HW_RANDOM_ATMEL + tristate "Atmel Random Number Generator support" + depends on (ARCH_AT91 || COMPILE_TEST) +--- a/drivers/char/hw_random/Makefile ++++ b/drivers/char/hw_random/Makefile +@@ -8,6 +8,7 @@ rng-core-y := core.o + obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o + obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o + obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o ++obj-$(CONFIG_HW_RANDOM_AIROHA) += airoha-trng.o + obj-$(CONFIG_HW_RANDOM_ATMEL) += atmel-rng.o + obj-$(CONFIG_HW_RANDOM_BA431) += ba431-rng.o + obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o +--- /dev/null ++++ b/drivers/char/hw_random/airoha-trng.c +@@ -0,0 +1,243 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* Copyright (C) 2024 Christian Marangi */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define TRNG_IP_RDY 0x800 ++#define CNT_TRANS GENMASK(15, 8) ++#define SAMPLE_RDY BIT(0) ++#define TRNG_NS_SEK_AND_DAT_EN 0x804 ++#define RNG_EN BIT(31) /* referenced as ring_en */ ++#define RAW_DATA_EN BIT(16) ++#define TRNG_HEALTH_TEST_SW_RST 0x808 ++#define SW_RST BIT(0) /* Active High */ ++#define TRNG_INTR_EN 0x818 ++#define INTR_MASK BIT(16) ++#define CONTINUOUS_HEALTH_INITR_EN BIT(2) ++#define SW_STARTUP_INITR_EN BIT(1) ++#define RST_STARTUP_INITR_EN BIT(0) ++/* Notice that Health Test are done only out of Reset and with RNG_EN */ ++#define TRNG_HEALTH_TEST_STATUS 0x824 ++#define CONTINUOUS_HEALTH_AP_TEST_FAIL BIT(23) ++#define CONTINUOUS_HEALTH_RC_TEST_FAIL BIT(22) ++#define SW_STARTUP_TEST_DONE BIT(21) ++#define SW_STARTUP_AP_TEST_FAIL BIT(20) ++#define SW_STARTUP_RC_TEST_FAIL BIT(19) ++#define RST_STARTUP_TEST_DONE BIT(18) ++#define RST_STARTUP_AP_TEST_FAIL BIT(17) ++#define RST_STARTUP_RC_TEST_FAIL BIT(16) ++#define RAW_DATA_VALID BIT(7) ++ ++#define TRNG_RAW_DATA_OUT 0x828 ++ ++#define TRNG_CNT_TRANS_VALID 0x80 ++#define BUSY_LOOP_SLEEP 10 ++#define BUSY_LOOP_TIMEOUT (BUSY_LOOP_SLEEP * 10000) ++ ++struct airoha_trng { ++ void __iomem *base; ++ struct hwrng rng; ++ struct device *dev; ++ ++ struct completion rng_op_done; ++}; ++ ++static int airoha_trng_irq_mask(struct airoha_trng *trng) ++{ ++ u32 val; ++ ++ val = readl(trng->base + TRNG_INTR_EN); ++ val |= INTR_MASK; ++ writel(val, trng->base + TRNG_INTR_EN); ++ ++ return 0; ++} ++ ++static int airoha_trng_irq_unmask(struct airoha_trng *trng) ++{ ++ u32 val; ++ ++ val = readl(trng->base + TRNG_INTR_EN); ++ val &= ~INTR_MASK; ++ writel(val, trng->base + TRNG_INTR_EN); ++ ++ return 0; ++} ++ ++static int airoha_trng_init(struct hwrng *rng) ++{ ++ struct airoha_trng *trng = container_of(rng, struct airoha_trng, rng); ++ int ret; ++ u32 val; ++ ++ val = readl(trng->base + TRNG_NS_SEK_AND_DAT_EN); ++ val |= RNG_EN; ++ writel(val, trng->base + TRNG_NS_SEK_AND_DAT_EN); ++ ++ /* Set out of SW Reset */ ++ airoha_trng_irq_unmask(trng); ++ writel(0, trng->base + TRNG_HEALTH_TEST_SW_RST); ++ ++ ret = wait_for_completion_timeout(&trng->rng_op_done, BUSY_LOOP_TIMEOUT); ++ if (ret <= 0) { ++ dev_err(trng->dev, "Timeout waiting for Health Check\n"); ++ airoha_trng_irq_mask(trng); ++ return -ENODEV; ++ } ++ ++ /* Check if Health Test Failed */ ++ val = readl(trng->base + TRNG_HEALTH_TEST_STATUS); ++ if (val & (RST_STARTUP_AP_TEST_FAIL | RST_STARTUP_RC_TEST_FAIL)) { ++ dev_err(trng->dev, "Health Check fail: %s test fail\n", ++ val & RST_STARTUP_AP_TEST_FAIL ? "AP" : "RC"); ++ return -ENODEV; ++ } ++ ++ /* Check if IP is ready */ ++ ret = readl_poll_timeout(trng->base + TRNG_IP_RDY, val, ++ val & SAMPLE_RDY, 10, 1000); ++ if (ret < 0) { ++ dev_err(trng->dev, "Timeout waiting for IP ready"); ++ return -ENODEV; ++ } ++ ++ /* CNT_TRANS must be 0x80 for IP to be considered ready */ ++ ret = readl_poll_timeout(trng->base + TRNG_IP_RDY, val, ++ FIELD_GET(CNT_TRANS, val) == TRNG_CNT_TRANS_VALID, ++ 10, 1000); ++ if (ret < 0) { ++ dev_err(trng->dev, "Timeout waiting for IP ready"); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static void airoha_trng_cleanup(struct hwrng *rng) ++{ ++ struct airoha_trng *trng = container_of(rng, struct airoha_trng, rng); ++ u32 val; ++ ++ val = readl(trng->base + TRNG_NS_SEK_AND_DAT_EN); ++ val &= ~RNG_EN; ++ writel(val, trng->base + TRNG_NS_SEK_AND_DAT_EN); ++ ++ /* Put it in SW Reset */ ++ writel(SW_RST, trng->base + TRNG_HEALTH_TEST_SW_RST); ++} ++ ++static int airoha_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait) ++{ ++ struct airoha_trng *trng = container_of(rng, struct airoha_trng, rng); ++ u32 *data = buf; ++ u32 status; ++ int ret; ++ ++ ret = readl_poll_timeout(trng->base + TRNG_HEALTH_TEST_STATUS, status, ++ status & RAW_DATA_VALID, 10, 1000); ++ if (ret < 0) { ++ dev_err(trng->dev, "Timeout waiting for TRNG RAW Data valid\n"); ++ return ret; ++ } ++ ++ *data = readl(trng->base + TRNG_RAW_DATA_OUT); ++ ++ return 4; ++} ++ ++static irqreturn_t airoha_trng_irq(int irq, void *priv) ++{ ++ struct airoha_trng *trng = (struct airoha_trng *)priv; ++ ++ airoha_trng_irq_mask(trng); ++ /* Just complete the task, we will read the value later */ ++ complete(&trng->rng_op_done); ++ ++ return IRQ_HANDLED; ++} ++ ++static int airoha_trng_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct airoha_trng *trng; ++ int irq, ret; ++ u32 val; ++ ++ trng = devm_kzalloc(dev, sizeof(*trng), GFP_KERNEL); ++ if (!trng) ++ return -ENOMEM; ++ ++ trng->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(trng->base)) ++ return PTR_ERR(trng->base); ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) ++ return irq; ++ ++ airoha_trng_irq_mask(trng); ++ ret = devm_request_irq(&pdev->dev, irq, airoha_trng_irq, 0, ++ pdev->name, (void *)trng); ++ if (ret) { ++ dev_err(dev, "Can't get interrupt working.\n"); ++ return ret; ++ } ++ ++ init_completion(&trng->rng_op_done); ++ ++ /* Enable interrupt for SW reset Health Check */ ++ val = readl(trng->base + TRNG_INTR_EN); ++ val |= RST_STARTUP_INITR_EN; ++ writel(val, trng->base + TRNG_INTR_EN); ++ ++ /* Set output to raw data */ ++ val = readl(trng->base + TRNG_NS_SEK_AND_DAT_EN); ++ val |= RAW_DATA_EN; ++ writel(val, trng->base + TRNG_NS_SEK_AND_DAT_EN); ++ ++ /* Put it in SW Reset */ ++ writel(SW_RST, trng->base + TRNG_HEALTH_TEST_SW_RST); ++ ++ trng->dev = dev; ++ trng->rng.name = pdev->name; ++ trng->rng.init = airoha_trng_init; ++ trng->rng.cleanup = airoha_trng_cleanup; ++ trng->rng.read = airoha_trng_read; ++ ++ ret = devm_hwrng_register(dev, &trng->rng); ++ if (ret) { ++ dev_err(dev, "failed to register rng device: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id airoha_trng_of_match[] = { ++ { .compatible = "airoha,en7581-trng", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, airoha_trng_of_match); ++ ++static struct platform_driver airoha_trng_driver = { ++ .driver = { ++ .name = "airoha-trng", ++ .of_match_table = airoha_trng_of_match, ++ }, ++ .probe = airoha_trng_probe, ++}; ++ ++module_platform_driver(airoha_trng_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Christian Marangi "); ++MODULE_DESCRIPTION("Airoha True Random Number Generator driver"); diff --git a/lede/target/linux/airoha/patches-6.12/031-01-v6.13-net-airoha-Read-completion-queue-data-in-airoha_qdma.patch b/lede/target/linux/airoha/patches-6.12/031-01-v6.13-net-airoha-Read-completion-queue-data-in-airoha_qdma.patch new file mode 100644 index 0000000000..390d21b290 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/031-01-v6.13-net-airoha-Read-completion-queue-data-in-airoha_qdma.patch @@ -0,0 +1,92 @@ +From 3affa310de523d63e52ea8e2efb3c476df29e414 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 29 Oct 2024 13:17:09 +0100 +Subject: [PATCH 1/2] net: airoha: Read completion queue data in + airoha_qdma_tx_napi_poll() + +In order to avoid any possible race, read completion queue head and +pending entry in airoha_qdma_tx_napi_poll routine instead of doing it in +airoha_irq_handler. Remove unused airoha_tx_irq_queue unused fields. +This is a preliminary patch to add Qdisc offload for airoha_eth driver. + +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20241029-airoha-en7581-tx-napi-work-v1-1-96ad1686b946@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/airoha_eth.c | 31 +++++++++------------- + 1 file changed, 13 insertions(+), 18 deletions(-) + +--- a/drivers/net/ethernet/mediatek/airoha_eth.c ++++ b/drivers/net/ethernet/mediatek/airoha_eth.c +@@ -752,11 +752,9 @@ struct airoha_tx_irq_queue { + struct airoha_qdma *qdma; + + struct napi_struct napi; +- u32 *q; + + int size; +- int queued; +- u16 head; ++ u32 *q; + }; + + struct airoha_hw_stats { +@@ -1655,25 +1653,31 @@ static int airoha_qdma_init_rx(struct ai + static int airoha_qdma_tx_napi_poll(struct napi_struct *napi, int budget) + { + struct airoha_tx_irq_queue *irq_q; ++ int id, done = 0, irq_queued; + struct airoha_qdma *qdma; + struct airoha_eth *eth; +- int id, done = 0; ++ u32 status, head; + + irq_q = container_of(napi, struct airoha_tx_irq_queue, napi); + qdma = irq_q->qdma; + id = irq_q - &qdma->q_tx_irq[0]; + eth = qdma->eth; + +- while (irq_q->queued > 0 && done < budget) { +- u32 qid, last, val = irq_q->q[irq_q->head]; ++ status = airoha_qdma_rr(qdma, REG_IRQ_STATUS(id)); ++ head = FIELD_GET(IRQ_HEAD_IDX_MASK, status); ++ head = head % irq_q->size; ++ irq_queued = FIELD_GET(IRQ_ENTRY_LEN_MASK, status); ++ ++ while (irq_queued > 0 && done < budget) { ++ u32 qid, last, val = irq_q->q[head]; + struct airoha_queue *q; + + if (val == 0xff) + break; + +- irq_q->q[irq_q->head] = 0xff; /* mark as done */ +- irq_q->head = (irq_q->head + 1) % irq_q->size; +- irq_q->queued--; ++ irq_q->q[head] = 0xff; /* mark as done */ ++ head = (head + 1) % irq_q->size; ++ irq_queued--; + done++; + + last = FIELD_GET(IRQ_DESC_IDX_MASK, val); +@@ -2025,20 +2029,11 @@ static irqreturn_t airoha_irq_handler(in + + if (intr[0] & INT_TX_MASK) { + for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) { +- struct airoha_tx_irq_queue *irq_q = &qdma->q_tx_irq[i]; +- u32 status, head; +- + if (!(intr[0] & TX_DONE_INT_MASK(i))) + continue; + + airoha_qdma_irq_disable(qdma, QDMA_INT_REG_IDX0, + TX_DONE_INT_MASK(i)); +- +- status = airoha_qdma_rr(qdma, REG_IRQ_STATUS(i)); +- head = FIELD_GET(IRQ_HEAD_IDX_MASK, status); +- irq_q->head = head % irq_q->size; +- irq_q->queued = FIELD_GET(IRQ_ENTRY_LEN_MASK, status); +- + napi_schedule(&qdma->q_tx_irq[i].napi); + } + } diff --git a/lede/target/linux/airoha/patches-6.12/031-02-v6.13-net-airoha-Simplify-Tx-napi-logic.patch b/lede/target/linux/airoha/patches-6.12/031-02-v6.13-net-airoha-Simplify-Tx-napi-logic.patch new file mode 100644 index 0000000000..04b10f39cb --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/031-02-v6.13-net-airoha-Simplify-Tx-napi-logic.patch @@ -0,0 +1,130 @@ +From 0c729f53b8c33b9e5eadc2d5e673759e3510501e Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 29 Oct 2024 13:17:10 +0100 +Subject: [PATCH 2/2] net: airoha: Simplify Tx napi logic + +Simplify Tx napi logic relying just on the packet index provided by +completion queue indicating the completed packet that can be removed +from the Tx DMA ring. +This is a preliminary patch to add Qdisc offload for airoha_eth driver. + +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20241029-airoha-en7581-tx-napi-work-v1-2-96ad1686b946@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/airoha_eth.c | 73 ++++++++++++---------- + 1 file changed, 41 insertions(+), 32 deletions(-) + +--- a/drivers/net/ethernet/mediatek/airoha_eth.c ++++ b/drivers/net/ethernet/mediatek/airoha_eth.c +@@ -1669,8 +1669,12 @@ static int airoha_qdma_tx_napi_poll(stru + irq_queued = FIELD_GET(IRQ_ENTRY_LEN_MASK, status); + + while (irq_queued > 0 && done < budget) { +- u32 qid, last, val = irq_q->q[head]; ++ u32 qid, val = irq_q->q[head]; ++ struct airoha_qdma_desc *desc; ++ struct airoha_queue_entry *e; + struct airoha_queue *q; ++ u32 index, desc_ctrl; ++ struct sk_buff *skb; + + if (val == 0xff) + break; +@@ -1680,9 +1684,7 @@ static int airoha_qdma_tx_napi_poll(stru + irq_queued--; + done++; + +- last = FIELD_GET(IRQ_DESC_IDX_MASK, val); + qid = FIELD_GET(IRQ_RING_IDX_MASK, val); +- + if (qid >= ARRAY_SIZE(qdma->q_tx)) + continue; + +@@ -1690,46 +1692,53 @@ static int airoha_qdma_tx_napi_poll(stru + if (!q->ndesc) + continue; + ++ index = FIELD_GET(IRQ_DESC_IDX_MASK, val); ++ if (index >= q->ndesc) ++ continue; ++ + spin_lock_bh(&q->lock); + +- while (q->queued > 0) { +- struct airoha_qdma_desc *desc = &q->desc[q->tail]; +- struct airoha_queue_entry *e = &q->entry[q->tail]; +- u32 desc_ctrl = le32_to_cpu(desc->ctrl); +- struct sk_buff *skb = e->skb; +- u16 index = q->tail; +- +- if (!(desc_ctrl & QDMA_DESC_DONE_MASK) && +- !(desc_ctrl & QDMA_DESC_DROP_MASK)) +- break; ++ if (!q->queued) ++ goto unlock; + +- q->tail = (q->tail + 1) % q->ndesc; +- q->queued--; ++ desc = &q->desc[index]; ++ desc_ctrl = le32_to_cpu(desc->ctrl); + +- dma_unmap_single(eth->dev, e->dma_addr, e->dma_len, +- DMA_TO_DEVICE); +- +- WRITE_ONCE(desc->msg0, 0); +- WRITE_ONCE(desc->msg1, 0); ++ if (!(desc_ctrl & QDMA_DESC_DONE_MASK) && ++ !(desc_ctrl & QDMA_DESC_DROP_MASK)) ++ goto unlock; ++ ++ e = &q->entry[index]; ++ skb = e->skb; ++ ++ dma_unmap_single(eth->dev, e->dma_addr, e->dma_len, ++ DMA_TO_DEVICE); ++ memset(e, 0, sizeof(*e)); ++ WRITE_ONCE(desc->msg0, 0); ++ WRITE_ONCE(desc->msg1, 0); ++ q->queued--; ++ ++ /* completion ring can report out-of-order indexes if hw QoS ++ * is enabled and packets with different priority are queued ++ * to same DMA ring. Take into account possible out-of-order ++ * reports incrementing DMA ring tail pointer ++ */ ++ while (q->tail != q->head && !q->entry[q->tail].dma_addr) ++ q->tail = (q->tail + 1) % q->ndesc; + +- if (skb) { +- u16 queue = skb_get_queue_mapping(skb); +- struct netdev_queue *txq; +- +- txq = netdev_get_tx_queue(skb->dev, queue); +- netdev_tx_completed_queue(txq, 1, skb->len); +- if (netif_tx_queue_stopped(txq) && +- q->ndesc - q->queued >= q->free_thr) +- netif_tx_wake_queue(txq); +- +- dev_kfree_skb_any(skb); +- e->skb = NULL; +- } ++ if (skb) { ++ u16 queue = skb_get_queue_mapping(skb); ++ struct netdev_queue *txq; ++ ++ txq = netdev_get_tx_queue(skb->dev, queue); ++ netdev_tx_completed_queue(txq, 1, skb->len); ++ if (netif_tx_queue_stopped(txq) && ++ q->ndesc - q->queued >= q->free_thr) ++ netif_tx_wake_queue(txq); + +- if (index == last) +- break; ++ dev_kfree_skb_any(skb); + } +- ++unlock: + spin_unlock_bh(&q->lock); + } + diff --git a/lede/target/linux/airoha/patches-6.12/032-v6.13-watchdog-Add-support-for-Airoha-EN7851-watchdog.patch b/lede/target/linux/airoha/patches-6.12/032-v6.13-watchdog-Add-support-for-Airoha-EN7851-watchdog.patch new file mode 100644 index 0000000000..ac65bec2a1 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/032-v6.13-watchdog-Add-support-for-Airoha-EN7851-watchdog.patch @@ -0,0 +1,267 @@ +From 3cf67f3769b8227ca75ca7102180a2e270ee01aa Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 11 Oct 2024 12:43:53 +0200 +Subject: [PATCH] watchdog: Add support for Airoha EN7851 watchdog + +Add support for Airoha EN7851 watchdog. This is a very basic watchdog +with no pretimeout support, max timeout is 28 seconds and it ticks based +on half the SoC BUS clock. + +Signed-off-by: Christian Marangi +Reviewed-by: Guenter Roeck +Link: https://lore.kernel.org/r/20241011104411.28659-2-ansuelsmth@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Wim Van Sebroeck +--- + drivers/watchdog/Kconfig | 8 ++ + drivers/watchdog/Makefile | 1 + + drivers/watchdog/airoha_wdt.c | 216 ++++++++++++++++++++++++++++++++++ + 3 files changed, 225 insertions(+) + create mode 100644 drivers/watchdog/airoha_wdt.c + +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -408,6 +408,14 @@ config SL28CPLD_WATCHDOG + + # ARM Architecture + ++config AIROHA_WATCHDOG ++ tristate "Airoha EN7581 Watchdog" ++ depends on ARCH_AIROHA || COMPILE_TEST ++ select WATCHDOG_CORE ++ help ++ Watchdog timer embedded into Airoha SoC. This will reboot your ++ system when the timeout is reached. ++ + config ARM_SP805_WATCHDOG + tristate "ARM SP805 Watchdog" + depends on (ARM || ARM64 || COMPILE_TEST) && ARM_AMBA +--- a/drivers/watchdog/Makefile ++++ b/drivers/watchdog/Makefile +@@ -40,6 +40,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb. + obj-$(CONFIG_ARM_SP805_WATCHDOG) += sp805_wdt.o + obj-$(CONFIG_ARM_SBSA_WATCHDOG) += sbsa_gwdt.o + obj-$(CONFIG_ARMADA_37XX_WATCHDOG) += armada_37xx_wdt.o ++obj-$(CONFIG_AIROHA_WATCHDOG) += airoha_wdt.o + obj-$(CONFIG_ASM9260_WATCHDOG) += asm9260_wdt.o + obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o + obj-$(CONFIG_AT91SAM9X_WATCHDOG) += at91sam9_wdt.o +--- /dev/null ++++ b/drivers/watchdog/airoha_wdt.c +@@ -0,0 +1,216 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Airoha Watchdog Driver ++ * ++ * Copyright (c) 2024, AIROHA All rights reserved. ++ * ++ * Mayur Kumar ++ * Christian Marangi ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Base address of timer and watchdog registers */ ++#define TIMER_CTRL 0x0 ++#define WDT_ENABLE BIT(25) ++#define WDT_TIMER_INTERRUPT BIT(21) ++/* Timer3 is used as Watchdog Timer */ ++#define WDT_TIMER_ENABLE BIT(5) ++#define WDT_TIMER_LOAD_VALUE 0x2c ++#define WDT_TIMER_CUR_VALUE 0x30 ++#define WDT_TIMER_VAL GENMASK(31, 0) ++#define WDT_RELOAD 0x38 ++#define WDT_RLD BIT(0) ++ ++/* Airoha watchdog structure description */ ++struct airoha_wdt_desc { ++ struct watchdog_device wdog_dev; ++ unsigned int wdt_freq; ++ void __iomem *base; ++}; ++ ++#define WDT_HEARTBEAT 24 ++static int heartbeat = WDT_HEARTBEAT; ++module_param(heartbeat, int, 0); ++MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. (default=" ++ __MODULE_STRING(WDT_HEARTBEAT) ")"); ++ ++static bool nowayout = WATCHDOG_NOWAYOUT; ++module_param(nowayout, bool, 0); ++MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" ++ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); ++ ++static int airoha_wdt_start(struct watchdog_device *wdog_dev) ++{ ++ struct airoha_wdt_desc *airoha_wdt = watchdog_get_drvdata(wdog_dev); ++ u32 val; ++ ++ val = readl(airoha_wdt->base + TIMER_CTRL); ++ val |= (WDT_TIMER_ENABLE | WDT_ENABLE | WDT_TIMER_INTERRUPT); ++ writel(val, airoha_wdt->base + TIMER_CTRL); ++ val = wdog_dev->timeout * airoha_wdt->wdt_freq; ++ writel(val, airoha_wdt->base + WDT_TIMER_LOAD_VALUE); ++ ++ return 0; ++} ++ ++static int airoha_wdt_stop(struct watchdog_device *wdog_dev) ++{ ++ struct airoha_wdt_desc *airoha_wdt = watchdog_get_drvdata(wdog_dev); ++ u32 val; ++ ++ val = readl(airoha_wdt->base + TIMER_CTRL); ++ val &= (~WDT_ENABLE & ~WDT_TIMER_ENABLE); ++ writel(val, airoha_wdt->base + TIMER_CTRL); ++ ++ return 0; ++} ++ ++static int airoha_wdt_ping(struct watchdog_device *wdog_dev) ++{ ++ struct airoha_wdt_desc *airoha_wdt = watchdog_get_drvdata(wdog_dev); ++ u32 val; ++ ++ val = readl(airoha_wdt->base + WDT_RELOAD); ++ val |= WDT_RLD; ++ writel(val, airoha_wdt->base + WDT_RELOAD); ++ ++ return 0; ++} ++ ++static int airoha_wdt_set_timeout(struct watchdog_device *wdog_dev, unsigned int timeout) ++{ ++ wdog_dev->timeout = timeout; ++ ++ if (watchdog_active(wdog_dev)) { ++ airoha_wdt_stop(wdog_dev); ++ return airoha_wdt_start(wdog_dev); ++ } ++ ++ return 0; ++} ++ ++static unsigned int airoha_wdt_get_timeleft(struct watchdog_device *wdog_dev) ++{ ++ struct airoha_wdt_desc *airoha_wdt = watchdog_get_drvdata(wdog_dev); ++ u32 val; ++ ++ val = readl(airoha_wdt->base + WDT_TIMER_CUR_VALUE); ++ return DIV_ROUND_UP(val, airoha_wdt->wdt_freq); ++} ++ ++static const struct watchdog_info airoha_wdt_info = { ++ .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, ++ .identity = "Airoha Watchdog", ++}; ++ ++static const struct watchdog_ops airoha_wdt_ops = { ++ .owner = THIS_MODULE, ++ .start = airoha_wdt_start, ++ .stop = airoha_wdt_stop, ++ .ping = airoha_wdt_ping, ++ .set_timeout = airoha_wdt_set_timeout, ++ .get_timeleft = airoha_wdt_get_timeleft, ++}; ++ ++static int airoha_wdt_probe(struct platform_device *pdev) ++{ ++ struct airoha_wdt_desc *airoha_wdt; ++ struct watchdog_device *wdog_dev; ++ struct device *dev = &pdev->dev; ++ struct clk *bus_clk; ++ int ret; ++ ++ airoha_wdt = devm_kzalloc(dev, sizeof(*airoha_wdt), GFP_KERNEL); ++ if (!airoha_wdt) ++ return -ENOMEM; ++ ++ airoha_wdt->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(airoha_wdt->base)) ++ return PTR_ERR(airoha_wdt->base); ++ ++ bus_clk = devm_clk_get_enabled(dev, "bus"); ++ if (IS_ERR(bus_clk)) ++ return dev_err_probe(dev, PTR_ERR(bus_clk), ++ "failed to enable bus clock\n"); ++ ++ /* Watchdog ticks at half the bus rate */ ++ airoha_wdt->wdt_freq = clk_get_rate(bus_clk) / 2; ++ ++ /* Initialize struct watchdog device */ ++ wdog_dev = &airoha_wdt->wdog_dev; ++ wdog_dev->timeout = heartbeat; ++ wdog_dev->info = &airoha_wdt_info; ++ wdog_dev->ops = &airoha_wdt_ops; ++ /* Bus 300MHz, watchdog 150MHz, 28 seconds */ ++ wdog_dev->max_timeout = FIELD_MAX(WDT_TIMER_VAL) / airoha_wdt->wdt_freq; ++ wdog_dev->parent = dev; ++ ++ watchdog_set_drvdata(wdog_dev, airoha_wdt); ++ watchdog_set_nowayout(wdog_dev, nowayout); ++ watchdog_stop_on_unregister(wdog_dev); ++ ++ ret = devm_watchdog_register_device(dev, wdog_dev); ++ if (ret) ++ return ret; ++ ++ platform_set_drvdata(pdev, airoha_wdt); ++ return 0; ++} ++ ++static int airoha_wdt_suspend(struct device *dev) ++{ ++ struct airoha_wdt_desc *airoha_wdt = dev_get_drvdata(dev); ++ ++ if (watchdog_active(&airoha_wdt->wdog_dev)) ++ airoha_wdt_stop(&airoha_wdt->wdog_dev); ++ ++ return 0; ++} ++ ++static int airoha_wdt_resume(struct device *dev) ++{ ++ struct airoha_wdt_desc *airoha_wdt = dev_get_drvdata(dev); ++ ++ if (watchdog_active(&airoha_wdt->wdog_dev)) { ++ airoha_wdt_start(&airoha_wdt->wdog_dev); ++ airoha_wdt_ping(&airoha_wdt->wdog_dev); ++ } ++ return 0; ++} ++ ++static const struct of_device_id airoha_wdt_of_match[] = { ++ { .compatible = "airoha,en7581-wdt", }, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(of, airoha_wdt_of_match); ++ ++static DEFINE_SIMPLE_DEV_PM_OPS(airoha_wdt_pm_ops, airoha_wdt_suspend, airoha_wdt_resume); ++ ++static struct platform_driver airoha_wdt_driver = { ++ .probe = airoha_wdt_probe, ++ .driver = { ++ .name = "airoha-wdt", ++ .pm = pm_sleep_ptr(&airoha_wdt_pm_ops), ++ .of_match_table = airoha_wdt_of_match, ++ }, ++}; ++ ++module_platform_driver(airoha_wdt_driver); ++ ++MODULE_AUTHOR("Mayur Kumar "); ++MODULE_AUTHOR("Christian Marangi "); ++MODULE_DESCRIPTION("Airoha EN7581 Watchdog Driver"); ++MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/airoha/patches-6.12/033-05-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch b/lede/target/linux/airoha/patches-6.12/033-05-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch new file mode 100644 index 0000000000..6d6868f75a --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/033-05-v6.13-clk-en7523-move-en7581_reset_register-in-en7581_clk_.patch @@ -0,0 +1,174 @@ +From 82e6bf912d5846646892becea659b39d178d79e3 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 12 Nov 2024 01:08:53 +0100 +Subject: [PATCH 5/6] clk: en7523: move en7581_reset_register() in + en7581_clk_hw_init() + +Move en7581_reset_register routine in en7581_clk_hw_init() since reset +feature is supported just by EN7581 SoC. +Get rid of reset struct in en_clk_soc_data data struct. + +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-6-8ada5e394ae4@kernel.org +Signed-off-by: Stephen Boyd +--- + drivers/clk/clk-en7523.c | 93 ++++++++++++++-------------------------- + 1 file changed, 33 insertions(+), 60 deletions(-) + +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -76,11 +76,6 @@ struct en_rst_data { + + struct en_clk_soc_data { + const struct clk_ops pcie_ops; +- struct { +- const u16 *bank_ofs; +- const u16 *idx_map; +- u16 idx_map_nr; +- } reset; + int (*hw_init)(struct platform_device *pdev, + struct clk_hw_onecell_data *clk_data); + }; +@@ -596,32 +591,6 @@ static void en7581_register_clocks(struc + clk_data->num = EN7523_NUM_CLOCKS; + } + +-static int en7581_clk_hw_init(struct platform_device *pdev, +- struct clk_hw_onecell_data *clk_data) +-{ +- void __iomem *np_base; +- struct regmap *map; +- u32 val; +- +- map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); +- if (IS_ERR(map)) +- return PTR_ERR(map); +- +- np_base = devm_platform_ioremap_resource(pdev, 0); +- if (IS_ERR(np_base)) +- return PTR_ERR(np_base); +- +- en7581_register_clocks(&pdev->dev, clk_data, map, np_base); +- +- val = readl(np_base + REG_NP_SCU_SSTR); +- val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); +- writel(val, np_base + REG_NP_SCU_SSTR); +- val = readl(np_base + REG_NP_SCU_PCIC); +- writel(val | 3, np_base + REG_NP_SCU_PCIC); +- +- return 0; +-} +- + static int en7523_reset_update(struct reset_controller_dev *rcdev, + unsigned long id, bool assert) + { +@@ -671,23 +640,18 @@ static int en7523_reset_xlate(struct res + return rst_data->idx_map[reset_spec->args[0]]; + } + +-static const struct reset_control_ops en7523_reset_ops = { ++static const struct reset_control_ops en7581_reset_ops = { + .assert = en7523_reset_assert, + .deassert = en7523_reset_deassert, + .status = en7523_reset_status, + }; + +-static int en7523_reset_register(struct platform_device *pdev, +- const struct en_clk_soc_data *soc_data) ++static int en7581_reset_register(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; + struct en_rst_data *rst_data; + void __iomem *base; + +- /* no reset lines available */ +- if (!soc_data->reset.idx_map_nr) +- return 0; +- + base = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(base)) + return PTR_ERR(base); +@@ -696,13 +660,13 @@ static int en7523_reset_register(struct + if (!rst_data) + return -ENOMEM; + +- rst_data->bank_ofs = soc_data->reset.bank_ofs; +- rst_data->idx_map = soc_data->reset.idx_map; ++ rst_data->bank_ofs = en7581_rst_ofs; ++ rst_data->idx_map = en7581_rst_map; + rst_data->base = base; + +- rst_data->rcdev.nr_resets = soc_data->reset.idx_map_nr; ++ rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map); + rst_data->rcdev.of_xlate = en7523_reset_xlate; +- rst_data->rcdev.ops = &en7523_reset_ops; ++ rst_data->rcdev.ops = &en7581_reset_ops; + rst_data->rcdev.of_node = dev->of_node; + rst_data->rcdev.of_reset_n_cells = 1; + rst_data->rcdev.owner = THIS_MODULE; +@@ -711,6 +675,32 @@ static int en7523_reset_register(struct + return devm_reset_controller_register(dev, &rst_data->rcdev); + } + ++static int en7581_clk_hw_init(struct platform_device *pdev, ++ struct clk_hw_onecell_data *clk_data) ++{ ++ void __iomem *np_base; ++ struct regmap *map; ++ u32 val; ++ ++ map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); ++ if (IS_ERR(map)) ++ return PTR_ERR(map); ++ ++ np_base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(np_base)) ++ return PTR_ERR(np_base); ++ ++ en7581_register_clocks(&pdev->dev, clk_data, map, np_base); ++ ++ val = readl(np_base + REG_NP_SCU_SSTR); ++ val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); ++ writel(val, np_base + REG_NP_SCU_SSTR); ++ val = readl(np_base + REG_NP_SCU_PCIC); ++ writel(val | 3, np_base + REG_NP_SCU_PCIC); ++ ++ return en7581_reset_register(pdev); ++} ++ + static int en7523_clk_probe(struct platform_device *pdev) + { + struct device_node *node = pdev->dev.of_node; +@@ -729,19 +719,7 @@ static int en7523_clk_probe(struct platf + if (r) + return r; + +- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +- if (r) +- return dev_err_probe(&pdev->dev, r, "Could not register clock provider: %s\n", +- pdev->name); +- +- r = en7523_reset_register(pdev, soc_data); +- if (r) { +- of_clk_del_provider(node); +- return dev_err_probe(&pdev->dev, r, "Could not register reset controller: %s\n", +- pdev->name); +- } +- +- return 0; ++ return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + } + + static const struct en_clk_soc_data en7523_data = { +@@ -759,11 +737,6 @@ static const struct en_clk_soc_data en75 + .enable = en7581_pci_enable, + .disable = en7581_pci_disable, + }, +- .reset = { +- .bank_ofs = en7581_rst_ofs, +- .idx_map = en7581_rst_map, +- .idx_map_nr = ARRAY_SIZE(en7581_rst_map), +- }, + .hw_init = en7581_clk_hw_init, + }; + diff --git a/lede/target/linux/airoha/patches-6.12/033-06-v6.13-clk-en7523-map-io-region-in-a-single-block.patch b/lede/target/linux/airoha/patches-6.12/033-06-v6.13-clk-en7523-map-io-region-in-a-single-block.patch new file mode 100644 index 0000000000..51945a9492 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/033-06-v6.13-clk-en7523-map-io-region-in-a-single-block.patch @@ -0,0 +1,84 @@ +From a9eaf305017a5ebe73ab34e85bd5414055a88f29 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 12 Nov 2024 01:08:54 +0100 +Subject: [PATCH 6/6] clk: en7523: map io region in a single block + +Map all clock-controller memory region in a single block. +This patch does not introduce any backward incompatibility since the dts +for EN7581 SoC is not upstream yet. + +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-7-8ada5e394ae4@kernel.org +Signed-off-by: Stephen Boyd +--- + drivers/clk/clk-en7523.c | 32 +++++++++++++------------------- + 1 file changed, 13 insertions(+), 19 deletions(-) + +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -39,8 +39,8 @@ + #define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11) + #define REG_CRYPTO_CLKSRC2 0x20c + +-#define REG_RST_CTRL2 0x00 +-#define REG_RST_CTRL1 0x04 ++#define REG_RST_CTRL2 0x830 ++#define REG_RST_CTRL1 0x834 + + struct en_clk_desc { + int id; +@@ -646,15 +646,9 @@ static const struct reset_control_ops en + .status = en7523_reset_status, + }; + +-static int en7581_reset_register(struct platform_device *pdev) ++static int en7581_reset_register(struct device *dev, void __iomem *base) + { +- struct device *dev = &pdev->dev; + struct en_rst_data *rst_data; +- void __iomem *base; +- +- base = devm_platform_ioremap_resource(pdev, 1); +- if (IS_ERR(base)) +- return PTR_ERR(base); + + rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL); + if (!rst_data) +@@ -678,27 +672,27 @@ static int en7581_reset_register(struct + static int en7581_clk_hw_init(struct platform_device *pdev, + struct clk_hw_onecell_data *clk_data) + { +- void __iomem *np_base; + struct regmap *map; ++ void __iomem *base; + u32 val; + + map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); + if (IS_ERR(map)) + return PTR_ERR(map); + +- np_base = devm_platform_ioremap_resource(pdev, 0); +- if (IS_ERR(np_base)) +- return PTR_ERR(np_base); ++ base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); + +- en7581_register_clocks(&pdev->dev, clk_data, map, np_base); ++ en7581_register_clocks(&pdev->dev, clk_data, map, base); + +- val = readl(np_base + REG_NP_SCU_SSTR); ++ val = readl(base + REG_NP_SCU_SSTR); + val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); +- writel(val, np_base + REG_NP_SCU_SSTR); +- val = readl(np_base + REG_NP_SCU_PCIC); +- writel(val | 3, np_base + REG_NP_SCU_PCIC); ++ writel(val, base + REG_NP_SCU_SSTR); ++ val = readl(base + REG_NP_SCU_PCIC); ++ writel(val | 3, base + REG_NP_SCU_PCIC); + +- return en7581_reset_register(pdev); ++ return en7581_reset_register(&pdev->dev, base); + } + + static int en7523_clk_probe(struct platform_device *pdev) diff --git a/lede/target/linux/airoha/patches-6.12/034-01-v6.13-pinctrl-airoha-Add-support-for-EN7581-SoC.patch b/lede/target/linux/airoha/patches-6.12/034-01-v6.13-pinctrl-airoha-Add-support-for-EN7581-SoC.patch new file mode 100644 index 0000000000..0f0fdeec1e --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/034-01-v6.13-pinctrl-airoha-Add-support-for-EN7581-SoC.patch @@ -0,0 +1,3060 @@ +From 1c8ace2d0725c1c8d5012f8a56c5fb31805aad27 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 23 Oct 2024 01:20:05 +0200 +Subject: [PATCH] pinctrl: airoha: Add support for EN7581 SoC + +Introduce pinctrl driver for EN7581 SoC. Current EN7581 pinctrl driver +supports the following functionalities: +- pin multiplexing +- pin pull-up, pull-down, open-drain, current strength, + {input,output}_enable, output_{low,high} +- gpio controller +- irq controller + +Tested-by: Benjamin Larsson +Co-developed-by: Benjamin Larsson +Signed-off-by: Benjamin Larsson +Reviewed-by: Linus Walleij +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/20241023-en7581-pinctrl-v9-5-afb0cbcab0ec@kernel.org +Signed-off-by: Linus Walleij +--- + MAINTAINERS | 7 + + drivers/pinctrl/mediatek/Kconfig | 17 +- + drivers/pinctrl/mediatek/Makefile | 1 + + drivers/pinctrl/mediatek/pinctrl-airoha.c | 2970 +++++++++++++++++++++ + 4 files changed, 2994 insertions(+), 1 deletion(-) + create mode 100644 drivers/pinctrl/mediatek/pinctrl-airoha.c + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -18191,6 +18191,13 @@ F: drivers/pinctrl/ + F: include/dt-bindings/pinctrl/ + F: include/linux/pinctrl/ + ++PIN CONTROLLER - AIROHA ++M: Lorenzo Bianconi ++L: linux-mediatek@lists.infradead.org (moderated for non-subscribers) ++S: Maintained ++F: Documentation/devicetree/bindings/pinctrl/airoha,en7581-pinctrl.yaml ++F: drivers/pinctrl/mediatek/pinctrl-airoha.c ++ + PIN CONTROLLER - AMD + M: Basavaraj Natikar + M: Shyam Sundar S K +--- a/drivers/pinctrl/mediatek/Kconfig ++++ b/drivers/pinctrl/mediatek/Kconfig +@@ -1,6 +1,6 @@ + # SPDX-License-Identifier: GPL-2.0-only + menu "MediaTek pinctrl drivers" +- depends on ARCH_MEDIATEK || RALINK || COMPILE_TEST ++ depends on ARCH_MEDIATEK || ARCH_AIROHA || RALINK || COMPILE_TEST + + config EINT_MTK + tristate "MediaTek External Interrupt Support" +@@ -126,6 +126,21 @@ config PINCTRL_MT8127 + select PINCTRL_MTK + + # For ARMv8 SoCs ++config PINCTRL_AIROHA ++ tristate "Airoha EN7581 pin control" ++ depends on OF ++ depends on ARM64 || COMPILE_TEST ++ select PINMUX ++ select GENERIC_PINCONF ++ select GENERIC_PINCTRL_GROUPS ++ select GENERIC_PINMUX_FUNCTIONS ++ select GPIOLIB ++ select GPIOLIB_IRQCHIP ++ select REGMAP_MMIO ++ help ++ Say yes here to support pin controller and gpio driver ++ on Airoha EN7581 SoC. ++ + config PINCTRL_MT2712 + bool "MediaTek MT2712 pin control" + depends on OF +--- a/drivers/pinctrl/mediatek/Makefile ++++ b/drivers/pinctrl/mediatek/Makefile +@@ -8,6 +8,7 @@ obj-$(CONFIG_PINCTRL_MTK_MOORE) += pinc + obj-$(CONFIG_PINCTRL_MTK_PARIS) += pinctrl-paris.o + + # SoC Drivers ++obj-$(CONFIG_PINCTRL_AIROHA) += pinctrl-airoha.o + obj-$(CONFIG_PINCTRL_MT7620) += pinctrl-mt7620.o + obj-$(CONFIG_PINCTRL_MT7621) += pinctrl-mt7621.o + obj-$(CONFIG_PINCTRL_MT76X8) += pinctrl-mt76x8.o +--- /dev/null ++++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c +@@ -0,0 +1,2970 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Author: Lorenzo Bianconi ++ * Author: Benjamin Larsson ++ * Author: Markus Gothe ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../core.h" ++#include "../pinconf.h" ++#include "../pinmux.h" ++ ++#define PINCTRL_PIN_GROUP(id) \ ++ PINCTRL_PINGROUP(#id, id##_pins, ARRAY_SIZE(id##_pins)) ++ ++#define PINCTRL_FUNC_DESC(id) \ ++ { \ ++ .desc = { \ ++ .func = { \ ++ .name = #id, \ ++ .groups = id##_groups, \ ++ .ngroups = ARRAY_SIZE(id##_groups), \ ++ } \ ++ }, \ ++ .groups = id##_func_group, \ ++ .group_size = ARRAY_SIZE(id##_func_group), \ ++ } ++ ++#define PINCTRL_CONF_DESC(p, offset, mask) \ ++ { \ ++ .pin = p, \ ++ .reg = { offset, mask }, \ ++ } ++ ++/* MUX */ ++#define REG_GPIO_2ND_I2C_MODE 0x0214 ++#define GPIO_MDC_IO_MASTER_MODE_MODE BIT(14) ++#define GPIO_I2C_MASTER_MODE_MODE BIT(13) ++#define GPIO_I2S_MODE_MASK BIT(12) ++#define GPIO_I2C_SLAVE_MODE_MODE BIT(11) ++#define GPIO_LAN3_LED1_MODE_MASK BIT(10) ++#define GPIO_LAN3_LED0_MODE_MASK BIT(9) ++#define GPIO_LAN2_LED1_MODE_MASK BIT(8) ++#define GPIO_LAN2_LED0_MODE_MASK BIT(7) ++#define GPIO_LAN1_LED1_MODE_MASK BIT(6) ++#define GPIO_LAN1_LED0_MODE_MASK BIT(5) ++#define GPIO_LAN0_LED1_MODE_MASK BIT(4) ++#define GPIO_LAN0_LED0_MODE_MASK BIT(3) ++#define PON_TOD_1PPS_MODE_MASK BIT(2) ++#define GSW_TOD_1PPS_MODE_MASK BIT(1) ++#define GPIO_2ND_I2C_MODE_MASK BIT(0) ++ ++#define REG_GPIO_SPI_CS1_MODE 0x0218 ++#define GPIO_PCM_SPI_CS4_MODE_MASK BIT(21) ++#define GPIO_PCM_SPI_CS3_MODE_MASK BIT(20) ++#define GPIO_PCM_SPI_CS2_MODE_P156_MASK BIT(19) ++#define GPIO_PCM_SPI_CS2_MODE_P128_MASK BIT(18) ++#define GPIO_PCM_SPI_CS1_MODE_MASK BIT(17) ++#define GPIO_PCM_SPI_MODE_MASK BIT(16) ++#define GPIO_PCM2_MODE_MASK BIT(13) ++#define GPIO_PCM1_MODE_MASK BIT(12) ++#define GPIO_PCM_INT_MODE_MASK BIT(9) ++#define GPIO_PCM_RESET_MODE_MASK BIT(8) ++#define GPIO_SPI_QUAD_MODE_MASK BIT(4) ++#define GPIO_SPI_CS4_MODE_MASK BIT(3) ++#define GPIO_SPI_CS3_MODE_MASK BIT(2) ++#define GPIO_SPI_CS2_MODE_MASK BIT(1) ++#define GPIO_SPI_CS1_MODE_MASK BIT(0) ++ ++#define REG_GPIO_PON_MODE 0x021c ++#define GPIO_PARALLEL_NAND_MODE_MASK BIT(14) ++#define GPIO_SGMII_MDIO_MODE_MASK BIT(13) ++#define GPIO_PCIE_RESET2_MASK BIT(12) ++#define SIPO_RCLK_MODE_MASK BIT(11) ++#define GPIO_PCIE_RESET1_MASK BIT(10) ++#define GPIO_PCIE_RESET0_MASK BIT(9) ++#define GPIO_UART5_MODE_MASK BIT(8) ++#define GPIO_UART4_MODE_MASK BIT(7) ++#define GPIO_HSUART_CTS_RTS_MODE_MASK BIT(6) ++#define GPIO_HSUART_MODE_MASK BIT(5) ++#define GPIO_UART2_CTS_RTS_MODE_MASK BIT(4) ++#define GPIO_UART2_MODE_MASK BIT(3) ++#define GPIO_SIPO_MODE_MASK BIT(2) ++#define GPIO_EMMC_MODE_MASK BIT(1) ++#define GPIO_PON_MODE_MASK BIT(0) ++ ++#define REG_NPU_UART_EN 0x0224 ++#define JTAG_UDI_EN_MASK BIT(4) ++#define JTAG_DFD_EN_MASK BIT(3) ++ ++/* LED MAP */ ++#define REG_LAN_LED0_MAPPING 0x027c ++#define REG_LAN_LED1_MAPPING 0x0280 ++ ++#define LAN4_LED_MAPPING_MASK GENMASK(18, 16) ++#define LAN4_PHY4_LED_MAP BIT(18) ++#define LAN4_PHY2_LED_MAP BIT(17) ++#define LAN4_PHY1_LED_MAP BIT(16) ++#define LAN4_PHY0_LED_MAP 0 ++#define LAN4_PHY3_LED_MAP GENMASK(17, 16) ++ ++#define LAN3_LED_MAPPING_MASK GENMASK(14, 12) ++#define LAN3_PHY4_LED_MAP BIT(14) ++#define LAN3_PHY2_LED_MAP BIT(13) ++#define LAN3_PHY1_LED_MAP BIT(12) ++#define LAN3_PHY0_LED_MAP 0 ++#define LAN3_PHY3_LED_MAP GENMASK(13, 12) ++ ++#define LAN2_LED_MAPPING_MASK GENMASK(10, 8) ++#define LAN2_PHY4_LED_MAP BIT(12) ++#define LAN2_PHY2_LED_MAP BIT(11) ++#define LAN2_PHY1_LED_MAP BIT(10) ++#define LAN2_PHY0_LED_MAP 0 ++#define LAN2_PHY3_LED_MAP GENMASK(11, 10) ++ ++#define LAN1_LED_MAPPING_MASK GENMASK(6, 4) ++#define LAN1_PHY4_LED_MAP BIT(6) ++#define LAN1_PHY2_LED_MAP BIT(5) ++#define LAN1_PHY1_LED_MAP BIT(4) ++#define LAN1_PHY0_LED_MAP 0 ++#define LAN1_PHY3_LED_MAP GENMASK(5, 4) ++ ++#define LAN0_LED_MAPPING_MASK GENMASK(2, 0) ++#define LAN0_PHY4_LED_MAP BIT(3) ++#define LAN0_PHY2_LED_MAP BIT(2) ++#define LAN0_PHY1_LED_MAP BIT(1) ++#define LAN0_PHY0_LED_MAP 0 ++#define LAN0_PHY3_LED_MAP GENMASK(2, 1) ++ ++/* CONF */ ++#define REG_I2C_SDA_E2 0x001c ++#define SPI_MISO_E2_MASK BIT(14) ++#define SPI_MOSI_E2_MASK BIT(13) ++#define SPI_CLK_E2_MASK BIT(12) ++#define SPI_CS0_E2_MASK BIT(11) ++#define PCIE2_RESET_E2_MASK BIT(10) ++#define PCIE1_RESET_E2_MASK BIT(9) ++#define PCIE0_RESET_E2_MASK BIT(8) ++#define UART1_RXD_E2_MASK BIT(3) ++#define UART1_TXD_E2_MASK BIT(2) ++#define I2C_SCL_E2_MASK BIT(1) ++#define I2C_SDA_E2_MASK BIT(0) ++ ++#define REG_I2C_SDA_E4 0x0020 ++#define SPI_MISO_E4_MASK BIT(14) ++#define SPI_MOSI_E4_MASK BIT(13) ++#define SPI_CLK_E4_MASK BIT(12) ++#define SPI_CS0_E4_MASK BIT(11) ++#define PCIE2_RESET_E4_MASK BIT(10) ++#define PCIE1_RESET_E4_MASK BIT(9) ++#define PCIE0_RESET_E4_MASK BIT(8) ++#define UART1_RXD_E4_MASK BIT(3) ++#define UART1_TXD_E4_MASK BIT(2) ++#define I2C_SCL_E4_MASK BIT(1) ++#define I2C_SDA_E4_MASK BIT(0) ++ ++#define REG_GPIO_L_E2 0x0024 ++#define REG_GPIO_L_E4 0x0028 ++#define REG_GPIO_H_E2 0x002c ++#define REG_GPIO_H_E4 0x0030 ++ ++#define REG_I2C_SDA_PU 0x0044 ++#define SPI_MISO_PU_MASK BIT(14) ++#define SPI_MOSI_PU_MASK BIT(13) ++#define SPI_CLK_PU_MASK BIT(12) ++#define SPI_CS0_PU_MASK BIT(11) ++#define PCIE2_RESET_PU_MASK BIT(10) ++#define PCIE1_RESET_PU_MASK BIT(9) ++#define PCIE0_RESET_PU_MASK BIT(8) ++#define UART1_RXD_PU_MASK BIT(3) ++#define UART1_TXD_PU_MASK BIT(2) ++#define I2C_SCL_PU_MASK BIT(1) ++#define I2C_SDA_PU_MASK BIT(0) ++ ++#define REG_I2C_SDA_PD 0x0048 ++#define SPI_MISO_PD_MASK BIT(14) ++#define SPI_MOSI_PD_MASK BIT(13) ++#define SPI_CLK_PD_MASK BIT(12) ++#define SPI_CS0_PD_MASK BIT(11) ++#define PCIE2_RESET_PD_MASK BIT(10) ++#define PCIE1_RESET_PD_MASK BIT(9) ++#define PCIE0_RESET_PD_MASK BIT(8) ++#define UART1_RXD_PD_MASK BIT(3) ++#define UART1_TXD_PD_MASK BIT(2) ++#define I2C_SCL_PD_MASK BIT(1) ++#define I2C_SDA_PD_MASK BIT(0) ++ ++#define REG_GPIO_L_PU 0x004c ++#define REG_GPIO_L_PD 0x0050 ++#define REG_GPIO_H_PU 0x0054 ++#define REG_GPIO_H_PD 0x0058 ++ ++#define REG_PCIE_RESET_OD 0x018c ++#define PCIE2_RESET_OD_MASK BIT(2) ++#define PCIE1_RESET_OD_MASK BIT(1) ++#define PCIE0_RESET_OD_MASK BIT(0) ++ ++/* GPIOs */ ++#define REG_GPIO_CTRL 0x0000 ++#define REG_GPIO_DATA 0x0004 ++#define REG_GPIO_INT 0x0008 ++#define REG_GPIO_INT_EDGE 0x000c ++#define REG_GPIO_INT_LEVEL 0x0010 ++#define REG_GPIO_OE 0x0014 ++#define REG_GPIO_CTRL1 0x0020 ++ ++/* PWM MODE CONF */ ++#define REG_GPIO_FLASH_MODE_CFG 0x0034 ++#define GPIO15_FLASH_MODE_CFG BIT(15) ++#define GPIO14_FLASH_MODE_CFG BIT(14) ++#define GPIO13_FLASH_MODE_CFG BIT(13) ++#define GPIO12_FLASH_MODE_CFG BIT(12) ++#define GPIO11_FLASH_MODE_CFG BIT(11) ++#define GPIO10_FLASH_MODE_CFG BIT(10) ++#define GPIO9_FLASH_MODE_CFG BIT(9) ++#define GPIO8_FLASH_MODE_CFG BIT(8) ++#define GPIO7_FLASH_MODE_CFG BIT(7) ++#define GPIO6_FLASH_MODE_CFG BIT(6) ++#define GPIO5_FLASH_MODE_CFG BIT(5) ++#define GPIO4_FLASH_MODE_CFG BIT(4) ++#define GPIO3_FLASH_MODE_CFG BIT(3) ++#define GPIO2_FLASH_MODE_CFG BIT(2) ++#define GPIO1_FLASH_MODE_CFG BIT(1) ++#define GPIO0_FLASH_MODE_CFG BIT(0) ++ ++#define REG_GPIO_CTRL2 0x0060 ++#define REG_GPIO_CTRL3 0x0064 ++ ++/* PWM MODE CONF EXT */ ++#define REG_GPIO_FLASH_MODE_CFG_EXT 0x0068 ++#define GPIO51_FLASH_MODE_CFG BIT(31) ++#define GPIO50_FLASH_MODE_CFG BIT(30) ++#define GPIO49_FLASH_MODE_CFG BIT(29) ++#define GPIO48_FLASH_MODE_CFG BIT(28) ++#define GPIO47_FLASH_MODE_CFG BIT(27) ++#define GPIO46_FLASH_MODE_CFG BIT(26) ++#define GPIO45_FLASH_MODE_CFG BIT(25) ++#define GPIO44_FLASH_MODE_CFG BIT(24) ++#define GPIO43_FLASH_MODE_CFG BIT(23) ++#define GPIO42_FLASH_MODE_CFG BIT(22) ++#define GPIO41_FLASH_MODE_CFG BIT(21) ++#define GPIO40_FLASH_MODE_CFG BIT(20) ++#define GPIO39_FLASH_MODE_CFG BIT(19) ++#define GPIO38_FLASH_MODE_CFG BIT(18) ++#define GPIO37_FLASH_MODE_CFG BIT(17) ++#define GPIO36_FLASH_MODE_CFG BIT(16) ++#define GPIO31_FLASH_MODE_CFG BIT(15) ++#define GPIO30_FLASH_MODE_CFG BIT(14) ++#define GPIO29_FLASH_MODE_CFG BIT(13) ++#define GPIO28_FLASH_MODE_CFG BIT(12) ++#define GPIO27_FLASH_MODE_CFG BIT(11) ++#define GPIO26_FLASH_MODE_CFG BIT(10) ++#define GPIO25_FLASH_MODE_CFG BIT(9) ++#define GPIO24_FLASH_MODE_CFG BIT(8) ++#define GPIO23_FLASH_MODE_CFG BIT(7) ++#define GPIO22_FLASH_MODE_CFG BIT(6) ++#define GPIO21_FLASH_MODE_CFG BIT(5) ++#define GPIO20_FLASH_MODE_CFG BIT(4) ++#define GPIO19_FLASH_MODE_CFG BIT(3) ++#define GPIO18_FLASH_MODE_CFG BIT(2) ++#define GPIO17_FLASH_MODE_CFG BIT(1) ++#define GPIO16_FLASH_MODE_CFG BIT(0) ++ ++#define REG_GPIO_DATA1 0x0070 ++#define REG_GPIO_OE1 0x0078 ++#define REG_GPIO_INT1 0x007c ++#define REG_GPIO_INT_EDGE1 0x0080 ++#define REG_GPIO_INT_EDGE2 0x0084 ++#define REG_GPIO_INT_EDGE3 0x0088 ++#define REG_GPIO_INT_LEVEL1 0x008c ++#define REG_GPIO_INT_LEVEL2 0x0090 ++#define REG_GPIO_INT_LEVEL3 0x0094 ++ ++#define AIROHA_NUM_PINS 64 ++#define AIROHA_PIN_BANK_SIZE (AIROHA_NUM_PINS / 2) ++#define AIROHA_REG_GPIOCTRL_NUM_PIN (AIROHA_NUM_PINS / 4) ++ ++static const u32 gpio_data_regs[] = { ++ REG_GPIO_DATA, ++ REG_GPIO_DATA1 ++}; ++ ++static const u32 gpio_out_regs[] = { ++ REG_GPIO_OE, ++ REG_GPIO_OE1 ++}; ++ ++static const u32 gpio_dir_regs[] = { ++ REG_GPIO_CTRL, ++ REG_GPIO_CTRL1, ++ REG_GPIO_CTRL2, ++ REG_GPIO_CTRL3 ++}; ++ ++static const u32 irq_status_regs[] = { ++ REG_GPIO_INT, ++ REG_GPIO_INT1 ++}; ++ ++static const u32 irq_level_regs[] = { ++ REG_GPIO_INT_LEVEL, ++ REG_GPIO_INT_LEVEL1, ++ REG_GPIO_INT_LEVEL2, ++ REG_GPIO_INT_LEVEL3 ++}; ++ ++static const u32 irq_edge_regs[] = { ++ REG_GPIO_INT_EDGE, ++ REG_GPIO_INT_EDGE1, ++ REG_GPIO_INT_EDGE2, ++ REG_GPIO_INT_EDGE3 ++}; ++ ++struct airoha_pinctrl_reg { ++ u32 offset; ++ u32 mask; ++}; ++ ++enum airoha_pinctrl_mux_func { ++ AIROHA_FUNC_MUX, ++ AIROHA_FUNC_PWM_MUX, ++ AIROHA_FUNC_PWM_EXT_MUX, ++}; ++ ++struct airoha_pinctrl_func_group { ++ const char *name; ++ struct { ++ enum airoha_pinctrl_mux_func mux; ++ u32 offset; ++ u32 mask; ++ u32 val; ++ } regmap[2]; ++ int regmap_size; ++}; ++ ++struct airoha_pinctrl_func { ++ const struct function_desc desc; ++ const struct airoha_pinctrl_func_group *groups; ++ u8 group_size; ++}; ++ ++struct airoha_pinctrl_conf { ++ u32 pin; ++ struct airoha_pinctrl_reg reg; ++}; ++ ++struct airoha_pinctrl_gpiochip { ++ struct gpio_chip chip; ++ ++ /* gpio */ ++ const u32 *data; ++ const u32 *dir; ++ const u32 *out; ++ /* irq */ ++ const u32 *status; ++ const u32 *level; ++ const u32 *edge; ++ ++ u32 irq_type[AIROHA_NUM_PINS]; ++}; ++ ++struct airoha_pinctrl { ++ struct pinctrl_dev *ctrl; ++ ++ struct regmap *chip_scu; ++ struct regmap *regmap; ++ ++ struct airoha_pinctrl_gpiochip gpiochip; ++}; ++ ++static struct pinctrl_pin_desc airoha_pinctrl_pins[] = { ++ PINCTRL_PIN(0, "uart1_txd"), ++ PINCTRL_PIN(1, "uart1_rxd"), ++ PINCTRL_PIN(2, "i2c_scl"), ++ PINCTRL_PIN(3, "i2c_sda"), ++ PINCTRL_PIN(4, "spi_cs0"), ++ PINCTRL_PIN(5, "spi_clk"), ++ PINCTRL_PIN(6, "spi_mosi"), ++ PINCTRL_PIN(7, "spi_miso"), ++ PINCTRL_PIN(13, "gpio0"), ++ PINCTRL_PIN(14, "gpio1"), ++ PINCTRL_PIN(15, "gpio2"), ++ PINCTRL_PIN(16, "gpio3"), ++ PINCTRL_PIN(17, "gpio4"), ++ PINCTRL_PIN(18, "gpio5"), ++ PINCTRL_PIN(19, "gpio6"), ++ PINCTRL_PIN(20, "gpio7"), ++ PINCTRL_PIN(21, "gpio8"), ++ PINCTRL_PIN(22, "gpio9"), ++ PINCTRL_PIN(23, "gpio10"), ++ PINCTRL_PIN(24, "gpio11"), ++ PINCTRL_PIN(25, "gpio12"), ++ PINCTRL_PIN(26, "gpio13"), ++ PINCTRL_PIN(27, "gpio14"), ++ PINCTRL_PIN(28, "gpio15"), ++ PINCTRL_PIN(29, "gpio16"), ++ PINCTRL_PIN(30, "gpio17"), ++ PINCTRL_PIN(31, "gpio18"), ++ PINCTRL_PIN(32, "gpio19"), ++ PINCTRL_PIN(33, "gpio20"), ++ PINCTRL_PIN(34, "gpio21"), ++ PINCTRL_PIN(35, "gpio22"), ++ PINCTRL_PIN(36, "gpio23"), ++ PINCTRL_PIN(37, "gpio24"), ++ PINCTRL_PIN(38, "gpio25"), ++ PINCTRL_PIN(39, "gpio26"), ++ PINCTRL_PIN(40, "gpio27"), ++ PINCTRL_PIN(41, "gpio28"), ++ PINCTRL_PIN(42, "gpio29"), ++ PINCTRL_PIN(43, "gpio30"), ++ PINCTRL_PIN(44, "gpio31"), ++ PINCTRL_PIN(45, "gpio32"), ++ PINCTRL_PIN(46, "gpio33"), ++ PINCTRL_PIN(47, "gpio34"), ++ PINCTRL_PIN(48, "gpio35"), ++ PINCTRL_PIN(49, "gpio36"), ++ PINCTRL_PIN(50, "gpio37"), ++ PINCTRL_PIN(51, "gpio38"), ++ PINCTRL_PIN(52, "gpio39"), ++ PINCTRL_PIN(53, "gpio40"), ++ PINCTRL_PIN(54, "gpio41"), ++ PINCTRL_PIN(55, "gpio42"), ++ PINCTRL_PIN(56, "gpio43"), ++ PINCTRL_PIN(57, "gpio44"), ++ PINCTRL_PIN(58, "gpio45"), ++ PINCTRL_PIN(59, "gpio46"), ++ PINCTRL_PIN(61, "pcie_reset0"), ++ PINCTRL_PIN(62, "pcie_reset1"), ++ PINCTRL_PIN(63, "pcie_reset2"), ++}; ++ ++static const int pon_pins[] = { 49, 50, 51, 52, 53, 54 }; ++static const int pon_tod_1pps_pins[] = { 46 }; ++static const int gsw_tod_1pps_pins[] = { 46 }; ++static const int sipo_pins[] = { 16, 17 }; ++static const int sipo_rclk_pins[] = { 16, 17, 43 }; ++static const int mdio_pins[] = { 14, 15 }; ++static const int uart2_pins[] = { 48, 55 }; ++static const int uart2_cts_rts_pins[] = { 46, 47 }; ++static const int hsuart_pins[] = { 28, 29 }; ++static const int hsuart_cts_rts_pins[] = { 26, 27 }; ++static const int uart4_pins[] = { 38, 39 }; ++static const int uart5_pins[] = { 18, 19 }; ++static const int i2c0_pins[] = { 2, 3 }; ++static const int i2c1_pins[] = { 14, 15 }; ++static const int jtag_udi_pins[] = { 16, 17, 18, 19, 20 }; ++static const int jtag_dfd_pins[] = { 16, 17, 18, 19, 20 }; ++static const int i2s_pins[] = { 26, 27, 28, 29 }; ++static const int pcm1_pins[] = { 22, 23, 24, 25 }; ++static const int pcm2_pins[] = { 18, 19, 20, 21 }; ++static const int spi_quad_pins[] = { 32, 33 }; ++static const int spi_pins[] = { 4, 5, 6, 7 }; ++static const int spi_cs1_pins[] = { 34 }; ++static const int pcm_spi_pins[] = { 18, 19, 20, 21, 22, 23, 24, 25 }; ++static const int pcm_spi_int_pins[] = { 14 }; ++static const int pcm_spi_rst_pins[] = { 15 }; ++static const int pcm_spi_cs1_pins[] = { 43 }; ++static const int pcm_spi_cs2_pins[] = { 40 }; ++static const int pcm_spi_cs2_p128_pins[] = { 40 }; ++static const int pcm_spi_cs2_p156_pins[] = { 40 }; ++static const int pcm_spi_cs3_pins[] = { 41 }; ++static const int pcm_spi_cs4_pins[] = { 42 }; ++static const int emmc_pins[] = { 4, 5, 6, 30, 31, 32, 33, 34, 35, 36, 37 }; ++static const int pnand_pins[] = { 4, 5, 6, 7, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42 }; ++static const int gpio0_pins[] = { 13 }; ++static const int gpio1_pins[] = { 14 }; ++static const int gpio2_pins[] = { 15 }; ++static const int gpio3_pins[] = { 16 }; ++static const int gpio4_pins[] = { 17 }; ++static const int gpio5_pins[] = { 18 }; ++static const int gpio6_pins[] = { 19 }; ++static const int gpio7_pins[] = { 20 }; ++static const int gpio8_pins[] = { 21 }; ++static const int gpio9_pins[] = { 22 }; ++static const int gpio10_pins[] = { 23 }; ++static const int gpio11_pins[] = { 24 }; ++static const int gpio12_pins[] = { 25 }; ++static const int gpio13_pins[] = { 26 }; ++static const int gpio14_pins[] = { 27 }; ++static const int gpio15_pins[] = { 28 }; ++static const int gpio16_pins[] = { 29 }; ++static const int gpio17_pins[] = { 30 }; ++static const int gpio18_pins[] = { 31 }; ++static const int gpio19_pins[] = { 32 }; ++static const int gpio20_pins[] = { 33 }; ++static const int gpio21_pins[] = { 34 }; ++static const int gpio22_pins[] = { 35 }; ++static const int gpio23_pins[] = { 36 }; ++static const int gpio24_pins[] = { 37 }; ++static const int gpio25_pins[] = { 38 }; ++static const int gpio26_pins[] = { 39 }; ++static const int gpio27_pins[] = { 40 }; ++static const int gpio28_pins[] = { 41 }; ++static const int gpio29_pins[] = { 42 }; ++static const int gpio30_pins[] = { 43 }; ++static const int gpio31_pins[] = { 44 }; ++static const int gpio33_pins[] = { 46 }; ++static const int gpio34_pins[] = { 47 }; ++static const int gpio35_pins[] = { 48 }; ++static const int gpio36_pins[] = { 49 }; ++static const int gpio37_pins[] = { 50 }; ++static const int gpio38_pins[] = { 51 }; ++static const int gpio39_pins[] = { 52 }; ++static const int gpio40_pins[] = { 53 }; ++static const int gpio41_pins[] = { 54 }; ++static const int gpio42_pins[] = { 55 }; ++static const int gpio43_pins[] = { 56 }; ++static const int gpio44_pins[] = { 57 }; ++static const int gpio45_pins[] = { 58 }; ++static const int gpio46_pins[] = { 59 }; ++static const int pcie_reset0_pins[] = { 61 }; ++static const int pcie_reset1_pins[] = { 62 }; ++static const int pcie_reset2_pins[] = { 63 }; ++ ++static const struct pingroup airoha_pinctrl_groups[] = { ++ PINCTRL_PIN_GROUP(pon), ++ PINCTRL_PIN_GROUP(pon_tod_1pps), ++ PINCTRL_PIN_GROUP(gsw_tod_1pps), ++ PINCTRL_PIN_GROUP(sipo), ++ PINCTRL_PIN_GROUP(sipo_rclk), ++ PINCTRL_PIN_GROUP(mdio), ++ PINCTRL_PIN_GROUP(uart2), ++ PINCTRL_PIN_GROUP(uart2_cts_rts), ++ PINCTRL_PIN_GROUP(hsuart), ++ PINCTRL_PIN_GROUP(hsuart_cts_rts), ++ PINCTRL_PIN_GROUP(uart4), ++ PINCTRL_PIN_GROUP(uart5), ++ PINCTRL_PIN_GROUP(i2c0), ++ PINCTRL_PIN_GROUP(i2c1), ++ PINCTRL_PIN_GROUP(jtag_udi), ++ PINCTRL_PIN_GROUP(jtag_dfd), ++ PINCTRL_PIN_GROUP(i2s), ++ PINCTRL_PIN_GROUP(pcm1), ++ PINCTRL_PIN_GROUP(pcm2), ++ PINCTRL_PIN_GROUP(spi), ++ PINCTRL_PIN_GROUP(spi_quad), ++ PINCTRL_PIN_GROUP(spi_cs1), ++ PINCTRL_PIN_GROUP(pcm_spi), ++ PINCTRL_PIN_GROUP(pcm_spi_int), ++ PINCTRL_PIN_GROUP(pcm_spi_rst), ++ PINCTRL_PIN_GROUP(pcm_spi_cs1), ++ PINCTRL_PIN_GROUP(pcm_spi_cs2_p128), ++ PINCTRL_PIN_GROUP(pcm_spi_cs2_p156), ++ PINCTRL_PIN_GROUP(pcm_spi_cs2), ++ PINCTRL_PIN_GROUP(pcm_spi_cs3), ++ PINCTRL_PIN_GROUP(pcm_spi_cs4), ++ PINCTRL_PIN_GROUP(emmc), ++ PINCTRL_PIN_GROUP(pnand), ++ PINCTRL_PIN_GROUP(gpio0), ++ PINCTRL_PIN_GROUP(gpio1), ++ PINCTRL_PIN_GROUP(gpio2), ++ PINCTRL_PIN_GROUP(gpio3), ++ PINCTRL_PIN_GROUP(gpio4), ++ PINCTRL_PIN_GROUP(gpio5), ++ PINCTRL_PIN_GROUP(gpio6), ++ PINCTRL_PIN_GROUP(gpio7), ++ PINCTRL_PIN_GROUP(gpio8), ++ PINCTRL_PIN_GROUP(gpio9), ++ PINCTRL_PIN_GROUP(gpio10), ++ PINCTRL_PIN_GROUP(gpio11), ++ PINCTRL_PIN_GROUP(gpio12), ++ PINCTRL_PIN_GROUP(gpio13), ++ PINCTRL_PIN_GROUP(gpio14), ++ PINCTRL_PIN_GROUP(gpio15), ++ PINCTRL_PIN_GROUP(gpio16), ++ PINCTRL_PIN_GROUP(gpio17), ++ PINCTRL_PIN_GROUP(gpio18), ++ PINCTRL_PIN_GROUP(gpio19), ++ PINCTRL_PIN_GROUP(gpio20), ++ PINCTRL_PIN_GROUP(gpio21), ++ PINCTRL_PIN_GROUP(gpio22), ++ PINCTRL_PIN_GROUP(gpio23), ++ PINCTRL_PIN_GROUP(gpio24), ++ PINCTRL_PIN_GROUP(gpio25), ++ PINCTRL_PIN_GROUP(gpio26), ++ PINCTRL_PIN_GROUP(gpio27), ++ PINCTRL_PIN_GROUP(gpio28), ++ PINCTRL_PIN_GROUP(gpio29), ++ PINCTRL_PIN_GROUP(gpio30), ++ PINCTRL_PIN_GROUP(gpio31), ++ PINCTRL_PIN_GROUP(gpio33), ++ PINCTRL_PIN_GROUP(gpio34), ++ PINCTRL_PIN_GROUP(gpio35), ++ PINCTRL_PIN_GROUP(gpio36), ++ PINCTRL_PIN_GROUP(gpio37), ++ PINCTRL_PIN_GROUP(gpio38), ++ PINCTRL_PIN_GROUP(gpio39), ++ PINCTRL_PIN_GROUP(gpio40), ++ PINCTRL_PIN_GROUP(gpio41), ++ PINCTRL_PIN_GROUP(gpio42), ++ PINCTRL_PIN_GROUP(gpio43), ++ PINCTRL_PIN_GROUP(gpio44), ++ PINCTRL_PIN_GROUP(gpio45), ++ PINCTRL_PIN_GROUP(gpio46), ++ PINCTRL_PIN_GROUP(pcie_reset0), ++ PINCTRL_PIN_GROUP(pcie_reset1), ++ PINCTRL_PIN_GROUP(pcie_reset2), ++}; ++ ++static const char *const pon_groups[] = { "pon" }; ++static const char *const tod_1pps_groups[] = { "pon_tod_1pps", "gsw_tod_1pps" }; ++static const char *const sipo_groups[] = { "sipo", "sipo_rclk" }; ++static const char *const mdio_groups[] = { "mdio" }; ++static const char *const uart_groups[] = { "uart2", "uart2_cts_rts", "hsuart", ++ "hsuart_cts_rts", "uart4", ++ "uart5" }; ++static const char *const i2c_groups[] = { "i2c1" }; ++static const char *const jtag_groups[] = { "jtag_udi", "jtag_dfd" }; ++static const char *const pcm_groups[] = { "pcm1", "pcm2" }; ++static const char *const spi_groups[] = { "spi_quad", "spi_cs1" }; ++static const char *const pcm_spi_groups[] = { "pcm_spi", "pcm_spi_int", ++ "pcm_spi_rst", "pcm_spi_cs1", ++ "pcm_spi_cs2_p156", ++ "pcm_spi_cs2_p128", ++ "pcm_spi_cs3", "pcm_spi_cs4" }; ++static const char *const i2s_groups[] = { "i2s" }; ++static const char *const emmc_groups[] = { "emmc" }; ++static const char *const pnand_groups[] = { "pnand" }; ++static const char *const pcie_reset_groups[] = { "pcie_reset0", "pcie_reset1", ++ "pcie_reset2" }; ++static const char *const pwm_groups[] = { "gpio0", "gpio1", ++ "gpio2", "gpio3", ++ "gpio4", "gpio5", ++ "gpio6", "gpio7", ++ "gpio8", "gpio9", ++ "gpio10", "gpio11", ++ "gpio12", "gpio13", ++ "gpio14", "gpio15", ++ "gpio16", "gpio17", ++ "gpio18", "gpio19", ++ "gpio20", "gpio21", ++ "gpio22", "gpio23", ++ "gpio24", "gpio25", ++ "gpio26", "gpio27", ++ "gpio28", "gpio29", ++ "gpio30", "gpio31", ++ "gpio36", "gpio37", ++ "gpio38", "gpio39", ++ "gpio40", "gpio41", ++ "gpio42", "gpio43", ++ "gpio44", "gpio45", ++ "gpio46", "gpio47" }; ++static const char *const phy1_led0_groups[] = { "gpio33", "gpio34", ++ "gpio35", "gpio42" }; ++static const char *const phy2_led0_groups[] = { "gpio33", "gpio34", ++ "gpio35", "gpio42" }; ++static const char *const phy3_led0_groups[] = { "gpio33", "gpio34", ++ "gpio35", "gpio42" }; ++static const char *const phy4_led0_groups[] = { "gpio33", "gpio34", ++ "gpio35", "gpio42" }; ++static const char *const phy1_led1_groups[] = { "gpio43", "gpio44", ++ "gpio45", "gpio46" }; ++static const char *const phy2_led1_groups[] = { "gpio43", "gpio44", ++ "gpio45", "gpio46" }; ++static const char *const phy3_led1_groups[] = { "gpio43", "gpio44", ++ "gpio45", "gpio46" }; ++static const char *const phy4_led1_groups[] = { "gpio43", "gpio44", ++ "gpio45", "gpio46" }; ++ ++static const struct airoha_pinctrl_func_group pon_func_group[] = { ++ { ++ .name = "pon", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_PON_MODE, ++ GPIO_PON_MODE_MASK, ++ GPIO_PON_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group tod_1pps_func_group[] = { ++ { ++ .name = "pon_tod_1pps", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ PON_TOD_1PPS_MODE_MASK, ++ PON_TOD_1PPS_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gsw_tod_1pps", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GSW_TOD_1PPS_MODE_MASK, ++ GSW_TOD_1PPS_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group sipo_func_group[] = { ++ { ++ .name = "sipo", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_PON_MODE, ++ GPIO_SIPO_MODE_MASK | SIPO_RCLK_MODE_MASK, ++ GPIO_SIPO_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "sipo_rclk", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_PON_MODE, ++ GPIO_SIPO_MODE_MASK | SIPO_RCLK_MODE_MASK, ++ GPIO_SIPO_MODE_MASK | SIPO_RCLK_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group mdio_func_group[] = { ++ { ++ .name = "mdio", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_PON_MODE, ++ GPIO_SGMII_MDIO_MODE_MASK, ++ GPIO_SGMII_MDIO_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_MDC_IO_MASTER_MODE_MODE, ++ GPIO_MDC_IO_MASTER_MODE_MODE ++ }, ++ .regmap_size = 2, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group uart_func_group[] = { ++ { ++ .name = "uart2", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_PON_MODE, ++ GPIO_UART2_MODE_MASK, ++ GPIO_UART2_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "uart2_cts_rts", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_PON_MODE, ++ GPIO_UART2_MODE_MASK | GPIO_UART2_CTS_RTS_MODE_MASK, ++ GPIO_UART2_MODE_MASK | GPIO_UART2_CTS_RTS_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "hsuart", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_PON_MODE, ++ GPIO_HSUART_MODE_MASK | GPIO_HSUART_CTS_RTS_MODE_MASK, ++ GPIO_HSUART_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, ++ { ++ .name = "hsuart_cts_rts", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_PON_MODE, ++ GPIO_HSUART_MODE_MASK | GPIO_HSUART_CTS_RTS_MODE_MASK, ++ GPIO_HSUART_MODE_MASK | GPIO_HSUART_CTS_RTS_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "uart4", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_PON_MODE, ++ GPIO_UART4_MODE_MASK, ++ GPIO_UART4_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "uart5", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_PON_MODE, ++ GPIO_UART5_MODE_MASK, ++ GPIO_UART5_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group i2c_func_group[] = { ++ { ++ .name = "i2c1", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_2ND_I2C_MODE_MASK, ++ GPIO_2ND_I2C_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group jtag_func_group[] = { ++ { ++ .name = "jtag_udi", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_NPU_UART_EN, ++ JTAG_UDI_EN_MASK, ++ JTAG_UDI_EN_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "jtag_dfd", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_NPU_UART_EN, ++ JTAG_DFD_EN_MASK, ++ JTAG_DFD_EN_MASK ++ }, ++ .regmap_size = 1, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group pcm_func_group[] = { ++ { ++ .name = "pcm1", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_PCM1_MODE_MASK, ++ GPIO_PCM1_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "pcm2", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_PCM2_MODE_MASK, ++ GPIO_PCM2_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group spi_func_group[] = { ++ { ++ .name = "spi_quad", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_SPI_QUAD_MODE_MASK, ++ GPIO_SPI_QUAD_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "spi_cs1", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_SPI_CS1_MODE_MASK, ++ GPIO_SPI_CS1_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "spi_cs2", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_SPI_CS2_MODE_MASK, ++ GPIO_SPI_CS2_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "spi_cs3", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_SPI_CS3_MODE_MASK, ++ GPIO_SPI_CS3_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "spi_cs4", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_SPI_CS4_MODE_MASK, ++ GPIO_SPI_CS4_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group pcm_spi_func_group[] = { ++ { ++ .name = "pcm_spi", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_PCM_SPI_MODE_MASK, ++ GPIO_PCM_SPI_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "pcm_spi_int", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_PCM_INT_MODE_MASK, ++ GPIO_PCM_INT_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "pcm_spi_rst", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_PCM_RESET_MODE_MASK, ++ GPIO_PCM_RESET_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "pcm_spi_cs1", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_PCM_SPI_CS1_MODE_MASK, ++ GPIO_PCM_SPI_CS1_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "pcm_spi_cs2_p128", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_PCM_SPI_CS2_MODE_P128_MASK, ++ GPIO_PCM_SPI_CS2_MODE_P128_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "pcm_spi_cs2_p156", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_PCM_SPI_CS2_MODE_P156_MASK, ++ GPIO_PCM_SPI_CS2_MODE_P156_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "pcm_spi_cs3", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_PCM_SPI_CS3_MODE_MASK, ++ GPIO_PCM_SPI_CS3_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "pcm_spi_cs4", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_PCM_SPI_CS4_MODE_MASK, ++ GPIO_PCM_SPI_CS4_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group i2s_func_group[] = { ++ { ++ .name = "i2s", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_I2S_MODE_MASK, ++ GPIO_I2S_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group emmc_func_group[] = { ++ { ++ .name = "emmc", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_PON_MODE, ++ GPIO_EMMC_MODE_MASK, ++ GPIO_EMMC_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group pnand_func_group[] = { ++ { ++ .name = "pnand", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_PON_MODE, ++ GPIO_PARALLEL_NAND_MODE_MASK, ++ GPIO_PARALLEL_NAND_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group pcie_reset_func_group[] = { ++ { ++ .name = "pcie_reset0", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_PON_MODE, ++ GPIO_PCIE_RESET0_MASK, ++ GPIO_PCIE_RESET0_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "pcie_reset1", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_PON_MODE, ++ GPIO_PCIE_RESET1_MASK, ++ GPIO_PCIE_RESET1_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "pcie_reset2", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_PON_MODE, ++ GPIO_PCIE_RESET2_MASK, ++ GPIO_PCIE_RESET2_MASK ++ }, ++ .regmap_size = 1, ++ }, ++}; ++ ++/* PWM */ ++static const struct airoha_pinctrl_func_group pwm_func_group[] = { ++ { ++ .name = "gpio0", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_MUX, ++ REG_GPIO_FLASH_MODE_CFG, ++ GPIO0_FLASH_MODE_CFG, ++ GPIO0_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio1", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_MUX, ++ REG_GPIO_FLASH_MODE_CFG, ++ GPIO1_FLASH_MODE_CFG, ++ GPIO1_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio2", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_MUX, ++ REG_GPIO_FLASH_MODE_CFG, ++ GPIO2_FLASH_MODE_CFG, ++ GPIO2_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio3", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_MUX, ++ REG_GPIO_FLASH_MODE_CFG, ++ GPIO3_FLASH_MODE_CFG, ++ GPIO3_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio4", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_MUX, ++ REG_GPIO_FLASH_MODE_CFG, ++ GPIO4_FLASH_MODE_CFG, ++ GPIO4_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio5", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_MUX, ++ REG_GPIO_FLASH_MODE_CFG, ++ GPIO5_FLASH_MODE_CFG, ++ GPIO5_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio6", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_MUX, ++ REG_GPIO_FLASH_MODE_CFG, ++ GPIO6_FLASH_MODE_CFG, ++ GPIO6_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio7", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_MUX, ++ REG_GPIO_FLASH_MODE_CFG, ++ GPIO7_FLASH_MODE_CFG, ++ GPIO7_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio8", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_MUX, ++ REG_GPIO_FLASH_MODE_CFG, ++ GPIO8_FLASH_MODE_CFG, ++ GPIO8_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio9", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_MUX, ++ REG_GPIO_FLASH_MODE_CFG, ++ GPIO9_FLASH_MODE_CFG, ++ GPIO9_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio10", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_MUX, ++ REG_GPIO_FLASH_MODE_CFG, ++ GPIO10_FLASH_MODE_CFG, ++ GPIO10_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio11", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_MUX, ++ REG_GPIO_FLASH_MODE_CFG, ++ GPIO11_FLASH_MODE_CFG, ++ GPIO11_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio12", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_MUX, ++ REG_GPIO_FLASH_MODE_CFG, ++ GPIO12_FLASH_MODE_CFG, ++ GPIO12_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio13", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_MUX, ++ REG_GPIO_FLASH_MODE_CFG, ++ GPIO13_FLASH_MODE_CFG, ++ GPIO13_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio14", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_MUX, ++ REG_GPIO_FLASH_MODE_CFG, ++ GPIO14_FLASH_MODE_CFG, ++ GPIO14_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio15", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_MUX, ++ REG_GPIO_FLASH_MODE_CFG, ++ GPIO15_FLASH_MODE_CFG, ++ GPIO15_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio16", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO16_FLASH_MODE_CFG, ++ GPIO16_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio17", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO17_FLASH_MODE_CFG, ++ GPIO17_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio18", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO18_FLASH_MODE_CFG, ++ GPIO18_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio19", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO19_FLASH_MODE_CFG, ++ GPIO19_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio20", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO20_FLASH_MODE_CFG, ++ GPIO20_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio21", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO21_FLASH_MODE_CFG, ++ GPIO21_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio22", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO22_FLASH_MODE_CFG, ++ GPIO22_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio23", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO23_FLASH_MODE_CFG, ++ GPIO23_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio24", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO24_FLASH_MODE_CFG, ++ GPIO24_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio25", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO25_FLASH_MODE_CFG, ++ GPIO25_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio26", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO26_FLASH_MODE_CFG, ++ GPIO26_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio27", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO27_FLASH_MODE_CFG, ++ GPIO27_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio28", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO28_FLASH_MODE_CFG, ++ GPIO28_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio29", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO29_FLASH_MODE_CFG, ++ GPIO29_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio30", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO30_FLASH_MODE_CFG, ++ GPIO30_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio31", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO31_FLASH_MODE_CFG, ++ GPIO31_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio36", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO36_FLASH_MODE_CFG, ++ GPIO36_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio37", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO37_FLASH_MODE_CFG, ++ GPIO37_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio38", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO38_FLASH_MODE_CFG, ++ GPIO38_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio39", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO39_FLASH_MODE_CFG, ++ GPIO39_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio40", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO40_FLASH_MODE_CFG, ++ GPIO40_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio41", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO41_FLASH_MODE_CFG, ++ GPIO41_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio42", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO42_FLASH_MODE_CFG, ++ GPIO42_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio43", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO43_FLASH_MODE_CFG, ++ GPIO43_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio44", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO44_FLASH_MODE_CFG, ++ GPIO44_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio45", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO45_FLASH_MODE_CFG, ++ GPIO45_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio46", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO46_FLASH_MODE_CFG, ++ GPIO46_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "gpio47", ++ .regmap[0] = { ++ AIROHA_FUNC_PWM_EXT_MUX, ++ REG_GPIO_FLASH_MODE_CFG_EXT, ++ GPIO47_FLASH_MODE_CFG, ++ GPIO47_FLASH_MODE_CFG ++ }, ++ .regmap_size = 1, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group phy1_led0_func_group[] = { ++ { ++ .name = "gpio33", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN0_LED0_MODE_MASK, ++ GPIO_LAN0_LED0_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED0_MAPPING, ++ LAN1_LED_MAPPING_MASK, ++ LAN1_PHY1_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio34", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN1_LED0_MODE_MASK, ++ GPIO_LAN1_LED0_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED0_MAPPING, ++ LAN2_LED_MAPPING_MASK, ++ LAN2_PHY1_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio35", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN2_LED0_MODE_MASK, ++ GPIO_LAN2_LED0_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED0_MAPPING, ++ LAN3_LED_MAPPING_MASK, ++ LAN3_PHY1_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio42", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN3_LED0_MODE_MASK, ++ GPIO_LAN3_LED0_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED0_MAPPING, ++ LAN4_LED_MAPPING_MASK, ++ LAN4_PHY1_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group phy2_led0_func_group[] = { ++ { ++ .name = "gpio33", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN0_LED0_MODE_MASK, ++ GPIO_LAN0_LED0_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED0_MAPPING, ++ LAN1_LED_MAPPING_MASK, ++ LAN1_PHY2_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio34", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN1_LED0_MODE_MASK, ++ GPIO_LAN1_LED0_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED0_MAPPING, ++ LAN2_LED_MAPPING_MASK, ++ LAN2_PHY2_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio35", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN2_LED0_MODE_MASK, ++ GPIO_LAN2_LED0_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED0_MAPPING, ++ LAN3_LED_MAPPING_MASK, ++ LAN3_PHY2_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio42", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN3_LED0_MODE_MASK, ++ GPIO_LAN3_LED0_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED0_MAPPING, ++ LAN4_LED_MAPPING_MASK, ++ LAN4_PHY2_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group phy3_led0_func_group[] = { ++ { ++ .name = "gpio33", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN0_LED0_MODE_MASK, ++ GPIO_LAN0_LED0_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED0_MAPPING, ++ LAN1_LED_MAPPING_MASK, ++ LAN1_PHY3_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio34", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN1_LED0_MODE_MASK, ++ GPIO_LAN1_LED0_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED0_MAPPING, ++ LAN2_LED_MAPPING_MASK, ++ LAN2_PHY3_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio35", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN2_LED0_MODE_MASK, ++ GPIO_LAN2_LED0_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED0_MAPPING, ++ LAN3_LED_MAPPING_MASK, ++ LAN3_PHY3_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio42", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN3_LED0_MODE_MASK, ++ GPIO_LAN3_LED0_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED0_MAPPING, ++ LAN4_LED_MAPPING_MASK, ++ LAN4_PHY3_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group phy4_led0_func_group[] = { ++ { ++ .name = "gpio33", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN0_LED0_MODE_MASK, ++ GPIO_LAN0_LED0_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED0_MAPPING, ++ LAN1_LED_MAPPING_MASK, ++ LAN1_PHY4_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio34", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN1_LED0_MODE_MASK, ++ GPIO_LAN1_LED0_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED0_MAPPING, ++ LAN2_LED_MAPPING_MASK, ++ LAN2_PHY4_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio35", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN2_LED0_MODE_MASK, ++ GPIO_LAN2_LED0_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED0_MAPPING, ++ LAN3_LED_MAPPING_MASK, ++ LAN3_PHY4_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio42", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN3_LED0_MODE_MASK, ++ GPIO_LAN3_LED0_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED0_MAPPING, ++ LAN4_LED_MAPPING_MASK, ++ LAN4_PHY4_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group phy1_led1_func_group[] = { ++ { ++ .name = "gpio43", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN0_LED1_MODE_MASK, ++ GPIO_LAN0_LED1_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED1_MAPPING, ++ LAN1_LED_MAPPING_MASK, ++ LAN1_PHY1_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio44", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN1_LED1_MODE_MASK, ++ GPIO_LAN1_LED1_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED1_MAPPING, ++ LAN2_LED_MAPPING_MASK, ++ LAN2_PHY1_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio45", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN2_LED1_MODE_MASK, ++ GPIO_LAN2_LED1_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED1_MAPPING, ++ LAN3_LED_MAPPING_MASK, ++ LAN3_PHY1_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio46", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN3_LED0_MODE_MASK, ++ GPIO_LAN3_LED0_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED1_MAPPING, ++ LAN4_LED_MAPPING_MASK, ++ LAN4_PHY1_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group phy2_led1_func_group[] = { ++ { ++ .name = "gpio43", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN0_LED1_MODE_MASK, ++ GPIO_LAN0_LED1_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED1_MAPPING, ++ LAN1_LED_MAPPING_MASK, ++ LAN1_PHY2_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio44", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN1_LED1_MODE_MASK, ++ GPIO_LAN1_LED1_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED1_MAPPING, ++ LAN2_LED_MAPPING_MASK, ++ LAN2_PHY2_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio45", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN2_LED1_MODE_MASK, ++ GPIO_LAN2_LED1_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED1_MAPPING, ++ LAN3_LED_MAPPING_MASK, ++ LAN3_PHY2_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio46", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN3_LED0_MODE_MASK, ++ GPIO_LAN3_LED0_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED1_MAPPING, ++ LAN4_LED_MAPPING_MASK, ++ LAN4_PHY2_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group phy3_led1_func_group[] = { ++ { ++ .name = "gpio43", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN0_LED1_MODE_MASK, ++ GPIO_LAN0_LED1_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED1_MAPPING, ++ LAN1_LED_MAPPING_MASK, ++ LAN1_PHY3_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio44", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN1_LED1_MODE_MASK, ++ GPIO_LAN1_LED1_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED1_MAPPING, ++ LAN2_LED_MAPPING_MASK, ++ LAN2_PHY3_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio45", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN2_LED1_MODE_MASK, ++ GPIO_LAN2_LED1_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED1_MAPPING, ++ LAN3_LED_MAPPING_MASK, ++ LAN3_PHY3_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio46", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN3_LED0_MODE_MASK, ++ GPIO_LAN3_LED0_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED1_MAPPING, ++ LAN4_LED_MAPPING_MASK, ++ LAN4_PHY3_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func_group phy4_led1_func_group[] = { ++ { ++ .name = "gpio43", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN0_LED1_MODE_MASK, ++ GPIO_LAN0_LED1_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED1_MAPPING, ++ LAN1_LED_MAPPING_MASK, ++ LAN1_PHY4_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio44", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN1_LED1_MODE_MASK, ++ GPIO_LAN1_LED1_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED1_MAPPING, ++ LAN2_LED_MAPPING_MASK, ++ LAN2_PHY4_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio45", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN2_LED1_MODE_MASK, ++ GPIO_LAN2_LED1_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED1_MAPPING, ++ LAN3_LED_MAPPING_MASK, ++ LAN3_PHY4_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, { ++ .name = "gpio46", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_2ND_I2C_MODE, ++ GPIO_LAN3_LED0_MODE_MASK, ++ GPIO_LAN3_LED0_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_LAN_LED1_MAPPING, ++ LAN4_LED_MAPPING_MASK, ++ LAN4_PHY4_LED_MAP ++ }, ++ .regmap_size = 2, ++ }, ++}; ++ ++static const struct airoha_pinctrl_func airoha_pinctrl_funcs[] = { ++ PINCTRL_FUNC_DESC(pon), ++ PINCTRL_FUNC_DESC(tod_1pps), ++ PINCTRL_FUNC_DESC(sipo), ++ PINCTRL_FUNC_DESC(mdio), ++ PINCTRL_FUNC_DESC(uart), ++ PINCTRL_FUNC_DESC(i2c), ++ PINCTRL_FUNC_DESC(jtag), ++ PINCTRL_FUNC_DESC(pcm), ++ PINCTRL_FUNC_DESC(spi), ++ PINCTRL_FUNC_DESC(pcm_spi), ++ PINCTRL_FUNC_DESC(i2s), ++ PINCTRL_FUNC_DESC(emmc), ++ PINCTRL_FUNC_DESC(pnand), ++ PINCTRL_FUNC_DESC(pcie_reset), ++ PINCTRL_FUNC_DESC(pwm), ++ PINCTRL_FUNC_DESC(phy1_led0), ++ PINCTRL_FUNC_DESC(phy2_led0), ++ PINCTRL_FUNC_DESC(phy3_led0), ++ PINCTRL_FUNC_DESC(phy4_led0), ++ PINCTRL_FUNC_DESC(phy1_led1), ++ PINCTRL_FUNC_DESC(phy2_led1), ++ PINCTRL_FUNC_DESC(phy3_led1), ++ PINCTRL_FUNC_DESC(phy4_led1), ++}; ++ ++static const struct airoha_pinctrl_conf airoha_pinctrl_pullup_conf[] = { ++ PINCTRL_CONF_DESC(0, REG_I2C_SDA_PU, UART1_TXD_PU_MASK), ++ PINCTRL_CONF_DESC(1, REG_I2C_SDA_PU, UART1_RXD_PU_MASK), ++ PINCTRL_CONF_DESC(2, REG_I2C_SDA_PU, I2C_SDA_PU_MASK), ++ PINCTRL_CONF_DESC(3, REG_I2C_SDA_PU, I2C_SCL_PU_MASK), ++ PINCTRL_CONF_DESC(4, REG_I2C_SDA_PU, SPI_CS0_PU_MASK), ++ PINCTRL_CONF_DESC(5, REG_I2C_SDA_PU, SPI_CLK_PU_MASK), ++ PINCTRL_CONF_DESC(6, REG_I2C_SDA_PU, SPI_MOSI_PU_MASK), ++ PINCTRL_CONF_DESC(7, REG_I2C_SDA_PU, SPI_MISO_PU_MASK), ++ PINCTRL_CONF_DESC(13, REG_GPIO_L_PU, BIT(0)), ++ PINCTRL_CONF_DESC(14, REG_GPIO_L_PU, BIT(1)), ++ PINCTRL_CONF_DESC(15, REG_GPIO_L_PU, BIT(2)), ++ PINCTRL_CONF_DESC(16, REG_GPIO_L_PU, BIT(3)), ++ PINCTRL_CONF_DESC(17, REG_GPIO_L_PU, BIT(4)), ++ PINCTRL_CONF_DESC(18, REG_GPIO_L_PU, BIT(5)), ++ PINCTRL_CONF_DESC(19, REG_GPIO_L_PU, BIT(6)), ++ PINCTRL_CONF_DESC(20, REG_GPIO_L_PU, BIT(7)), ++ PINCTRL_CONF_DESC(21, REG_GPIO_L_PU, BIT(8)), ++ PINCTRL_CONF_DESC(22, REG_GPIO_L_PU, BIT(9)), ++ PINCTRL_CONF_DESC(23, REG_GPIO_L_PU, BIT(10)), ++ PINCTRL_CONF_DESC(24, REG_GPIO_L_PU, BIT(11)), ++ PINCTRL_CONF_DESC(25, REG_GPIO_L_PU, BIT(12)), ++ PINCTRL_CONF_DESC(26, REG_GPIO_L_PU, BIT(13)), ++ PINCTRL_CONF_DESC(27, REG_GPIO_L_PU, BIT(14)), ++ PINCTRL_CONF_DESC(28, REG_GPIO_L_PU, BIT(15)), ++ PINCTRL_CONF_DESC(29, REG_GPIO_L_PU, BIT(16)), ++ PINCTRL_CONF_DESC(30, REG_GPIO_L_PU, BIT(17)), ++ PINCTRL_CONF_DESC(31, REG_GPIO_L_PU, BIT(18)), ++ PINCTRL_CONF_DESC(32, REG_GPIO_L_PU, BIT(18)), ++ PINCTRL_CONF_DESC(33, REG_GPIO_L_PU, BIT(20)), ++ PINCTRL_CONF_DESC(34, REG_GPIO_L_PU, BIT(21)), ++ PINCTRL_CONF_DESC(35, REG_GPIO_L_PU, BIT(22)), ++ PINCTRL_CONF_DESC(36, REG_GPIO_L_PU, BIT(23)), ++ PINCTRL_CONF_DESC(37, REG_GPIO_L_PU, BIT(24)), ++ PINCTRL_CONF_DESC(38, REG_GPIO_L_PU, BIT(25)), ++ PINCTRL_CONF_DESC(39, REG_GPIO_L_PU, BIT(26)), ++ PINCTRL_CONF_DESC(40, REG_GPIO_L_PU, BIT(27)), ++ PINCTRL_CONF_DESC(41, REG_GPIO_L_PU, BIT(28)), ++ PINCTRL_CONF_DESC(42, REG_GPIO_L_PU, BIT(29)), ++ PINCTRL_CONF_DESC(43, REG_GPIO_L_PU, BIT(30)), ++ PINCTRL_CONF_DESC(44, REG_GPIO_L_PU, BIT(31)), ++ PINCTRL_CONF_DESC(45, REG_GPIO_H_PU, BIT(0)), ++ PINCTRL_CONF_DESC(46, REG_GPIO_H_PU, BIT(1)), ++ PINCTRL_CONF_DESC(47, REG_GPIO_H_PU, BIT(2)), ++ PINCTRL_CONF_DESC(48, REG_GPIO_H_PU, BIT(3)), ++ PINCTRL_CONF_DESC(49, REG_GPIO_H_PU, BIT(4)), ++ PINCTRL_CONF_DESC(50, REG_GPIO_H_PU, BIT(5)), ++ PINCTRL_CONF_DESC(51, REG_GPIO_H_PU, BIT(6)), ++ PINCTRL_CONF_DESC(52, REG_GPIO_H_PU, BIT(7)), ++ PINCTRL_CONF_DESC(53, REG_GPIO_H_PU, BIT(8)), ++ PINCTRL_CONF_DESC(54, REG_GPIO_H_PU, BIT(9)), ++ PINCTRL_CONF_DESC(55, REG_GPIO_H_PU, BIT(10)), ++ PINCTRL_CONF_DESC(56, REG_GPIO_H_PU, BIT(11)), ++ PINCTRL_CONF_DESC(57, REG_GPIO_H_PU, BIT(12)), ++ PINCTRL_CONF_DESC(58, REG_GPIO_H_PU, BIT(13)), ++ PINCTRL_CONF_DESC(59, REG_GPIO_H_PU, BIT(14)), ++ PINCTRL_CONF_DESC(61, REG_I2C_SDA_PU, PCIE0_RESET_PU_MASK), ++ PINCTRL_CONF_DESC(62, REG_I2C_SDA_PU, PCIE1_RESET_PU_MASK), ++ PINCTRL_CONF_DESC(63, REG_I2C_SDA_PU, PCIE2_RESET_PU_MASK), ++}; ++ ++static const struct airoha_pinctrl_conf airoha_pinctrl_pulldown_conf[] = { ++ PINCTRL_CONF_DESC(0, REG_I2C_SDA_PD, UART1_TXD_PD_MASK), ++ PINCTRL_CONF_DESC(1, REG_I2C_SDA_PD, UART1_RXD_PD_MASK), ++ PINCTRL_CONF_DESC(2, REG_I2C_SDA_PD, I2C_SDA_PD_MASK), ++ PINCTRL_CONF_DESC(3, REG_I2C_SDA_PD, I2C_SCL_PD_MASK), ++ PINCTRL_CONF_DESC(4, REG_I2C_SDA_PD, SPI_CS0_PD_MASK), ++ PINCTRL_CONF_DESC(5, REG_I2C_SDA_PD, SPI_CLK_PD_MASK), ++ PINCTRL_CONF_DESC(6, REG_I2C_SDA_PD, SPI_MOSI_PD_MASK), ++ PINCTRL_CONF_DESC(7, REG_I2C_SDA_PD, SPI_MISO_PD_MASK), ++ PINCTRL_CONF_DESC(13, REG_GPIO_L_PD, BIT(0)), ++ PINCTRL_CONF_DESC(14, REG_GPIO_L_PD, BIT(1)), ++ PINCTRL_CONF_DESC(15, REG_GPIO_L_PD, BIT(2)), ++ PINCTRL_CONF_DESC(16, REG_GPIO_L_PD, BIT(3)), ++ PINCTRL_CONF_DESC(17, REG_GPIO_L_PD, BIT(4)), ++ PINCTRL_CONF_DESC(18, REG_GPIO_L_PD, BIT(5)), ++ PINCTRL_CONF_DESC(19, REG_GPIO_L_PD, BIT(6)), ++ PINCTRL_CONF_DESC(20, REG_GPIO_L_PD, BIT(7)), ++ PINCTRL_CONF_DESC(21, REG_GPIO_L_PD, BIT(8)), ++ PINCTRL_CONF_DESC(22, REG_GPIO_L_PD, BIT(9)), ++ PINCTRL_CONF_DESC(23, REG_GPIO_L_PD, BIT(10)), ++ PINCTRL_CONF_DESC(24, REG_GPIO_L_PD, BIT(11)), ++ PINCTRL_CONF_DESC(25, REG_GPIO_L_PD, BIT(12)), ++ PINCTRL_CONF_DESC(26, REG_GPIO_L_PD, BIT(13)), ++ PINCTRL_CONF_DESC(27, REG_GPIO_L_PD, BIT(14)), ++ PINCTRL_CONF_DESC(28, REG_GPIO_L_PD, BIT(15)), ++ PINCTRL_CONF_DESC(29, REG_GPIO_L_PD, BIT(16)), ++ PINCTRL_CONF_DESC(30, REG_GPIO_L_PD, BIT(17)), ++ PINCTRL_CONF_DESC(31, REG_GPIO_L_PD, BIT(18)), ++ PINCTRL_CONF_DESC(32, REG_GPIO_L_PD, BIT(18)), ++ PINCTRL_CONF_DESC(33, REG_GPIO_L_PD, BIT(20)), ++ PINCTRL_CONF_DESC(34, REG_GPIO_L_PD, BIT(21)), ++ PINCTRL_CONF_DESC(35, REG_GPIO_L_PD, BIT(22)), ++ PINCTRL_CONF_DESC(36, REG_GPIO_L_PD, BIT(23)), ++ PINCTRL_CONF_DESC(37, REG_GPIO_L_PD, BIT(24)), ++ PINCTRL_CONF_DESC(38, REG_GPIO_L_PD, BIT(25)), ++ PINCTRL_CONF_DESC(39, REG_GPIO_L_PD, BIT(26)), ++ PINCTRL_CONF_DESC(40, REG_GPIO_L_PD, BIT(27)), ++ PINCTRL_CONF_DESC(41, REG_GPIO_L_PD, BIT(28)), ++ PINCTRL_CONF_DESC(42, REG_GPIO_L_PD, BIT(29)), ++ PINCTRL_CONF_DESC(43, REG_GPIO_L_PD, BIT(30)), ++ PINCTRL_CONF_DESC(44, REG_GPIO_L_PD, BIT(31)), ++ PINCTRL_CONF_DESC(45, REG_GPIO_H_PD, BIT(0)), ++ PINCTRL_CONF_DESC(46, REG_GPIO_H_PD, BIT(1)), ++ PINCTRL_CONF_DESC(47, REG_GPIO_H_PD, BIT(2)), ++ PINCTRL_CONF_DESC(48, REG_GPIO_H_PD, BIT(3)), ++ PINCTRL_CONF_DESC(49, REG_GPIO_H_PD, BIT(4)), ++ PINCTRL_CONF_DESC(50, REG_GPIO_H_PD, BIT(5)), ++ PINCTRL_CONF_DESC(51, REG_GPIO_H_PD, BIT(6)), ++ PINCTRL_CONF_DESC(52, REG_GPIO_H_PD, BIT(7)), ++ PINCTRL_CONF_DESC(53, REG_GPIO_H_PD, BIT(8)), ++ PINCTRL_CONF_DESC(54, REG_GPIO_H_PD, BIT(9)), ++ PINCTRL_CONF_DESC(55, REG_GPIO_H_PD, BIT(10)), ++ PINCTRL_CONF_DESC(56, REG_GPIO_H_PD, BIT(11)), ++ PINCTRL_CONF_DESC(57, REG_GPIO_H_PD, BIT(12)), ++ PINCTRL_CONF_DESC(58, REG_GPIO_H_PD, BIT(13)), ++ PINCTRL_CONF_DESC(59, REG_GPIO_H_PD, BIT(14)), ++ PINCTRL_CONF_DESC(61, REG_I2C_SDA_PD, PCIE0_RESET_PD_MASK), ++ PINCTRL_CONF_DESC(62, REG_I2C_SDA_PD, PCIE1_RESET_PD_MASK), ++ PINCTRL_CONF_DESC(63, REG_I2C_SDA_PD, PCIE2_RESET_PD_MASK), ++}; ++ ++static const struct airoha_pinctrl_conf airoha_pinctrl_drive_e2_conf[] = { ++ PINCTRL_CONF_DESC(0, REG_I2C_SDA_E2, UART1_TXD_E2_MASK), ++ PINCTRL_CONF_DESC(1, REG_I2C_SDA_E2, UART1_RXD_E2_MASK), ++ PINCTRL_CONF_DESC(2, REG_I2C_SDA_E2, I2C_SDA_E2_MASK), ++ PINCTRL_CONF_DESC(3, REG_I2C_SDA_E2, I2C_SCL_E2_MASK), ++ PINCTRL_CONF_DESC(4, REG_I2C_SDA_E2, SPI_CS0_E2_MASK), ++ PINCTRL_CONF_DESC(5, REG_I2C_SDA_E2, SPI_CLK_E2_MASK), ++ PINCTRL_CONF_DESC(6, REG_I2C_SDA_E2, SPI_MOSI_E2_MASK), ++ PINCTRL_CONF_DESC(7, REG_I2C_SDA_E2, SPI_MISO_E2_MASK), ++ PINCTRL_CONF_DESC(13, REG_GPIO_L_E2, BIT(0)), ++ PINCTRL_CONF_DESC(14, REG_GPIO_L_E2, BIT(1)), ++ PINCTRL_CONF_DESC(15, REG_GPIO_L_E2, BIT(2)), ++ PINCTRL_CONF_DESC(16, REG_GPIO_L_E2, BIT(3)), ++ PINCTRL_CONF_DESC(17, REG_GPIO_L_E2, BIT(4)), ++ PINCTRL_CONF_DESC(18, REG_GPIO_L_E2, BIT(5)), ++ PINCTRL_CONF_DESC(19, REG_GPIO_L_E2, BIT(6)), ++ PINCTRL_CONF_DESC(20, REG_GPIO_L_E2, BIT(7)), ++ PINCTRL_CONF_DESC(21, REG_GPIO_L_E2, BIT(8)), ++ PINCTRL_CONF_DESC(22, REG_GPIO_L_E2, BIT(9)), ++ PINCTRL_CONF_DESC(23, REG_GPIO_L_E2, BIT(10)), ++ PINCTRL_CONF_DESC(24, REG_GPIO_L_E2, BIT(11)), ++ PINCTRL_CONF_DESC(25, REG_GPIO_L_E2, BIT(12)), ++ PINCTRL_CONF_DESC(26, REG_GPIO_L_E2, BIT(13)), ++ PINCTRL_CONF_DESC(27, REG_GPIO_L_E2, BIT(14)), ++ PINCTRL_CONF_DESC(28, REG_GPIO_L_E2, BIT(15)), ++ PINCTRL_CONF_DESC(29, REG_GPIO_L_E2, BIT(16)), ++ PINCTRL_CONF_DESC(30, REG_GPIO_L_E2, BIT(17)), ++ PINCTRL_CONF_DESC(31, REG_GPIO_L_E2, BIT(18)), ++ PINCTRL_CONF_DESC(32, REG_GPIO_L_E2, BIT(18)), ++ PINCTRL_CONF_DESC(33, REG_GPIO_L_E2, BIT(20)), ++ PINCTRL_CONF_DESC(34, REG_GPIO_L_E2, BIT(21)), ++ PINCTRL_CONF_DESC(35, REG_GPIO_L_E2, BIT(22)), ++ PINCTRL_CONF_DESC(36, REG_GPIO_L_E2, BIT(23)), ++ PINCTRL_CONF_DESC(37, REG_GPIO_L_E2, BIT(24)), ++ PINCTRL_CONF_DESC(38, REG_GPIO_L_E2, BIT(25)), ++ PINCTRL_CONF_DESC(39, REG_GPIO_L_E2, BIT(26)), ++ PINCTRL_CONF_DESC(40, REG_GPIO_L_E2, BIT(27)), ++ PINCTRL_CONF_DESC(41, REG_GPIO_L_E2, BIT(28)), ++ PINCTRL_CONF_DESC(42, REG_GPIO_L_E2, BIT(29)), ++ PINCTRL_CONF_DESC(43, REG_GPIO_L_E2, BIT(30)), ++ PINCTRL_CONF_DESC(44, REG_GPIO_L_E2, BIT(31)), ++ PINCTRL_CONF_DESC(45, REG_GPIO_H_E2, BIT(0)), ++ PINCTRL_CONF_DESC(46, REG_GPIO_H_E2, BIT(1)), ++ PINCTRL_CONF_DESC(47, REG_GPIO_H_E2, BIT(2)), ++ PINCTRL_CONF_DESC(48, REG_GPIO_H_E2, BIT(3)), ++ PINCTRL_CONF_DESC(49, REG_GPIO_H_E2, BIT(4)), ++ PINCTRL_CONF_DESC(50, REG_GPIO_H_E2, BIT(5)), ++ PINCTRL_CONF_DESC(51, REG_GPIO_H_E2, BIT(6)), ++ PINCTRL_CONF_DESC(52, REG_GPIO_H_E2, BIT(7)), ++ PINCTRL_CONF_DESC(53, REG_GPIO_H_E2, BIT(8)), ++ PINCTRL_CONF_DESC(54, REG_GPIO_H_E2, BIT(9)), ++ PINCTRL_CONF_DESC(55, REG_GPIO_H_E2, BIT(10)), ++ PINCTRL_CONF_DESC(56, REG_GPIO_H_E2, BIT(11)), ++ PINCTRL_CONF_DESC(57, REG_GPIO_H_E2, BIT(12)), ++ PINCTRL_CONF_DESC(58, REG_GPIO_H_E2, BIT(13)), ++ PINCTRL_CONF_DESC(59, REG_GPIO_H_E2, BIT(14)), ++ PINCTRL_CONF_DESC(61, REG_I2C_SDA_E2, PCIE0_RESET_E2_MASK), ++ PINCTRL_CONF_DESC(62, REG_I2C_SDA_E2, PCIE1_RESET_E2_MASK), ++ PINCTRL_CONF_DESC(63, REG_I2C_SDA_E2, PCIE2_RESET_E2_MASK), ++}; ++ ++static const struct airoha_pinctrl_conf airoha_pinctrl_drive_e4_conf[] = { ++ PINCTRL_CONF_DESC(0, REG_I2C_SDA_E4, UART1_TXD_E4_MASK), ++ PINCTRL_CONF_DESC(1, REG_I2C_SDA_E4, UART1_RXD_E4_MASK), ++ PINCTRL_CONF_DESC(2, REG_I2C_SDA_E4, I2C_SDA_E4_MASK), ++ PINCTRL_CONF_DESC(3, REG_I2C_SDA_E4, I2C_SCL_E4_MASK), ++ PINCTRL_CONF_DESC(4, REG_I2C_SDA_E4, SPI_CS0_E4_MASK), ++ PINCTRL_CONF_DESC(5, REG_I2C_SDA_E4, SPI_CLK_E4_MASK), ++ PINCTRL_CONF_DESC(6, REG_I2C_SDA_E4, SPI_MOSI_E4_MASK), ++ PINCTRL_CONF_DESC(7, REG_I2C_SDA_E4, SPI_MISO_E4_MASK), ++ PINCTRL_CONF_DESC(13, REG_GPIO_L_E4, BIT(0)), ++ PINCTRL_CONF_DESC(14, REG_GPIO_L_E4, BIT(1)), ++ PINCTRL_CONF_DESC(15, REG_GPIO_L_E4, BIT(2)), ++ PINCTRL_CONF_DESC(16, REG_GPIO_L_E4, BIT(3)), ++ PINCTRL_CONF_DESC(17, REG_GPIO_L_E4, BIT(4)), ++ PINCTRL_CONF_DESC(18, REG_GPIO_L_E4, BIT(5)), ++ PINCTRL_CONF_DESC(19, REG_GPIO_L_E4, BIT(6)), ++ PINCTRL_CONF_DESC(20, REG_GPIO_L_E4, BIT(7)), ++ PINCTRL_CONF_DESC(21, REG_GPIO_L_E4, BIT(8)), ++ PINCTRL_CONF_DESC(22, REG_GPIO_L_E4, BIT(9)), ++ PINCTRL_CONF_DESC(23, REG_GPIO_L_E4, BIT(10)), ++ PINCTRL_CONF_DESC(24, REG_GPIO_L_E4, BIT(11)), ++ PINCTRL_CONF_DESC(25, REG_GPIO_L_E4, BIT(12)), ++ PINCTRL_CONF_DESC(26, REG_GPIO_L_E4, BIT(13)), ++ PINCTRL_CONF_DESC(27, REG_GPIO_L_E4, BIT(14)), ++ PINCTRL_CONF_DESC(28, REG_GPIO_L_E4, BIT(15)), ++ PINCTRL_CONF_DESC(29, REG_GPIO_L_E4, BIT(16)), ++ PINCTRL_CONF_DESC(30, REG_GPIO_L_E4, BIT(17)), ++ PINCTRL_CONF_DESC(31, REG_GPIO_L_E4, BIT(18)), ++ PINCTRL_CONF_DESC(32, REG_GPIO_L_E4, BIT(18)), ++ PINCTRL_CONF_DESC(33, REG_GPIO_L_E4, BIT(20)), ++ PINCTRL_CONF_DESC(34, REG_GPIO_L_E4, BIT(21)), ++ PINCTRL_CONF_DESC(35, REG_GPIO_L_E4, BIT(22)), ++ PINCTRL_CONF_DESC(36, REG_GPIO_L_E4, BIT(23)), ++ PINCTRL_CONF_DESC(37, REG_GPIO_L_E4, BIT(24)), ++ PINCTRL_CONF_DESC(38, REG_GPIO_L_E4, BIT(25)), ++ PINCTRL_CONF_DESC(39, REG_GPIO_L_E4, BIT(26)), ++ PINCTRL_CONF_DESC(40, REG_GPIO_L_E4, BIT(27)), ++ PINCTRL_CONF_DESC(41, REG_GPIO_L_E4, BIT(28)), ++ PINCTRL_CONF_DESC(42, REG_GPIO_L_E4, BIT(29)), ++ PINCTRL_CONF_DESC(43, REG_GPIO_L_E4, BIT(30)), ++ PINCTRL_CONF_DESC(44, REG_GPIO_L_E4, BIT(31)), ++ PINCTRL_CONF_DESC(45, REG_GPIO_H_E4, BIT(0)), ++ PINCTRL_CONF_DESC(46, REG_GPIO_H_E4, BIT(1)), ++ PINCTRL_CONF_DESC(47, REG_GPIO_H_E4, BIT(2)), ++ PINCTRL_CONF_DESC(48, REG_GPIO_H_E4, BIT(3)), ++ PINCTRL_CONF_DESC(49, REG_GPIO_H_E4, BIT(4)), ++ PINCTRL_CONF_DESC(50, REG_GPIO_H_E4, BIT(5)), ++ PINCTRL_CONF_DESC(51, REG_GPIO_H_E4, BIT(6)), ++ PINCTRL_CONF_DESC(52, REG_GPIO_H_E4, BIT(7)), ++ PINCTRL_CONF_DESC(53, REG_GPIO_H_E4, BIT(8)), ++ PINCTRL_CONF_DESC(54, REG_GPIO_H_E4, BIT(9)), ++ PINCTRL_CONF_DESC(55, REG_GPIO_H_E4, BIT(10)), ++ PINCTRL_CONF_DESC(56, REG_GPIO_H_E4, BIT(11)), ++ PINCTRL_CONF_DESC(57, REG_GPIO_H_E4, BIT(12)), ++ PINCTRL_CONF_DESC(58, REG_GPIO_H_E4, BIT(13)), ++ PINCTRL_CONF_DESC(59, REG_GPIO_H_E4, BIT(14)), ++ PINCTRL_CONF_DESC(61, REG_I2C_SDA_E4, PCIE0_RESET_E4_MASK), ++ PINCTRL_CONF_DESC(62, REG_I2C_SDA_E4, PCIE1_RESET_E4_MASK), ++ PINCTRL_CONF_DESC(63, REG_I2C_SDA_E4, PCIE2_RESET_E4_MASK), ++}; ++ ++static const struct airoha_pinctrl_conf airoha_pinctrl_pcie_rst_od_conf[] = { ++ PINCTRL_CONF_DESC(61, REG_PCIE_RESET_OD, PCIE0_RESET_OD_MASK), ++ PINCTRL_CONF_DESC(62, REG_PCIE_RESET_OD, PCIE1_RESET_OD_MASK), ++ PINCTRL_CONF_DESC(63, REG_PCIE_RESET_OD, PCIE2_RESET_OD_MASK), ++}; ++ ++static int airoha_convert_pin_to_reg_offset(struct pinctrl_dev *pctrl_dev, ++ struct pinctrl_gpio_range *range, ++ int pin) ++{ ++ if (!range) ++ range = pinctrl_find_gpio_range_from_pin_nolock(pctrl_dev, ++ pin); ++ if (!range) ++ return -EINVAL; ++ ++ return pin - range->pin_base; ++} ++ ++/* gpio callbacks */ ++static void airoha_gpio_set(struct gpio_chip *chip, unsigned int gpio, ++ int value) ++{ ++ struct airoha_pinctrl *pinctrl = gpiochip_get_data(chip); ++ u32 offset = gpio % AIROHA_PIN_BANK_SIZE; ++ u8 index = gpio / AIROHA_PIN_BANK_SIZE; ++ ++ regmap_update_bits(pinctrl->regmap, pinctrl->gpiochip.data[index], ++ BIT(offset), value ? BIT(offset) : 0); ++} ++ ++static int airoha_gpio_get(struct gpio_chip *chip, unsigned int gpio) ++{ ++ struct airoha_pinctrl *pinctrl = gpiochip_get_data(chip); ++ u32 val, pin = gpio % AIROHA_PIN_BANK_SIZE; ++ u8 index = gpio / AIROHA_PIN_BANK_SIZE; ++ int err; ++ ++ err = regmap_read(pinctrl->regmap, ++ pinctrl->gpiochip.data[index], &val); ++ ++ return err ? err : !!(val & BIT(pin)); ++} ++ ++static int airoha_gpio_direction_output(struct gpio_chip *chip, ++ unsigned int gpio, int value) ++{ ++ int err; ++ ++ err = pinctrl_gpio_direction_output(chip, gpio); ++ if (err) ++ return err; ++ ++ airoha_gpio_set(chip, gpio, value); ++ ++ return 0; ++} ++ ++/* irq callbacks */ ++static void airoha_irq_unmask(struct irq_data *data) ++{ ++ u8 offset = data->hwirq % AIROHA_REG_GPIOCTRL_NUM_PIN; ++ u8 index = data->hwirq / AIROHA_REG_GPIOCTRL_NUM_PIN; ++ u32 mask = GENMASK(2 * offset + 1, 2 * offset); ++ struct airoha_pinctrl_gpiochip *gpiochip; ++ struct airoha_pinctrl *pinctrl; ++ u32 val = BIT(2 * offset); ++ ++ gpiochip = irq_data_get_irq_chip_data(data); ++ if (WARN_ON_ONCE(data->hwirq >= ARRAY_SIZE(gpiochip->irq_type))) ++ return; ++ ++ pinctrl = container_of(gpiochip, struct airoha_pinctrl, gpiochip); ++ switch (gpiochip->irq_type[data->hwirq]) { ++ case IRQ_TYPE_LEVEL_LOW: ++ val = val << 1; ++ fallthrough; ++ case IRQ_TYPE_LEVEL_HIGH: ++ regmap_update_bits(pinctrl->regmap, gpiochip->level[index], ++ mask, val); ++ break; ++ case IRQ_TYPE_EDGE_FALLING: ++ val = val << 1; ++ fallthrough; ++ case IRQ_TYPE_EDGE_RISING: ++ regmap_update_bits(pinctrl->regmap, gpiochip->edge[index], ++ mask, val); ++ break; ++ case IRQ_TYPE_EDGE_BOTH: ++ regmap_set_bits(pinctrl->regmap, gpiochip->edge[index], mask); ++ break; ++ default: ++ break; ++ } ++} ++ ++static void airoha_irq_mask(struct irq_data *data) ++{ ++ u8 offset = data->hwirq % AIROHA_REG_GPIOCTRL_NUM_PIN; ++ u8 index = data->hwirq / AIROHA_REG_GPIOCTRL_NUM_PIN; ++ u32 mask = GENMASK(2 * offset + 1, 2 * offset); ++ struct airoha_pinctrl_gpiochip *gpiochip; ++ struct airoha_pinctrl *pinctrl; ++ ++ gpiochip = irq_data_get_irq_chip_data(data); ++ pinctrl = container_of(gpiochip, struct airoha_pinctrl, gpiochip); ++ ++ regmap_clear_bits(pinctrl->regmap, gpiochip->level[index], mask); ++ regmap_clear_bits(pinctrl->regmap, gpiochip->edge[index], mask); ++} ++ ++static int airoha_irq_type(struct irq_data *data, unsigned int type) ++{ ++ struct airoha_pinctrl_gpiochip *gpiochip; ++ ++ gpiochip = irq_data_get_irq_chip_data(data); ++ if (data->hwirq >= ARRAY_SIZE(gpiochip->irq_type)) ++ return -EINVAL; ++ ++ if (type == IRQ_TYPE_PROBE) { ++ if (gpiochip->irq_type[data->hwirq]) ++ return 0; ++ ++ type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; ++ } ++ gpiochip->irq_type[data->hwirq] = type & IRQ_TYPE_SENSE_MASK; ++ ++ return 0; ++} ++ ++static irqreturn_t airoha_irq_handler(int irq, void *data) ++{ ++ struct airoha_pinctrl *pinctrl = data; ++ bool handled = false; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(irq_status_regs); i++) { ++ struct gpio_irq_chip *girq = &pinctrl->gpiochip.chip.irq; ++ u32 status; ++ int irq; ++ ++ if (regmap_read(pinctrl->regmap, pinctrl->gpiochip.status[i], ++ &status)) ++ continue; ++ ++ for_each_set_bit(irq, (unsigned long *)&status, ++ AIROHA_PIN_BANK_SIZE) { ++ u32 offset = irq + i * AIROHA_PIN_BANK_SIZE; ++ ++ generic_handle_irq(irq_find_mapping(girq->domain, ++ offset)); ++ regmap_write(pinctrl->regmap, ++ pinctrl->gpiochip.status[i], BIT(irq)); ++ } ++ handled |= !!status; ++ } ++ ++ return handled ? IRQ_HANDLED : IRQ_NONE; ++} ++ ++static const struct irq_chip airoha_gpio_irq_chip = { ++ .name = "airoha-gpio-irq", ++ .irq_unmask = airoha_irq_unmask, ++ .irq_mask = airoha_irq_mask, ++ .irq_mask_ack = airoha_irq_mask, ++ .irq_set_type = airoha_irq_type, ++ .flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_IMMUTABLE, ++}; ++ ++static int airoha_pinctrl_add_gpiochip(struct airoha_pinctrl *pinctrl, ++ struct platform_device *pdev) ++{ ++ struct airoha_pinctrl_gpiochip *chip = &pinctrl->gpiochip; ++ struct gpio_chip *gc = &chip->chip; ++ struct gpio_irq_chip *girq = &gc->irq; ++ struct device *dev = &pdev->dev; ++ int irq, err; ++ ++ chip->data = gpio_data_regs; ++ chip->dir = gpio_dir_regs; ++ chip->out = gpio_out_regs; ++ chip->status = irq_status_regs; ++ chip->level = irq_level_regs; ++ chip->edge = irq_edge_regs; ++ ++ gc->parent = dev; ++ gc->label = dev_name(dev); ++ gc->request = gpiochip_generic_request; ++ gc->free = gpiochip_generic_free; ++ gc->direction_input = pinctrl_gpio_direction_input; ++ gc->direction_output = airoha_gpio_direction_output; ++ gc->set = airoha_gpio_set; ++ gc->get = airoha_gpio_get; ++ gc->base = -1; ++ gc->ngpio = AIROHA_NUM_PINS; ++ ++ girq->default_type = IRQ_TYPE_NONE; ++ girq->handler = handle_simple_irq; ++ gpio_irq_chip_set_chip(girq, &airoha_gpio_irq_chip); ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) ++ return irq; ++ ++ err = devm_request_irq(dev, irq, airoha_irq_handler, IRQF_SHARED, ++ dev_name(dev), pinctrl); ++ if (err) { ++ dev_err(dev, "error requesting irq %d: %d\n", irq, err); ++ return err; ++ } ++ ++ return devm_gpiochip_add_data(dev, gc, pinctrl); ++} ++ ++/* pinmux callbacks */ ++static int airoha_pinmux_set_mux(struct pinctrl_dev *pctrl_dev, ++ unsigned int selector, ++ unsigned int group) ++{ ++ struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); ++ const struct airoha_pinctrl_func *func; ++ struct function_desc *desc; ++ struct group_desc *grp; ++ int i; ++ ++ desc = pinmux_generic_get_function(pctrl_dev, selector); ++ if (!desc) ++ return -EINVAL; ++ ++ grp = pinctrl_generic_get_group(pctrl_dev, group); ++ if (!grp) ++ return -EINVAL; ++ ++ dev_dbg(pctrl_dev->dev, "enable function %s group %s\n", ++ desc->func.name, grp->grp.name); ++ ++ func = desc->data; ++ for (i = 0; i < func->group_size; i++) { ++ const struct airoha_pinctrl_func_group *group; ++ int j; ++ ++ group = &func->groups[i]; ++ if (strcmp(group->name, grp->grp.name)) ++ continue; ++ ++ for (j = 0; j < group->regmap_size; j++) { ++ switch (group->regmap[j].mux) { ++ case AIROHA_FUNC_PWM_EXT_MUX: ++ case AIROHA_FUNC_PWM_MUX: ++ regmap_update_bits(pinctrl->regmap, ++ group->regmap[j].offset, ++ group->regmap[j].mask, ++ group->regmap[j].val); ++ break; ++ default: ++ regmap_update_bits(pinctrl->chip_scu, ++ group->regmap[j].offset, ++ group->regmap[j].mask, ++ group->regmap[j].val); ++ break; ++ } ++ } ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++static int airoha_pinmux_set_direction(struct pinctrl_dev *pctrl_dev, ++ struct pinctrl_gpio_range *range, ++ unsigned int p, bool input) ++{ ++ struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); ++ u32 mask, index; ++ int err, pin; ++ ++ pin = airoha_convert_pin_to_reg_offset(pctrl_dev, range, p); ++ if (pin < 0) ++ return pin; ++ ++ /* set output enable */ ++ mask = BIT(pin % AIROHA_PIN_BANK_SIZE); ++ index = pin / AIROHA_PIN_BANK_SIZE; ++ err = regmap_update_bits(pinctrl->regmap, pinctrl->gpiochip.out[index], ++ mask, !input ? mask : 0); ++ if (err) ++ return err; ++ ++ /* set direction */ ++ mask = BIT(2 * (pin % AIROHA_REG_GPIOCTRL_NUM_PIN)); ++ index = pin / AIROHA_REG_GPIOCTRL_NUM_PIN; ++ return regmap_update_bits(pinctrl->regmap, ++ pinctrl->gpiochip.dir[index], mask, ++ !input ? mask : 0); ++} ++ ++static const struct pinmux_ops airoha_pmxops = { ++ .get_functions_count = pinmux_generic_get_function_count, ++ .get_function_name = pinmux_generic_get_function_name, ++ .get_function_groups = pinmux_generic_get_function_groups, ++ .gpio_set_direction = airoha_pinmux_set_direction, ++ .set_mux = airoha_pinmux_set_mux, ++ .strict = true, ++}; ++ ++/* pinconf callbacks */ ++static const struct airoha_pinctrl_reg * ++airoha_pinctrl_get_conf_reg(const struct airoha_pinctrl_conf *conf, ++ int conf_size, int pin) ++{ ++ int i; ++ ++ for (i = 0; i < conf_size; i++) { ++ if (conf[i].pin == pin) ++ return &conf[i].reg; ++ } ++ ++ return NULL; ++} ++ ++static int airoha_pinctrl_get_conf(struct airoha_pinctrl *pinctrl, ++ const struct airoha_pinctrl_conf *conf, ++ int conf_size, int pin, u32 *val) ++{ ++ const struct airoha_pinctrl_reg *reg; ++ ++ reg = airoha_pinctrl_get_conf_reg(conf, conf_size, pin); ++ if (!reg) ++ return -EINVAL; ++ ++ if (regmap_read(pinctrl->chip_scu, reg->offset, val)) ++ return -EINVAL; ++ ++ *val = (*val & reg->mask) >> __ffs(reg->mask); ++ ++ return 0; ++} ++ ++static int airoha_pinctrl_set_conf(struct airoha_pinctrl *pinctrl, ++ const struct airoha_pinctrl_conf *conf, ++ int conf_size, int pin, u32 val) ++{ ++ const struct airoha_pinctrl_reg *reg = NULL; ++ ++ reg = airoha_pinctrl_get_conf_reg(conf, conf_size, pin); ++ if (!reg) ++ return -EINVAL; ++ ++ ++ if (regmap_update_bits(pinctrl->chip_scu, reg->offset, reg->mask, ++ val << __ffs(reg->mask))) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++#define airoha_pinctrl_get_pullup_conf(pinctrl, pin, val) \ ++ airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_pullup_conf, \ ++ ARRAY_SIZE(airoha_pinctrl_pullup_conf), \ ++ (pin), (val)) ++#define airoha_pinctrl_get_pulldown_conf(pinctrl, pin, val) \ ++ airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_pulldown_conf, \ ++ ARRAY_SIZE(airoha_pinctrl_pulldown_conf), \ ++ (pin), (val)) ++#define airoha_pinctrl_get_drive_e2_conf(pinctrl, pin, val) \ ++ airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_drive_e2_conf, \ ++ ARRAY_SIZE(airoha_pinctrl_drive_e2_conf), \ ++ (pin), (val)) ++#define airoha_pinctrl_get_drive_e4_conf(pinctrl, pin, val) \ ++ airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_drive_e4_conf, \ ++ ARRAY_SIZE(airoha_pinctrl_drive_e4_conf), \ ++ (pin), (val)) ++#define airoha_pinctrl_get_pcie_rst_od_conf(pinctrl, pin, val) \ ++ airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_pcie_rst_od_conf, \ ++ ARRAY_SIZE(airoha_pinctrl_pcie_rst_od_conf), \ ++ (pin), (val)) ++#define airoha_pinctrl_set_pullup_conf(pinctrl, pin, val) \ ++ airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_pullup_conf, \ ++ ARRAY_SIZE(airoha_pinctrl_pullup_conf), \ ++ (pin), (val)) ++#define airoha_pinctrl_set_pulldown_conf(pinctrl, pin, val) \ ++ airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_pulldown_conf, \ ++ ARRAY_SIZE(airoha_pinctrl_pulldown_conf), \ ++ (pin), (val)) ++#define airoha_pinctrl_set_drive_e2_conf(pinctrl, pin, val) \ ++ airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_drive_e2_conf, \ ++ ARRAY_SIZE(airoha_pinctrl_drive_e2_conf), \ ++ (pin), (val)) ++#define airoha_pinctrl_set_drive_e4_conf(pinctrl, pin, val) \ ++ airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_drive_e4_conf, \ ++ ARRAY_SIZE(airoha_pinctrl_drive_e4_conf), \ ++ (pin), (val)) ++#define airoha_pinctrl_set_pcie_rst_od_conf(pinctrl, pin, val) \ ++ airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_pcie_rst_od_conf, \ ++ ARRAY_SIZE(airoha_pinctrl_pcie_rst_od_conf), \ ++ (pin), (val)) ++ ++static int airoha_pinconf_get_direction(struct pinctrl_dev *pctrl_dev, u32 p) ++{ ++ struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); ++ u32 val, mask; ++ int err, pin; ++ u8 index; ++ ++ pin = airoha_convert_pin_to_reg_offset(pctrl_dev, NULL, p); ++ if (pin < 0) ++ return pin; ++ ++ index = pin / AIROHA_REG_GPIOCTRL_NUM_PIN; ++ err = regmap_read(pinctrl->regmap, pinctrl->gpiochip.dir[index], &val); ++ if (err) ++ return err; ++ ++ mask = BIT(2 * (pin % AIROHA_REG_GPIOCTRL_NUM_PIN)); ++ return val & mask ? PIN_CONFIG_OUTPUT_ENABLE : PIN_CONFIG_INPUT_ENABLE; ++} ++ ++static int airoha_pinconf_get(struct pinctrl_dev *pctrl_dev, ++ unsigned int pin, unsigned long *config) ++{ ++ struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); ++ enum pin_config_param param = pinconf_to_config_param(*config); ++ u32 arg; ++ ++ switch (param) { ++ case PIN_CONFIG_BIAS_PULL_DOWN: ++ case PIN_CONFIG_BIAS_DISABLE: ++ case PIN_CONFIG_BIAS_PULL_UP: { ++ u32 pull_up, pull_down; ++ ++ if (airoha_pinctrl_get_pullup_conf(pinctrl, pin, &pull_up) || ++ airoha_pinctrl_get_pulldown_conf(pinctrl, pin, &pull_down)) ++ return -EINVAL; ++ ++ if (param == PIN_CONFIG_BIAS_PULL_UP && ++ !(pull_up && !pull_down)) ++ return -EINVAL; ++ else if (param == PIN_CONFIG_BIAS_PULL_DOWN && ++ !(pull_down && !pull_up)) ++ return -EINVAL; ++ else if (pull_up || pull_down) ++ return -EINVAL; ++ ++ arg = 1; ++ break; ++ } ++ case PIN_CONFIG_DRIVE_STRENGTH: { ++ u32 e2, e4; ++ ++ if (airoha_pinctrl_get_drive_e2_conf(pinctrl, pin, &e2) || ++ airoha_pinctrl_get_drive_e4_conf(pinctrl, pin, &e4)) ++ return -EINVAL; ++ ++ arg = e4 << 1 | e2; ++ break; ++ } ++ case PIN_CONFIG_DRIVE_OPEN_DRAIN: ++ if (airoha_pinctrl_get_pcie_rst_od_conf(pinctrl, pin, &arg)) ++ return -EINVAL; ++ break; ++ case PIN_CONFIG_OUTPUT_ENABLE: ++ case PIN_CONFIG_INPUT_ENABLE: ++ arg = airoha_pinconf_get_direction(pctrl_dev, pin); ++ if (arg != param) ++ return -EINVAL; ++ ++ arg = 1; ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ *config = pinconf_to_config_packed(param, arg); ++ ++ return 0; ++} ++ ++static int airoha_pinconf_set_pin_value(struct pinctrl_dev *pctrl_dev, ++ unsigned int p, bool value) ++{ ++ struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); ++ int pin; ++ ++ pin = airoha_convert_pin_to_reg_offset(pctrl_dev, NULL, p); ++ if (pin < 0) ++ return pin; ++ ++ airoha_gpio_set(&pinctrl->gpiochip.chip, pin, value); ++ ++ return 0; ++} ++ ++static int airoha_pinconf_set(struct pinctrl_dev *pctrl_dev, ++ unsigned int pin, unsigned long *configs, ++ unsigned int num_configs) ++{ ++ struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); ++ int i; ++ ++ for (i = 0; i < num_configs; i++) { ++ u32 param = pinconf_to_config_param(configs[i]); ++ u32 arg = pinconf_to_config_argument(configs[i]); ++ ++ switch (param) { ++ case PIN_CONFIG_BIAS_DISABLE: ++ airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 0); ++ airoha_pinctrl_set_pullup_conf(pinctrl, pin, 0); ++ break; ++ case PIN_CONFIG_BIAS_PULL_UP: ++ airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 0); ++ airoha_pinctrl_set_pullup_conf(pinctrl, pin, 1); ++ break; ++ case PIN_CONFIG_BIAS_PULL_DOWN: ++ airoha_pinctrl_set_pulldown_conf(pinctrl, pin, 1); ++ airoha_pinctrl_set_pullup_conf(pinctrl, pin, 0); ++ break; ++ case PIN_CONFIG_DRIVE_STRENGTH: { ++ u32 e2 = 0, e4 = 0; ++ ++ switch (arg) { ++ case MTK_DRIVE_2mA: ++ break; ++ case MTK_DRIVE_4mA: ++ e2 = 1; ++ break; ++ case MTK_DRIVE_6mA: ++ e4 = 1; ++ break; ++ case MTK_DRIVE_8mA: ++ e2 = 1; ++ e4 = 1; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ airoha_pinctrl_set_drive_e2_conf(pinctrl, pin, e2); ++ airoha_pinctrl_set_drive_e4_conf(pinctrl, pin, e4); ++ break; ++ } ++ case PIN_CONFIG_DRIVE_OPEN_DRAIN: ++ airoha_pinctrl_set_pcie_rst_od_conf(pinctrl, pin, !!arg); ++ break; ++ case PIN_CONFIG_OUTPUT_ENABLE: ++ case PIN_CONFIG_INPUT_ENABLE: ++ case PIN_CONFIG_OUTPUT: { ++ bool input = param == PIN_CONFIG_INPUT_ENABLE; ++ int err; ++ ++ err = airoha_pinmux_set_direction(pctrl_dev, NULL, pin, ++ input); ++ if (err) ++ return err; ++ ++ if (param == PIN_CONFIG_OUTPUT) { ++ err = airoha_pinconf_set_pin_value(pctrl_dev, ++ pin, !!arg); ++ if (err) ++ return err; ++ } ++ break; ++ } ++ default: ++ return -EOPNOTSUPP; ++ } ++ } ++ ++ return 0; ++} ++ ++static int airoha_pinconf_group_get(struct pinctrl_dev *pctrl_dev, ++ unsigned int group, unsigned long *config) ++{ ++ u32 cur_config = 0; ++ int i; ++ ++ for (i = 0; i < airoha_pinctrl_groups[group].npins; i++) { ++ if (airoha_pinconf_get(pctrl_dev, ++ airoha_pinctrl_groups[group].pins[i], ++ config)) ++ return -EOPNOTSUPP; ++ ++ if (i && cur_config != *config) ++ return -EOPNOTSUPP; ++ ++ cur_config = *config; ++ } ++ ++ return 0; ++} ++ ++static int airoha_pinconf_group_set(struct pinctrl_dev *pctrl_dev, ++ unsigned int group, unsigned long *configs, ++ unsigned int num_configs) ++{ ++ int i; ++ ++ for (i = 0; i < airoha_pinctrl_groups[group].npins; i++) { ++ int err; ++ ++ err = airoha_pinconf_set(pctrl_dev, ++ airoha_pinctrl_groups[group].pins[i], ++ configs, num_configs); ++ if (err) ++ return err; ++ } ++ ++ return 0; ++} ++ ++static const struct pinconf_ops airoha_confops = { ++ .is_generic = true, ++ .pin_config_get = airoha_pinconf_get, ++ .pin_config_set = airoha_pinconf_set, ++ .pin_config_group_get = airoha_pinconf_group_get, ++ .pin_config_group_set = airoha_pinconf_group_set, ++ .pin_config_config_dbg_show = pinconf_generic_dump_config, ++}; ++ ++static const struct pinctrl_ops airoha_pctlops = { ++ .get_groups_count = pinctrl_generic_get_group_count, ++ .get_group_name = pinctrl_generic_get_group_name, ++ .get_group_pins = pinctrl_generic_get_group_pins, ++ .dt_node_to_map = pinconf_generic_dt_node_to_map_all, ++ .dt_free_map = pinconf_generic_dt_free_map, ++}; ++ ++static struct pinctrl_desc airoha_pinctrl_desc = { ++ .name = KBUILD_MODNAME, ++ .owner = THIS_MODULE, ++ .pctlops = &airoha_pctlops, ++ .pmxops = &airoha_pmxops, ++ .confops = &airoha_confops, ++ .pins = airoha_pinctrl_pins, ++ .npins = ARRAY_SIZE(airoha_pinctrl_pins), ++}; ++ ++static int airoha_pinctrl_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct airoha_pinctrl *pinctrl; ++ struct regmap *map; ++ int err, i; ++ ++ pinctrl = devm_kzalloc(dev, sizeof(*pinctrl), GFP_KERNEL); ++ if (!pinctrl) ++ return -ENOMEM; ++ ++ pinctrl->regmap = device_node_to_regmap(dev->parent->of_node); ++ if (IS_ERR(pinctrl->regmap)) ++ return PTR_ERR(pinctrl->regmap); ++ ++ map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); ++ if (IS_ERR(map)) ++ return PTR_ERR(map); ++ ++ pinctrl->chip_scu = map; ++ ++ err = devm_pinctrl_register_and_init(dev, &airoha_pinctrl_desc, ++ pinctrl, &pinctrl->ctrl); ++ if (err) ++ return err; ++ ++ /* build pin groups */ ++ for (i = 0; i < ARRAY_SIZE(airoha_pinctrl_groups); i++) { ++ const struct pingroup *grp = &airoha_pinctrl_groups[i]; ++ ++ err = pinctrl_generic_add_group(pinctrl->ctrl, grp->name, ++ grp->pins, grp->npins, ++ (void *)grp); ++ if (err < 0) { ++ dev_err(&pdev->dev, "Failed to register group %s\n", ++ grp->name); ++ return err; ++ } ++ } ++ ++ /* build functions */ ++ for (i = 0; i < ARRAY_SIZE(airoha_pinctrl_funcs); i++) { ++ const struct airoha_pinctrl_func *func; ++ ++ func = &airoha_pinctrl_funcs[i]; ++ err = pinmux_generic_add_function(pinctrl->ctrl, ++ func->desc.func.name, ++ func->desc.func.groups, ++ func->desc.func.ngroups, ++ (void *)func); ++ if (err < 0) { ++ dev_err(dev, "Failed to register function %s\n", ++ func->desc.func.name); ++ return err; ++ } ++ } ++ ++ err = pinctrl_enable(pinctrl->ctrl); ++ if (err) ++ return err; ++ ++ /* build gpio-chip */ ++ return airoha_pinctrl_add_gpiochip(pinctrl, pdev); ++} ++ ++static const struct of_device_id airoha_pinctrl_of_match[] = { ++ { .compatible = "airoha,en7581-pinctrl" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, airoha_pinctrl_of_match); ++ ++static struct platform_driver airoha_pinctrl_driver = { ++ .probe = airoha_pinctrl_probe, ++ .driver = { ++ .name = "pinctrl-airoha", ++ .of_match_table = airoha_pinctrl_of_match, ++ }, ++}; ++module_platform_driver(airoha_pinctrl_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Lorenzo Bianconi "); ++MODULE_AUTHOR("Benjamin Larsson "); ++MODULE_AUTHOR("Markus Gothe "); ++MODULE_DESCRIPTION("Pinctrl driver for Airoha SoC"); diff --git a/lede/target/linux/airoha/patches-6.12/034-02-v6.13-pinctrl-airoha-Use-unsigned-long-for-bit-search.patch b/lede/target/linux/airoha/patches-6.12/034-02-v6.13-pinctrl-airoha-Use-unsigned-long-for-bit-search.patch new file mode 100644 index 0000000000..62fae6aa38 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/034-02-v6.13-pinctrl-airoha-Use-unsigned-long-for-bit-search.patch @@ -0,0 +1,61 @@ +From ac6f0825e582f2216a582c9edf0cee7bfe347ba6 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Sun, 17 Nov 2024 03:45:38 -0800 +Subject: [PATCH] pinctrl: airoha: Use unsigned long for bit search + +Instead of risking alignment problems and causing (false positive) array +bound warnings when casting a u32 to (64-bit) unsigned long, just use a +native unsigned long for doing bit searches. Avoids warning with GCC 15's +-Warray-bounds -fdiagnostics-details: + +In file included from ../include/linux/bitmap.h:11, + from ../include/linux/cpumask.h:12, + from ../arch/x86/include/asm/paravirt.h:21, + from ../arch/x86/include/asm/irqflags.h:80, + from ../include/linux/irqflags.h:18, + from ../include/linux/spinlock.h:59, + from ../include/linux/irq.h:14, + from ../include/linux/irqchip/chained_irq.h:10, + from ../include/linux/gpio/driver.h:8, + from ../drivers/pinctrl/mediatek/pinctrl-airoha.c:11: +In function 'find_next_bit', + inlined from 'airoha_irq_handler' at ../drivers/pinctrl/mediatek/pinctrl-airoha.c:2394:3: +../include/linux/find.h:65:23: error: array subscript 'long unsigned int[0]' is partly outside array bounds of 'u32[1]' {aka 'unsigned int[1]'} [-Werror=array-bounds=] + 65 | val = *addr & GENMASK(size - 1, offset); + | ^~~~~ +../drivers/pinctrl/mediatek/pinctrl-airoha.c: In function 'airoha_irq_handler': +../drivers/pinctrl/mediatek/pinctrl-airoha.c:2387:21: note: object 'status' of size 4 + 2387 | u32 status; + | ^~~~~~ + +Signed-off-by: Kees Cook +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/20241117114534.work.292-kees@kernel.org +Signed-off-by: Linus Walleij +--- + drivers/pinctrl/mediatek/pinctrl-airoha.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/pinctrl/mediatek/pinctrl-airoha.c ++++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c +@@ -2384,15 +2384,16 @@ static irqreturn_t airoha_irq_handler(in + + for (i = 0; i < ARRAY_SIZE(irq_status_regs); i++) { + struct gpio_irq_chip *girq = &pinctrl->gpiochip.chip.irq; +- u32 status; ++ u32 regmap; ++ unsigned long status; + int irq; + + if (regmap_read(pinctrl->regmap, pinctrl->gpiochip.status[i], +- &status)) ++ ®map)) + continue; + +- for_each_set_bit(irq, (unsigned long *)&status, +- AIROHA_PIN_BANK_SIZE) { ++ status = regmap; ++ for_each_set_bit(irq, &status, AIROHA_PIN_BANK_SIZE) { + u32 offset = irq + i * AIROHA_PIN_BANK_SIZE; + + generic_handle_irq(irq_find_mapping(girq->domain, diff --git a/lede/target/linux/airoha/patches-6.12/036-v6.13-net-airoha-Fix-typo-in-REG_CDM2_FWD_CFG-configuratio.patch b/lede/target/linux/airoha/patches-6.12/036-v6.13-net-airoha-Fix-typo-in-REG_CDM2_FWD_CFG-configuratio.patch new file mode 100644 index 0000000000..a71197150f --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/036-v6.13-net-airoha-Fix-typo-in-REG_CDM2_FWD_CFG-configuratio.patch @@ -0,0 +1,35 @@ +From 30d9d8f6a2d7e44a9f91737dd409dbc87ac6f6b7 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 15 Oct 2024 09:58:09 +0200 +Subject: [PATCH] net: airoha: Fix typo in REG_CDM2_FWD_CFG configuration + +Fix typo in airoha_fe_init routine configuring CDM2_OAM_QSEL_MASK field +of REG_CDM2_FWD_CFG register. +This bug is not introducing any user visible problem since Frame Engine +CDM2 port is used just by the second QDMA block and we currently enable +just QDMA1 block connected to the MT7530 dsa switch via CDM1 port. + +Introduced by commit 23020f049327 ("net: airoha: Introduce ethernet +support for EN7581 SoC") + +Reported-by: ChihWei Cheng +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Message-ID: <20241015-airoha-eth-cdm2-fixes-v1-1-9dc6993286c3@kernel.org> +Signed-off-by: Andrew Lunn +--- + drivers/net/ethernet/mediatek/airoha_eth.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mediatek/airoha_eth.c ++++ b/drivers/net/ethernet/mediatek/airoha_eth.c +@@ -1369,7 +1369,8 @@ static int airoha_fe_init(struct airoha_ + airoha_fe_set(eth, REG_GDM_MISC_CFG, + GDM2_RDM_ACK_WAIT_PREF_MASK | + GDM2_CHN_VLD_MODE_MASK); +- airoha_fe_rmw(eth, REG_CDM2_FWD_CFG, CDM2_OAM_QSEL_MASK, 15); ++ airoha_fe_rmw(eth, REG_CDM2_FWD_CFG, CDM2_OAM_QSEL_MASK, ++ FIELD_PREP(CDM2_OAM_QSEL_MASK, 15)); + + /* init fragment and assemble Force Port */ + /* NPU Core-3, NPU Bridge Channel-3 */ diff --git a/lede/target/linux/airoha/patches-6.12/038-01-v6.14-net-airoha-Enable-Tx-drop-capability-for-each-Tx-DMA.patch b/lede/target/linux/airoha/patches-6.12/038-01-v6.14-net-airoha-Enable-Tx-drop-capability-for-each-Tx-DMA.patch new file mode 100644 index 0000000000..b6bbcf3191 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/038-01-v6.14-net-airoha-Enable-Tx-drop-capability-for-each-Tx-DMA.patch @@ -0,0 +1,27 @@ +From 5f795590380476f1c9b7ed0ac945c9b0269dc23a Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 3 Jan 2025 13:17:02 +0100 +Subject: [PATCH 1/4] net: airoha: Enable Tx drop capability for each Tx DMA + ring + +This is a preliminary patch in order to enable hw Qdisc offloading. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/mediatek/airoha_eth.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/ethernet/mediatek/airoha_eth.c ++++ b/drivers/net/ethernet/mediatek/airoha_eth.c +@@ -1789,6 +1789,10 @@ static int airoha_qdma_init_tx_queue(str + WRITE_ONCE(q->desc[i].ctrl, cpu_to_le32(val)); + } + ++ /* xmit ring drop default setting */ ++ airoha_qdma_set(qdma, REG_TX_RING_BLOCKING(qid), ++ TX_RING_IRQ_BLOCKING_TX_DROP_EN_MASK); ++ + airoha_qdma_wr(qdma, REG_TX_RING_BASE(qid), dma_addr); + airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK, + FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head)); diff --git a/lede/target/linux/airoha/patches-6.12/038-02-v6.14-net-airoha-Introduce-ndo_select_queue-callback.patch b/lede/target/linux/airoha/patches-6.12/038-02-v6.14-net-airoha-Introduce-ndo_select_queue-callback.patch new file mode 100644 index 0000000000..f150dd929a --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/038-02-v6.14-net-airoha-Introduce-ndo_select_queue-callback.patch @@ -0,0 +1,86 @@ +From 2b288b81560b94958cd68bbe54673e55a1730c95 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 3 Jan 2025 13:17:03 +0100 +Subject: [PATCH 2/4] net: airoha: Introduce ndo_select_queue callback + +Airoha EN7581 SoC supports 32 Tx DMA rings used to feed packets to QoS +channels. Each channels supports 8 QoS queues where the user can apply +QoS scheduling policies. In a similar way, the user can configure hw +rate shaping for each QoS channel. +Introduce ndo_select_queue callback in order to select the tx queue +based on QoS channel and QoS queue. In particular, for dsa device select +QoS channel according to the dsa user port index, rely on port id +otherwise. Select QoS queue based on the skb priority. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/mediatek/airoha_eth.c | 30 ++++++++++++++++++++-- + 1 file changed, 28 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mediatek/airoha_eth.c ++++ b/drivers/net/ethernet/mediatek/airoha_eth.c +@@ -23,6 +23,8 @@ + #define AIROHA_MAX_NUM_XSI_RSTS 5 + #define AIROHA_MAX_MTU 2000 + #define AIROHA_MAX_PACKET_SIZE 2048 ++#define AIROHA_NUM_QOS_CHANNELS 4 ++#define AIROHA_NUM_QOS_QUEUES 8 + #define AIROHA_NUM_TX_RING 32 + #define AIROHA_NUM_RX_RING 32 + #define AIROHA_FE_MC_MAX_VLAN_TABLE 64 +@@ -2421,21 +2423,44 @@ static void airoha_dev_get_stats64(struc + } while (u64_stats_fetch_retry(&port->stats.syncp, start)); + } + ++static u16 airoha_dev_select_queue(struct net_device *dev, struct sk_buff *skb, ++ struct net_device *sb_dev) ++{ ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ int queue, channel; ++ ++ /* For dsa device select QoS channel according to the dsa user port ++ * index, rely on port id otherwise. Select QoS queue based on the ++ * skb priority. ++ */ ++ channel = netdev_uses_dsa(dev) ? skb_get_queue_mapping(skb) : port->id; ++ channel = channel % AIROHA_NUM_QOS_CHANNELS; ++ queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES; /* QoS queue */ ++ queue = channel * AIROHA_NUM_QOS_QUEUES + queue; ++ ++ return queue < dev->num_tx_queues ? queue : 0; ++} ++ + static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, + struct net_device *dev) + { + struct skb_shared_info *sinfo = skb_shinfo(skb); + struct airoha_gdm_port *port = netdev_priv(dev); +- u32 msg0 = 0, msg1, len = skb_headlen(skb); +- int i, qid = skb_get_queue_mapping(skb); ++ u32 msg0, msg1, len = skb_headlen(skb); + struct airoha_qdma *qdma = port->qdma; + u32 nr_frags = 1 + sinfo->nr_frags; + struct netdev_queue *txq; + struct airoha_queue *q; + void *data = skb->data; ++ int i, qid; + u16 index; + u8 fport; + ++ qid = skb_get_queue_mapping(skb) % ARRAY_SIZE(qdma->q_tx); ++ msg0 = FIELD_PREP(QDMA_ETH_TXMSG_CHAN_MASK, ++ qid / AIROHA_NUM_QOS_QUEUES) | ++ FIELD_PREP(QDMA_ETH_TXMSG_QUEUE_MASK, ++ qid % AIROHA_NUM_QOS_QUEUES); + if (skb->ip_summed == CHECKSUM_PARTIAL) + msg0 |= FIELD_PREP(QDMA_ETH_TXMSG_TCO_MASK, 1) | + FIELD_PREP(QDMA_ETH_TXMSG_UCO_MASK, 1) | +@@ -2609,6 +2634,7 @@ static const struct net_device_ops airoh + .ndo_init = airoha_dev_init, + .ndo_open = airoha_dev_open, + .ndo_stop = airoha_dev_stop, ++ .ndo_select_queue = airoha_dev_select_queue, + .ndo_start_xmit = airoha_dev_xmit, + .ndo_get_stats64 = airoha_dev_get_stats64, + .ndo_set_mac_address = airoha_dev_set_macaddr, diff --git a/lede/target/linux/airoha/patches-6.12/038-03-v6.14-net-airoha-Add-sched-ETS-offload-support.patch b/lede/target/linux/airoha/patches-6.12/038-03-v6.14-net-airoha-Add-sched-ETS-offload-support.patch new file mode 100644 index 0000000000..4ea0742377 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/038-03-v6.14-net-airoha-Add-sched-ETS-offload-support.patch @@ -0,0 +1,292 @@ +From 20bf7d07c956e5c7a22d3076c599cbb7a6054917 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 3 Jan 2025 13:17:04 +0100 +Subject: [PATCH 3/4] net: airoha: Add sched ETS offload support + +Introduce support for ETS Qdisc offload available on the Airoha EN7581 +ethernet controller. In order to be effective, ETS Qdisc must configured +as leaf of a HTB Qdisc (HTB Qdisc offload will be added in the following +patch). ETS Qdisc available on EN7581 ethernet controller supports at +most 8 concurrent bands (QoS queues). We can enable an ETS Qdisc for +each available QoS channel. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/mediatek/airoha_eth.c | 196 ++++++++++++++++++++- + 1 file changed, 195 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mediatek/airoha_eth.c ++++ b/drivers/net/ethernet/mediatek/airoha_eth.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + + #define AIROHA_MAX_NUM_GDM_PORTS 1 +@@ -543,9 +544,24 @@ + #define INGRESS_SLOW_TICK_RATIO_MASK GENMASK(29, 16) + #define INGRESS_FAST_TICK_MASK GENMASK(15, 0) + ++#define REG_QUEUE_CLOSE_CFG(_n) (0x00a0 + ((_n) & 0xfc)) ++#define TXQ_DISABLE_CHAN_QUEUE_MASK(_n, _m) BIT((_m) + (((_n) & 0x3) << 3)) ++ + #define REG_TXQ_DIS_CFG_BASE(_n) ((_n) ? 0x20a0 : 0x00a0) + #define REG_TXQ_DIS_CFG(_n, _m) (REG_TXQ_DIS_CFG_BASE((_n)) + (_m) << 2) + ++#define REG_CNTR_CFG(_n) (0x0400 + ((_n) << 3)) ++#define CNTR_EN_MASK BIT(31) ++#define CNTR_ALL_CHAN_EN_MASK BIT(30) ++#define CNTR_ALL_QUEUE_EN_MASK BIT(29) ++#define CNTR_ALL_DSCP_RING_EN_MASK BIT(28) ++#define CNTR_SRC_MASK GENMASK(27, 24) ++#define CNTR_DSCP_RING_MASK GENMASK(20, 16) ++#define CNTR_CHAN_MASK GENMASK(7, 3) ++#define CNTR_QUEUE_MASK GENMASK(2, 0) ++ ++#define REG_CNTR_VAL(_n) (0x0404 + ((_n) << 3)) ++ + #define REG_LMGR_INIT_CFG 0x1000 + #define LMGR_INIT_START BIT(31) + #define LMGR_SRAM_MODE_MASK BIT(30) +@@ -571,9 +587,19 @@ + #define TWRR_WEIGHT_SCALE_MASK BIT(31) + #define TWRR_WEIGHT_BASE_MASK BIT(3) + ++#define REG_TXWRR_WEIGHT_CFG 0x1024 ++#define TWRR_RW_CMD_MASK BIT(31) ++#define TWRR_RW_CMD_DONE BIT(30) ++#define TWRR_CHAN_IDX_MASK GENMASK(23, 19) ++#define TWRR_QUEUE_IDX_MASK GENMASK(18, 16) ++#define TWRR_VALUE_MASK GENMASK(15, 0) ++ + #define REG_PSE_BUF_USAGE_CFG 0x1028 + #define PSE_BUF_ESTIMATE_EN_MASK BIT(29) + ++#define REG_CHAN_QOS_MODE(_n) (0x1040 + ((_n) << 2)) ++#define CHAN_QOS_MODE_MASK(_n) GENMASK(2 + ((_n) << 2), (_n) << 2) ++ + #define REG_GLB_TRTCM_CFG 0x1080 + #define GLB_TRTCM_EN_MASK BIT(31) + #define GLB_TRTCM_MODE_MASK BIT(30) +@@ -722,6 +748,17 @@ enum { + FE_PSE_PORT_DROP = 0xf, + }; + ++enum tx_sched_mode { ++ TC_SCH_WRR8, ++ TC_SCH_SP, ++ TC_SCH_WRR7, ++ TC_SCH_WRR6, ++ TC_SCH_WRR5, ++ TC_SCH_WRR4, ++ TC_SCH_WRR3, ++ TC_SCH_WRR2, ++}; ++ + struct airoha_queue_entry { + union { + void *buf; +@@ -812,6 +849,10 @@ struct airoha_gdm_port { + int id; + + struct airoha_hw_stats stats; ++ ++ /* qos stats counters */ ++ u64 cpu_tx_packets; ++ u64 fwd_tx_packets; + }; + + struct airoha_eth { +@@ -1961,6 +2002,27 @@ static void airoha_qdma_init_qos(struct + FIELD_PREP(SLA_SLOW_TICK_RATIO_MASK, 40)); + } + ++static void airoha_qdma_init_qos_stats(struct airoha_qdma *qdma) ++{ ++ int i; ++ ++ for (i = 0; i < AIROHA_NUM_QOS_CHANNELS; i++) { ++ /* Tx-cpu transferred count */ ++ airoha_qdma_wr(qdma, REG_CNTR_VAL(i << 1), 0); ++ airoha_qdma_wr(qdma, REG_CNTR_CFG(i << 1), ++ CNTR_EN_MASK | CNTR_ALL_QUEUE_EN_MASK | ++ CNTR_ALL_DSCP_RING_EN_MASK | ++ FIELD_PREP(CNTR_CHAN_MASK, i)); ++ /* Tx-fwd transferred count */ ++ airoha_qdma_wr(qdma, REG_CNTR_VAL((i << 1) + 1), 0); ++ airoha_qdma_wr(qdma, REG_CNTR_CFG(i << 1), ++ CNTR_EN_MASK | CNTR_ALL_QUEUE_EN_MASK | ++ CNTR_ALL_DSCP_RING_EN_MASK | ++ FIELD_PREP(CNTR_SRC_MASK, 1) | ++ FIELD_PREP(CNTR_CHAN_MASK, i)); ++ } ++} ++ + static int airoha_qdma_hw_init(struct airoha_qdma *qdma) + { + int i; +@@ -2011,6 +2073,7 @@ static int airoha_qdma_hw_init(struct ai + + airoha_qdma_set(qdma, REG_TXQ_CNGST_CFG, + TXQ_CNGST_DROP_EN | TXQ_CNGST_DEI_DROP_EN); ++ airoha_qdma_init_qos_stats(qdma); + + return 0; + } +@@ -2630,6 +2693,135 @@ airoha_ethtool_get_rmon_stats(struct net + } while (u64_stats_fetch_retry(&port->stats.syncp, start)); + } + ++static int airoha_qdma_set_chan_tx_sched(struct airoha_gdm_port *port, ++ int channel, enum tx_sched_mode mode, ++ const u16 *weights, u8 n_weights) ++{ ++ int i; ++ ++ for (i = 0; i < AIROHA_NUM_TX_RING; i++) ++ airoha_qdma_clear(port->qdma, REG_QUEUE_CLOSE_CFG(channel), ++ TXQ_DISABLE_CHAN_QUEUE_MASK(channel, i)); ++ ++ for (i = 0; i < n_weights; i++) { ++ u32 status; ++ int err; ++ ++ airoha_qdma_wr(port->qdma, REG_TXWRR_WEIGHT_CFG, ++ TWRR_RW_CMD_MASK | ++ FIELD_PREP(TWRR_CHAN_IDX_MASK, channel) | ++ FIELD_PREP(TWRR_QUEUE_IDX_MASK, i) | ++ FIELD_PREP(TWRR_VALUE_MASK, weights[i])); ++ err = read_poll_timeout(airoha_qdma_rr, status, ++ status & TWRR_RW_CMD_DONE, ++ USEC_PER_MSEC, 10 * USEC_PER_MSEC, ++ true, port->qdma, ++ REG_TXWRR_WEIGHT_CFG); ++ if (err) ++ return err; ++ } ++ ++ airoha_qdma_rmw(port->qdma, REG_CHAN_QOS_MODE(channel >> 3), ++ CHAN_QOS_MODE_MASK(channel), ++ mode << __ffs(CHAN_QOS_MODE_MASK(channel))); ++ ++ return 0; ++} ++ ++static int airoha_qdma_set_tx_prio_sched(struct airoha_gdm_port *port, ++ int channel) ++{ ++ static const u16 w[AIROHA_NUM_QOS_QUEUES] = {}; ++ ++ return airoha_qdma_set_chan_tx_sched(port, channel, TC_SCH_SP, w, ++ ARRAY_SIZE(w)); ++} ++ ++static int airoha_qdma_set_tx_ets_sched(struct airoha_gdm_port *port, ++ int channel, ++ struct tc_ets_qopt_offload *opt) ++{ ++ struct tc_ets_qopt_offload_replace_params *p = &opt->replace_params; ++ enum tx_sched_mode mode = TC_SCH_SP; ++ u16 w[AIROHA_NUM_QOS_QUEUES] = {}; ++ int i, nstrict = 0; ++ ++ if (p->bands > AIROHA_NUM_QOS_QUEUES) ++ return -EINVAL; ++ ++ for (i = 0; i < p->bands; i++) { ++ if (!p->quanta[i]) ++ nstrict++; ++ } ++ ++ /* this configuration is not supported by the hw */ ++ if (nstrict == AIROHA_NUM_QOS_QUEUES - 1) ++ return -EINVAL; ++ ++ for (i = 0; i < p->bands - nstrict; i++) ++ w[i] = p->weights[nstrict + i]; ++ ++ if (!nstrict) ++ mode = TC_SCH_WRR8; ++ else if (nstrict < AIROHA_NUM_QOS_QUEUES - 1) ++ mode = nstrict + 1; ++ ++ return airoha_qdma_set_chan_tx_sched(port, channel, mode, w, ++ ARRAY_SIZE(w)); ++} ++ ++static int airoha_qdma_get_tx_ets_stats(struct airoha_gdm_port *port, ++ int channel, ++ struct tc_ets_qopt_offload *opt) ++{ ++ u64 cpu_tx_packets = airoha_qdma_rr(port->qdma, ++ REG_CNTR_VAL(channel << 1)); ++ u64 fwd_tx_packets = airoha_qdma_rr(port->qdma, ++ REG_CNTR_VAL((channel << 1) + 1)); ++ u64 tx_packets = (cpu_tx_packets - port->cpu_tx_packets) + ++ (fwd_tx_packets - port->fwd_tx_packets); ++ _bstats_update(opt->stats.bstats, 0, tx_packets); ++ ++ port->cpu_tx_packets = cpu_tx_packets; ++ port->fwd_tx_packets = fwd_tx_packets; ++ ++ return 0; ++} ++ ++static int airoha_tc_setup_qdisc_ets(struct airoha_gdm_port *port, ++ struct tc_ets_qopt_offload *opt) ++{ ++ int channel = TC_H_MAJ(opt->handle) >> 16; ++ ++ if (opt->parent == TC_H_ROOT) ++ return -EINVAL; ++ ++ switch (opt->command) { ++ case TC_ETS_REPLACE: ++ return airoha_qdma_set_tx_ets_sched(port, channel, opt); ++ case TC_ETS_DESTROY: ++ /* PRIO is default qdisc scheduler */ ++ return airoha_qdma_set_tx_prio_sched(port, channel); ++ case TC_ETS_STATS: ++ return airoha_qdma_get_tx_ets_stats(port, channel, opt); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static int airoha_dev_tc_setup(struct net_device *dev, enum tc_setup_type type, ++ void *type_data) ++{ ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ ++ switch (type) { ++ case TC_SETUP_QDISC_ETS: ++ return airoha_tc_setup_qdisc_ets(port, type_data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ + static const struct net_device_ops airoha_netdev_ops = { + .ndo_init = airoha_dev_init, + .ndo_open = airoha_dev_open, +@@ -2638,6 +2830,7 @@ static const struct net_device_ops airoh + .ndo_start_xmit = airoha_dev_xmit, + .ndo_get_stats64 = airoha_dev_get_stats64, + .ndo_set_mac_address = airoha_dev_set_macaddr, ++ .ndo_setup_tc = airoha_dev_tc_setup, + }; + + static const struct ethtool_ops airoha_ethtool_ops = { +@@ -2687,7 +2880,8 @@ static int airoha_alloc_gdm_port(struct + dev->watchdog_timeo = 5 * HZ; + dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | + NETIF_F_TSO6 | NETIF_F_IPV6_CSUM | +- NETIF_F_SG | NETIF_F_TSO; ++ NETIF_F_SG | NETIF_F_TSO | ++ NETIF_F_HW_TC; + dev->features |= dev->hw_features; + dev->dev.of_node = np; + dev->irq = qdma->irq; diff --git a/lede/target/linux/airoha/patches-6.12/038-04-v6.14-net-airoha-Add-sched-HTB-offload-support.patch b/lede/target/linux/airoha/patches-6.12/038-04-v6.14-net-airoha-Add-sched-HTB-offload-support.patch new file mode 100644 index 0000000000..4240a89952 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/038-04-v6.14-net-airoha-Add-sched-HTB-offload-support.patch @@ -0,0 +1,371 @@ +From ef1ca9271313b4ea7b03de69576aacef1e78f381 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 3 Jan 2025 13:17:05 +0100 +Subject: [PATCH 4/4] net: airoha: Add sched HTB offload support + +Introduce support for HTB Qdisc offload available in the Airoha EN7581 +ethernet controller. EN7581 can offload only one level of HTB leafs. +Each HTB leaf represents a QoS channel supported by EN7581 SoC. +The typical use-case is creating a HTB leaf for QoS channel to rate +limit the egress traffic and attach an ETS Qdisc to each HTB leaf in +order to enforce traffic prioritization. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/mediatek/airoha_eth.c | 288 ++++++++++++++++++++- + 1 file changed, 287 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mediatek/airoha_eth.c ++++ b/drivers/net/ethernet/mediatek/airoha_eth.c +@@ -28,6 +28,8 @@ + #define AIROHA_NUM_QOS_QUEUES 8 + #define AIROHA_NUM_TX_RING 32 + #define AIROHA_NUM_RX_RING 32 ++#define AIROHA_NUM_NETDEV_TX_RINGS (AIROHA_NUM_TX_RING + \ ++ AIROHA_NUM_QOS_CHANNELS) + #define AIROHA_FE_MC_MAX_VLAN_TABLE 64 + #define AIROHA_FE_MC_MAX_VLAN_PORT 16 + #define AIROHA_NUM_TX_IRQ 2 +@@ -43,6 +45,9 @@ + #define PSE_RSV_PAGES 128 + #define PSE_QUEUE_RSV_PAGES 64 + ++#define QDMA_METER_IDX(_n) ((_n) & 0xff) ++#define QDMA_METER_GROUP(_n) (((_n) >> 8) & 0x3) ++ + /* FE */ + #define PSE_BASE 0x0100 + #define CSR_IFC_BASE 0x0200 +@@ -583,6 +588,17 @@ + #define EGRESS_SLOW_TICK_RATIO_MASK GENMASK(29, 16) + #define EGRESS_FAST_TICK_MASK GENMASK(15, 0) + ++#define TRTCM_PARAM_RW_MASK BIT(31) ++#define TRTCM_PARAM_RW_DONE_MASK BIT(30) ++#define TRTCM_PARAM_TYPE_MASK GENMASK(29, 28) ++#define TRTCM_METER_GROUP_MASK GENMASK(27, 26) ++#define TRTCM_PARAM_INDEX_MASK GENMASK(23, 17) ++#define TRTCM_PARAM_RATE_TYPE_MASK BIT(16) ++ ++#define REG_TRTCM_CFG_PARAM(_n) ((_n) + 0x4) ++#define REG_TRTCM_DATA_LOW(_n) ((_n) + 0x8) ++#define REG_TRTCM_DATA_HIGH(_n) ((_n) + 0xc) ++ + #define REG_TXWRR_MODE_CFG 0x1020 + #define TWRR_WEIGHT_SCALE_MASK BIT(31) + #define TWRR_WEIGHT_BASE_MASK BIT(3) +@@ -759,6 +775,29 @@ enum tx_sched_mode { + TC_SCH_WRR2, + }; + ++enum trtcm_param_type { ++ TRTCM_MISC_MODE, /* meter_en, pps_mode, tick_sel */ ++ TRTCM_TOKEN_RATE_MODE, ++ TRTCM_BUCKETSIZE_SHIFT_MODE, ++ TRTCM_BUCKET_COUNTER_MODE, ++}; ++ ++enum trtcm_mode_type { ++ TRTCM_COMMIT_MODE, ++ TRTCM_PEAK_MODE, ++}; ++ ++enum trtcm_param { ++ TRTCM_TICK_SEL = BIT(0), ++ TRTCM_PKT_MODE = BIT(1), ++ TRTCM_METER_MODE = BIT(2), ++}; ++ ++#define MIN_TOKEN_SIZE 4096 ++#define MAX_TOKEN_SIZE_OFFSET 17 ++#define TRTCM_TOKEN_RATE_MASK GENMASK(23, 6) ++#define TRTCM_TOKEN_RATE_FRACTION_MASK GENMASK(5, 0) ++ + struct airoha_queue_entry { + union { + void *buf; +@@ -850,6 +889,8 @@ struct airoha_gdm_port { + + struct airoha_hw_stats stats; + ++ DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); ++ + /* qos stats counters */ + u64 cpu_tx_packets; + u64 fwd_tx_packets; +@@ -2809,6 +2850,243 @@ static int airoha_tc_setup_qdisc_ets(str + } + } + ++static int airoha_qdma_get_trtcm_param(struct airoha_qdma *qdma, int channel, ++ u32 addr, enum trtcm_param_type param, ++ enum trtcm_mode_type mode, ++ u32 *val_low, u32 *val_high) ++{ ++ u32 idx = QDMA_METER_IDX(channel), group = QDMA_METER_GROUP(channel); ++ u32 val, config = FIELD_PREP(TRTCM_PARAM_TYPE_MASK, param) | ++ FIELD_PREP(TRTCM_METER_GROUP_MASK, group) | ++ FIELD_PREP(TRTCM_PARAM_INDEX_MASK, idx) | ++ FIELD_PREP(TRTCM_PARAM_RATE_TYPE_MASK, mode); ++ ++ airoha_qdma_wr(qdma, REG_TRTCM_CFG_PARAM(addr), config); ++ if (read_poll_timeout(airoha_qdma_rr, val, ++ val & TRTCM_PARAM_RW_DONE_MASK, ++ USEC_PER_MSEC, 10 * USEC_PER_MSEC, true, ++ qdma, REG_TRTCM_CFG_PARAM(addr))) ++ return -ETIMEDOUT; ++ ++ *val_low = airoha_qdma_rr(qdma, REG_TRTCM_DATA_LOW(addr)); ++ if (val_high) ++ *val_high = airoha_qdma_rr(qdma, REG_TRTCM_DATA_HIGH(addr)); ++ ++ return 0; ++} ++ ++static int airoha_qdma_set_trtcm_param(struct airoha_qdma *qdma, int channel, ++ u32 addr, enum trtcm_param_type param, ++ enum trtcm_mode_type mode, u32 val) ++{ ++ u32 idx = QDMA_METER_IDX(channel), group = QDMA_METER_GROUP(channel); ++ u32 config = TRTCM_PARAM_RW_MASK | ++ FIELD_PREP(TRTCM_PARAM_TYPE_MASK, param) | ++ FIELD_PREP(TRTCM_METER_GROUP_MASK, group) | ++ FIELD_PREP(TRTCM_PARAM_INDEX_MASK, idx) | ++ FIELD_PREP(TRTCM_PARAM_RATE_TYPE_MASK, mode); ++ ++ airoha_qdma_wr(qdma, REG_TRTCM_DATA_LOW(addr), val); ++ airoha_qdma_wr(qdma, REG_TRTCM_CFG_PARAM(addr), config); ++ ++ return read_poll_timeout(airoha_qdma_rr, val, ++ val & TRTCM_PARAM_RW_DONE_MASK, ++ USEC_PER_MSEC, 10 * USEC_PER_MSEC, true, ++ qdma, REG_TRTCM_CFG_PARAM(addr)); ++} ++ ++static int airoha_qdma_set_trtcm_config(struct airoha_qdma *qdma, int channel, ++ u32 addr, enum trtcm_mode_type mode, ++ bool enable, u32 enable_mask) ++{ ++ u32 val; ++ ++ if (airoha_qdma_get_trtcm_param(qdma, channel, addr, TRTCM_MISC_MODE, ++ mode, &val, NULL)) ++ return -EINVAL; ++ ++ val = enable ? val | enable_mask : val & ~enable_mask; ++ ++ return airoha_qdma_set_trtcm_param(qdma, channel, addr, TRTCM_MISC_MODE, ++ mode, val); ++} ++ ++static int airoha_qdma_set_trtcm_token_bucket(struct airoha_qdma *qdma, ++ int channel, u32 addr, ++ enum trtcm_mode_type mode, ++ u32 rate_val, u32 bucket_size) ++{ ++ u32 val, config, tick, unit, rate, rate_frac; ++ int err; ++ ++ if (airoha_qdma_get_trtcm_param(qdma, channel, addr, TRTCM_MISC_MODE, ++ mode, &config, NULL)) ++ return -EINVAL; ++ ++ val = airoha_qdma_rr(qdma, addr); ++ tick = FIELD_GET(INGRESS_FAST_TICK_MASK, val); ++ if (config & TRTCM_TICK_SEL) ++ tick *= FIELD_GET(INGRESS_SLOW_TICK_RATIO_MASK, val); ++ if (!tick) ++ return -EINVAL; ++ ++ unit = (config & TRTCM_PKT_MODE) ? 1000000 / tick : 8000 / tick; ++ if (!unit) ++ return -EINVAL; ++ ++ rate = rate_val / unit; ++ rate_frac = rate_val % unit; ++ rate_frac = FIELD_PREP(TRTCM_TOKEN_RATE_MASK, rate_frac) / unit; ++ rate = FIELD_PREP(TRTCM_TOKEN_RATE_MASK, rate) | ++ FIELD_PREP(TRTCM_TOKEN_RATE_FRACTION_MASK, rate_frac); ++ ++ err = airoha_qdma_set_trtcm_param(qdma, channel, addr, ++ TRTCM_TOKEN_RATE_MODE, mode, rate); ++ if (err) ++ return err; ++ ++ val = max_t(u32, bucket_size, MIN_TOKEN_SIZE); ++ val = min_t(u32, __fls(val), MAX_TOKEN_SIZE_OFFSET); ++ ++ return airoha_qdma_set_trtcm_param(qdma, channel, addr, ++ TRTCM_BUCKETSIZE_SHIFT_MODE, ++ mode, val); ++} ++ ++static int airoha_qdma_set_tx_rate_limit(struct airoha_gdm_port *port, ++ int channel, u32 rate, ++ u32 bucket_size) ++{ ++ int i, err; ++ ++ for (i = 0; i <= TRTCM_PEAK_MODE; i++) { ++ err = airoha_qdma_set_trtcm_config(port->qdma, channel, ++ REG_EGRESS_TRTCM_CFG, i, ++ !!rate, TRTCM_METER_MODE); ++ if (err) ++ return err; ++ ++ err = airoha_qdma_set_trtcm_token_bucket(port->qdma, channel, ++ REG_EGRESS_TRTCM_CFG, ++ i, rate, bucket_size); ++ if (err) ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int airoha_tc_htb_alloc_leaf_queue(struct airoha_gdm_port *port, ++ struct tc_htb_qopt_offload *opt) ++{ ++ u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; ++ u32 rate = div_u64(opt->rate, 1000) << 3; /* kbps */ ++ struct net_device *dev = port->dev; ++ int num_tx_queues = dev->real_num_tx_queues; ++ int err; ++ ++ if (opt->parent_classid != TC_HTB_CLASSID_ROOT) { ++ NL_SET_ERR_MSG_MOD(opt->extack, "invalid parent classid"); ++ return -EINVAL; ++ } ++ ++ err = airoha_qdma_set_tx_rate_limit(port, channel, rate, opt->quantum); ++ if (err) { ++ NL_SET_ERR_MSG_MOD(opt->extack, ++ "failed configuring htb offload"); ++ return err; ++ } ++ ++ if (opt->command == TC_HTB_NODE_MODIFY) ++ return 0; ++ ++ err = netif_set_real_num_tx_queues(dev, num_tx_queues + 1); ++ if (err) { ++ airoha_qdma_set_tx_rate_limit(port, channel, 0, opt->quantum); ++ NL_SET_ERR_MSG_MOD(opt->extack, ++ "failed setting real_num_tx_queues"); ++ return err; ++ } ++ ++ set_bit(channel, port->qos_sq_bmap); ++ opt->qid = AIROHA_NUM_TX_RING + channel; ++ ++ return 0; ++} ++ ++static void airoha_tc_remove_htb_queue(struct airoha_gdm_port *port, int queue) ++{ ++ struct net_device *dev = port->dev; ++ ++ netif_set_real_num_tx_queues(dev, dev->real_num_tx_queues - 1); ++ airoha_qdma_set_tx_rate_limit(port, queue + 1, 0, 0); ++ clear_bit(queue, port->qos_sq_bmap); ++} ++ ++static int airoha_tc_htb_delete_leaf_queue(struct airoha_gdm_port *port, ++ struct tc_htb_qopt_offload *opt) ++{ ++ u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; ++ ++ if (!test_bit(channel, port->qos_sq_bmap)) { ++ NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); ++ return -EINVAL; ++ } ++ ++ airoha_tc_remove_htb_queue(port, channel); ++ ++ return 0; ++} ++ ++static int airoha_tc_htb_destroy(struct airoha_gdm_port *port) ++{ ++ int q; ++ ++ for_each_set_bit(q, port->qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS) ++ airoha_tc_remove_htb_queue(port, q); ++ ++ return 0; ++} ++ ++static int airoha_tc_get_htb_get_leaf_queue(struct airoha_gdm_port *port, ++ struct tc_htb_qopt_offload *opt) ++{ ++ u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; ++ ++ if (!test_bit(channel, port->qos_sq_bmap)) { ++ NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); ++ return -EINVAL; ++ } ++ ++ opt->qid = channel; ++ ++ return 0; ++} ++ ++static int airoha_tc_setup_qdisc_htb(struct airoha_gdm_port *port, ++ struct tc_htb_qopt_offload *opt) ++{ ++ switch (opt->command) { ++ case TC_HTB_CREATE: ++ break; ++ case TC_HTB_DESTROY: ++ return airoha_tc_htb_destroy(port); ++ case TC_HTB_NODE_MODIFY: ++ case TC_HTB_LEAF_ALLOC_QUEUE: ++ return airoha_tc_htb_alloc_leaf_queue(port, opt); ++ case TC_HTB_LEAF_DEL: ++ case TC_HTB_LEAF_DEL_LAST: ++ case TC_HTB_LEAF_DEL_LAST_FORCE: ++ return airoha_tc_htb_delete_leaf_queue(port, opt); ++ case TC_HTB_LEAF_QUERY_QUEUE: ++ return airoha_tc_get_htb_get_leaf_queue(port, opt); ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ return 0; ++} ++ + static int airoha_dev_tc_setup(struct net_device *dev, enum tc_setup_type type, + void *type_data) + { +@@ -2817,6 +3095,8 @@ static int airoha_dev_tc_setup(struct ne + switch (type) { + case TC_SETUP_QDISC_ETS: + return airoha_tc_setup_qdisc_ets(port, type_data); ++ case TC_SETUP_QDISC_HTB: ++ return airoha_tc_setup_qdisc_htb(port, type_data); + default: + return -EOPNOTSUPP; + } +@@ -2867,7 +3147,8 @@ static int airoha_alloc_gdm_port(struct + } + + dev = devm_alloc_etherdev_mqs(eth->dev, sizeof(*port), +- AIROHA_NUM_TX_RING, AIROHA_NUM_RX_RING); ++ AIROHA_NUM_NETDEV_TX_RINGS, ++ AIROHA_NUM_RX_RING); + if (!dev) { + dev_err(eth->dev, "alloc_etherdev failed\n"); + return -ENOMEM; +@@ -2887,6 +3168,11 @@ static int airoha_alloc_gdm_port(struct + dev->irq = qdma->irq; + SET_NETDEV_DEV(dev, eth->dev); + ++ /* reserve hw queues for HTB offloading */ ++ err = netif_set_real_num_tx_queues(dev, AIROHA_NUM_TX_RING); ++ if (err) ++ return err; ++ + err = of_get_ethdev_address(np, dev); + if (err) { + if (err == -EPROBE_DEFER) diff --git a/lede/target/linux/airoha/patches-6.12/039-v6.14-cpufreq-airoha-Add-EN7581-CPUFreq-SMCCC-driver.patch b/lede/target/linux/airoha/patches-6.12/039-v6.14-cpufreq-airoha-Add-EN7581-CPUFreq-SMCCC-driver.patch new file mode 100644 index 0000000000..c4faaacbe0 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/039-v6.14-cpufreq-airoha-Add-EN7581-CPUFreq-SMCCC-driver.patch @@ -0,0 +1,232 @@ +From 84cf9e541cccb8cb698518a9897942e8c78f1d83 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 9 Jan 2025 14:12:58 +0100 +Subject: [PATCH] cpufreq: airoha: Add EN7581 CPUFreq SMCCC driver + +Add simple CPU Freq driver for Airoha EN7581 SoC that control CPU +frequency scaling with SMC APIs and register a generic "cpufreq-dt" +device. + +All CPU share the same frequency and can't be controlled independently. +CPU frequency is controlled by the attached PM domain. + +Add SoC compatible to cpufreq-dt-plat block list as a dedicated cpufreq +driver is needed with OPP v2 nodes declared in DTS. + +Signed-off-by: Christian Marangi +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/Kconfig.arm | 8 ++ + drivers/cpufreq/Makefile | 1 + + drivers/cpufreq/airoha-cpufreq.c | 152 +++++++++++++++++++++++++++ + drivers/cpufreq/cpufreq-dt-platdev.c | 2 + + 4 files changed, 163 insertions(+) + create mode 100644 drivers/cpufreq/airoha-cpufreq.c + +--- a/drivers/cpufreq/Kconfig.arm ++++ b/drivers/cpufreq/Kconfig.arm +@@ -15,6 +15,14 @@ config ARM_ALLWINNER_SUN50I_CPUFREQ_NVME + To compile this driver as a module, choose M here: the + module will be called sun50i-cpufreq-nvmem. + ++config ARM_AIROHA_SOC_CPUFREQ ++ tristate "Airoha EN7581 SoC CPUFreq support" ++ depends on ARCH_AIROHA || COMPILE_TEST ++ select PM_OPP ++ default ARCH_AIROHA ++ help ++ This adds the CPUFreq driver for Airoha EN7581 SoCs. ++ + config ARM_APPLE_SOC_CPUFREQ + tristate "Apple Silicon SoC CPUFreq support" + depends on ARCH_APPLE || (COMPILE_TEST && 64BIT) +--- a/drivers/cpufreq/Makefile ++++ b/drivers/cpufreq/Makefile +@@ -52,6 +52,7 @@ obj-$(CONFIG_X86_AMD_FREQ_SENSITIVITY) + + + ################################################################################## + # ARM SoC drivers ++obj-$(CONFIG_ARM_AIROHA_SOC_CPUFREQ) += airoha-cpufreq.o + obj-$(CONFIG_ARM_APPLE_SOC_CPUFREQ) += apple-soc-cpufreq.o + obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o + obj-$(CONFIG_ARM_ARMADA_8K_CPUFREQ) += armada-8k-cpufreq.o +--- /dev/null ++++ b/drivers/cpufreq/airoha-cpufreq.c +@@ -0,0 +1,166 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "cpufreq-dt.h" ++ ++struct airoha_cpufreq_priv { ++ int opp_token; ++ struct device **virt_devs; ++ struct platform_device *cpufreq_dt; ++}; ++ ++static struct platform_device *cpufreq_pdev; ++ ++/* NOP function to disable OPP from setting clock */ ++static int airoha_cpufreq_config_clks_nop(struct device *dev, ++ struct opp_table *opp_table, ++ struct dev_pm_opp *old_opp, ++ struct dev_pm_opp *opp, ++ void *data, bool scaling_down) ++{ ++ return 0; ++} ++ ++static const char * const airoha_cpufreq_clk_names[] = { "cpu", NULL }; ++static const char * const airoha_cpufreq_pd_names[] = { "perf", NULL }; ++ ++static int airoha_cpufreq_probe(struct platform_device *pdev) ++{ ++ struct dev_pm_opp_config config = { ++ .clk_names = airoha_cpufreq_clk_names, ++ .config_clks = airoha_cpufreq_config_clks_nop, ++ .genpd_names = airoha_cpufreq_pd_names, ++ }; ++ struct platform_device *cpufreq_dt; ++ struct airoha_cpufreq_priv *priv; ++ struct device *dev = &pdev->dev; ++ struct device **virt_devs = NULL; ++ struct device *cpu_dev; ++ int ret; ++ ++ /* CPUs refer to the same OPP table */ ++ cpu_dev = get_cpu_device(0); ++ if (!cpu_dev) ++ return -ENODEV; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ /* Set OPP table conf with NOP config_clks */ ++ priv->opp_token = dev_pm_opp_set_config(cpu_dev, &config); ++ if (priv->opp_token < 0) ++ return dev_err_probe(dev, priv->opp_token, "Failed to set OPP config\n"); ++ ++ /* Set Attached PM for OPP ACTIVE */ ++ if (virt_devs) { ++ const char * const *name = airoha_cpufreq_pd_names; ++ int i, j; ++ ++ for (i = 0; *name; i++, name++) { ++ ret = pm_runtime_resume_and_get(virt_devs[i]); ++ if (ret) { ++ dev_err(cpu_dev, "failed to resume %s: %d\n", ++ *name, ret); ++ ++ /* Rollback previous PM runtime calls */ ++ name = config.genpd_names; ++ for (j = 0; *name && j < i; j++, name++) ++ pm_runtime_put(virt_devs[j]); ++ ++ goto err_register_cpufreq; ++ } ++ } ++ priv->virt_devs = virt_devs; ++ } ++ ++ cpufreq_dt = platform_device_register_simple("cpufreq-dt", -1, NULL, 0); ++ ret = PTR_ERR_OR_ZERO(cpufreq_dt); ++ if (ret) { ++ dev_err(dev, "failed to create cpufreq-dt device: %d\n", ret); ++ goto err_register_cpufreq; ++ } ++ ++ priv->cpufreq_dt = cpufreq_dt; ++ platform_set_drvdata(pdev, priv); ++ ++ return 0; ++ ++err_register_cpufreq: ++ dev_pm_opp_clear_config(priv->opp_token); ++ ++ return ret; ++} ++ ++static void airoha_cpufreq_remove(struct platform_device *pdev) ++{ ++ struct airoha_cpufreq_priv *priv = platform_get_drvdata(pdev); ++ const char * const *name = airoha_cpufreq_pd_names; ++ int i; ++ ++ platform_device_unregister(priv->cpufreq_dt); ++ ++ dev_pm_opp_clear_config(priv->opp_token); ++ ++ for (i = 0; *name; i++, name++) ++ pm_runtime_put(priv->virt_devs[i]); ++} ++ ++static struct platform_driver airoha_cpufreq_driver = { ++ .probe = airoha_cpufreq_probe, ++ .remove_new = airoha_cpufreq_remove, ++ .driver = { ++ .name = "airoha-cpufreq", ++ }, ++}; ++ ++static const struct of_device_id airoha_cpufreq_match_list[] __initconst = { ++ { .compatible = "airoha,en7581" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, airoha_cpufreq_match_list); ++ ++static int __init airoha_cpufreq_init(void) ++{ ++ struct device_node *np = of_find_node_by_path("/"); ++ const struct of_device_id *match; ++ int ret; ++ ++ if (!np) ++ return -ENODEV; ++ ++ match = of_match_node(airoha_cpufreq_match_list, np); ++ of_node_put(np); ++ if (!match) ++ return -ENODEV; ++ ++ ret = platform_driver_register(&airoha_cpufreq_driver); ++ if (unlikely(ret < 0)) ++ return ret; ++ ++ cpufreq_pdev = platform_device_register_data(NULL, "airoha-cpufreq", ++ -1, match, sizeof(*match)); ++ ret = PTR_ERR_OR_ZERO(cpufreq_pdev); ++ if (ret) ++ platform_driver_unregister(&airoha_cpufreq_driver); ++ ++ return ret; ++} ++module_init(airoha_cpufreq_init); ++ ++static void __exit airoha_cpufreq_exit(void) ++{ ++ platform_device_unregister(cpufreq_pdev); ++ platform_driver_unregister(&airoha_cpufreq_driver); ++} ++module_exit(airoha_cpufreq_exit); ++ ++MODULE_AUTHOR("Christian Marangi "); ++MODULE_DESCRIPTION("CPUfreq driver for Airoha SoCs"); ++MODULE_LICENSE("GPL"); +--- a/drivers/cpufreq/cpufreq-dt-platdev.c ++++ b/drivers/cpufreq/cpufreq-dt-platdev.c +@@ -103,6 +103,8 @@ static const struct of_device_id allowli + * platforms using "operating-points-v2" property. + */ + static const struct of_device_id blocklist[] __initconst = { ++ { .compatible = "airoha,en7581", }, ++ + { .compatible = "allwinner,sun50i-h6", }, + { .compatible = "allwinner,sun50i-h616", }, + { .compatible = "allwinner,sun50i-h618", }, diff --git a/lede/target/linux/airoha/patches-6.12/039-v6.14-net-airoha-Enforce-ETS-Qdisc-priomap.patch b/lede/target/linux/airoha/patches-6.12/039-v6.14-net-airoha-Enforce-ETS-Qdisc-priomap.patch new file mode 100644 index 0000000000..151865b89c --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/039-v6.14-net-airoha-Enforce-ETS-Qdisc-priomap.patch @@ -0,0 +1,53 @@ +From b56e4d660a9688ff83f5cbdc6e3ea063352d0d79 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Sun, 12 Jan 2025 19:32:45 +0100 +Subject: [PATCH] net: airoha: Enforce ETS Qdisc priomap + +EN7581 SoC supports fixed QoS band priority where WRR queues have lowest +priorities with respect to SP ones. +E.g: WRR0, WRR1, .., WRRm, SP0, SP1, .., SPn + +Enforce ETS Qdisc priomap according to the hw capabilities. + +Suggested-by: Davide Caratti +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Davide Caratti +Link: https://patch.msgid.link/20250112-airoha_ets_priomap-v1-1-fb616de159ba@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/airoha_eth.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mediatek/airoha_eth.c ++++ b/drivers/net/ethernet/mediatek/airoha_eth.c +@@ -2785,7 +2785,7 @@ static int airoha_qdma_set_tx_ets_sched( + struct tc_ets_qopt_offload_replace_params *p = &opt->replace_params; + enum tx_sched_mode mode = TC_SCH_SP; + u16 w[AIROHA_NUM_QOS_QUEUES] = {}; +- int i, nstrict = 0; ++ int i, nstrict = 0, nwrr, qidx; + + if (p->bands > AIROHA_NUM_QOS_QUEUES) + return -EINVAL; +@@ -2799,7 +2799,20 @@ static int airoha_qdma_set_tx_ets_sched( + if (nstrict == AIROHA_NUM_QOS_QUEUES - 1) + return -EINVAL; + +- for (i = 0; i < p->bands - nstrict; i++) ++ /* EN7581 SoC supports fixed QoS band priority where WRR queues have ++ * lowest priorities with respect to SP ones. ++ * e.g: WRR0, WRR1, .., WRRm, SP0, SP1, .., SPn ++ */ ++ nwrr = p->bands - nstrict; ++ qidx = nstrict && nwrr ? nstrict : 0; ++ for (i = 1; i <= p->bands; i++) { ++ if (p->priomap[i % AIROHA_NUM_QOS_QUEUES] != qidx) ++ return -EINVAL; ++ ++ qidx = i == nwrr ? 0 : qidx + 1; ++ } ++ ++ for (i = 0; i < nwrr; i++) + w[i] = p->weights[nstrict + i]; + + if (!nstrict) diff --git a/lede/target/linux/airoha/patches-6.12/040-v6.14-pmdomain-airoha-Add-Airoha-CPU-PM-Domain-support.patch b/lede/target/linux/airoha/patches-6.12/040-v6.14-pmdomain-airoha-Add-Airoha-CPU-PM-Domain-support.patch new file mode 100644 index 0000000000..8dc8a3d304 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/040-v6.14-pmdomain-airoha-Add-Airoha-CPU-PM-Domain-support.patch @@ -0,0 +1,196 @@ +From 82e703dd438b71432cc0ccbb90925d1e32dd014a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 9 Jan 2025 14:12:57 +0100 +Subject: [PATCH] pmdomain: airoha: Add Airoha CPU PM Domain support + +Add Airoha CPU PM Domain support to control frequency and power of CPU +present on Airoha EN7581 SoC. + +Frequency and power can be controlled with the use of the SMC command by +passing the performance state. The driver also expose a read-only clock +that expose the current CPU frequency with SMC command. + +Signed-off-by: Christian Marangi +Link: https://lore.kernel.org/r/20250109131313.32317-1-ansuelsmth@gmail.com +Signed-off-by: Ulf Hansson +--- + drivers/pmdomain/mediatek/Kconfig | 12 ++ + drivers/pmdomain/mediatek/Makefile | 1 + + .../pmdomain/mediatek/airoha-cpu-pmdomain.c | 144 ++++++++++++++++++ + 3 files changed, 157 insertions(+) + create mode 100644 drivers/pmdomain/mediatek/airoha-cpu-pmdomain.c + +--- a/drivers/soc/mediatek/Kconfig ++++ b/drivers/soc/mediatek/Kconfig +@@ -2,6 +2,17 @@ + # + # MediaTek SoC drivers + # ++config AIROHA_CPU_PM_DOMAIN ++ tristate "Airoha CPU power domain" ++ default ARCH_AIROHA ++ depends on PM ++ select PM_GENERIC_DOMAINS ++ help ++ Say y here to enable CPU power domain support for Airoha SoC. ++ ++ CPU frequency and power is controlled by ATF with SMC command to ++ set performance states. ++ + menu "MediaTek SoC drivers" + depends on ARCH_MEDIATEK || COMPILE_TEST + +--- a/drivers/pmdomain/mediatek/Makefile ++++ b/drivers/pmdomain/mediatek/Makefile +@@ -1,3 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0-only + obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o + obj-$(CONFIG_MTK_SCPSYS_PM_DOMAINS) += mtk-pm-domains.o ++obj-$(CONFIG_AIROHA_CPU_PM_DOMAIN) += airoha-cpu-pmdomain.o +--- /dev/null ++++ b/drivers/pmdomain/mediatek/airoha-cpu-pmdomain.c +@@ -0,0 +1,144 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define AIROHA_SIP_AVS_HANDLE 0x82000301 ++#define AIROHA_AVS_OP_BASE 0xddddddd0 ++#define AIROHA_AVS_OP_MASK GENMASK(1, 0) ++#define AIROHA_AVS_OP_FREQ_DYN_ADJ (AIROHA_AVS_OP_BASE | \ ++ FIELD_PREP(AIROHA_AVS_OP_MASK, 0x1)) ++#define AIROHA_AVS_OP_GET_FREQ (AIROHA_AVS_OP_BASE | \ ++ FIELD_PREP(AIROHA_AVS_OP_MASK, 0x2)) ++ ++struct airoha_cpu_pmdomain_priv { ++ struct clk_hw hw; ++ struct generic_pm_domain pd; ++}; ++ ++static long airoha_cpu_pmdomain_clk_round(struct clk_hw *hw, unsigned long rate, ++ unsigned long *parent_rate) ++{ ++ return rate; ++} ++ ++static unsigned long airoha_cpu_pmdomain_clk_get(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct arm_smccc_res res; ++ ++ arm_smccc_1_1_invoke(AIROHA_SIP_AVS_HANDLE, AIROHA_AVS_OP_GET_FREQ, ++ 0, 0, 0, 0, 0, 0, &res); ++ ++ /* SMCCC returns freq in MHz */ ++ return (int)(res.a0 * 1000 * 1000); ++} ++ ++/* Airoha CPU clk SMCC is always enabled */ ++static int airoha_cpu_pmdomain_clk_is_enabled(struct clk_hw *hw) ++{ ++ return true; ++} ++ ++static const struct clk_ops airoha_cpu_pmdomain_clk_ops = { ++ .recalc_rate = airoha_cpu_pmdomain_clk_get, ++ .is_enabled = airoha_cpu_pmdomain_clk_is_enabled, ++ .round_rate = airoha_cpu_pmdomain_clk_round, ++}; ++ ++static int airoha_cpu_pmdomain_set_performance_state(struct generic_pm_domain *domain, ++ unsigned int state) ++{ ++ struct arm_smccc_res res; ++ ++ arm_smccc_1_1_invoke(AIROHA_SIP_AVS_HANDLE, AIROHA_AVS_OP_FREQ_DYN_ADJ, ++ 0, state, 0, 0, 0, 0, &res); ++ ++ /* SMC signal correct apply by unsetting BIT 0 */ ++ return res.a0 & BIT(0) ? -EINVAL : 0; ++} ++ ++static int airoha_cpu_pmdomain_probe(struct platform_device *pdev) ++{ ++ struct airoha_cpu_pmdomain_priv *priv; ++ struct device *dev = &pdev->dev; ++ const struct clk_init_data init = { ++ .name = "cpu", ++ .ops = &airoha_cpu_pmdomain_clk_ops, ++ /* Clock with no set_rate, can't cache */ ++ .flags = CLK_GET_RATE_NOCACHE, ++ }; ++ struct generic_pm_domain *pd; ++ int ret; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ /* Init and register a get-only clk for Cpufreq */ ++ priv->hw.init = &init; ++ ret = devm_clk_hw_register(dev, &priv->hw); ++ if (ret) ++ return ret; ++ ++ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, ++ &priv->hw); ++ if (ret) ++ return ret; ++ ++ /* Init and register a PD for CPU */ ++ pd = &priv->pd; ++ pd->name = "cpu_pd"; ++ pd->flags = GENPD_FLAG_ALWAYS_ON; ++ pd->set_performance_state = airoha_cpu_pmdomain_set_performance_state; ++ ++ ret = pm_genpd_init(pd, NULL, false); ++ if (ret) ++ return ret; ++ ++ ret = of_genpd_add_provider_simple(dev->of_node, pd); ++ if (ret) ++ goto err_add_provider; ++ ++ platform_set_drvdata(pdev, priv); ++ ++ return 0; ++ ++err_add_provider: ++ pm_genpd_remove(pd); ++ ++ return ret; ++} ++ ++static void airoha_cpu_pmdomain_remove(struct platform_device *pdev) ++{ ++ struct airoha_cpu_pmdomain_priv *priv = platform_get_drvdata(pdev); ++ ++ of_genpd_del_provider(pdev->dev.of_node); ++ pm_genpd_remove(&priv->pd); ++} ++ ++static const struct of_device_id airoha_cpu_pmdomain_of_match[] = { ++ { .compatible = "airoha,en7581-cpufreq" }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, airoha_cpu_pmdomain_of_match); ++ ++static struct platform_driver airoha_cpu_pmdomain_driver = { ++ .probe = airoha_cpu_pmdomain_probe, ++ .remove_new = airoha_cpu_pmdomain_remove, ++ .driver = { ++ .name = "airoha-cpu-pmdomain", ++ .of_match_table = airoha_cpu_pmdomain_of_match, ++ }, ++}; ++module_platform_driver(airoha_cpu_pmdomain_driver); ++ ++MODULE_AUTHOR("Christian Marangi "); ++MODULE_DESCRIPTION("CPU PM domain driver for Airoha SoCs"); ++MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/airoha/patches-6.12/041-01-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch b/lede/target/linux/airoha/patches-6.12/041-01-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch new file mode 100644 index 0000000000..96d2bbf28e --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/041-01-v6.14-clk-en7523-Rework-clock-handling-for-different-clock.patch @@ -0,0 +1,83 @@ +From e4a9748e7103c47e575459db2b6a77d14f34da2b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 14 Jan 2025 00:10:02 +0100 +Subject: [PATCH 1/4] clk: en7523: Rework clock handling for different clock + numbers + +Airoha EN7581 SoC have additional clock compared to EN7523 but current +driver permits to only support up to EN7523 clock numbers. + +To handle this, rework the clock handling and permit to declare the +clocks number in match_data and alloca clk_data based on the compatible +match_data. + +Signed-off-by: Christian Marangi +Link: https://lore.kernel.org/r/20250113231030.6735-2-ansuelsmth@gmail.com +Signed-off-by: Stephen Boyd +--- + drivers/clk/clk-en7523.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -75,6 +75,7 @@ struct en_rst_data { + }; + + struct en_clk_soc_data { ++ u32 num_clocks; + const struct clk_ops pcie_ops; + int (*hw_init)(struct platform_device *pdev, + struct clk_hw_onecell_data *clk_data); +@@ -504,8 +505,6 @@ static void en7523_register_clocks(struc + u32 rate; + int i; + +- clk_data->num = EN7523_NUM_CLOCKS; +- + for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) { + const struct en_clk_desc *desc = &en7523_base_clks[i]; + u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg; +@@ -587,8 +586,6 @@ static void en7581_register_clocks(struc + + hw = en7523_register_pcie_clk(dev, base); + clk_data->hws[EN7523_CLK_PCIE] = hw; +- +- clk_data->num = EN7523_NUM_CLOCKS; + } + + static int en7523_reset_update(struct reset_controller_dev *rcdev, +@@ -702,13 +699,15 @@ static int en7523_clk_probe(struct platf + struct clk_hw_onecell_data *clk_data; + int r; + ++ soc_data = device_get_match_data(&pdev->dev); ++ + clk_data = devm_kzalloc(&pdev->dev, +- struct_size(clk_data, hws, EN7523_NUM_CLOCKS), ++ struct_size(clk_data, hws, soc_data->num_clocks), + GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + +- soc_data = device_get_match_data(&pdev->dev); ++ clk_data->num = soc_data->num_clocks; + r = soc_data->hw_init(pdev, clk_data); + if (r) + return r; +@@ -717,6 +716,7 @@ static int en7523_clk_probe(struct platf + } + + static const struct en_clk_soc_data en7523_data = { ++ .num_clocks = ARRAY_SIZE(en7523_base_clks) + 1, + .pcie_ops = { + .is_enabled = en7523_pci_is_enabled, + .prepare = en7523_pci_prepare, +@@ -726,6 +726,8 @@ static const struct en_clk_soc_data en75 + }; + + static const struct en_clk_soc_data en7581_data = { ++ /* We increment num_clocks by 1 to account for additional PCIe clock */ ++ .num_clocks = ARRAY_SIZE(en7581_base_clks) + 1, + .pcie_ops = { + .is_enabled = en7581_pci_is_enabled, + .enable = en7581_pci_enable, diff --git a/lede/target/linux/airoha/patches-6.12/041-02-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch b/lede/target/linux/airoha/patches-6.12/041-02-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch new file mode 100644 index 0000000000..5db79a4748 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/041-02-v6.14-dt-bindings-clock-drop-NUM_CLOCKS-define-for-EN7581.patch @@ -0,0 +1,26 @@ +From 02d3b7557ce28c373ea1e925ae16ab5988284313 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 14 Jan 2025 00:10:03 +0100 +Subject: [PATCH 2/4] dt-bindings: clock: drop NUM_CLOCKS define for EN7581 + +Drop NUM_CLOCKS define for EN7581 include. This is not a binding and +should not be placed here. Value is derived internally in the user +driver. + +Signed-off-by: Christian Marangi +Acked-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20250113231030.6735-3-ansuelsmth@gmail.com +Signed-off-by: Stephen Boyd +--- + include/dt-bindings/clock/en7523-clk.h | 2 -- + 1 file changed, 2 deletions(-) + +--- a/include/dt-bindings/clock/en7523-clk.h ++++ b/include/dt-bindings/clock/en7523-clk.h +@@ -12,6 +12,4 @@ + #define EN7523_CLK_CRYPTO 6 + #define EN7523_CLK_PCIE 7 + +-#define EN7523_NUM_CLOCKS 8 +- + #endif /* _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ */ diff --git a/lede/target/linux/airoha/patches-6.12/041-03-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch b/lede/target/linux/airoha/patches-6.12/041-03-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch new file mode 100644 index 0000000000..a3f0c9e6fe --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/041-03-v6.14-dt-bindings-clock-add-ID-for-eMMC-for-EN7581.patch @@ -0,0 +1,25 @@ +From 82108ad3285f58f314ad41398f44017c7dbe44de Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 14 Jan 2025 00:10:04 +0100 +Subject: [PATCH 3/4] dt-bindings: clock: add ID for eMMC for EN7581 + +Add ID for eMMC for EN7581. This is to control clock selection of eMMC +between 200MHz and 150MHz. + +Signed-off-by: Christian Marangi +Acked-by: Conor Dooley +Link: https://lore.kernel.org/r/20250113231030.6735-4-ansuelsmth@gmail.com +Signed-off-by: Stephen Boyd +--- + include/dt-bindings/clock/en7523-clk.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/include/dt-bindings/clock/en7523-clk.h ++++ b/include/dt-bindings/clock/en7523-clk.h +@@ -12,4 +12,6 @@ + #define EN7523_CLK_CRYPTO 6 + #define EN7523_CLK_PCIE 7 + ++#define EN7581_CLK_EMMC 8 ++ + #endif /* _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ */ diff --git a/lede/target/linux/airoha/patches-6.12/041-04-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch b/lede/target/linux/airoha/patches-6.12/041-04-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch new file mode 100644 index 0000000000..6c8a3300be --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/041-04-v6.14-clk-en7523-Add-clock-for-eMMC-for-EN7581.patch @@ -0,0 +1,41 @@ +From bfe257f9780d8f77045a7da6ec959ee0659d2f98 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 14 Jan 2025 00:10:05 +0100 +Subject: [PATCH 4/4] clk: en7523: Add clock for eMMC for EN7581 + +Add clock for eMMC for EN7581. This is used to give info of the current +eMMC source clock and to switch it from 200MHz or 150MHz. + +Signed-off-by: Christian Marangi +Link: https://lore.kernel.org/r/20250113231030.6735-5-ansuelsmth@gmail.com +Signed-off-by: Stephen Boyd +--- + drivers/clk/clk-en7523.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -91,6 +91,7 @@ static const u32 emi7581_base[] = { 5400 + static const u32 bus7581_base[] = { 600000000, 540000000 }; + static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 }; + static const u32 crypto_base[] = { 540000000, 480000000 }; ++static const u32 emmc7581_base[] = { 200000000, 150000000 }; + + static const struct en_clk_desc en7523_base_clks[] = { + { +@@ -281,6 +282,15 @@ static const struct en_clk_desc en7581_b + .base_shift = 0, + .base_values = crypto_base, + .n_base_values = ARRAY_SIZE(crypto_base), ++ }, { ++ .id = EN7581_CLK_EMMC, ++ .name = "emmc", ++ ++ .base_reg = REG_CRYPTO_CLKSRC2, ++ .base_bits = 1, ++ .base_shift = 12, ++ .base_values = emmc7581_base, ++ .n_base_values = ARRAY_SIZE(emmc7581_base), + } + }; + diff --git a/lede/target/linux/airoha/patches-6.12/042-01-v6.14-PCI-mediatek-gen3-Rely-on-clk_bulk_prepare_enable-in.patch b/lede/target/linux/airoha/patches-6.12/042-01-v6.14-PCI-mediatek-gen3-Rely-on-clk_bulk_prepare_enable-in.patch new file mode 100644 index 0000000000..c77ae7bfca --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/042-01-v6.14-PCI-mediatek-gen3-Rely-on-clk_bulk_prepare_enable-in.patch @@ -0,0 +1,57 @@ +From 0e7a622da17da0042294860cdb7a2fac091d25b1 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 8 Jan 2025 10:50:40 +0100 +Subject: [PATCH 1/6] PCI: mediatek-gen3: Rely on clk_bulk_prepare_enable() in + mtk_pcie_en7581_power_up() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Replace clk_bulk_prepare() and clk_bulk_enable() with +clk_bulk_prepare_enable() in mtk_pcie_en7581_power_up() routine. + +Link: https://lore.kernel.org/r/20250108-pcie-en7581-fixes-v6-1-21ac939a3b9b@kernel.org +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Krzysztof Wilczyński +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Manivannan Sadhasivam +--- + drivers/pci/controller/pcie-mediatek-gen3.c | 14 +++----------- + 1 file changed, 3 insertions(+), 11 deletions(-) + +--- a/drivers/pci/controller/pcie-mediatek-gen3.c ++++ b/drivers/pci/controller/pcie-mediatek-gen3.c +@@ -900,12 +900,6 @@ static int mtk_pcie_en7581_power_up(stru + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); + +- err = clk_bulk_prepare(pcie->num_clks, pcie->clks); +- if (err) { +- dev_err(dev, "failed to prepare clock\n"); +- goto err_clk_prepare; +- } +- + val = FIELD_PREP(PCIE_VAL_LN0_DOWNSTREAM, 0x47) | + FIELD_PREP(PCIE_VAL_LN1_DOWNSTREAM, 0x47) | + FIELD_PREP(PCIE_VAL_LN0_UPSTREAM, 0x41) | +@@ -918,17 +912,15 @@ static int mtk_pcie_en7581_power_up(stru + FIELD_PREP(PCIE_K_FINETUNE_MAX, 0xf); + writel_relaxed(val, pcie->base + PCIE_PIPE4_PIE8_REG); + +- err = clk_bulk_enable(pcie->num_clks, pcie->clks); ++ err = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks); + if (err) { + dev_err(dev, "failed to prepare clock\n"); +- goto err_clk_enable; ++ goto err_clk_prepare_enable; + } + + return 0; + +-err_clk_enable: +- clk_bulk_unprepare(pcie->num_clks, pcie->clks); +-err_clk_prepare: ++err_clk_prepare_enable: + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets); diff --git a/lede/target/linux/airoha/patches-6.12/042-02-v6.14-PCI-mediatek-gen3-Move-reset-assert-callbacks-in-.po.patch b/lede/target/linux/airoha/patches-6.12/042-02-v6.14-PCI-mediatek-gen3-Move-reset-assert-callbacks-in-.po.patch new file mode 100644 index 0000000000..f56a2ce7eb --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/042-02-v6.14-PCI-mediatek-gen3-Move-reset-assert-callbacks-in-.po.patch @@ -0,0 +1,86 @@ +From e4c7dfd953f7618f0ccb70d87c1629634f306fab Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 8 Jan 2025 10:50:41 +0100 +Subject: [PATCH 2/6] PCI: mediatek-gen3: Move reset/assert callbacks in + .power_up() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In order to make the code more readable, the reset_control_bulk_assert() +function for PHY reset lines is moved to make it pair with +reset_control_bulk_deassert() in mtk_pcie_power_up() and +mtk_pcie_en7581_power_up(). The same change is done for +reset_control_assert() used to assert MAC reset line. + +Introduce PCIE_MTK_RESET_TIME_US macro for the time needed to +complete PCIe reset on MediaTek controller. + +Link: https://lore.kernel.org/r/20250108-pcie-en7581-fixes-v6-2-21ac939a3b9b@kernel.org +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Krzysztof Wilczyński +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Manivannan Sadhasivam +--- + drivers/pci/controller/pcie-mediatek-gen3.c | 28 +++++++++++++-------- + 1 file changed, 18 insertions(+), 10 deletions(-) + +--- a/drivers/pci/controller/pcie-mediatek-gen3.c ++++ b/drivers/pci/controller/pcie-mediatek-gen3.c +@@ -120,6 +120,8 @@ + + #define MAX_NUM_PHY_RESETS 3 + ++#define PCIE_MTK_RESET_TIME_US 10 ++ + /* Time in ms needed to complete PCIe reset on EN7581 SoC */ + #define PCIE_EN7581_RESET_TIME_MS 100 + +@@ -868,9 +870,14 @@ static int mtk_pcie_en7581_power_up(stru + u32 val; + + /* +- * Wait for the time needed to complete the bulk assert in +- * mtk_pcie_setup for EN7581 SoC. ++ * The controller may have been left out of reset by the bootloader ++ * so make sure that we get a clean start by asserting resets here. + */ ++ reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, ++ pcie->phy_resets); ++ reset_control_assert(pcie->mac_reset); ++ ++ /* Wait for the time needed to complete the reset lines assert. */ + mdelay(PCIE_EN7581_RESET_TIME_MS); + + err = phy_init(pcie->phy); +@@ -937,6 +944,15 @@ static int mtk_pcie_power_up(struct mtk_ + struct device *dev = pcie->dev; + int err; + ++ /* ++ * The controller may have been left out of reset by the bootloader ++ * so make sure that we get a clean start by asserting resets here. ++ */ ++ reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, ++ pcie->phy_resets); ++ reset_control_assert(pcie->mac_reset); ++ usleep_range(PCIE_MTK_RESET_TIME_US, 2 * PCIE_MTK_RESET_TIME_US); ++ + /* PHY power on and enable pipe clock */ + err = reset_control_bulk_deassert(pcie->soc->phy_resets.num_resets, pcie->phy_resets); + if (err) { +@@ -1009,14 +1025,6 @@ static int mtk_pcie_setup(struct mtk_gen + * counter since the bulk is shared. + */ + reset_control_bulk_deassert(pcie->soc->phy_resets.num_resets, pcie->phy_resets); +- /* +- * The controller may have been left out of reset by the bootloader +- * so make sure that we get a clean start by asserting resets here. +- */ +- reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets); +- +- reset_control_assert(pcie->mac_reset); +- usleep_range(10, 20); + + /* Don't touch the hardware registers before power up */ + err = pcie->soc->power_up(pcie); diff --git a/lede/target/linux/airoha/patches-6.12/042-03-v6.14-PCI-mediatek-gen3-Add-comment-about-initialization-o.patch b/lede/target/linux/airoha/patches-6.12/042-03-v6.14-PCI-mediatek-gen3-Add-comment-about-initialization-o.patch new file mode 100644 index 0000000000..056d773317 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/042-03-v6.14-PCI-mediatek-gen3-Add-comment-about-initialization-o.patch @@ -0,0 +1,35 @@ +From 0c9d2d2ef0d916b490a9222ed20ff4616fca876d Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 8 Jan 2025 10:50:42 +0100 +Subject: [PATCH 3/6] PCI: mediatek-gen3: Add comment about initialization + order in mtk_pcie_en7581_power_up() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add a comment in mtk_pcie_en7581_power_up() to clarify, unlike the other +MediaTek Gen3 controllers, the Airoha EN7581 requires PHY initialization +and power-on before PHY reset deassert. + +Link: https://lore.kernel.org/r/20250108-pcie-en7581-fixes-v6-3-21ac939a3b9b@kernel.org +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Krzysztof Wilczyński +Reviewed-by: Manivannan Sadhasivam +Reviewed-by: AngeloGioacchino Del Regno +--- + drivers/pci/controller/pcie-mediatek-gen3.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/pci/controller/pcie-mediatek-gen3.c ++++ b/drivers/pci/controller/pcie-mediatek-gen3.c +@@ -880,6 +880,10 @@ static int mtk_pcie_en7581_power_up(stru + /* Wait for the time needed to complete the reset lines assert. */ + mdelay(PCIE_EN7581_RESET_TIME_MS); + ++ /* ++ * Unlike the other MediaTek Gen3 controllers, the Airoha EN7581 ++ * requires PHY initialization and power-on before PHY reset deassert. ++ */ + err = phy_init(pcie->phy); + if (err) { + dev_err(dev, "failed to initialize PHY\n"); diff --git a/lede/target/linux/airoha/patches-6.12/042-04-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch b/lede/target/linux/airoha/patches-6.12/042-04-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch new file mode 100644 index 0000000000..845209d58d --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/042-04-v6.14-PCI-mediatek-gen3-Move-reset-delay-in-mtk_pcie_en758.patch @@ -0,0 +1,59 @@ +From 90d4e466c9ea2010f33880a36317a8486ccbe082 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 8 Jan 2025 10:50:43 +0100 +Subject: [PATCH 4/6] PCI: mediatek-gen3: Move reset delay in + mtk_pcie_en7581_power_up() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Airoha EN7581 has a hw bug asserting/releasing PCIE_PE_RSTB signal +causing occasional PCIe link down issues. In order to overcome the +problem, PCIe block is reset using REG_PCI_CONTROL (0x88) and +REG_RESET_CONTROL (0x834) registers available in the clock module +running clk_bulk_prepare_enable() in mtk_pcie_en7581_power_up(). + +In order to make the code more readable, move the wait for the time +needed to complete the PCIe reset from en7581_pci_enable() to +mtk_pcie_en7581_power_up(). + +Reduce reset timeout from 250ms to the standard PCIE_T_PVPERL_MS value +(100ms) since it has no impact on the driver behavior. + +Link: https://lore.kernel.org/r/20250108-pcie-en7581-fixes-v6-4-21ac939a3b9b@kernel.org +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Krzysztof Wilczyński +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Manivannan Sadhasivam +Acked-by: Stephen Boyd +--- + drivers/clk/clk-en7523.c | 1 - + drivers/pci/controller/pcie-mediatek-gen3.c | 7 +++++++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -489,7 +489,6 @@ static int en7581_pci_enable(struct clk_ + REG_PCI_CONTROL_PERSTOUT; + val = readl(np_base + REG_PCI_CONTROL); + writel(val | mask, np_base + REG_PCI_CONTROL); +- msleep(250); + + return 0; + } +--- a/drivers/pci/controller/pcie-mediatek-gen3.c ++++ b/drivers/pci/controller/pcie-mediatek-gen3.c +@@ -929,6 +929,13 @@ static int mtk_pcie_en7581_power_up(stru + goto err_clk_prepare_enable; + } + ++ /* ++ * Airoha EN7581 performs PCIe reset via clk callbacks since it has a ++ * hw issue with PCIE_PE_RSTB signal. Add wait for the time needed to ++ * complete the PCIe reset. ++ */ ++ msleep(PCIE_T_PVPERL_MS); ++ + return 0; + + err_clk_prepare_enable: diff --git a/lede/target/linux/airoha/patches-6.12/042-05-v6.14-PCI-mediatek-gen3-Rely-on-msleep-in-mtk_pcie_en7581_.patch b/lede/target/linux/airoha/patches-6.12/042-05-v6.14-PCI-mediatek-gen3-Rely-on-msleep-in-mtk_pcie_en7581_.patch new file mode 100644 index 0000000000..92a33a0afd --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/042-05-v6.14-PCI-mediatek-gen3-Rely-on-msleep-in-mtk_pcie_en7581_.patch @@ -0,0 +1,41 @@ +From c98bee18d0a094e37100c85effe5e161418f8644 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 8 Jan 2025 10:50:44 +0100 +Subject: [PATCH 5/6] PCI: mediatek-gen3: Rely on msleep() in + mtk_pcie_en7581_power_up() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since mtk_pcie_en7581_power_up() runs in non-atomic context, rely on +msleep() routine instead of mdelay(). + +Link: https://lore.kernel.org/r/20250108-pcie-en7581-fixes-v6-5-21ac939a3b9b@kernel.org +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Krzysztof Wilczyński +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Manivannan Sadhasivam +--- + drivers/pci/controller/pcie-mediatek-gen3.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/pci/controller/pcie-mediatek-gen3.c ++++ b/drivers/pci/controller/pcie-mediatek-gen3.c +@@ -878,7 +878,7 @@ static int mtk_pcie_en7581_power_up(stru + reset_control_assert(pcie->mac_reset); + + /* Wait for the time needed to complete the reset lines assert. */ +- mdelay(PCIE_EN7581_RESET_TIME_MS); ++ msleep(PCIE_EN7581_RESET_TIME_MS); + + /* + * Unlike the other MediaTek Gen3 controllers, the Airoha EN7581 +@@ -906,7 +906,7 @@ static int mtk_pcie_en7581_power_up(stru + * Wait for the time needed to complete the bulk de-assert above. + * This time is specific for EN7581 SoC. + */ +- mdelay(PCIE_EN7581_RESET_TIME_MS); ++ msleep(PCIE_EN7581_RESET_TIME_MS); + + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); diff --git a/lede/target/linux/airoha/patches-6.12/042-06-v6.14-PCI-mediatek-gen3-Avoid-PCIe-resetting-via-PERST-for.patch b/lede/target/linux/airoha/patches-6.12/042-06-v6.14-PCI-mediatek-gen3-Avoid-PCIe-resetting-via-PERST-for.patch new file mode 100644 index 0000000000..080d501698 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/042-06-v6.14-PCI-mediatek-gen3-Avoid-PCIe-resetting-via-PERST-for.patch @@ -0,0 +1,128 @@ +From 491cb9c5084790aafa02e843349492c284373231 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Thu, 9 Jan 2025 00:30:45 +0100 +Subject: [PATCH 6/6] PCI: mediatek-gen3: Avoid PCIe resetting via PERST# for + Airoha EN7581 SoC +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Airoha EN7581 has a hw bug asserting/releasing PERST# signal causing +occasional PCIe link down issues. In order to overcome the problem, +PERST# signal is not asserted/released during device probe or +suspend/resume phase and the PCIe block is reset using +en7523_reset_assert() and en7581_pci_enable(). + +Introduce flags field in the mtk_gen3_pcie_pdata struct in order to +specify per-SoC capabilities. + +Link: https://lore.kernel.org/r/20250109-pcie-en7581-rst-fix-v4-1-4a45c89fb143@kernel.org +Tested-by: Hui Ma +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Krzysztof Wilczyński +--- + drivers/pci/controller/pcie-mediatek-gen3.c | 59 ++++++++++++++------- + 1 file changed, 41 insertions(+), 18 deletions(-) + +--- a/drivers/pci/controller/pcie-mediatek-gen3.c ++++ b/drivers/pci/controller/pcie-mediatek-gen3.c +@@ -127,10 +127,18 @@ + + struct mtk_gen3_pcie; + ++enum mtk_gen3_pcie_flags { ++ SKIP_PCIE_RSTB = BIT(0), /* Skip PERST# assertion during device ++ * probing or suspend/resume phase to ++ * avoid hw bugs/issues. ++ */ ++}; ++ + /** + * struct mtk_gen3_pcie_pdata - differentiate between host generations + * @power_up: pcie power_up callback + * @phy_resets: phy reset lines SoC data. ++ * @flags: pcie device flags. + */ + struct mtk_gen3_pcie_pdata { + int (*power_up)(struct mtk_gen3_pcie *pcie); +@@ -138,6 +146,7 @@ struct mtk_gen3_pcie_pdata { + const char *id[MAX_NUM_PHY_RESETS]; + int num_resets; + } phy_resets; ++ u32 flags; + }; + + /** +@@ -404,22 +413,33 @@ static int mtk_pcie_startup_port(struct + val |= PCIE_DISABLE_DVFSRC_VLT_REQ; + writel_relaxed(val, pcie->base + PCIE_MISC_CTRL_REG); + +- /* Assert all reset signals */ +- val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG); +- val |= PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | PCIE_PE_RSTB; +- writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG); +- + /* +- * Described in PCIe CEM specification sections 2.2 (PERST# Signal) +- * and 2.2.1 (Initial Power-Up (G3 to S0)). +- * The deassertion of PERST# should be delayed 100ms (TPVPERL) +- * for the power and clock to become stable. ++ * Airoha EN7581 has a hw bug asserting/releasing PCIE_PE_RSTB signal ++ * causing occasional PCIe link down. In order to overcome the issue, ++ * PCIE_RSTB signals are not asserted/released at this stage and the ++ * PCIe block is reset using en7523_reset_assert() and ++ * en7581_pci_enable(). + */ +- msleep(100); +- +- /* De-assert reset signals */ +- val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | PCIE_PE_RSTB); +- writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG); ++ if (!(pcie->soc->flags & SKIP_PCIE_RSTB)) { ++ /* Assert all reset signals */ ++ val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG); ++ val |= PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | ++ PCIE_PE_RSTB; ++ writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG); ++ ++ /* ++ * Described in PCIe CEM specification revision 6.0. ++ * ++ * The deassertion of PERST# should be delayed 100ms (TPVPERL) ++ * for the power and clock to become stable. ++ */ ++ msleep(PCIE_T_PVPERL_MS); ++ ++ /* De-assert reset signals */ ++ val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | ++ PCIE_PE_RSTB); ++ writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG); ++ } + + /* Check if the link is up or not */ + err = readl_poll_timeout(pcie->base + PCIE_LINK_STATUS_REG, val, +@@ -1171,10 +1191,12 @@ static int mtk_pcie_suspend_noirq(struct + return err; + } + +- /* Pull down the PERST# pin */ +- val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG); +- val |= PCIE_PE_RSTB; +- writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG); ++ if (!(pcie->soc->flags & SKIP_PCIE_RSTB)) { ++ /* Assert the PERST# pin */ ++ val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG); ++ val |= PCIE_PE_RSTB; ++ writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG); ++ } + + dev_dbg(pcie->dev, "entered L2 states successfully"); + +@@ -1225,6 +1247,7 @@ static const struct mtk_gen3_pcie_pdata + .id[2] = "phy-lane2", + .num_resets = 3, + }, ++ .flags = SKIP_PCIE_RSTB, + }; + + static const struct of_device_id mtk_pcie_of_match[] = { diff --git a/lede/target/linux/airoha/patches-6.12/043-v6.15-PCI-mediatek-gen3-Remove-leftover-mac_reset-assert-f.patch b/lede/target/linux/airoha/patches-6.12/043-v6.15-PCI-mediatek-gen3-Remove-leftover-mac_reset-assert-f.patch new file mode 100644 index 0000000000..7d7ee4aae1 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/043-v6.15-PCI-mediatek-gen3-Remove-leftover-mac_reset-assert-f.patch @@ -0,0 +1,34 @@ +From b6d7bb0d3bd74b491e2e6fd59c4d5110d06fd63b Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Sat, 1 Feb 2025 12:00:18 +0100 +Subject: [PATCH] PCI: mediatek-gen3: Remove leftover mac_reset assert for + Airoha EN7581 SoC +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Remove a leftover assert for mac_reset line in mtk_pcie_en7581_power_up(). + +This is not harmful since EN7581 does not requires mac_reset and +mac_reset is not defined in EN7581 device tree. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Manivannan Sadhasivam +Reviewed-by: Philipp Zabel +Link: https://lore.kernel.org/r/20250201-pcie-en7581-remove-mac_reset-v2-1-a06786cdc683@kernel.org +[kwilczynski: commit log] +Signed-off-by: Krzysztof Wilczyński +--- + drivers/pci/controller/pcie-mediatek-gen3.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/pci/controller/pcie-mediatek-gen3.c ++++ b/drivers/pci/controller/pcie-mediatek-gen3.c +@@ -895,7 +895,6 @@ static int mtk_pcie_en7581_power_up(stru + */ + reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, + pcie->phy_resets); +- reset_control_assert(pcie->mac_reset); + + /* Wait for the time needed to complete the reset lines assert. */ + msleep(PCIE_EN7581_RESET_TIME_MS); diff --git a/lede/target/linux/airoha/patches-6.12/044-v6.15-PCI-mediatek-gen3-Configure-PBUS_CSR-registers-for-E.patch b/lede/target/linux/airoha/patches-6.12/044-v6.15-PCI-mediatek-gen3-Configure-PBUS_CSR-registers-for-E.patch new file mode 100644 index 0000000000..4415eac0ee --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/044-v6.15-PCI-mediatek-gen3-Configure-PBUS_CSR-registers-for-E.patch @@ -0,0 +1,81 @@ +From 249b78298078448a699c39356d27d8183af4b281 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 25 Feb 2025 09:04:07 +0100 +Subject: [PATCH] PCI: mediatek-gen3: Configure PBUS_CSR registers for EN7581 + SoC +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Configure PBus base address and address mask to allow the hw +to detect if a given address is accessible on PCIe controller. + +Fixes: f6ab898356dd ("PCI: mediatek-gen3: Add Airoha EN7581 support") +Reviewed-by: Manivannan Sadhasivam +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/20250225-en7581-pcie-pbus-csr-v4-2-24324382424a@kernel.org +Signed-off-by: Krzysztof Wilczyński +--- + drivers/pci/controller/pcie-mediatek-gen3.c | 28 ++++++++++++++++++++- + 1 file changed, 27 insertions(+), 1 deletion(-) + +--- a/drivers/pci/controller/pcie-mediatek-gen3.c ++++ b/drivers/pci/controller/pcie-mediatek-gen3.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -24,6 +25,7 @@ + #include + #include + #include ++#include + #include + + #include "../pci.h" +@@ -885,9 +887,13 @@ static int mtk_pcie_parse_port(struct mt + + static int mtk_pcie_en7581_power_up(struct mtk_gen3_pcie *pcie) + { ++ struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie); + struct device *dev = pcie->dev; ++ struct resource_entry *entry; ++ struct regmap *pbus_regmap; ++ u32 val, args[2], size; ++ resource_size_t addr; + int err; +- u32 val; + + /* + * The controller may have been left out of reset by the bootloader +@@ -900,6 +906,26 @@ static int mtk_pcie_en7581_power_up(stru + msleep(PCIE_EN7581_RESET_TIME_MS); + + /* ++ * Configure PBus base address and base address mask to allow the ++ * hw to detect if a given address is accessible on PCIe controller. ++ */ ++ pbus_regmap = syscon_regmap_lookup_by_phandle_args(dev->of_node, ++ "mediatek,pbus-csr", ++ ARRAY_SIZE(args), ++ args); ++ if (IS_ERR(pbus_regmap)) ++ return PTR_ERR(pbus_regmap); ++ ++ entry = resource_list_first_type(&host->windows, IORESOURCE_MEM); ++ if (!entry) ++ return -ENODEV; ++ ++ addr = entry->res->start - entry->offset; ++ regmap_write(pbus_regmap, args[0], lower_32_bits(addr)); ++ size = lower_32_bits(resource_size(entry->res)); ++ regmap_write(pbus_regmap, args[1], GENMASK(31, __fls(size))); ++ ++ /* + * Unlike the other MediaTek Gen3 controllers, the Airoha EN7581 + * requires PHY initialization and power-on before PHY reset deassert. + */ diff --git a/lede/target/linux/airoha/patches-6.12/046-v6.15-net-airoha-Fix-TSO-support-for-header-cloned-skbs.patch b/lede/target/linux/airoha/patches-6.12/046-v6.15-net-airoha-Fix-TSO-support-for-header-cloned-skbs.patch new file mode 100644 index 0000000000..376973b56b --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/046-v6.15-net-airoha-Fix-TSO-support-for-header-cloned-skbs.patch @@ -0,0 +1,60 @@ +From c6287e1a858e336cc202b484c6138a0fe252c6b3 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Thu, 13 Feb 2025 16:34:20 +0100 +Subject: [PATCH] net: airoha: Fix TSO support for header cloned skbs + +For GSO packets, skb_cow_head() will reallocate the skb for TSO header +cloned skbs in airoha_dev_xmit(). For this reason, sinfo pointer can be +no more valid. Fix the issue relying on skb_shinfo() macro directly in +airoha_dev_xmit(). + +The problem exists since +commit 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC") +but it is not a user visible, since we can't currently enable TSO +for DSA user ports since we are missing to initialize net_device +vlan_features field. + +Reviewed-by: Mateusz Polchlopek +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250213-airoha-en7581-flowtable-offload-v4-1-b69ca16d74db@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/mediatek/airoha_eth.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/mediatek/airoha_eth.c ++++ b/drivers/net/ethernet/mediatek/airoha_eth.c +@@ -2548,11 +2548,10 @@ static u16 airoha_dev_select_queue(struc + static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, + struct net_device *dev) + { +- struct skb_shared_info *sinfo = skb_shinfo(skb); + struct airoha_gdm_port *port = netdev_priv(dev); ++ u32 nr_frags = 1 + skb_shinfo(skb)->nr_frags; + u32 msg0, msg1, len = skb_headlen(skb); + struct airoha_qdma *qdma = port->qdma; +- u32 nr_frags = 1 + sinfo->nr_frags; + struct netdev_queue *txq; + struct airoha_queue *q; + void *data = skb->data; +@@ -2575,8 +2574,9 @@ static netdev_tx_t airoha_dev_xmit(struc + if (skb_cow_head(skb, 0)) + goto error; + +- if (sinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { +- __be16 csum = cpu_to_be16(sinfo->gso_size); ++ if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | ++ SKB_GSO_TCPV6)) { ++ __be16 csum = cpu_to_be16(skb_shinfo(skb)->gso_size); + + tcp_hdr(skb)->check = (__force __sum16)csum; + msg0 |= FIELD_PREP(QDMA_ETH_TXMSG_TSO_MASK, 1); +@@ -2605,7 +2605,7 @@ static netdev_tx_t airoha_dev_xmit(struc + for (i = 0; i < nr_frags; i++) { + struct airoha_qdma_desc *desc = &q->desc[index]; + struct airoha_queue_entry *e = &q->entry[index]; +- skb_frag_t *frag = &sinfo->frags[i]; ++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + dma_addr_t addr; + u32 val; + diff --git a/lede/target/linux/airoha/patches-6.12/047-v6.13-net-airoha-Reset-BQL-stopping-the-netdevice.patch b/lede/target/linux/airoha/patches-6.12/047-v6.13-net-airoha-Reset-BQL-stopping-the-netdevice.patch new file mode 100644 index 0000000000..228ca7a9fa --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/047-v6.13-net-airoha-Reset-BQL-stopping-the-netdevice.patch @@ -0,0 +1,42 @@ +From c9f947769b77c8e8f318bfc8a0777e5d20c44d8d Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Thu, 17 Oct 2024 16:01:41 +0200 +Subject: [PATCH] net: airoha: Reset BQL stopping the netdevice + +Run airoha_qdma_cleanup_tx_queue() in ndo_stop callback in order to +unmap pending skbs. Moreover, reset BQL txq state stopping the netdevice, + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Hariprasad Kelam +Message-ID: <20241017-airoha-en7581-reset-bql-v1-1-08c0c9888de5@kernel.org> +Signed-off-by: Andrew Lunn +--- + drivers/net/ethernet/mediatek/airoha_eth.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mediatek/airoha_eth.c ++++ b/drivers/net/ethernet/mediatek/airoha_eth.c +@@ -2468,7 +2468,7 @@ static int airoha_dev_stop(struct net_de + { + struct airoha_gdm_port *port = netdev_priv(dev); + struct airoha_qdma *qdma = port->qdma; +- int err; ++ int i, err; + + netif_tx_disable(dev); + err = airoha_set_gdm_ports(qdma->eth, false); +@@ -2479,6 +2479,14 @@ static int airoha_dev_stop(struct net_de + GLOBAL_CFG_TX_DMA_EN_MASK | + GLOBAL_CFG_RX_DMA_EN_MASK); + ++ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { ++ if (!qdma->q_tx[i].ndesc) ++ continue; ++ ++ airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]); ++ netdev_tx_reset_subqueue(dev, i); ++ } ++ + return 0; + } + diff --git a/lede/target/linux/airoha/patches-6.12/048-01-v6.15-net-airoha-Move-airoha_eth-driver-in-a-dedicated-fol.patch b/lede/target/linux/airoha/patches-6.12/048-01-v6.15-net-airoha-Move-airoha_eth-driver-in-a-dedicated-fol.patch new file mode 100644 index 0000000000..d2771e6361 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/048-01-v6.15-net-airoha-Move-airoha_eth-driver-in-a-dedicated-fol.patch @@ -0,0 +1,6823 @@ +From fb3dda82fd38ca42140f29b3082324dcdc128293 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 28 Feb 2025 11:54:09 +0100 +Subject: [PATCH 01/15] net: airoha: Move airoha_eth driver in a dedicated + folder + +The airoha_eth driver has no codebase shared with mtk_eth_soc one. +Moreover, the upcoming features (flowtable hw offloading, PCS, ..) will +not reuse any code from MediaTek driver. Move the Airoha driver in a +dedicated folder. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/Kconfig | 2 ++ + drivers/net/ethernet/Makefile | 1 + + drivers/net/ethernet/airoha/Kconfig | 18 ++++++++++++++++++ + drivers/net/ethernet/airoha/Makefile | 6 ++++++ + .../ethernet/{mediatek => airoha}/airoha_eth.c | 0 + drivers/net/ethernet/mediatek/Kconfig | 8 -------- + drivers/net/ethernet/mediatek/Makefile | 1 - + 7 files changed, 27 insertions(+), 9 deletions(-) + create mode 100644 drivers/net/ethernet/airoha/Kconfig + create mode 100644 drivers/net/ethernet/airoha/Makefile + rename drivers/net/ethernet/{mediatek => airoha}/airoha_eth.c (100%) + +--- a/drivers/net/ethernet/Kconfig ++++ b/drivers/net/ethernet/Kconfig +@@ -20,6 +20,8 @@ source "drivers/net/ethernet/actions/Kco + source "drivers/net/ethernet/adaptec/Kconfig" + source "drivers/net/ethernet/aeroflex/Kconfig" + source "drivers/net/ethernet/agere/Kconfig" ++source "drivers/net/ethernet/airoha/Kconfig" ++source "drivers/net/ethernet/mellanox/Kconfig" + source "drivers/net/ethernet/alacritech/Kconfig" + source "drivers/net/ethernet/allwinner/Kconfig" + source "drivers/net/ethernet/alteon/Kconfig" +--- a/drivers/net/ethernet/Makefile ++++ b/drivers/net/ethernet/Makefile +@@ -10,6 +10,7 @@ obj-$(CONFIG_NET_VENDOR_ADAPTEC) += adap + obj-$(CONFIG_GRETH) += aeroflex/ + obj-$(CONFIG_NET_VENDOR_ADI) += adi/ + obj-$(CONFIG_NET_VENDOR_AGERE) += agere/ ++obj-$(CONFIG_NET_VENDOR_AIROHA) += airoha/ + obj-$(CONFIG_NET_VENDOR_ALACRITECH) += alacritech/ + obj-$(CONFIG_NET_VENDOR_ALLWINNER) += allwinner/ + obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/ +--- /dev/null ++++ b/drivers/net/ethernet/airoha/Kconfig +@@ -0,0 +1,18 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++config NET_VENDOR_AIROHA ++ bool "Airoha devices" ++ depends on ARCH_AIROHA || COMPILE_TEST ++ help ++ If you have a Airoha SoC with ethernet, say Y. ++ ++if NET_VENDOR_AIROHA ++ ++config NET_AIROHA ++ tristate "Airoha SoC Gigabit Ethernet support" ++ depends on NET_DSA || !NET_DSA ++ select PAGE_POOL ++ help ++ This driver supports the gigabit ethernet MACs in the ++ Airoha SoC family. ++ ++endif #NET_VENDOR_AIROHA +--- /dev/null ++++ b/drivers/net/ethernet/airoha/Makefile +@@ -0,0 +1,6 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++# ++# Airoha for the Mediatek SoCs built-in ethernet macs ++# ++ ++obj-$(CONFIG_NET_AIROHA) += airoha_eth.o +--- a/drivers/net/ethernet/mediatek/Kconfig ++++ b/drivers/net/ethernet/mediatek/Kconfig +@@ -7,14 +7,6 @@ config NET_VENDOR_MEDIATEK + + if NET_VENDOR_MEDIATEK + +-config NET_AIROHA +- tristate "Airoha SoC Gigabit Ethernet support" +- depends on NET_DSA || !NET_DSA +- select PAGE_POOL +- help +- This driver supports the gigabit ethernet MACs in the +- Airoha SoC family. +- + config NET_MEDIATEK_SOC_WED + depends on ARCH_MEDIATEK || COMPILE_TEST + def_bool NET_MEDIATEK_SOC != n +--- a/drivers/net/ethernet/mediatek/Makefile ++++ b/drivers/net/ethernet/mediatek/Makefile +@@ -11,4 +11,3 @@ mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) + + endif + obj-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_ops.o + obj-$(CONFIG_NET_MEDIATEK_STAR_EMAC) += mtk_star_emac.o +-obj-$(CONFIG_NET_AIROHA) += airoha_eth.o +--- /dev/null ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -0,0 +1,3358 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2024 AIROHA Inc ++ * Author: Lorenzo Bianconi ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define AIROHA_MAX_NUM_GDM_PORTS 1 ++#define AIROHA_MAX_NUM_QDMA 2 ++#define AIROHA_MAX_NUM_RSTS 3 ++#define AIROHA_MAX_NUM_XSI_RSTS 5 ++#define AIROHA_MAX_MTU 2000 ++#define AIROHA_MAX_PACKET_SIZE 2048 ++#define AIROHA_NUM_QOS_CHANNELS 4 ++#define AIROHA_NUM_QOS_QUEUES 8 ++#define AIROHA_NUM_TX_RING 32 ++#define AIROHA_NUM_RX_RING 32 ++#define AIROHA_NUM_NETDEV_TX_RINGS (AIROHA_NUM_TX_RING + \ ++ AIROHA_NUM_QOS_CHANNELS) ++#define AIROHA_FE_MC_MAX_VLAN_TABLE 64 ++#define AIROHA_FE_MC_MAX_VLAN_PORT 16 ++#define AIROHA_NUM_TX_IRQ 2 ++#define HW_DSCP_NUM 2048 ++#define IRQ_QUEUE_LEN(_n) ((_n) ? 1024 : 2048) ++#define TX_DSCP_NUM 1024 ++#define RX_DSCP_NUM(_n) \ ++ ((_n) == 2 ? 128 : \ ++ (_n) == 11 ? 128 : \ ++ (_n) == 15 ? 128 : \ ++ (_n) == 0 ? 1024 : 16) ++ ++#define PSE_RSV_PAGES 128 ++#define PSE_QUEUE_RSV_PAGES 64 ++ ++#define QDMA_METER_IDX(_n) ((_n) & 0xff) ++#define QDMA_METER_GROUP(_n) (((_n) >> 8) & 0x3) ++ ++/* FE */ ++#define PSE_BASE 0x0100 ++#define CSR_IFC_BASE 0x0200 ++#define CDM1_BASE 0x0400 ++#define GDM1_BASE 0x0500 ++#define PPE1_BASE 0x0c00 ++ ++#define CDM2_BASE 0x1400 ++#define GDM2_BASE 0x1500 ++ ++#define GDM3_BASE 0x1100 ++#define GDM4_BASE 0x2500 ++ ++#define GDM_BASE(_n) \ ++ ((_n) == 4 ? GDM4_BASE : \ ++ (_n) == 3 ? GDM3_BASE : \ ++ (_n) == 2 ? GDM2_BASE : GDM1_BASE) ++ ++#define REG_FE_DMA_GLO_CFG 0x0000 ++#define FE_DMA_GLO_L2_SPACE_MASK GENMASK(7, 4) ++#define FE_DMA_GLO_PG_SZ_MASK BIT(3) ++ ++#define REG_FE_RST_GLO_CFG 0x0004 ++#define FE_RST_GDM4_MBI_ARB_MASK BIT(3) ++#define FE_RST_GDM3_MBI_ARB_MASK BIT(2) ++#define FE_RST_CORE_MASK BIT(0) ++ ++#define REG_FE_WAN_MAC_H 0x0030 ++#define REG_FE_LAN_MAC_H 0x0040 ++ ++#define REG_FE_MAC_LMIN(_n) ((_n) + 0x04) ++#define REG_FE_MAC_LMAX(_n) ((_n) + 0x08) ++ ++#define REG_FE_CDM1_OQ_MAP0 0x0050 ++#define REG_FE_CDM1_OQ_MAP1 0x0054 ++#define REG_FE_CDM1_OQ_MAP2 0x0058 ++#define REG_FE_CDM1_OQ_MAP3 0x005c ++ ++#define REG_FE_PCE_CFG 0x0070 ++#define PCE_DPI_EN_MASK BIT(2) ++#define PCE_KA_EN_MASK BIT(1) ++#define PCE_MC_EN_MASK BIT(0) ++ ++#define REG_FE_PSE_QUEUE_CFG_WR 0x0080 ++#define PSE_CFG_PORT_ID_MASK GENMASK(27, 24) ++#define PSE_CFG_QUEUE_ID_MASK GENMASK(20, 16) ++#define PSE_CFG_WR_EN_MASK BIT(8) ++#define PSE_CFG_OQRSV_SEL_MASK BIT(0) ++ ++#define REG_FE_PSE_QUEUE_CFG_VAL 0x0084 ++#define PSE_CFG_OQ_RSV_MASK GENMASK(13, 0) ++ ++#define PSE_FQ_CFG 0x008c ++#define PSE_FQ_LIMIT_MASK GENMASK(14, 0) ++ ++#define REG_FE_PSE_BUF_SET 0x0090 ++#define PSE_SHARE_USED_LTHD_MASK GENMASK(31, 16) ++#define PSE_ALLRSV_MASK GENMASK(14, 0) ++ ++#define REG_PSE_SHARE_USED_THD 0x0094 ++#define PSE_SHARE_USED_MTHD_MASK GENMASK(31, 16) ++#define PSE_SHARE_USED_HTHD_MASK GENMASK(15, 0) ++ ++#define REG_GDM_MISC_CFG 0x0148 ++#define GDM2_RDM_ACK_WAIT_PREF_MASK BIT(9) ++#define GDM2_CHN_VLD_MODE_MASK BIT(5) ++ ++#define REG_FE_CSR_IFC_CFG CSR_IFC_BASE ++#define FE_IFC_EN_MASK BIT(0) ++ ++#define REG_FE_VIP_PORT_EN 0x01f0 ++#define REG_FE_IFC_PORT_EN 0x01f4 ++ ++#define REG_PSE_IQ_REV1 (PSE_BASE + 0x08) ++#define PSE_IQ_RES1_P2_MASK GENMASK(23, 16) ++ ++#define REG_PSE_IQ_REV2 (PSE_BASE + 0x0c) ++#define PSE_IQ_RES2_P5_MASK GENMASK(15, 8) ++#define PSE_IQ_RES2_P4_MASK GENMASK(7, 0) ++ ++#define REG_FE_VIP_EN(_n) (0x0300 + ((_n) << 3)) ++#define PATN_FCPU_EN_MASK BIT(7) ++#define PATN_SWP_EN_MASK BIT(6) ++#define PATN_DP_EN_MASK BIT(5) ++#define PATN_SP_EN_MASK BIT(4) ++#define PATN_TYPE_MASK GENMASK(3, 1) ++#define PATN_EN_MASK BIT(0) ++ ++#define REG_FE_VIP_PATN(_n) (0x0304 + ((_n) << 3)) ++#define PATN_DP_MASK GENMASK(31, 16) ++#define PATN_SP_MASK GENMASK(15, 0) ++ ++#define REG_CDM1_VLAN_CTRL CDM1_BASE ++#define CDM1_VLAN_MASK GENMASK(31, 16) ++ ++#define REG_CDM1_FWD_CFG (CDM1_BASE + 0x08) ++#define CDM1_VIP_QSEL_MASK GENMASK(24, 20) ++ ++#define REG_CDM1_CRSN_QSEL(_n) (CDM1_BASE + 0x10 + ((_n) << 2)) ++#define CDM1_CRSN_QSEL_REASON_MASK(_n) \ ++ GENMASK(4 + (((_n) % 4) << 3), (((_n) % 4) << 3)) ++ ++#define REG_CDM2_FWD_CFG (CDM2_BASE + 0x08) ++#define CDM2_OAM_QSEL_MASK GENMASK(31, 27) ++#define CDM2_VIP_QSEL_MASK GENMASK(24, 20) ++ ++#define REG_CDM2_CRSN_QSEL(_n) (CDM2_BASE + 0x10 + ((_n) << 2)) ++#define CDM2_CRSN_QSEL_REASON_MASK(_n) \ ++ GENMASK(4 + (((_n) % 4) << 3), (((_n) % 4) << 3)) ++ ++#define REG_GDM_FWD_CFG(_n) GDM_BASE(_n) ++#define GDM_DROP_CRC_ERR BIT(23) ++#define GDM_IP4_CKSUM BIT(22) ++#define GDM_TCP_CKSUM BIT(21) ++#define GDM_UDP_CKSUM BIT(20) ++#define GDM_UCFQ_MASK GENMASK(15, 12) ++#define GDM_BCFQ_MASK GENMASK(11, 8) ++#define GDM_MCFQ_MASK GENMASK(7, 4) ++#define GDM_OCFQ_MASK GENMASK(3, 0) ++ ++#define REG_GDM_INGRESS_CFG(_n) (GDM_BASE(_n) + 0x10) ++#define GDM_INGRESS_FC_EN_MASK BIT(1) ++#define GDM_STAG_EN_MASK BIT(0) ++ ++#define REG_GDM_LEN_CFG(_n) (GDM_BASE(_n) + 0x14) ++#define GDM_SHORT_LEN_MASK GENMASK(13, 0) ++#define GDM_LONG_LEN_MASK GENMASK(29, 16) ++ ++#define REG_FE_CPORT_CFG (GDM1_BASE + 0x40) ++#define FE_CPORT_PAD BIT(26) ++#define FE_CPORT_PORT_XFC_MASK BIT(25) ++#define FE_CPORT_QUEUE_XFC_MASK BIT(24) ++ ++#define REG_FE_GDM_MIB_CLEAR(_n) (GDM_BASE(_n) + 0xf0) ++#define FE_GDM_MIB_RX_CLEAR_MASK BIT(1) ++#define FE_GDM_MIB_TX_CLEAR_MASK BIT(0) ++ ++#define REG_FE_GDM1_MIB_CFG (GDM1_BASE + 0xf4) ++#define FE_STRICT_RFC2819_MODE_MASK BIT(31) ++#define FE_GDM1_TX_MIB_SPLIT_EN_MASK BIT(17) ++#define FE_GDM1_RX_MIB_SPLIT_EN_MASK BIT(16) ++#define FE_TX_MIB_ID_MASK GENMASK(15, 8) ++#define FE_RX_MIB_ID_MASK GENMASK(7, 0) ++ ++#define REG_FE_GDM_TX_OK_PKT_CNT_L(_n) (GDM_BASE(_n) + 0x104) ++#define REG_FE_GDM_TX_OK_BYTE_CNT_L(_n) (GDM_BASE(_n) + 0x10c) ++#define REG_FE_GDM_TX_ETH_PKT_CNT_L(_n) (GDM_BASE(_n) + 0x110) ++#define REG_FE_GDM_TX_ETH_BYTE_CNT_L(_n) (GDM_BASE(_n) + 0x114) ++#define REG_FE_GDM_TX_ETH_DROP_CNT(_n) (GDM_BASE(_n) + 0x118) ++#define REG_FE_GDM_TX_ETH_BC_CNT(_n) (GDM_BASE(_n) + 0x11c) ++#define REG_FE_GDM_TX_ETH_MC_CNT(_n) (GDM_BASE(_n) + 0x120) ++#define REG_FE_GDM_TX_ETH_RUNT_CNT(_n) (GDM_BASE(_n) + 0x124) ++#define REG_FE_GDM_TX_ETH_LONG_CNT(_n) (GDM_BASE(_n) + 0x128) ++#define REG_FE_GDM_TX_ETH_E64_CNT_L(_n) (GDM_BASE(_n) + 0x12c) ++#define REG_FE_GDM_TX_ETH_L64_CNT_L(_n) (GDM_BASE(_n) + 0x130) ++#define REG_FE_GDM_TX_ETH_L127_CNT_L(_n) (GDM_BASE(_n) + 0x134) ++#define REG_FE_GDM_TX_ETH_L255_CNT_L(_n) (GDM_BASE(_n) + 0x138) ++#define REG_FE_GDM_TX_ETH_L511_CNT_L(_n) (GDM_BASE(_n) + 0x13c) ++#define REG_FE_GDM_TX_ETH_L1023_CNT_L(_n) (GDM_BASE(_n) + 0x140) ++ ++#define REG_FE_GDM_RX_OK_PKT_CNT_L(_n) (GDM_BASE(_n) + 0x148) ++#define REG_FE_GDM_RX_FC_DROP_CNT(_n) (GDM_BASE(_n) + 0x14c) ++#define REG_FE_GDM_RX_RC_DROP_CNT(_n) (GDM_BASE(_n) + 0x150) ++#define REG_FE_GDM_RX_OVERFLOW_DROP_CNT(_n) (GDM_BASE(_n) + 0x154) ++#define REG_FE_GDM_RX_ERROR_DROP_CNT(_n) (GDM_BASE(_n) + 0x158) ++#define REG_FE_GDM_RX_OK_BYTE_CNT_L(_n) (GDM_BASE(_n) + 0x15c) ++#define REG_FE_GDM_RX_ETH_PKT_CNT_L(_n) (GDM_BASE(_n) + 0x160) ++#define REG_FE_GDM_RX_ETH_BYTE_CNT_L(_n) (GDM_BASE(_n) + 0x164) ++#define REG_FE_GDM_RX_ETH_DROP_CNT(_n) (GDM_BASE(_n) + 0x168) ++#define REG_FE_GDM_RX_ETH_BC_CNT(_n) (GDM_BASE(_n) + 0x16c) ++#define REG_FE_GDM_RX_ETH_MC_CNT(_n) (GDM_BASE(_n) + 0x170) ++#define REG_FE_GDM_RX_ETH_CRC_ERR_CNT(_n) (GDM_BASE(_n) + 0x174) ++#define REG_FE_GDM_RX_ETH_FRAG_CNT(_n) (GDM_BASE(_n) + 0x178) ++#define REG_FE_GDM_RX_ETH_JABBER_CNT(_n) (GDM_BASE(_n) + 0x17c) ++#define REG_FE_GDM_RX_ETH_RUNT_CNT(_n) (GDM_BASE(_n) + 0x180) ++#define REG_FE_GDM_RX_ETH_LONG_CNT(_n) (GDM_BASE(_n) + 0x184) ++#define REG_FE_GDM_RX_ETH_E64_CNT_L(_n) (GDM_BASE(_n) + 0x188) ++#define REG_FE_GDM_RX_ETH_L64_CNT_L(_n) (GDM_BASE(_n) + 0x18c) ++#define REG_FE_GDM_RX_ETH_L127_CNT_L(_n) (GDM_BASE(_n) + 0x190) ++#define REG_FE_GDM_RX_ETH_L255_CNT_L(_n) (GDM_BASE(_n) + 0x194) ++#define REG_FE_GDM_RX_ETH_L511_CNT_L(_n) (GDM_BASE(_n) + 0x198) ++#define REG_FE_GDM_RX_ETH_L1023_CNT_L(_n) (GDM_BASE(_n) + 0x19c) ++ ++#define REG_PPE1_TB_HASH_CFG (PPE1_BASE + 0x250) ++#define PPE1_SRAM_TABLE_EN_MASK BIT(0) ++#define PPE1_SRAM_HASH1_EN_MASK BIT(8) ++#define PPE1_DRAM_TABLE_EN_MASK BIT(16) ++#define PPE1_DRAM_HASH1_EN_MASK BIT(24) ++ ++#define REG_FE_GDM_TX_OK_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x280) ++#define REG_FE_GDM_TX_OK_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x284) ++#define REG_FE_GDM_TX_ETH_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x288) ++#define REG_FE_GDM_TX_ETH_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x28c) ++ ++#define REG_FE_GDM_RX_OK_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x290) ++#define REG_FE_GDM_RX_OK_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x294) ++#define REG_FE_GDM_RX_ETH_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x298) ++#define REG_FE_GDM_RX_ETH_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x29c) ++#define REG_FE_GDM_TX_ETH_E64_CNT_H(_n) (GDM_BASE(_n) + 0x2b8) ++#define REG_FE_GDM_TX_ETH_L64_CNT_H(_n) (GDM_BASE(_n) + 0x2bc) ++#define REG_FE_GDM_TX_ETH_L127_CNT_H(_n) (GDM_BASE(_n) + 0x2c0) ++#define REG_FE_GDM_TX_ETH_L255_CNT_H(_n) (GDM_BASE(_n) + 0x2c4) ++#define REG_FE_GDM_TX_ETH_L511_CNT_H(_n) (GDM_BASE(_n) + 0x2c8) ++#define REG_FE_GDM_TX_ETH_L1023_CNT_H(_n) (GDM_BASE(_n) + 0x2cc) ++#define REG_FE_GDM_RX_ETH_E64_CNT_H(_n) (GDM_BASE(_n) + 0x2e8) ++#define REG_FE_GDM_RX_ETH_L64_CNT_H(_n) (GDM_BASE(_n) + 0x2ec) ++#define REG_FE_GDM_RX_ETH_L127_CNT_H(_n) (GDM_BASE(_n) + 0x2f0) ++#define REG_FE_GDM_RX_ETH_L255_CNT_H(_n) (GDM_BASE(_n) + 0x2f4) ++#define REG_FE_GDM_RX_ETH_L511_CNT_H(_n) (GDM_BASE(_n) + 0x2f8) ++#define REG_FE_GDM_RX_ETH_L1023_CNT_H(_n) (GDM_BASE(_n) + 0x2fc) ++ ++#define REG_GDM2_CHN_RLS (GDM2_BASE + 0x20) ++#define MBI_RX_AGE_SEL_MASK GENMASK(26, 25) ++#define MBI_TX_AGE_SEL_MASK GENMASK(18, 17) ++ ++#define REG_GDM3_FWD_CFG GDM3_BASE ++#define GDM3_PAD_EN_MASK BIT(28) ++ ++#define REG_GDM4_FWD_CFG GDM4_BASE ++#define GDM4_PAD_EN_MASK BIT(28) ++#define GDM4_SPORT_OFFSET0_MASK GENMASK(11, 8) ++ ++#define REG_GDM4_SRC_PORT_SET (GDM4_BASE + 0x23c) ++#define GDM4_SPORT_OFF2_MASK GENMASK(19, 16) ++#define GDM4_SPORT_OFF1_MASK GENMASK(15, 12) ++#define GDM4_SPORT_OFF0_MASK GENMASK(11, 8) ++ ++#define REG_IP_FRAG_FP 0x2010 ++#define IP_ASSEMBLE_PORT_MASK GENMASK(24, 21) ++#define IP_ASSEMBLE_NBQ_MASK GENMASK(20, 16) ++#define IP_FRAGMENT_PORT_MASK GENMASK(8, 5) ++#define IP_FRAGMENT_NBQ_MASK GENMASK(4, 0) ++ ++#define REG_MC_VLAN_EN 0x2100 ++#define MC_VLAN_EN_MASK BIT(0) ++ ++#define REG_MC_VLAN_CFG 0x2104 ++#define MC_VLAN_CFG_CMD_DONE_MASK BIT(31) ++#define MC_VLAN_CFG_TABLE_ID_MASK GENMASK(21, 16) ++#define MC_VLAN_CFG_PORT_ID_MASK GENMASK(11, 8) ++#define MC_VLAN_CFG_TABLE_SEL_MASK BIT(4) ++#define MC_VLAN_CFG_RW_MASK BIT(0) ++ ++#define REG_MC_VLAN_DATA 0x2108 ++ ++#define REG_CDM5_RX_OQ1_DROP_CNT 0x29d4 ++ ++/* QDMA */ ++#define REG_QDMA_GLOBAL_CFG 0x0004 ++#define GLOBAL_CFG_RX_2B_OFFSET_MASK BIT(31) ++#define GLOBAL_CFG_DMA_PREFERENCE_MASK GENMASK(30, 29) ++#define GLOBAL_CFG_CPU_TXR_RR_MASK BIT(28) ++#define GLOBAL_CFG_DSCP_BYTE_SWAP_MASK BIT(27) ++#define GLOBAL_CFG_PAYLOAD_BYTE_SWAP_MASK BIT(26) ++#define GLOBAL_CFG_MULTICAST_MODIFY_FP_MASK BIT(25) ++#define GLOBAL_CFG_OAM_MODIFY_MASK BIT(24) ++#define GLOBAL_CFG_RESET_MASK BIT(23) ++#define GLOBAL_CFG_RESET_DONE_MASK BIT(22) ++#define GLOBAL_CFG_MULTICAST_EN_MASK BIT(21) ++#define GLOBAL_CFG_IRQ1_EN_MASK BIT(20) ++#define GLOBAL_CFG_IRQ0_EN_MASK BIT(19) ++#define GLOBAL_CFG_LOOPCNT_EN_MASK BIT(18) ++#define GLOBAL_CFG_RD_BYPASS_WR_MASK BIT(17) ++#define GLOBAL_CFG_QDMA_LOOPBACK_MASK BIT(16) ++#define GLOBAL_CFG_LPBK_RXQ_SEL_MASK GENMASK(13, 8) ++#define GLOBAL_CFG_CHECK_DONE_MASK BIT(7) ++#define GLOBAL_CFG_TX_WB_DONE_MASK BIT(6) ++#define GLOBAL_CFG_MAX_ISSUE_NUM_MASK GENMASK(5, 4) ++#define GLOBAL_CFG_RX_DMA_BUSY_MASK BIT(3) ++#define GLOBAL_CFG_RX_DMA_EN_MASK BIT(2) ++#define GLOBAL_CFG_TX_DMA_BUSY_MASK BIT(1) ++#define GLOBAL_CFG_TX_DMA_EN_MASK BIT(0) ++ ++#define REG_FWD_DSCP_BASE 0x0010 ++#define REG_FWD_BUF_BASE 0x0014 ++ ++#define REG_HW_FWD_DSCP_CFG 0x0018 ++#define HW_FWD_DSCP_PAYLOAD_SIZE_MASK GENMASK(29, 28) ++#define HW_FWD_DSCP_SCATTER_LEN_MASK GENMASK(17, 16) ++#define HW_FWD_DSCP_MIN_SCATTER_LEN_MASK GENMASK(15, 0) ++ ++#define REG_INT_STATUS(_n) \ ++ (((_n) == 4) ? 0x0730 : \ ++ ((_n) == 3) ? 0x0724 : \ ++ ((_n) == 2) ? 0x0720 : \ ++ ((_n) == 1) ? 0x0024 : 0x0020) ++ ++#define REG_INT_ENABLE(_n) \ ++ (((_n) == 4) ? 0x0750 : \ ++ ((_n) == 3) ? 0x0744 : \ ++ ((_n) == 2) ? 0x0740 : \ ++ ((_n) == 1) ? 0x002c : 0x0028) ++ ++/* QDMA_CSR_INT_ENABLE1 */ ++#define RX15_COHERENT_INT_MASK BIT(31) ++#define RX14_COHERENT_INT_MASK BIT(30) ++#define RX13_COHERENT_INT_MASK BIT(29) ++#define RX12_COHERENT_INT_MASK BIT(28) ++#define RX11_COHERENT_INT_MASK BIT(27) ++#define RX10_COHERENT_INT_MASK BIT(26) ++#define RX9_COHERENT_INT_MASK BIT(25) ++#define RX8_COHERENT_INT_MASK BIT(24) ++#define RX7_COHERENT_INT_MASK BIT(23) ++#define RX6_COHERENT_INT_MASK BIT(22) ++#define RX5_COHERENT_INT_MASK BIT(21) ++#define RX4_COHERENT_INT_MASK BIT(20) ++#define RX3_COHERENT_INT_MASK BIT(19) ++#define RX2_COHERENT_INT_MASK BIT(18) ++#define RX1_COHERENT_INT_MASK BIT(17) ++#define RX0_COHERENT_INT_MASK BIT(16) ++#define TX7_COHERENT_INT_MASK BIT(15) ++#define TX6_COHERENT_INT_MASK BIT(14) ++#define TX5_COHERENT_INT_MASK BIT(13) ++#define TX4_COHERENT_INT_MASK BIT(12) ++#define TX3_COHERENT_INT_MASK BIT(11) ++#define TX2_COHERENT_INT_MASK BIT(10) ++#define TX1_COHERENT_INT_MASK BIT(9) ++#define TX0_COHERENT_INT_MASK BIT(8) ++#define CNT_OVER_FLOW_INT_MASK BIT(7) ++#define IRQ1_FULL_INT_MASK BIT(5) ++#define IRQ1_INT_MASK BIT(4) ++#define HWFWD_DSCP_LOW_INT_MASK BIT(3) ++#define HWFWD_DSCP_EMPTY_INT_MASK BIT(2) ++#define IRQ0_FULL_INT_MASK BIT(1) ++#define IRQ0_INT_MASK BIT(0) ++ ++#define TX_DONE_INT_MASK(_n) \ ++ ((_n) ? IRQ1_INT_MASK | IRQ1_FULL_INT_MASK \ ++ : IRQ0_INT_MASK | IRQ0_FULL_INT_MASK) ++ ++#define INT_TX_MASK \ ++ (IRQ1_INT_MASK | IRQ1_FULL_INT_MASK | \ ++ IRQ0_INT_MASK | IRQ0_FULL_INT_MASK) ++ ++#define INT_IDX0_MASK \ ++ (TX0_COHERENT_INT_MASK | TX1_COHERENT_INT_MASK | \ ++ TX2_COHERENT_INT_MASK | TX3_COHERENT_INT_MASK | \ ++ TX4_COHERENT_INT_MASK | TX5_COHERENT_INT_MASK | \ ++ TX6_COHERENT_INT_MASK | TX7_COHERENT_INT_MASK | \ ++ RX0_COHERENT_INT_MASK | RX1_COHERENT_INT_MASK | \ ++ RX2_COHERENT_INT_MASK | RX3_COHERENT_INT_MASK | \ ++ RX4_COHERENT_INT_MASK | RX7_COHERENT_INT_MASK | \ ++ RX8_COHERENT_INT_MASK | RX9_COHERENT_INT_MASK | \ ++ RX15_COHERENT_INT_MASK | INT_TX_MASK) ++ ++/* QDMA_CSR_INT_ENABLE2 */ ++#define RX15_NO_CPU_DSCP_INT_MASK BIT(31) ++#define RX14_NO_CPU_DSCP_INT_MASK BIT(30) ++#define RX13_NO_CPU_DSCP_INT_MASK BIT(29) ++#define RX12_NO_CPU_DSCP_INT_MASK BIT(28) ++#define RX11_NO_CPU_DSCP_INT_MASK BIT(27) ++#define RX10_NO_CPU_DSCP_INT_MASK BIT(26) ++#define RX9_NO_CPU_DSCP_INT_MASK BIT(25) ++#define RX8_NO_CPU_DSCP_INT_MASK BIT(24) ++#define RX7_NO_CPU_DSCP_INT_MASK BIT(23) ++#define RX6_NO_CPU_DSCP_INT_MASK BIT(22) ++#define RX5_NO_CPU_DSCP_INT_MASK BIT(21) ++#define RX4_NO_CPU_DSCP_INT_MASK BIT(20) ++#define RX3_NO_CPU_DSCP_INT_MASK BIT(19) ++#define RX2_NO_CPU_DSCP_INT_MASK BIT(18) ++#define RX1_NO_CPU_DSCP_INT_MASK BIT(17) ++#define RX0_NO_CPU_DSCP_INT_MASK BIT(16) ++#define RX15_DONE_INT_MASK BIT(15) ++#define RX14_DONE_INT_MASK BIT(14) ++#define RX13_DONE_INT_MASK BIT(13) ++#define RX12_DONE_INT_MASK BIT(12) ++#define RX11_DONE_INT_MASK BIT(11) ++#define RX10_DONE_INT_MASK BIT(10) ++#define RX9_DONE_INT_MASK BIT(9) ++#define RX8_DONE_INT_MASK BIT(8) ++#define RX7_DONE_INT_MASK BIT(7) ++#define RX6_DONE_INT_MASK BIT(6) ++#define RX5_DONE_INT_MASK BIT(5) ++#define RX4_DONE_INT_MASK BIT(4) ++#define RX3_DONE_INT_MASK BIT(3) ++#define RX2_DONE_INT_MASK BIT(2) ++#define RX1_DONE_INT_MASK BIT(1) ++#define RX0_DONE_INT_MASK BIT(0) ++ ++#define RX_DONE_INT_MASK \ ++ (RX0_DONE_INT_MASK | RX1_DONE_INT_MASK | \ ++ RX2_DONE_INT_MASK | RX3_DONE_INT_MASK | \ ++ RX4_DONE_INT_MASK | RX7_DONE_INT_MASK | \ ++ RX8_DONE_INT_MASK | RX9_DONE_INT_MASK | \ ++ RX15_DONE_INT_MASK) ++#define INT_IDX1_MASK \ ++ (RX_DONE_INT_MASK | \ ++ RX0_NO_CPU_DSCP_INT_MASK | RX1_NO_CPU_DSCP_INT_MASK | \ ++ RX2_NO_CPU_DSCP_INT_MASK | RX3_NO_CPU_DSCP_INT_MASK | \ ++ RX4_NO_CPU_DSCP_INT_MASK | RX7_NO_CPU_DSCP_INT_MASK | \ ++ RX8_NO_CPU_DSCP_INT_MASK | RX9_NO_CPU_DSCP_INT_MASK | \ ++ RX15_NO_CPU_DSCP_INT_MASK) ++ ++/* QDMA_CSR_INT_ENABLE5 */ ++#define TX31_COHERENT_INT_MASK BIT(31) ++#define TX30_COHERENT_INT_MASK BIT(30) ++#define TX29_COHERENT_INT_MASK BIT(29) ++#define TX28_COHERENT_INT_MASK BIT(28) ++#define TX27_COHERENT_INT_MASK BIT(27) ++#define TX26_COHERENT_INT_MASK BIT(26) ++#define TX25_COHERENT_INT_MASK BIT(25) ++#define TX24_COHERENT_INT_MASK BIT(24) ++#define TX23_COHERENT_INT_MASK BIT(23) ++#define TX22_COHERENT_INT_MASK BIT(22) ++#define TX21_COHERENT_INT_MASK BIT(21) ++#define TX20_COHERENT_INT_MASK BIT(20) ++#define TX19_COHERENT_INT_MASK BIT(19) ++#define TX18_COHERENT_INT_MASK BIT(18) ++#define TX17_COHERENT_INT_MASK BIT(17) ++#define TX16_COHERENT_INT_MASK BIT(16) ++#define TX15_COHERENT_INT_MASK BIT(15) ++#define TX14_COHERENT_INT_MASK BIT(14) ++#define TX13_COHERENT_INT_MASK BIT(13) ++#define TX12_COHERENT_INT_MASK BIT(12) ++#define TX11_COHERENT_INT_MASK BIT(11) ++#define TX10_COHERENT_INT_MASK BIT(10) ++#define TX9_COHERENT_INT_MASK BIT(9) ++#define TX8_COHERENT_INT_MASK BIT(8) ++ ++#define INT_IDX4_MASK \ ++ (TX8_COHERENT_INT_MASK | TX9_COHERENT_INT_MASK | \ ++ TX10_COHERENT_INT_MASK | TX11_COHERENT_INT_MASK | \ ++ TX12_COHERENT_INT_MASK | TX13_COHERENT_INT_MASK | \ ++ TX14_COHERENT_INT_MASK | TX15_COHERENT_INT_MASK | \ ++ TX16_COHERENT_INT_MASK | TX17_COHERENT_INT_MASK | \ ++ TX18_COHERENT_INT_MASK | TX19_COHERENT_INT_MASK | \ ++ TX20_COHERENT_INT_MASK | TX21_COHERENT_INT_MASK | \ ++ TX22_COHERENT_INT_MASK | TX23_COHERENT_INT_MASK | \ ++ TX24_COHERENT_INT_MASK | TX25_COHERENT_INT_MASK | \ ++ TX26_COHERENT_INT_MASK | TX27_COHERENT_INT_MASK | \ ++ TX28_COHERENT_INT_MASK | TX29_COHERENT_INT_MASK | \ ++ TX30_COHERENT_INT_MASK | TX31_COHERENT_INT_MASK) ++ ++#define REG_TX_IRQ_BASE(_n) ((_n) ? 0x0048 : 0x0050) ++ ++#define REG_TX_IRQ_CFG(_n) ((_n) ? 0x004c : 0x0054) ++#define TX_IRQ_THR_MASK GENMASK(27, 16) ++#define TX_IRQ_DEPTH_MASK GENMASK(11, 0) ++ ++#define REG_IRQ_CLEAR_LEN(_n) ((_n) ? 0x0064 : 0x0058) ++#define IRQ_CLEAR_LEN_MASK GENMASK(7, 0) ++ ++#define REG_IRQ_STATUS(_n) ((_n) ? 0x0068 : 0x005c) ++#define IRQ_ENTRY_LEN_MASK GENMASK(27, 16) ++#define IRQ_HEAD_IDX_MASK GENMASK(11, 0) ++ ++#define REG_TX_RING_BASE(_n) \ ++ (((_n) < 8) ? 0x0100 + ((_n) << 5) : 0x0b00 + (((_n) - 8) << 5)) ++ ++#define REG_TX_RING_BLOCKING(_n) \ ++ (((_n) < 8) ? 0x0104 + ((_n) << 5) : 0x0b04 + (((_n) - 8) << 5)) ++ ++#define TX_RING_IRQ_BLOCKING_MAP_MASK BIT(6) ++#define TX_RING_IRQ_BLOCKING_CFG_MASK BIT(4) ++#define TX_RING_IRQ_BLOCKING_TX_DROP_EN_MASK BIT(2) ++#define TX_RING_IRQ_BLOCKING_MAX_TH_TXRING_EN_MASK BIT(1) ++#define TX_RING_IRQ_BLOCKING_MIN_TH_TXRING_EN_MASK BIT(0) ++ ++#define REG_TX_CPU_IDX(_n) \ ++ (((_n) < 8) ? 0x0108 + ((_n) << 5) : 0x0b08 + (((_n) - 8) << 5)) ++ ++#define TX_RING_CPU_IDX_MASK GENMASK(15, 0) ++ ++#define REG_TX_DMA_IDX(_n) \ ++ (((_n) < 8) ? 0x010c + ((_n) << 5) : 0x0b0c + (((_n) - 8) << 5)) ++ ++#define TX_RING_DMA_IDX_MASK GENMASK(15, 0) ++ ++#define IRQ_RING_IDX_MASK GENMASK(20, 16) ++#define IRQ_DESC_IDX_MASK GENMASK(15, 0) ++ ++#define REG_RX_RING_BASE(_n) \ ++ (((_n) < 16) ? 0x0200 + ((_n) << 5) : 0x0e00 + (((_n) - 16) << 5)) ++ ++#define REG_RX_RING_SIZE(_n) \ ++ (((_n) < 16) ? 0x0204 + ((_n) << 5) : 0x0e04 + (((_n) - 16) << 5)) ++ ++#define RX_RING_THR_MASK GENMASK(31, 16) ++#define RX_RING_SIZE_MASK GENMASK(15, 0) ++ ++#define REG_RX_CPU_IDX(_n) \ ++ (((_n) < 16) ? 0x0208 + ((_n) << 5) : 0x0e08 + (((_n) - 16) << 5)) ++ ++#define RX_RING_CPU_IDX_MASK GENMASK(15, 0) ++ ++#define REG_RX_DMA_IDX(_n) \ ++ (((_n) < 16) ? 0x020c + ((_n) << 5) : 0x0e0c + (((_n) - 16) << 5)) ++ ++#define REG_RX_DELAY_INT_IDX(_n) \ ++ (((_n) < 16) ? 0x0210 + ((_n) << 5) : 0x0e10 + (((_n) - 16) << 5)) ++ ++#define RX_DELAY_INT_MASK GENMASK(15, 0) ++ ++#define RX_RING_DMA_IDX_MASK GENMASK(15, 0) ++ ++#define REG_INGRESS_TRTCM_CFG 0x0070 ++#define INGRESS_TRTCM_EN_MASK BIT(31) ++#define INGRESS_TRTCM_MODE_MASK BIT(30) ++#define INGRESS_SLOW_TICK_RATIO_MASK GENMASK(29, 16) ++#define INGRESS_FAST_TICK_MASK GENMASK(15, 0) ++ ++#define REG_QUEUE_CLOSE_CFG(_n) (0x00a0 + ((_n) & 0xfc)) ++#define TXQ_DISABLE_CHAN_QUEUE_MASK(_n, _m) BIT((_m) + (((_n) & 0x3) << 3)) ++ ++#define REG_TXQ_DIS_CFG_BASE(_n) ((_n) ? 0x20a0 : 0x00a0) ++#define REG_TXQ_DIS_CFG(_n, _m) (REG_TXQ_DIS_CFG_BASE((_n)) + (_m) << 2) ++ ++#define REG_CNTR_CFG(_n) (0x0400 + ((_n) << 3)) ++#define CNTR_EN_MASK BIT(31) ++#define CNTR_ALL_CHAN_EN_MASK BIT(30) ++#define CNTR_ALL_QUEUE_EN_MASK BIT(29) ++#define CNTR_ALL_DSCP_RING_EN_MASK BIT(28) ++#define CNTR_SRC_MASK GENMASK(27, 24) ++#define CNTR_DSCP_RING_MASK GENMASK(20, 16) ++#define CNTR_CHAN_MASK GENMASK(7, 3) ++#define CNTR_QUEUE_MASK GENMASK(2, 0) ++ ++#define REG_CNTR_VAL(_n) (0x0404 + ((_n) << 3)) ++ ++#define REG_LMGR_INIT_CFG 0x1000 ++#define LMGR_INIT_START BIT(31) ++#define LMGR_SRAM_MODE_MASK BIT(30) ++#define HW_FWD_PKTSIZE_OVERHEAD_MASK GENMASK(27, 20) ++#define HW_FWD_DESC_NUM_MASK GENMASK(16, 0) ++ ++#define REG_FWD_DSCP_LOW_THR 0x1004 ++#define FWD_DSCP_LOW_THR_MASK GENMASK(17, 0) ++ ++#define REG_EGRESS_RATE_METER_CFG 0x100c ++#define EGRESS_RATE_METER_EN_MASK BIT(31) ++#define EGRESS_RATE_METER_EQ_RATE_EN_MASK BIT(17) ++#define EGRESS_RATE_METER_WINDOW_SZ_MASK GENMASK(16, 12) ++#define EGRESS_RATE_METER_TIMESLICE_MASK GENMASK(10, 0) ++ ++#define REG_EGRESS_TRTCM_CFG 0x1010 ++#define EGRESS_TRTCM_EN_MASK BIT(31) ++#define EGRESS_TRTCM_MODE_MASK BIT(30) ++#define EGRESS_SLOW_TICK_RATIO_MASK GENMASK(29, 16) ++#define EGRESS_FAST_TICK_MASK GENMASK(15, 0) ++ ++#define TRTCM_PARAM_RW_MASK BIT(31) ++#define TRTCM_PARAM_RW_DONE_MASK BIT(30) ++#define TRTCM_PARAM_TYPE_MASK GENMASK(29, 28) ++#define TRTCM_METER_GROUP_MASK GENMASK(27, 26) ++#define TRTCM_PARAM_INDEX_MASK GENMASK(23, 17) ++#define TRTCM_PARAM_RATE_TYPE_MASK BIT(16) ++ ++#define REG_TRTCM_CFG_PARAM(_n) ((_n) + 0x4) ++#define REG_TRTCM_DATA_LOW(_n) ((_n) + 0x8) ++#define REG_TRTCM_DATA_HIGH(_n) ((_n) + 0xc) ++ ++#define REG_TXWRR_MODE_CFG 0x1020 ++#define TWRR_WEIGHT_SCALE_MASK BIT(31) ++#define TWRR_WEIGHT_BASE_MASK BIT(3) ++ ++#define REG_TXWRR_WEIGHT_CFG 0x1024 ++#define TWRR_RW_CMD_MASK BIT(31) ++#define TWRR_RW_CMD_DONE BIT(30) ++#define TWRR_CHAN_IDX_MASK GENMASK(23, 19) ++#define TWRR_QUEUE_IDX_MASK GENMASK(18, 16) ++#define TWRR_VALUE_MASK GENMASK(15, 0) ++ ++#define REG_PSE_BUF_USAGE_CFG 0x1028 ++#define PSE_BUF_ESTIMATE_EN_MASK BIT(29) ++ ++#define REG_CHAN_QOS_MODE(_n) (0x1040 + ((_n) << 2)) ++#define CHAN_QOS_MODE_MASK(_n) GENMASK(2 + ((_n) << 2), (_n) << 2) ++ ++#define REG_GLB_TRTCM_CFG 0x1080 ++#define GLB_TRTCM_EN_MASK BIT(31) ++#define GLB_TRTCM_MODE_MASK BIT(30) ++#define GLB_SLOW_TICK_RATIO_MASK GENMASK(29, 16) ++#define GLB_FAST_TICK_MASK GENMASK(15, 0) ++ ++#define REG_TXQ_CNGST_CFG 0x10a0 ++#define TXQ_CNGST_DROP_EN BIT(31) ++#define TXQ_CNGST_DEI_DROP_EN BIT(30) ++ ++#define REG_SLA_TRTCM_CFG 0x1150 ++#define SLA_TRTCM_EN_MASK BIT(31) ++#define SLA_TRTCM_MODE_MASK BIT(30) ++#define SLA_SLOW_TICK_RATIO_MASK GENMASK(29, 16) ++#define SLA_FAST_TICK_MASK GENMASK(15, 0) ++ ++/* CTRL */ ++#define QDMA_DESC_DONE_MASK BIT(31) ++#define QDMA_DESC_DROP_MASK BIT(30) /* tx: drop - rx: overflow */ ++#define QDMA_DESC_MORE_MASK BIT(29) /* more SG elements */ ++#define QDMA_DESC_DEI_MASK BIT(25) ++#define QDMA_DESC_NO_DROP_MASK BIT(24) ++#define QDMA_DESC_LEN_MASK GENMASK(15, 0) ++/* DATA */ ++#define QDMA_DESC_NEXT_ID_MASK GENMASK(15, 0) ++/* TX MSG0 */ ++#define QDMA_ETH_TXMSG_MIC_IDX_MASK BIT(30) ++#define QDMA_ETH_TXMSG_SP_TAG_MASK GENMASK(29, 14) ++#define QDMA_ETH_TXMSG_ICO_MASK BIT(13) ++#define QDMA_ETH_TXMSG_UCO_MASK BIT(12) ++#define QDMA_ETH_TXMSG_TCO_MASK BIT(11) ++#define QDMA_ETH_TXMSG_TSO_MASK BIT(10) ++#define QDMA_ETH_TXMSG_FAST_MASK BIT(9) ++#define QDMA_ETH_TXMSG_OAM_MASK BIT(8) ++#define QDMA_ETH_TXMSG_CHAN_MASK GENMASK(7, 3) ++#define QDMA_ETH_TXMSG_QUEUE_MASK GENMASK(2, 0) ++/* TX MSG1 */ ++#define QDMA_ETH_TXMSG_NO_DROP BIT(31) ++#define QDMA_ETH_TXMSG_METER_MASK GENMASK(30, 24) /* 0x7f no meters */ ++#define QDMA_ETH_TXMSG_FPORT_MASK GENMASK(23, 20) ++#define QDMA_ETH_TXMSG_NBOQ_MASK GENMASK(19, 15) ++#define QDMA_ETH_TXMSG_HWF_MASK BIT(14) ++#define QDMA_ETH_TXMSG_HOP_MASK BIT(13) ++#define QDMA_ETH_TXMSG_PTP_MASK BIT(12) ++#define QDMA_ETH_TXMSG_ACNT_G1_MASK GENMASK(10, 6) /* 0x1f do not count */ ++#define QDMA_ETH_TXMSG_ACNT_G0_MASK GENMASK(5, 0) /* 0x3f do not count */ ++ ++/* RX MSG1 */ ++#define QDMA_ETH_RXMSG_DEI_MASK BIT(31) ++#define QDMA_ETH_RXMSG_IP6_MASK BIT(30) ++#define QDMA_ETH_RXMSG_IP4_MASK BIT(29) ++#define QDMA_ETH_RXMSG_IP4F_MASK BIT(28) ++#define QDMA_ETH_RXMSG_L4_VALID_MASK BIT(27) ++#define QDMA_ETH_RXMSG_L4F_MASK BIT(26) ++#define QDMA_ETH_RXMSG_SPORT_MASK GENMASK(25, 21) ++#define QDMA_ETH_RXMSG_CRSN_MASK GENMASK(20, 16) ++#define QDMA_ETH_RXMSG_PPE_ENTRY_MASK GENMASK(15, 0) ++ ++struct airoha_qdma_desc { ++ __le32 rsv; ++ __le32 ctrl; ++ __le32 addr; ++ __le32 data; ++ __le32 msg0; ++ __le32 msg1; ++ __le32 msg2; ++ __le32 msg3; ++}; ++ ++/* CTRL0 */ ++#define QDMA_FWD_DESC_CTX_MASK BIT(31) ++#define QDMA_FWD_DESC_RING_MASK GENMASK(30, 28) ++#define QDMA_FWD_DESC_IDX_MASK GENMASK(27, 16) ++#define QDMA_FWD_DESC_LEN_MASK GENMASK(15, 0) ++/* CTRL1 */ ++#define QDMA_FWD_DESC_FIRST_IDX_MASK GENMASK(15, 0) ++/* CTRL2 */ ++#define QDMA_FWD_DESC_MORE_PKT_NUM_MASK GENMASK(2, 0) ++ ++struct airoha_qdma_fwd_desc { ++ __le32 addr; ++ __le32 ctrl0; ++ __le32 ctrl1; ++ __le32 ctrl2; ++ __le32 msg0; ++ __le32 msg1; ++ __le32 rsv0; ++ __le32 rsv1; ++}; ++ ++enum { ++ QDMA_INT_REG_IDX0, ++ QDMA_INT_REG_IDX1, ++ QDMA_INT_REG_IDX2, ++ QDMA_INT_REG_IDX3, ++ QDMA_INT_REG_IDX4, ++ QDMA_INT_REG_MAX ++}; ++ ++enum { ++ XSI_PCIE0_PORT, ++ XSI_PCIE1_PORT, ++ XSI_USB_PORT, ++ XSI_AE_PORT, ++ XSI_ETH_PORT, ++}; ++ ++enum { ++ XSI_PCIE0_VIP_PORT_MASK = BIT(22), ++ XSI_PCIE1_VIP_PORT_MASK = BIT(23), ++ XSI_USB_VIP_PORT_MASK = BIT(25), ++ XSI_ETH_VIP_PORT_MASK = BIT(24), ++}; ++ ++enum { ++ DEV_STATE_INITIALIZED, ++}; ++ ++enum { ++ CDM_CRSN_QSEL_Q1 = 1, ++ CDM_CRSN_QSEL_Q5 = 5, ++ CDM_CRSN_QSEL_Q6 = 6, ++ CDM_CRSN_QSEL_Q15 = 15, ++}; ++ ++enum { ++ CRSN_08 = 0x8, ++ CRSN_21 = 0x15, /* KA */ ++ CRSN_22 = 0x16, /* hit bind and force route to CPU */ ++ CRSN_24 = 0x18, ++ CRSN_25 = 0x19, ++}; ++ ++enum { ++ FE_PSE_PORT_CDM1, ++ FE_PSE_PORT_GDM1, ++ FE_PSE_PORT_GDM2, ++ FE_PSE_PORT_GDM3, ++ FE_PSE_PORT_PPE1, ++ FE_PSE_PORT_CDM2, ++ FE_PSE_PORT_CDM3, ++ FE_PSE_PORT_CDM4, ++ FE_PSE_PORT_PPE2, ++ FE_PSE_PORT_GDM4, ++ FE_PSE_PORT_CDM5, ++ FE_PSE_PORT_DROP = 0xf, ++}; ++ ++enum tx_sched_mode { ++ TC_SCH_WRR8, ++ TC_SCH_SP, ++ TC_SCH_WRR7, ++ TC_SCH_WRR6, ++ TC_SCH_WRR5, ++ TC_SCH_WRR4, ++ TC_SCH_WRR3, ++ TC_SCH_WRR2, ++}; ++ ++enum trtcm_param_type { ++ TRTCM_MISC_MODE, /* meter_en, pps_mode, tick_sel */ ++ TRTCM_TOKEN_RATE_MODE, ++ TRTCM_BUCKETSIZE_SHIFT_MODE, ++ TRTCM_BUCKET_COUNTER_MODE, ++}; ++ ++enum trtcm_mode_type { ++ TRTCM_COMMIT_MODE, ++ TRTCM_PEAK_MODE, ++}; ++ ++enum trtcm_param { ++ TRTCM_TICK_SEL = BIT(0), ++ TRTCM_PKT_MODE = BIT(1), ++ TRTCM_METER_MODE = BIT(2), ++}; ++ ++#define MIN_TOKEN_SIZE 4096 ++#define MAX_TOKEN_SIZE_OFFSET 17 ++#define TRTCM_TOKEN_RATE_MASK GENMASK(23, 6) ++#define TRTCM_TOKEN_RATE_FRACTION_MASK GENMASK(5, 0) ++ ++struct airoha_queue_entry { ++ union { ++ void *buf; ++ struct sk_buff *skb; ++ }; ++ dma_addr_t dma_addr; ++ u16 dma_len; ++}; ++ ++struct airoha_queue { ++ struct airoha_qdma *qdma; ++ ++ /* protect concurrent queue accesses */ ++ spinlock_t lock; ++ struct airoha_queue_entry *entry; ++ struct airoha_qdma_desc *desc; ++ u16 head; ++ u16 tail; ++ ++ int queued; ++ int ndesc; ++ int free_thr; ++ int buf_size; ++ ++ struct napi_struct napi; ++ struct page_pool *page_pool; ++}; ++ ++struct airoha_tx_irq_queue { ++ struct airoha_qdma *qdma; ++ ++ struct napi_struct napi; ++ ++ int size; ++ u32 *q; ++}; ++ ++struct airoha_hw_stats { ++ /* protect concurrent hw_stats accesses */ ++ spinlock_t lock; ++ struct u64_stats_sync syncp; ++ ++ /* get_stats64 */ ++ u64 rx_ok_pkts; ++ u64 tx_ok_pkts; ++ u64 rx_ok_bytes; ++ u64 tx_ok_bytes; ++ u64 rx_multicast; ++ u64 rx_errors; ++ u64 rx_drops; ++ u64 tx_drops; ++ u64 rx_crc_error; ++ u64 rx_over_errors; ++ /* ethtool stats */ ++ u64 tx_broadcast; ++ u64 tx_multicast; ++ u64 tx_len[7]; ++ u64 rx_broadcast; ++ u64 rx_fragment; ++ u64 rx_jabber; ++ u64 rx_len[7]; ++}; ++ ++struct airoha_qdma { ++ struct airoha_eth *eth; ++ void __iomem *regs; ++ ++ /* protect concurrent irqmask accesses */ ++ spinlock_t irq_lock; ++ u32 irqmask[QDMA_INT_REG_MAX]; ++ int irq; ++ ++ struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ]; ++ ++ struct airoha_queue q_tx[AIROHA_NUM_TX_RING]; ++ struct airoha_queue q_rx[AIROHA_NUM_RX_RING]; ++ ++ /* descriptor and packet buffers for qdma hw forward */ ++ struct { ++ void *desc; ++ void *q; ++ } hfwd; ++}; ++ ++struct airoha_gdm_port { ++ struct airoha_qdma *qdma; ++ struct net_device *dev; ++ int id; ++ ++ struct airoha_hw_stats stats; ++ ++ DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); ++ ++ /* qos stats counters */ ++ u64 cpu_tx_packets; ++ u64 fwd_tx_packets; ++}; ++ ++struct airoha_eth { ++ struct device *dev; ++ ++ unsigned long state; ++ void __iomem *fe_regs; ++ ++ struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS]; ++ struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS]; ++ ++ struct net_device *napi_dev; ++ ++ struct airoha_qdma qdma[AIROHA_MAX_NUM_QDMA]; ++ struct airoha_gdm_port *ports[AIROHA_MAX_NUM_GDM_PORTS]; ++}; ++ ++static u32 airoha_rr(void __iomem *base, u32 offset) ++{ ++ return readl(base + offset); ++} ++ ++static void airoha_wr(void __iomem *base, u32 offset, u32 val) ++{ ++ writel(val, base + offset); ++} ++ ++static u32 airoha_rmw(void __iomem *base, u32 offset, u32 mask, u32 val) ++{ ++ val |= (airoha_rr(base, offset) & ~mask); ++ airoha_wr(base, offset, val); ++ ++ return val; ++} ++ ++#define airoha_fe_rr(eth, offset) \ ++ airoha_rr((eth)->fe_regs, (offset)) ++#define airoha_fe_wr(eth, offset, val) \ ++ airoha_wr((eth)->fe_regs, (offset), (val)) ++#define airoha_fe_rmw(eth, offset, mask, val) \ ++ airoha_rmw((eth)->fe_regs, (offset), (mask), (val)) ++#define airoha_fe_set(eth, offset, val) \ ++ airoha_rmw((eth)->fe_regs, (offset), 0, (val)) ++#define airoha_fe_clear(eth, offset, val) \ ++ airoha_rmw((eth)->fe_regs, (offset), (val), 0) ++ ++#define airoha_qdma_rr(qdma, offset) \ ++ airoha_rr((qdma)->regs, (offset)) ++#define airoha_qdma_wr(qdma, offset, val) \ ++ airoha_wr((qdma)->regs, (offset), (val)) ++#define airoha_qdma_rmw(qdma, offset, mask, val) \ ++ airoha_rmw((qdma)->regs, (offset), (mask), (val)) ++#define airoha_qdma_set(qdma, offset, val) \ ++ airoha_rmw((qdma)->regs, (offset), 0, (val)) ++#define airoha_qdma_clear(qdma, offset, val) \ ++ airoha_rmw((qdma)->regs, (offset), (val), 0) ++ ++static void airoha_qdma_set_irqmask(struct airoha_qdma *qdma, int index, ++ u32 clear, u32 set) ++{ ++ unsigned long flags; ++ ++ if (WARN_ON_ONCE(index >= ARRAY_SIZE(qdma->irqmask))) ++ return; ++ ++ spin_lock_irqsave(&qdma->irq_lock, flags); ++ ++ qdma->irqmask[index] &= ~clear; ++ qdma->irqmask[index] |= set; ++ airoha_qdma_wr(qdma, REG_INT_ENABLE(index), qdma->irqmask[index]); ++ /* Read irq_enable register in order to guarantee the update above ++ * completes in the spinlock critical section. ++ */ ++ airoha_qdma_rr(qdma, REG_INT_ENABLE(index)); ++ ++ spin_unlock_irqrestore(&qdma->irq_lock, flags); ++} ++ ++static void airoha_qdma_irq_enable(struct airoha_qdma *qdma, int index, ++ u32 mask) ++{ ++ airoha_qdma_set_irqmask(qdma, index, 0, mask); ++} ++ ++static void airoha_qdma_irq_disable(struct airoha_qdma *qdma, int index, ++ u32 mask) ++{ ++ airoha_qdma_set_irqmask(qdma, index, mask, 0); ++} ++ ++static bool airhoa_is_lan_gdm_port(struct airoha_gdm_port *port) ++{ ++ /* GDM1 port on EN7581 SoC is connected to the lan dsa switch. ++ * GDM{2,3,4} can be used as wan port connected to an external ++ * phy module. ++ */ ++ return port->id == 1; ++} ++ ++static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr) ++{ ++ struct airoha_eth *eth = port->qdma->eth; ++ u32 val, reg; ++ ++ reg = airhoa_is_lan_gdm_port(port) ? REG_FE_LAN_MAC_H ++ : REG_FE_WAN_MAC_H; ++ val = (addr[0] << 16) | (addr[1] << 8) | addr[2]; ++ airoha_fe_wr(eth, reg, val); ++ ++ val = (addr[3] << 16) | (addr[4] << 8) | addr[5]; ++ airoha_fe_wr(eth, REG_FE_MAC_LMIN(reg), val); ++ airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), val); ++} ++ ++static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr, ++ u32 val) ++{ ++ airoha_fe_rmw(eth, addr, GDM_OCFQ_MASK, ++ FIELD_PREP(GDM_OCFQ_MASK, val)); ++ airoha_fe_rmw(eth, addr, GDM_MCFQ_MASK, ++ FIELD_PREP(GDM_MCFQ_MASK, val)); ++ airoha_fe_rmw(eth, addr, GDM_BCFQ_MASK, ++ FIELD_PREP(GDM_BCFQ_MASK, val)); ++ airoha_fe_rmw(eth, addr, GDM_UCFQ_MASK, ++ FIELD_PREP(GDM_UCFQ_MASK, val)); ++} ++ ++static int airoha_set_gdm_port(struct airoha_eth *eth, int port, bool enable) ++{ ++ u32 val = enable ? FE_PSE_PORT_PPE1 : FE_PSE_PORT_DROP; ++ u32 vip_port, cfg_addr; ++ ++ switch (port) { ++ case XSI_PCIE0_PORT: ++ vip_port = XSI_PCIE0_VIP_PORT_MASK; ++ cfg_addr = REG_GDM_FWD_CFG(3); ++ break; ++ case XSI_PCIE1_PORT: ++ vip_port = XSI_PCIE1_VIP_PORT_MASK; ++ cfg_addr = REG_GDM_FWD_CFG(3); ++ break; ++ case XSI_USB_PORT: ++ vip_port = XSI_USB_VIP_PORT_MASK; ++ cfg_addr = REG_GDM_FWD_CFG(4); ++ break; ++ case XSI_ETH_PORT: ++ vip_port = XSI_ETH_VIP_PORT_MASK; ++ cfg_addr = REG_GDM_FWD_CFG(4); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (enable) { ++ airoha_fe_set(eth, REG_FE_VIP_PORT_EN, vip_port); ++ airoha_fe_set(eth, REG_FE_IFC_PORT_EN, vip_port); ++ } else { ++ airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, vip_port); ++ airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, vip_port); ++ } ++ ++ airoha_set_gdm_port_fwd_cfg(eth, cfg_addr, val); ++ ++ return 0; ++} ++ ++static int airoha_set_gdm_ports(struct airoha_eth *eth, bool enable) ++{ ++ const int port_list[] = { ++ XSI_PCIE0_PORT, ++ XSI_PCIE1_PORT, ++ XSI_USB_PORT, ++ XSI_ETH_PORT ++ }; ++ int i, err; ++ ++ for (i = 0; i < ARRAY_SIZE(port_list); i++) { ++ err = airoha_set_gdm_port(eth, port_list[i], enable); ++ if (err) ++ goto error; ++ } ++ ++ return 0; ++ ++error: ++ for (i--; i >= 0; i--) ++ airoha_set_gdm_port(eth, port_list[i], false); ++ ++ return err; ++} ++ ++static void airoha_fe_maccr_init(struct airoha_eth *eth) ++{ ++ int p; ++ ++ for (p = 1; p <= ARRAY_SIZE(eth->ports); p++) { ++ airoha_fe_set(eth, REG_GDM_FWD_CFG(p), ++ GDM_TCP_CKSUM | GDM_UDP_CKSUM | GDM_IP4_CKSUM | ++ GDM_DROP_CRC_ERR); ++ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(p), ++ FE_PSE_PORT_CDM1); ++ airoha_fe_rmw(eth, REG_GDM_LEN_CFG(p), ++ GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, ++ FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | ++ FIELD_PREP(GDM_LONG_LEN_MASK, 4004)); ++ } ++ ++ airoha_fe_rmw(eth, REG_CDM1_VLAN_CTRL, CDM1_VLAN_MASK, ++ FIELD_PREP(CDM1_VLAN_MASK, 0x8100)); ++ ++ airoha_fe_set(eth, REG_FE_CPORT_CFG, FE_CPORT_PAD); ++} ++ ++static void airoha_fe_vip_setup(struct airoha_eth *eth) ++{ ++ airoha_fe_wr(eth, REG_FE_VIP_PATN(3), ETH_P_PPP_DISC); ++ airoha_fe_wr(eth, REG_FE_VIP_EN(3), PATN_FCPU_EN_MASK | PATN_EN_MASK); ++ ++ airoha_fe_wr(eth, REG_FE_VIP_PATN(4), PPP_LCP); ++ airoha_fe_wr(eth, REG_FE_VIP_EN(4), ++ PATN_FCPU_EN_MASK | FIELD_PREP(PATN_TYPE_MASK, 1) | ++ PATN_EN_MASK); ++ ++ airoha_fe_wr(eth, REG_FE_VIP_PATN(6), PPP_IPCP); ++ airoha_fe_wr(eth, REG_FE_VIP_EN(6), ++ PATN_FCPU_EN_MASK | FIELD_PREP(PATN_TYPE_MASK, 1) | ++ PATN_EN_MASK); ++ ++ airoha_fe_wr(eth, REG_FE_VIP_PATN(7), PPP_CHAP); ++ airoha_fe_wr(eth, REG_FE_VIP_EN(7), ++ PATN_FCPU_EN_MASK | FIELD_PREP(PATN_TYPE_MASK, 1) | ++ PATN_EN_MASK); ++ ++ /* BOOTP (0x43) */ ++ airoha_fe_wr(eth, REG_FE_VIP_PATN(8), 0x43); ++ airoha_fe_wr(eth, REG_FE_VIP_EN(8), ++ PATN_FCPU_EN_MASK | PATN_SP_EN_MASK | ++ FIELD_PREP(PATN_TYPE_MASK, 4) | PATN_EN_MASK); ++ ++ /* BOOTP (0x44) */ ++ airoha_fe_wr(eth, REG_FE_VIP_PATN(9), 0x44); ++ airoha_fe_wr(eth, REG_FE_VIP_EN(9), ++ PATN_FCPU_EN_MASK | PATN_SP_EN_MASK | ++ FIELD_PREP(PATN_TYPE_MASK, 4) | PATN_EN_MASK); ++ ++ /* ISAKMP */ ++ airoha_fe_wr(eth, REG_FE_VIP_PATN(10), 0x1f401f4); ++ airoha_fe_wr(eth, REG_FE_VIP_EN(10), ++ PATN_FCPU_EN_MASK | PATN_DP_EN_MASK | PATN_SP_EN_MASK | ++ FIELD_PREP(PATN_TYPE_MASK, 4) | PATN_EN_MASK); ++ ++ airoha_fe_wr(eth, REG_FE_VIP_PATN(11), PPP_IPV6CP); ++ airoha_fe_wr(eth, REG_FE_VIP_EN(11), ++ PATN_FCPU_EN_MASK | FIELD_PREP(PATN_TYPE_MASK, 1) | ++ PATN_EN_MASK); ++ ++ /* DHCPv6 */ ++ airoha_fe_wr(eth, REG_FE_VIP_PATN(12), 0x2220223); ++ airoha_fe_wr(eth, REG_FE_VIP_EN(12), ++ PATN_FCPU_EN_MASK | PATN_DP_EN_MASK | PATN_SP_EN_MASK | ++ FIELD_PREP(PATN_TYPE_MASK, 4) | PATN_EN_MASK); ++ ++ airoha_fe_wr(eth, REG_FE_VIP_PATN(19), PPP_PAP); ++ airoha_fe_wr(eth, REG_FE_VIP_EN(19), ++ PATN_FCPU_EN_MASK | FIELD_PREP(PATN_TYPE_MASK, 1) | ++ PATN_EN_MASK); ++ ++ /* ETH->ETH_P_1905 (0x893a) */ ++ airoha_fe_wr(eth, REG_FE_VIP_PATN(20), 0x893a); ++ airoha_fe_wr(eth, REG_FE_VIP_EN(20), ++ PATN_FCPU_EN_MASK | PATN_EN_MASK); ++ ++ airoha_fe_wr(eth, REG_FE_VIP_PATN(21), ETH_P_LLDP); ++ airoha_fe_wr(eth, REG_FE_VIP_EN(21), ++ PATN_FCPU_EN_MASK | PATN_EN_MASK); ++} ++ ++static u32 airoha_fe_get_pse_queue_rsv_pages(struct airoha_eth *eth, ++ u32 port, u32 queue) ++{ ++ u32 val; ++ ++ airoha_fe_rmw(eth, REG_FE_PSE_QUEUE_CFG_WR, ++ PSE_CFG_PORT_ID_MASK | PSE_CFG_QUEUE_ID_MASK, ++ FIELD_PREP(PSE_CFG_PORT_ID_MASK, port) | ++ FIELD_PREP(PSE_CFG_QUEUE_ID_MASK, queue)); ++ val = airoha_fe_rr(eth, REG_FE_PSE_QUEUE_CFG_VAL); ++ ++ return FIELD_GET(PSE_CFG_OQ_RSV_MASK, val); ++} ++ ++static void airoha_fe_set_pse_queue_rsv_pages(struct airoha_eth *eth, ++ u32 port, u32 queue, u32 val) ++{ ++ airoha_fe_rmw(eth, REG_FE_PSE_QUEUE_CFG_VAL, PSE_CFG_OQ_RSV_MASK, ++ FIELD_PREP(PSE_CFG_OQ_RSV_MASK, val)); ++ airoha_fe_rmw(eth, REG_FE_PSE_QUEUE_CFG_WR, ++ PSE_CFG_PORT_ID_MASK | PSE_CFG_QUEUE_ID_MASK | ++ PSE_CFG_WR_EN_MASK | PSE_CFG_OQRSV_SEL_MASK, ++ FIELD_PREP(PSE_CFG_PORT_ID_MASK, port) | ++ FIELD_PREP(PSE_CFG_QUEUE_ID_MASK, queue) | ++ PSE_CFG_WR_EN_MASK | PSE_CFG_OQRSV_SEL_MASK); ++} ++ ++static u32 airoha_fe_get_pse_all_rsv(struct airoha_eth *eth) ++{ ++ u32 val = airoha_fe_rr(eth, REG_FE_PSE_BUF_SET); ++ ++ return FIELD_GET(PSE_ALLRSV_MASK, val); ++} ++ ++static int airoha_fe_set_pse_oq_rsv(struct airoha_eth *eth, ++ u32 port, u32 queue, u32 val) ++{ ++ u32 orig_val = airoha_fe_get_pse_queue_rsv_pages(eth, port, queue); ++ u32 tmp, all_rsv, fq_limit; ++ ++ airoha_fe_set_pse_queue_rsv_pages(eth, port, queue, val); ++ ++ /* modify all rsv */ ++ all_rsv = airoha_fe_get_pse_all_rsv(eth); ++ all_rsv += (val - orig_val); ++ airoha_fe_rmw(eth, REG_FE_PSE_BUF_SET, PSE_ALLRSV_MASK, ++ FIELD_PREP(PSE_ALLRSV_MASK, all_rsv)); ++ ++ /* modify hthd */ ++ tmp = airoha_fe_rr(eth, PSE_FQ_CFG); ++ fq_limit = FIELD_GET(PSE_FQ_LIMIT_MASK, tmp); ++ tmp = fq_limit - all_rsv - 0x20; ++ airoha_fe_rmw(eth, REG_PSE_SHARE_USED_THD, ++ PSE_SHARE_USED_HTHD_MASK, ++ FIELD_PREP(PSE_SHARE_USED_HTHD_MASK, tmp)); ++ ++ tmp = fq_limit - all_rsv - 0x100; ++ airoha_fe_rmw(eth, REG_PSE_SHARE_USED_THD, ++ PSE_SHARE_USED_MTHD_MASK, ++ FIELD_PREP(PSE_SHARE_USED_MTHD_MASK, tmp)); ++ tmp = (3 * tmp) >> 2; ++ airoha_fe_rmw(eth, REG_FE_PSE_BUF_SET, ++ PSE_SHARE_USED_LTHD_MASK, ++ FIELD_PREP(PSE_SHARE_USED_LTHD_MASK, tmp)); ++ ++ return 0; ++} ++ ++static void airoha_fe_pse_ports_init(struct airoha_eth *eth) ++{ ++ const u32 pse_port_num_queues[] = { ++ [FE_PSE_PORT_CDM1] = 6, ++ [FE_PSE_PORT_GDM1] = 6, ++ [FE_PSE_PORT_GDM2] = 32, ++ [FE_PSE_PORT_GDM3] = 6, ++ [FE_PSE_PORT_PPE1] = 4, ++ [FE_PSE_PORT_CDM2] = 6, ++ [FE_PSE_PORT_CDM3] = 8, ++ [FE_PSE_PORT_CDM4] = 10, ++ [FE_PSE_PORT_PPE2] = 4, ++ [FE_PSE_PORT_GDM4] = 2, ++ [FE_PSE_PORT_CDM5] = 2, ++ }; ++ u32 all_rsv; ++ int q; ++ ++ all_rsv = airoha_fe_get_pse_all_rsv(eth); ++ /* hw misses PPE2 oq rsv */ ++ all_rsv += PSE_RSV_PAGES * pse_port_num_queues[FE_PSE_PORT_PPE2]; ++ airoha_fe_set(eth, REG_FE_PSE_BUF_SET, all_rsv); ++ ++ /* CMD1 */ ++ for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_CDM1]; q++) ++ airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_CDM1, q, ++ PSE_QUEUE_RSV_PAGES); ++ /* GMD1 */ ++ for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_GDM1]; q++) ++ airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_GDM1, q, ++ PSE_QUEUE_RSV_PAGES); ++ /* GMD2 */ ++ for (q = 6; q < pse_port_num_queues[FE_PSE_PORT_GDM2]; q++) ++ airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_GDM2, q, 0); ++ /* GMD3 */ ++ for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_GDM3]; q++) ++ airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_GDM3, q, ++ PSE_QUEUE_RSV_PAGES); ++ /* PPE1 */ ++ for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_PPE1]; q++) { ++ if (q < pse_port_num_queues[FE_PSE_PORT_PPE1]) ++ airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE1, q, ++ PSE_QUEUE_RSV_PAGES); ++ else ++ airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE1, q, 0); ++ } ++ /* CDM2 */ ++ for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_CDM2]; q++) ++ airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_CDM2, q, ++ PSE_QUEUE_RSV_PAGES); ++ /* CDM3 */ ++ for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_CDM3] - 1; q++) ++ airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_CDM3, q, 0); ++ /* CDM4 */ ++ for (q = 4; q < pse_port_num_queues[FE_PSE_PORT_CDM4]; q++) ++ airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_CDM4, q, ++ PSE_QUEUE_RSV_PAGES); ++ /* PPE2 */ ++ for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_PPE2]; q++) { ++ if (q < pse_port_num_queues[FE_PSE_PORT_PPE2] / 2) ++ airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE2, q, ++ PSE_QUEUE_RSV_PAGES); ++ else ++ airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE2, q, 0); ++ } ++ /* GMD4 */ ++ for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_GDM4]; q++) ++ airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_GDM4, q, ++ PSE_QUEUE_RSV_PAGES); ++ /* CDM5 */ ++ for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_CDM5]; q++) ++ airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_CDM5, q, ++ PSE_QUEUE_RSV_PAGES); ++} ++ ++static int airoha_fe_mc_vlan_clear(struct airoha_eth *eth) ++{ ++ int i; ++ ++ for (i = 0; i < AIROHA_FE_MC_MAX_VLAN_TABLE; i++) { ++ int err, j; ++ u32 val; ++ ++ airoha_fe_wr(eth, REG_MC_VLAN_DATA, 0x0); ++ ++ val = FIELD_PREP(MC_VLAN_CFG_TABLE_ID_MASK, i) | ++ MC_VLAN_CFG_TABLE_SEL_MASK | MC_VLAN_CFG_RW_MASK; ++ airoha_fe_wr(eth, REG_MC_VLAN_CFG, val); ++ err = read_poll_timeout(airoha_fe_rr, val, ++ val & MC_VLAN_CFG_CMD_DONE_MASK, ++ USEC_PER_MSEC, 5 * USEC_PER_MSEC, ++ false, eth, REG_MC_VLAN_CFG); ++ if (err) ++ return err; ++ ++ for (j = 0; j < AIROHA_FE_MC_MAX_VLAN_PORT; j++) { ++ airoha_fe_wr(eth, REG_MC_VLAN_DATA, 0x0); ++ ++ val = FIELD_PREP(MC_VLAN_CFG_TABLE_ID_MASK, i) | ++ FIELD_PREP(MC_VLAN_CFG_PORT_ID_MASK, j) | ++ MC_VLAN_CFG_RW_MASK; ++ airoha_fe_wr(eth, REG_MC_VLAN_CFG, val); ++ err = read_poll_timeout(airoha_fe_rr, val, ++ val & MC_VLAN_CFG_CMD_DONE_MASK, ++ USEC_PER_MSEC, ++ 5 * USEC_PER_MSEC, false, eth, ++ REG_MC_VLAN_CFG); ++ if (err) ++ return err; ++ } ++ } ++ ++ return 0; ++} ++ ++static void airoha_fe_crsn_qsel_init(struct airoha_eth *eth) ++{ ++ /* CDM1_CRSN_QSEL */ ++ airoha_fe_rmw(eth, REG_CDM1_CRSN_QSEL(CRSN_22 >> 2), ++ CDM1_CRSN_QSEL_REASON_MASK(CRSN_22), ++ FIELD_PREP(CDM1_CRSN_QSEL_REASON_MASK(CRSN_22), ++ CDM_CRSN_QSEL_Q1)); ++ airoha_fe_rmw(eth, REG_CDM1_CRSN_QSEL(CRSN_08 >> 2), ++ CDM1_CRSN_QSEL_REASON_MASK(CRSN_08), ++ FIELD_PREP(CDM1_CRSN_QSEL_REASON_MASK(CRSN_08), ++ CDM_CRSN_QSEL_Q1)); ++ airoha_fe_rmw(eth, REG_CDM1_CRSN_QSEL(CRSN_21 >> 2), ++ CDM1_CRSN_QSEL_REASON_MASK(CRSN_21), ++ FIELD_PREP(CDM1_CRSN_QSEL_REASON_MASK(CRSN_21), ++ CDM_CRSN_QSEL_Q1)); ++ airoha_fe_rmw(eth, REG_CDM1_CRSN_QSEL(CRSN_24 >> 2), ++ CDM1_CRSN_QSEL_REASON_MASK(CRSN_24), ++ FIELD_PREP(CDM1_CRSN_QSEL_REASON_MASK(CRSN_24), ++ CDM_CRSN_QSEL_Q6)); ++ airoha_fe_rmw(eth, REG_CDM1_CRSN_QSEL(CRSN_25 >> 2), ++ CDM1_CRSN_QSEL_REASON_MASK(CRSN_25), ++ FIELD_PREP(CDM1_CRSN_QSEL_REASON_MASK(CRSN_25), ++ CDM_CRSN_QSEL_Q1)); ++ /* CDM2_CRSN_QSEL */ ++ airoha_fe_rmw(eth, REG_CDM2_CRSN_QSEL(CRSN_08 >> 2), ++ CDM2_CRSN_QSEL_REASON_MASK(CRSN_08), ++ FIELD_PREP(CDM2_CRSN_QSEL_REASON_MASK(CRSN_08), ++ CDM_CRSN_QSEL_Q1)); ++ airoha_fe_rmw(eth, REG_CDM2_CRSN_QSEL(CRSN_21 >> 2), ++ CDM2_CRSN_QSEL_REASON_MASK(CRSN_21), ++ FIELD_PREP(CDM2_CRSN_QSEL_REASON_MASK(CRSN_21), ++ CDM_CRSN_QSEL_Q1)); ++ airoha_fe_rmw(eth, REG_CDM2_CRSN_QSEL(CRSN_22 >> 2), ++ CDM2_CRSN_QSEL_REASON_MASK(CRSN_22), ++ FIELD_PREP(CDM2_CRSN_QSEL_REASON_MASK(CRSN_22), ++ CDM_CRSN_QSEL_Q1)); ++ airoha_fe_rmw(eth, REG_CDM2_CRSN_QSEL(CRSN_24 >> 2), ++ CDM2_CRSN_QSEL_REASON_MASK(CRSN_24), ++ FIELD_PREP(CDM2_CRSN_QSEL_REASON_MASK(CRSN_24), ++ CDM_CRSN_QSEL_Q6)); ++ airoha_fe_rmw(eth, REG_CDM2_CRSN_QSEL(CRSN_25 >> 2), ++ CDM2_CRSN_QSEL_REASON_MASK(CRSN_25), ++ FIELD_PREP(CDM2_CRSN_QSEL_REASON_MASK(CRSN_25), ++ CDM_CRSN_QSEL_Q1)); ++} ++ ++static int airoha_fe_init(struct airoha_eth *eth) ++{ ++ airoha_fe_maccr_init(eth); ++ ++ /* PSE IQ reserve */ ++ airoha_fe_rmw(eth, REG_PSE_IQ_REV1, PSE_IQ_RES1_P2_MASK, ++ FIELD_PREP(PSE_IQ_RES1_P2_MASK, 0x10)); ++ airoha_fe_rmw(eth, REG_PSE_IQ_REV2, ++ PSE_IQ_RES2_P5_MASK | PSE_IQ_RES2_P4_MASK, ++ FIELD_PREP(PSE_IQ_RES2_P5_MASK, 0x40) | ++ FIELD_PREP(PSE_IQ_RES2_P4_MASK, 0x34)); ++ ++ /* enable FE copy engine for MC/KA/DPI */ ++ airoha_fe_wr(eth, REG_FE_PCE_CFG, ++ PCE_DPI_EN_MASK | PCE_KA_EN_MASK | PCE_MC_EN_MASK); ++ /* set vip queue selection to ring 1 */ ++ airoha_fe_rmw(eth, REG_CDM1_FWD_CFG, CDM1_VIP_QSEL_MASK, ++ FIELD_PREP(CDM1_VIP_QSEL_MASK, 0x4)); ++ airoha_fe_rmw(eth, REG_CDM2_FWD_CFG, CDM2_VIP_QSEL_MASK, ++ FIELD_PREP(CDM2_VIP_QSEL_MASK, 0x4)); ++ /* set GDM4 source interface offset to 8 */ ++ airoha_fe_rmw(eth, REG_GDM4_SRC_PORT_SET, ++ GDM4_SPORT_OFF2_MASK | ++ GDM4_SPORT_OFF1_MASK | ++ GDM4_SPORT_OFF0_MASK, ++ FIELD_PREP(GDM4_SPORT_OFF2_MASK, 8) | ++ FIELD_PREP(GDM4_SPORT_OFF1_MASK, 8) | ++ FIELD_PREP(GDM4_SPORT_OFF0_MASK, 8)); ++ ++ /* set PSE Page as 128B */ ++ airoha_fe_rmw(eth, REG_FE_DMA_GLO_CFG, ++ FE_DMA_GLO_L2_SPACE_MASK | FE_DMA_GLO_PG_SZ_MASK, ++ FIELD_PREP(FE_DMA_GLO_L2_SPACE_MASK, 2) | ++ FE_DMA_GLO_PG_SZ_MASK); ++ airoha_fe_wr(eth, REG_FE_RST_GLO_CFG, ++ FE_RST_CORE_MASK | FE_RST_GDM3_MBI_ARB_MASK | ++ FE_RST_GDM4_MBI_ARB_MASK); ++ usleep_range(1000, 2000); ++ ++ /* connect RxRing1 and RxRing15 to PSE Port0 OQ-1 ++ * connect other rings to PSE Port0 OQ-0 ++ */ ++ airoha_fe_wr(eth, REG_FE_CDM1_OQ_MAP0, BIT(4)); ++ airoha_fe_wr(eth, REG_FE_CDM1_OQ_MAP1, BIT(28)); ++ airoha_fe_wr(eth, REG_FE_CDM1_OQ_MAP2, BIT(4)); ++ airoha_fe_wr(eth, REG_FE_CDM1_OQ_MAP3, BIT(28)); ++ ++ airoha_fe_vip_setup(eth); ++ airoha_fe_pse_ports_init(eth); ++ ++ airoha_fe_set(eth, REG_GDM_MISC_CFG, ++ GDM2_RDM_ACK_WAIT_PREF_MASK | ++ GDM2_CHN_VLD_MODE_MASK); ++ airoha_fe_rmw(eth, REG_CDM2_FWD_CFG, CDM2_OAM_QSEL_MASK, ++ FIELD_PREP(CDM2_OAM_QSEL_MASK, 15)); ++ ++ /* init fragment and assemble Force Port */ ++ /* NPU Core-3, NPU Bridge Channel-3 */ ++ airoha_fe_rmw(eth, REG_IP_FRAG_FP, ++ IP_FRAGMENT_PORT_MASK | IP_FRAGMENT_NBQ_MASK, ++ FIELD_PREP(IP_FRAGMENT_PORT_MASK, 6) | ++ FIELD_PREP(IP_FRAGMENT_NBQ_MASK, 3)); ++ /* QDMA LAN, RX Ring-22 */ ++ airoha_fe_rmw(eth, REG_IP_FRAG_FP, ++ IP_ASSEMBLE_PORT_MASK | IP_ASSEMBLE_NBQ_MASK, ++ FIELD_PREP(IP_ASSEMBLE_PORT_MASK, 0) | ++ FIELD_PREP(IP_ASSEMBLE_NBQ_MASK, 22)); ++ ++ airoha_fe_set(eth, REG_GDM3_FWD_CFG, GDM3_PAD_EN_MASK); ++ airoha_fe_set(eth, REG_GDM4_FWD_CFG, GDM4_PAD_EN_MASK); ++ ++ airoha_fe_crsn_qsel_init(eth); ++ ++ airoha_fe_clear(eth, REG_FE_CPORT_CFG, FE_CPORT_QUEUE_XFC_MASK); ++ airoha_fe_set(eth, REG_FE_CPORT_CFG, FE_CPORT_PORT_XFC_MASK); ++ ++ /* default aging mode for mbi unlock issue */ ++ airoha_fe_rmw(eth, REG_GDM2_CHN_RLS, ++ MBI_RX_AGE_SEL_MASK | MBI_TX_AGE_SEL_MASK, ++ FIELD_PREP(MBI_RX_AGE_SEL_MASK, 3) | ++ FIELD_PREP(MBI_TX_AGE_SEL_MASK, 3)); ++ ++ /* disable IFC by default */ ++ airoha_fe_clear(eth, REG_FE_CSR_IFC_CFG, FE_IFC_EN_MASK); ++ ++ /* enable 1:N vlan action, init vlan table */ ++ airoha_fe_set(eth, REG_MC_VLAN_EN, MC_VLAN_EN_MASK); ++ ++ return airoha_fe_mc_vlan_clear(eth); ++} ++ ++static int airoha_qdma_fill_rx_queue(struct airoha_queue *q) ++{ ++ enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool); ++ struct airoha_qdma *qdma = q->qdma; ++ struct airoha_eth *eth = qdma->eth; ++ int qid = q - &qdma->q_rx[0]; ++ int nframes = 0; ++ ++ while (q->queued < q->ndesc - 1) { ++ struct airoha_queue_entry *e = &q->entry[q->head]; ++ struct airoha_qdma_desc *desc = &q->desc[q->head]; ++ struct page *page; ++ int offset; ++ u32 val; ++ ++ page = page_pool_dev_alloc_frag(q->page_pool, &offset, ++ q->buf_size); ++ if (!page) ++ break; ++ ++ q->head = (q->head + 1) % q->ndesc; ++ q->queued++; ++ nframes++; ++ ++ e->buf = page_address(page) + offset; ++ e->dma_addr = page_pool_get_dma_addr(page) + offset; ++ e->dma_len = SKB_WITH_OVERHEAD(q->buf_size); ++ ++ dma_sync_single_for_device(eth->dev, e->dma_addr, e->dma_len, ++ dir); ++ ++ val = FIELD_PREP(QDMA_DESC_LEN_MASK, e->dma_len); ++ WRITE_ONCE(desc->ctrl, cpu_to_le32(val)); ++ WRITE_ONCE(desc->addr, cpu_to_le32(e->dma_addr)); ++ val = FIELD_PREP(QDMA_DESC_NEXT_ID_MASK, q->head); ++ WRITE_ONCE(desc->data, cpu_to_le32(val)); ++ WRITE_ONCE(desc->msg0, 0); ++ WRITE_ONCE(desc->msg1, 0); ++ WRITE_ONCE(desc->msg2, 0); ++ WRITE_ONCE(desc->msg3, 0); ++ ++ airoha_qdma_rmw(qdma, REG_RX_CPU_IDX(qid), ++ RX_RING_CPU_IDX_MASK, ++ FIELD_PREP(RX_RING_CPU_IDX_MASK, q->head)); ++ } ++ ++ return nframes; ++} ++ ++static int airoha_qdma_get_gdm_port(struct airoha_eth *eth, ++ struct airoha_qdma_desc *desc) ++{ ++ u32 port, sport, msg1 = le32_to_cpu(desc->msg1); ++ ++ sport = FIELD_GET(QDMA_ETH_RXMSG_SPORT_MASK, msg1); ++ switch (sport) { ++ case 0x10 ... 0x13: ++ port = 0; ++ break; ++ case 0x2 ... 0x4: ++ port = sport - 1; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return port >= ARRAY_SIZE(eth->ports) ? -EINVAL : port; ++} ++ ++static int airoha_qdma_rx_process(struct airoha_queue *q, int budget) ++{ ++ enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool); ++ struct airoha_qdma *qdma = q->qdma; ++ struct airoha_eth *eth = qdma->eth; ++ int qid = q - &qdma->q_rx[0]; ++ int done = 0; ++ ++ while (done < budget) { ++ struct airoha_queue_entry *e = &q->entry[q->tail]; ++ struct airoha_qdma_desc *desc = &q->desc[q->tail]; ++ dma_addr_t dma_addr = le32_to_cpu(desc->addr); ++ u32 desc_ctrl = le32_to_cpu(desc->ctrl); ++ struct sk_buff *skb; ++ int len, p; ++ ++ if (!(desc_ctrl & QDMA_DESC_DONE_MASK)) ++ break; ++ ++ if (!dma_addr) ++ break; ++ ++ len = FIELD_GET(QDMA_DESC_LEN_MASK, desc_ctrl); ++ if (!len) ++ break; ++ ++ q->tail = (q->tail + 1) % q->ndesc; ++ q->queued--; ++ ++ dma_sync_single_for_cpu(eth->dev, dma_addr, ++ SKB_WITH_OVERHEAD(q->buf_size), dir); ++ ++ p = airoha_qdma_get_gdm_port(eth, desc); ++ if (p < 0 || !eth->ports[p]) { ++ page_pool_put_full_page(q->page_pool, ++ virt_to_head_page(e->buf), ++ true); ++ continue; ++ } ++ ++ skb = napi_build_skb(e->buf, q->buf_size); ++ if (!skb) { ++ page_pool_put_full_page(q->page_pool, ++ virt_to_head_page(e->buf), ++ true); ++ break; ++ } ++ ++ skb_reserve(skb, 2); ++ __skb_put(skb, len); ++ skb_mark_for_recycle(skb); ++ skb->dev = eth->ports[p]->dev; ++ skb->protocol = eth_type_trans(skb, skb->dev); ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ skb_record_rx_queue(skb, qid); ++ napi_gro_receive(&q->napi, skb); ++ ++ done++; ++ } ++ airoha_qdma_fill_rx_queue(q); ++ ++ return done; ++} ++ ++static int airoha_qdma_rx_napi_poll(struct napi_struct *napi, int budget) ++{ ++ struct airoha_queue *q = container_of(napi, struct airoha_queue, napi); ++ int cur, done = 0; ++ ++ do { ++ cur = airoha_qdma_rx_process(q, budget - done); ++ done += cur; ++ } while (cur && done < budget); ++ ++ if (done < budget && napi_complete(napi)) ++ airoha_qdma_irq_enable(q->qdma, QDMA_INT_REG_IDX1, ++ RX_DONE_INT_MASK); ++ ++ return done; ++} ++ ++static int airoha_qdma_init_rx_queue(struct airoha_queue *q, ++ struct airoha_qdma *qdma, int ndesc) ++{ ++ const struct page_pool_params pp_params = { ++ .order = 0, ++ .pool_size = 256, ++ .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV, ++ .dma_dir = DMA_FROM_DEVICE, ++ .max_len = PAGE_SIZE, ++ .nid = NUMA_NO_NODE, ++ .dev = qdma->eth->dev, ++ .napi = &q->napi, ++ }; ++ struct airoha_eth *eth = qdma->eth; ++ int qid = q - &qdma->q_rx[0], thr; ++ dma_addr_t dma_addr; ++ ++ q->buf_size = PAGE_SIZE / 2; ++ q->ndesc = ndesc; ++ q->qdma = qdma; ++ ++ q->entry = devm_kzalloc(eth->dev, q->ndesc * sizeof(*q->entry), ++ GFP_KERNEL); ++ if (!q->entry) ++ return -ENOMEM; ++ ++ q->page_pool = page_pool_create(&pp_params); ++ if (IS_ERR(q->page_pool)) { ++ int err = PTR_ERR(q->page_pool); ++ ++ q->page_pool = NULL; ++ return err; ++ } ++ ++ q->desc = dmam_alloc_coherent(eth->dev, q->ndesc * sizeof(*q->desc), ++ &dma_addr, GFP_KERNEL); ++ if (!q->desc) ++ return -ENOMEM; ++ ++ netif_napi_add(eth->napi_dev, &q->napi, airoha_qdma_rx_napi_poll); ++ ++ airoha_qdma_wr(qdma, REG_RX_RING_BASE(qid), dma_addr); ++ airoha_qdma_rmw(qdma, REG_RX_RING_SIZE(qid), ++ RX_RING_SIZE_MASK, ++ FIELD_PREP(RX_RING_SIZE_MASK, ndesc)); ++ ++ thr = clamp(ndesc >> 3, 1, 32); ++ airoha_qdma_rmw(qdma, REG_RX_RING_SIZE(qid), RX_RING_THR_MASK, ++ FIELD_PREP(RX_RING_THR_MASK, thr)); ++ airoha_qdma_rmw(qdma, REG_RX_DMA_IDX(qid), RX_RING_DMA_IDX_MASK, ++ FIELD_PREP(RX_RING_DMA_IDX_MASK, q->head)); ++ ++ airoha_qdma_fill_rx_queue(q); ++ ++ return 0; ++} ++ ++static void airoha_qdma_cleanup_rx_queue(struct airoha_queue *q) ++{ ++ struct airoha_eth *eth = q->qdma->eth; ++ ++ while (q->queued) { ++ struct airoha_queue_entry *e = &q->entry[q->tail]; ++ struct page *page = virt_to_head_page(e->buf); ++ ++ dma_sync_single_for_cpu(eth->dev, e->dma_addr, e->dma_len, ++ page_pool_get_dma_dir(q->page_pool)); ++ page_pool_put_full_page(q->page_pool, page, false); ++ q->tail = (q->tail + 1) % q->ndesc; ++ q->queued--; ++ } ++} ++ ++static int airoha_qdma_init_rx(struct airoha_qdma *qdma) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { ++ int err; ++ ++ if (!(RX_DONE_INT_MASK & BIT(i))) { ++ /* rx-queue not binded to irq */ ++ continue; ++ } ++ ++ err = airoha_qdma_init_rx_queue(&qdma->q_rx[i], qdma, ++ RX_DSCP_NUM(i)); ++ if (err) ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int airoha_qdma_tx_napi_poll(struct napi_struct *napi, int budget) ++{ ++ struct airoha_tx_irq_queue *irq_q; ++ int id, done = 0, irq_queued; ++ struct airoha_qdma *qdma; ++ struct airoha_eth *eth; ++ u32 status, head; ++ ++ irq_q = container_of(napi, struct airoha_tx_irq_queue, napi); ++ qdma = irq_q->qdma; ++ id = irq_q - &qdma->q_tx_irq[0]; ++ eth = qdma->eth; ++ ++ status = airoha_qdma_rr(qdma, REG_IRQ_STATUS(id)); ++ head = FIELD_GET(IRQ_HEAD_IDX_MASK, status); ++ head = head % irq_q->size; ++ irq_queued = FIELD_GET(IRQ_ENTRY_LEN_MASK, status); ++ ++ while (irq_queued > 0 && done < budget) { ++ u32 qid, val = irq_q->q[head]; ++ struct airoha_qdma_desc *desc; ++ struct airoha_queue_entry *e; ++ struct airoha_queue *q; ++ u32 index, desc_ctrl; ++ struct sk_buff *skb; ++ ++ if (val == 0xff) ++ break; ++ ++ irq_q->q[head] = 0xff; /* mark as done */ ++ head = (head + 1) % irq_q->size; ++ irq_queued--; ++ done++; ++ ++ qid = FIELD_GET(IRQ_RING_IDX_MASK, val); ++ if (qid >= ARRAY_SIZE(qdma->q_tx)) ++ continue; ++ ++ q = &qdma->q_tx[qid]; ++ if (!q->ndesc) ++ continue; ++ ++ index = FIELD_GET(IRQ_DESC_IDX_MASK, val); ++ if (index >= q->ndesc) ++ continue; ++ ++ spin_lock_bh(&q->lock); ++ ++ if (!q->queued) ++ goto unlock; ++ ++ desc = &q->desc[index]; ++ desc_ctrl = le32_to_cpu(desc->ctrl); ++ ++ if (!(desc_ctrl & QDMA_DESC_DONE_MASK) && ++ !(desc_ctrl & QDMA_DESC_DROP_MASK)) ++ goto unlock; ++ ++ e = &q->entry[index]; ++ skb = e->skb; ++ ++ dma_unmap_single(eth->dev, e->dma_addr, e->dma_len, ++ DMA_TO_DEVICE); ++ memset(e, 0, sizeof(*e)); ++ WRITE_ONCE(desc->msg0, 0); ++ WRITE_ONCE(desc->msg1, 0); ++ q->queued--; ++ ++ /* completion ring can report out-of-order indexes if hw QoS ++ * is enabled and packets with different priority are queued ++ * to same DMA ring. Take into account possible out-of-order ++ * reports incrementing DMA ring tail pointer ++ */ ++ while (q->tail != q->head && !q->entry[q->tail].dma_addr) ++ q->tail = (q->tail + 1) % q->ndesc; ++ ++ if (skb) { ++ u16 queue = skb_get_queue_mapping(skb); ++ struct netdev_queue *txq; ++ ++ txq = netdev_get_tx_queue(skb->dev, queue); ++ netdev_tx_completed_queue(txq, 1, skb->len); ++ if (netif_tx_queue_stopped(txq) && ++ q->ndesc - q->queued >= q->free_thr) ++ netif_tx_wake_queue(txq); ++ ++ dev_kfree_skb_any(skb); ++ } ++unlock: ++ spin_unlock_bh(&q->lock); ++ } ++ ++ if (done) { ++ int i, len = done >> 7; ++ ++ for (i = 0; i < len; i++) ++ airoha_qdma_rmw(qdma, REG_IRQ_CLEAR_LEN(id), ++ IRQ_CLEAR_LEN_MASK, 0x80); ++ airoha_qdma_rmw(qdma, REG_IRQ_CLEAR_LEN(id), ++ IRQ_CLEAR_LEN_MASK, (done & 0x7f)); ++ } ++ ++ if (done < budget && napi_complete(napi)) ++ airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX0, ++ TX_DONE_INT_MASK(id)); ++ ++ return done; ++} ++ ++static int airoha_qdma_init_tx_queue(struct airoha_queue *q, ++ struct airoha_qdma *qdma, int size) ++{ ++ struct airoha_eth *eth = qdma->eth; ++ int i, qid = q - &qdma->q_tx[0]; ++ dma_addr_t dma_addr; ++ ++ spin_lock_init(&q->lock); ++ q->ndesc = size; ++ q->qdma = qdma; ++ q->free_thr = 1 + MAX_SKB_FRAGS; ++ ++ q->entry = devm_kzalloc(eth->dev, q->ndesc * sizeof(*q->entry), ++ GFP_KERNEL); ++ if (!q->entry) ++ return -ENOMEM; ++ ++ q->desc = dmam_alloc_coherent(eth->dev, q->ndesc * sizeof(*q->desc), ++ &dma_addr, GFP_KERNEL); ++ if (!q->desc) ++ return -ENOMEM; ++ ++ for (i = 0; i < q->ndesc; i++) { ++ u32 val; ++ ++ val = FIELD_PREP(QDMA_DESC_DONE_MASK, 1); ++ WRITE_ONCE(q->desc[i].ctrl, cpu_to_le32(val)); ++ } ++ ++ /* xmit ring drop default setting */ ++ airoha_qdma_set(qdma, REG_TX_RING_BLOCKING(qid), ++ TX_RING_IRQ_BLOCKING_TX_DROP_EN_MASK); ++ ++ airoha_qdma_wr(qdma, REG_TX_RING_BASE(qid), dma_addr); ++ airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK, ++ FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head)); ++ airoha_qdma_rmw(qdma, REG_TX_DMA_IDX(qid), TX_RING_DMA_IDX_MASK, ++ FIELD_PREP(TX_RING_DMA_IDX_MASK, q->head)); ++ ++ return 0; ++} ++ ++static int airoha_qdma_tx_irq_init(struct airoha_tx_irq_queue *irq_q, ++ struct airoha_qdma *qdma, int size) ++{ ++ int id = irq_q - &qdma->q_tx_irq[0]; ++ struct airoha_eth *eth = qdma->eth; ++ dma_addr_t dma_addr; ++ ++ netif_napi_add_tx(eth->napi_dev, &irq_q->napi, ++ airoha_qdma_tx_napi_poll); ++ irq_q->q = dmam_alloc_coherent(eth->dev, size * sizeof(u32), ++ &dma_addr, GFP_KERNEL); ++ if (!irq_q->q) ++ return -ENOMEM; ++ ++ memset(irq_q->q, 0xff, size * sizeof(u32)); ++ irq_q->size = size; ++ irq_q->qdma = qdma; ++ ++ airoha_qdma_wr(qdma, REG_TX_IRQ_BASE(id), dma_addr); ++ airoha_qdma_rmw(qdma, REG_TX_IRQ_CFG(id), TX_IRQ_DEPTH_MASK, ++ FIELD_PREP(TX_IRQ_DEPTH_MASK, size)); ++ airoha_qdma_rmw(qdma, REG_TX_IRQ_CFG(id), TX_IRQ_THR_MASK, ++ FIELD_PREP(TX_IRQ_THR_MASK, 1)); ++ ++ return 0; ++} ++ ++static int airoha_qdma_init_tx(struct airoha_qdma *qdma) ++{ ++ int i, err; ++ ++ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) { ++ err = airoha_qdma_tx_irq_init(&qdma->q_tx_irq[i], qdma, ++ IRQ_QUEUE_LEN(i)); ++ if (err) ++ return err; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { ++ err = airoha_qdma_init_tx_queue(&qdma->q_tx[i], qdma, ++ TX_DSCP_NUM); ++ if (err) ++ return err; ++ } ++ ++ return 0; ++} ++ ++static void airoha_qdma_cleanup_tx_queue(struct airoha_queue *q) ++{ ++ struct airoha_eth *eth = q->qdma->eth; ++ ++ spin_lock_bh(&q->lock); ++ while (q->queued) { ++ struct airoha_queue_entry *e = &q->entry[q->tail]; ++ ++ dma_unmap_single(eth->dev, e->dma_addr, e->dma_len, ++ DMA_TO_DEVICE); ++ dev_kfree_skb_any(e->skb); ++ e->skb = NULL; ++ ++ q->tail = (q->tail + 1) % q->ndesc; ++ q->queued--; ++ } ++ spin_unlock_bh(&q->lock); ++} ++ ++static int airoha_qdma_init_hfwd_queues(struct airoha_qdma *qdma) ++{ ++ struct airoha_eth *eth = qdma->eth; ++ dma_addr_t dma_addr; ++ u32 status; ++ int size; ++ ++ size = HW_DSCP_NUM * sizeof(struct airoha_qdma_fwd_desc); ++ qdma->hfwd.desc = dmam_alloc_coherent(eth->dev, size, &dma_addr, ++ GFP_KERNEL); ++ if (!qdma->hfwd.desc) ++ return -ENOMEM; ++ ++ airoha_qdma_wr(qdma, REG_FWD_DSCP_BASE, dma_addr); ++ ++ size = AIROHA_MAX_PACKET_SIZE * HW_DSCP_NUM; ++ qdma->hfwd.q = dmam_alloc_coherent(eth->dev, size, &dma_addr, ++ GFP_KERNEL); ++ if (!qdma->hfwd.q) ++ return -ENOMEM; ++ ++ airoha_qdma_wr(qdma, REG_FWD_BUF_BASE, dma_addr); ++ ++ airoha_qdma_rmw(qdma, REG_HW_FWD_DSCP_CFG, ++ HW_FWD_DSCP_PAYLOAD_SIZE_MASK, ++ FIELD_PREP(HW_FWD_DSCP_PAYLOAD_SIZE_MASK, 0)); ++ airoha_qdma_rmw(qdma, REG_FWD_DSCP_LOW_THR, FWD_DSCP_LOW_THR_MASK, ++ FIELD_PREP(FWD_DSCP_LOW_THR_MASK, 128)); ++ airoha_qdma_rmw(qdma, REG_LMGR_INIT_CFG, ++ LMGR_INIT_START | LMGR_SRAM_MODE_MASK | ++ HW_FWD_DESC_NUM_MASK, ++ FIELD_PREP(HW_FWD_DESC_NUM_MASK, HW_DSCP_NUM) | ++ LMGR_INIT_START); ++ ++ return read_poll_timeout(airoha_qdma_rr, status, ++ !(status & LMGR_INIT_START), USEC_PER_MSEC, ++ 30 * USEC_PER_MSEC, true, qdma, ++ REG_LMGR_INIT_CFG); ++} ++ ++static void airoha_qdma_init_qos(struct airoha_qdma *qdma) ++{ ++ airoha_qdma_clear(qdma, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_SCALE_MASK); ++ airoha_qdma_set(qdma, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_BASE_MASK); ++ ++ airoha_qdma_clear(qdma, REG_PSE_BUF_USAGE_CFG, ++ PSE_BUF_ESTIMATE_EN_MASK); ++ ++ airoha_qdma_set(qdma, REG_EGRESS_RATE_METER_CFG, ++ EGRESS_RATE_METER_EN_MASK | ++ EGRESS_RATE_METER_EQ_RATE_EN_MASK); ++ /* 2047us x 31 = 63.457ms */ ++ airoha_qdma_rmw(qdma, REG_EGRESS_RATE_METER_CFG, ++ EGRESS_RATE_METER_WINDOW_SZ_MASK, ++ FIELD_PREP(EGRESS_RATE_METER_WINDOW_SZ_MASK, 0x1f)); ++ airoha_qdma_rmw(qdma, REG_EGRESS_RATE_METER_CFG, ++ EGRESS_RATE_METER_TIMESLICE_MASK, ++ FIELD_PREP(EGRESS_RATE_METER_TIMESLICE_MASK, 0x7ff)); ++ ++ /* ratelimit init */ ++ airoha_qdma_set(qdma, REG_GLB_TRTCM_CFG, GLB_TRTCM_EN_MASK); ++ /* fast-tick 25us */ ++ airoha_qdma_rmw(qdma, REG_GLB_TRTCM_CFG, GLB_FAST_TICK_MASK, ++ FIELD_PREP(GLB_FAST_TICK_MASK, 25)); ++ airoha_qdma_rmw(qdma, REG_GLB_TRTCM_CFG, GLB_SLOW_TICK_RATIO_MASK, ++ FIELD_PREP(GLB_SLOW_TICK_RATIO_MASK, 40)); ++ ++ airoha_qdma_set(qdma, REG_EGRESS_TRTCM_CFG, EGRESS_TRTCM_EN_MASK); ++ airoha_qdma_rmw(qdma, REG_EGRESS_TRTCM_CFG, EGRESS_FAST_TICK_MASK, ++ FIELD_PREP(EGRESS_FAST_TICK_MASK, 25)); ++ airoha_qdma_rmw(qdma, REG_EGRESS_TRTCM_CFG, ++ EGRESS_SLOW_TICK_RATIO_MASK, ++ FIELD_PREP(EGRESS_SLOW_TICK_RATIO_MASK, 40)); ++ ++ airoha_qdma_set(qdma, REG_INGRESS_TRTCM_CFG, INGRESS_TRTCM_EN_MASK); ++ airoha_qdma_clear(qdma, REG_INGRESS_TRTCM_CFG, ++ INGRESS_TRTCM_MODE_MASK); ++ airoha_qdma_rmw(qdma, REG_INGRESS_TRTCM_CFG, INGRESS_FAST_TICK_MASK, ++ FIELD_PREP(INGRESS_FAST_TICK_MASK, 125)); ++ airoha_qdma_rmw(qdma, REG_INGRESS_TRTCM_CFG, ++ INGRESS_SLOW_TICK_RATIO_MASK, ++ FIELD_PREP(INGRESS_SLOW_TICK_RATIO_MASK, 8)); ++ ++ airoha_qdma_set(qdma, REG_SLA_TRTCM_CFG, SLA_TRTCM_EN_MASK); ++ airoha_qdma_rmw(qdma, REG_SLA_TRTCM_CFG, SLA_FAST_TICK_MASK, ++ FIELD_PREP(SLA_FAST_TICK_MASK, 25)); ++ airoha_qdma_rmw(qdma, REG_SLA_TRTCM_CFG, SLA_SLOW_TICK_RATIO_MASK, ++ FIELD_PREP(SLA_SLOW_TICK_RATIO_MASK, 40)); ++} ++ ++static void airoha_qdma_init_qos_stats(struct airoha_qdma *qdma) ++{ ++ int i; ++ ++ for (i = 0; i < AIROHA_NUM_QOS_CHANNELS; i++) { ++ /* Tx-cpu transferred count */ ++ airoha_qdma_wr(qdma, REG_CNTR_VAL(i << 1), 0); ++ airoha_qdma_wr(qdma, REG_CNTR_CFG(i << 1), ++ CNTR_EN_MASK | CNTR_ALL_QUEUE_EN_MASK | ++ CNTR_ALL_DSCP_RING_EN_MASK | ++ FIELD_PREP(CNTR_CHAN_MASK, i)); ++ /* Tx-fwd transferred count */ ++ airoha_qdma_wr(qdma, REG_CNTR_VAL((i << 1) + 1), 0); ++ airoha_qdma_wr(qdma, REG_CNTR_CFG(i << 1), ++ CNTR_EN_MASK | CNTR_ALL_QUEUE_EN_MASK | ++ CNTR_ALL_DSCP_RING_EN_MASK | ++ FIELD_PREP(CNTR_SRC_MASK, 1) | ++ FIELD_PREP(CNTR_CHAN_MASK, i)); ++ } ++} ++ ++static int airoha_qdma_hw_init(struct airoha_qdma *qdma) ++{ ++ int i; ++ ++ /* clear pending irqs */ ++ for (i = 0; i < ARRAY_SIZE(qdma->irqmask); i++) ++ airoha_qdma_wr(qdma, REG_INT_STATUS(i), 0xffffffff); ++ ++ /* setup irqs */ ++ airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX0, INT_IDX0_MASK); ++ airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX1, INT_IDX1_MASK); ++ airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX4, INT_IDX4_MASK); ++ ++ /* setup irq binding */ ++ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { ++ if (!qdma->q_tx[i].ndesc) ++ continue; ++ ++ if (TX_RING_IRQ_BLOCKING_MAP_MASK & BIT(i)) ++ airoha_qdma_set(qdma, REG_TX_RING_BLOCKING(i), ++ TX_RING_IRQ_BLOCKING_CFG_MASK); ++ else ++ airoha_qdma_clear(qdma, REG_TX_RING_BLOCKING(i), ++ TX_RING_IRQ_BLOCKING_CFG_MASK); ++ } ++ ++ airoha_qdma_wr(qdma, REG_QDMA_GLOBAL_CFG, ++ GLOBAL_CFG_RX_2B_OFFSET_MASK | ++ FIELD_PREP(GLOBAL_CFG_DMA_PREFERENCE_MASK, 3) | ++ GLOBAL_CFG_CPU_TXR_RR_MASK | ++ GLOBAL_CFG_PAYLOAD_BYTE_SWAP_MASK | ++ GLOBAL_CFG_MULTICAST_MODIFY_FP_MASK | ++ GLOBAL_CFG_MULTICAST_EN_MASK | ++ GLOBAL_CFG_IRQ0_EN_MASK | GLOBAL_CFG_IRQ1_EN_MASK | ++ GLOBAL_CFG_TX_WB_DONE_MASK | ++ FIELD_PREP(GLOBAL_CFG_MAX_ISSUE_NUM_MASK, 2)); ++ ++ airoha_qdma_init_qos(qdma); ++ ++ /* disable qdma rx delay interrupt */ ++ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { ++ if (!qdma->q_rx[i].ndesc) ++ continue; ++ ++ airoha_qdma_clear(qdma, REG_RX_DELAY_INT_IDX(i), ++ RX_DELAY_INT_MASK); ++ } ++ ++ airoha_qdma_set(qdma, REG_TXQ_CNGST_CFG, ++ TXQ_CNGST_DROP_EN | TXQ_CNGST_DEI_DROP_EN); ++ airoha_qdma_init_qos_stats(qdma); ++ ++ return 0; ++} ++ ++static irqreturn_t airoha_irq_handler(int irq, void *dev_instance) ++{ ++ struct airoha_qdma *qdma = dev_instance; ++ u32 intr[ARRAY_SIZE(qdma->irqmask)]; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(qdma->irqmask); i++) { ++ intr[i] = airoha_qdma_rr(qdma, REG_INT_STATUS(i)); ++ intr[i] &= qdma->irqmask[i]; ++ airoha_qdma_wr(qdma, REG_INT_STATUS(i), intr[i]); ++ } ++ ++ if (!test_bit(DEV_STATE_INITIALIZED, &qdma->eth->state)) ++ return IRQ_NONE; ++ ++ if (intr[1] & RX_DONE_INT_MASK) { ++ airoha_qdma_irq_disable(qdma, QDMA_INT_REG_IDX1, ++ RX_DONE_INT_MASK); ++ ++ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { ++ if (!qdma->q_rx[i].ndesc) ++ continue; ++ ++ if (intr[1] & BIT(i)) ++ napi_schedule(&qdma->q_rx[i].napi); ++ } ++ } ++ ++ if (intr[0] & INT_TX_MASK) { ++ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) { ++ if (!(intr[0] & TX_DONE_INT_MASK(i))) ++ continue; ++ ++ airoha_qdma_irq_disable(qdma, QDMA_INT_REG_IDX0, ++ TX_DONE_INT_MASK(i)); ++ napi_schedule(&qdma->q_tx_irq[i].napi); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static int airoha_qdma_init(struct platform_device *pdev, ++ struct airoha_eth *eth, ++ struct airoha_qdma *qdma) ++{ ++ int err, id = qdma - ð->qdma[0]; ++ const char *res; ++ ++ spin_lock_init(&qdma->irq_lock); ++ qdma->eth = eth; ++ ++ res = devm_kasprintf(eth->dev, GFP_KERNEL, "qdma%d", id); ++ if (!res) ++ return -ENOMEM; ++ ++ qdma->regs = devm_platform_ioremap_resource_byname(pdev, res); ++ if (IS_ERR(qdma->regs)) ++ return dev_err_probe(eth->dev, PTR_ERR(qdma->regs), ++ "failed to iomap qdma%d regs\n", id); ++ ++ qdma->irq = platform_get_irq(pdev, 4 * id); ++ if (qdma->irq < 0) ++ return qdma->irq; ++ ++ err = devm_request_irq(eth->dev, qdma->irq, airoha_irq_handler, ++ IRQF_SHARED, KBUILD_MODNAME, qdma); ++ if (err) ++ return err; ++ ++ err = airoha_qdma_init_rx(qdma); ++ if (err) ++ return err; ++ ++ err = airoha_qdma_init_tx(qdma); ++ if (err) ++ return err; ++ ++ err = airoha_qdma_init_hfwd_queues(qdma); ++ if (err) ++ return err; ++ ++ return airoha_qdma_hw_init(qdma); ++} ++ ++static int airoha_hw_init(struct platform_device *pdev, ++ struct airoha_eth *eth) ++{ ++ int err, i; ++ ++ /* disable xsi */ ++ err = reset_control_bulk_assert(ARRAY_SIZE(eth->xsi_rsts), ++ eth->xsi_rsts); ++ if (err) ++ return err; ++ ++ err = reset_control_bulk_assert(ARRAY_SIZE(eth->rsts), eth->rsts); ++ if (err) ++ return err; ++ ++ msleep(20); ++ err = reset_control_bulk_deassert(ARRAY_SIZE(eth->rsts), eth->rsts); ++ if (err) ++ return err; ++ ++ msleep(20); ++ err = airoha_fe_init(eth); ++ if (err) ++ return err; ++ ++ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) { ++ err = airoha_qdma_init(pdev, eth, ð->qdma[i]); ++ if (err) ++ return err; ++ } ++ ++ set_bit(DEV_STATE_INITIALIZED, ð->state); ++ ++ return 0; ++} ++ ++static void airoha_hw_cleanup(struct airoha_qdma *qdma) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { ++ if (!qdma->q_rx[i].ndesc) ++ continue; ++ ++ netif_napi_del(&qdma->q_rx[i].napi); ++ airoha_qdma_cleanup_rx_queue(&qdma->q_rx[i]); ++ if (qdma->q_rx[i].page_pool) ++ page_pool_destroy(qdma->q_rx[i].page_pool); ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) ++ netif_napi_del(&qdma->q_tx_irq[i].napi); ++ ++ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { ++ if (!qdma->q_tx[i].ndesc) ++ continue; ++ ++ airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]); ++ } ++} ++ ++static void airoha_qdma_start_napi(struct airoha_qdma *qdma) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) ++ napi_enable(&qdma->q_tx_irq[i].napi); ++ ++ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { ++ if (!qdma->q_rx[i].ndesc) ++ continue; ++ ++ napi_enable(&qdma->q_rx[i].napi); ++ } ++} ++ ++static void airoha_qdma_stop_napi(struct airoha_qdma *qdma) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) ++ napi_disable(&qdma->q_tx_irq[i].napi); ++ ++ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { ++ if (!qdma->q_rx[i].ndesc) ++ continue; ++ ++ napi_disable(&qdma->q_rx[i].napi); ++ } ++} ++ ++static void airoha_update_hw_stats(struct airoha_gdm_port *port) ++{ ++ struct airoha_eth *eth = port->qdma->eth; ++ u32 val, i = 0; ++ ++ spin_lock(&port->stats.lock); ++ u64_stats_update_begin(&port->stats.syncp); ++ ++ /* TX */ ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_PKT_CNT_H(port->id)); ++ port->stats.tx_ok_pkts += ((u64)val << 32); ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_PKT_CNT_L(port->id)); ++ port->stats.tx_ok_pkts += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_BYTE_CNT_H(port->id)); ++ port->stats.tx_ok_bytes += ((u64)val << 32); ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_BYTE_CNT_L(port->id)); ++ port->stats.tx_ok_bytes += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_DROP_CNT(port->id)); ++ port->stats.tx_drops += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_BC_CNT(port->id)); ++ port->stats.tx_broadcast += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_MC_CNT(port->id)); ++ port->stats.tx_multicast += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_RUNT_CNT(port->id)); ++ port->stats.tx_len[i] += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_E64_CNT_H(port->id)); ++ port->stats.tx_len[i] += ((u64)val << 32); ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_E64_CNT_L(port->id)); ++ port->stats.tx_len[i++] += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L64_CNT_H(port->id)); ++ port->stats.tx_len[i] += ((u64)val << 32); ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L64_CNT_L(port->id)); ++ port->stats.tx_len[i++] += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L127_CNT_H(port->id)); ++ port->stats.tx_len[i] += ((u64)val << 32); ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L127_CNT_L(port->id)); ++ port->stats.tx_len[i++] += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L255_CNT_H(port->id)); ++ port->stats.tx_len[i] += ((u64)val << 32); ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L255_CNT_L(port->id)); ++ port->stats.tx_len[i++] += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L511_CNT_H(port->id)); ++ port->stats.tx_len[i] += ((u64)val << 32); ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L511_CNT_L(port->id)); ++ port->stats.tx_len[i++] += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L1023_CNT_H(port->id)); ++ port->stats.tx_len[i] += ((u64)val << 32); ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L1023_CNT_L(port->id)); ++ port->stats.tx_len[i++] += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_LONG_CNT(port->id)); ++ port->stats.tx_len[i++] += val; ++ ++ /* RX */ ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_PKT_CNT_H(port->id)); ++ port->stats.rx_ok_pkts += ((u64)val << 32); ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_PKT_CNT_L(port->id)); ++ port->stats.rx_ok_pkts += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_BYTE_CNT_H(port->id)); ++ port->stats.rx_ok_bytes += ((u64)val << 32); ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_BYTE_CNT_L(port->id)); ++ port->stats.rx_ok_bytes += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_DROP_CNT(port->id)); ++ port->stats.rx_drops += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_BC_CNT(port->id)); ++ port->stats.rx_broadcast += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_MC_CNT(port->id)); ++ port->stats.rx_multicast += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ERROR_DROP_CNT(port->id)); ++ port->stats.rx_errors += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_CRC_ERR_CNT(port->id)); ++ port->stats.rx_crc_error += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_OVERFLOW_DROP_CNT(port->id)); ++ port->stats.rx_over_errors += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_FRAG_CNT(port->id)); ++ port->stats.rx_fragment += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_JABBER_CNT(port->id)); ++ port->stats.rx_jabber += val; ++ ++ i = 0; ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_RUNT_CNT(port->id)); ++ port->stats.rx_len[i] += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_E64_CNT_H(port->id)); ++ port->stats.rx_len[i] += ((u64)val << 32); ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_E64_CNT_L(port->id)); ++ port->stats.rx_len[i++] += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L64_CNT_H(port->id)); ++ port->stats.rx_len[i] += ((u64)val << 32); ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L64_CNT_L(port->id)); ++ port->stats.rx_len[i++] += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L127_CNT_H(port->id)); ++ port->stats.rx_len[i] += ((u64)val << 32); ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L127_CNT_L(port->id)); ++ port->stats.rx_len[i++] += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L255_CNT_H(port->id)); ++ port->stats.rx_len[i] += ((u64)val << 32); ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L255_CNT_L(port->id)); ++ port->stats.rx_len[i++] += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L511_CNT_H(port->id)); ++ port->stats.rx_len[i] += ((u64)val << 32); ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L511_CNT_L(port->id)); ++ port->stats.rx_len[i++] += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L1023_CNT_H(port->id)); ++ port->stats.rx_len[i] += ((u64)val << 32); ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L1023_CNT_L(port->id)); ++ port->stats.rx_len[i++] += val; ++ ++ val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_LONG_CNT(port->id)); ++ port->stats.rx_len[i++] += val; ++ ++ /* reset mib counters */ ++ airoha_fe_set(eth, REG_FE_GDM_MIB_CLEAR(port->id), ++ FE_GDM_MIB_RX_CLEAR_MASK | FE_GDM_MIB_TX_CLEAR_MASK); ++ ++ u64_stats_update_end(&port->stats.syncp); ++ spin_unlock(&port->stats.lock); ++} ++ ++static int airoha_dev_open(struct net_device *dev) ++{ ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ struct airoha_qdma *qdma = port->qdma; ++ int err; ++ ++ netif_tx_start_all_queues(dev); ++ err = airoha_set_gdm_ports(qdma->eth, true); ++ if (err) ++ return err; ++ ++ if (netdev_uses_dsa(dev)) ++ airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id), ++ GDM_STAG_EN_MASK); ++ else ++ airoha_fe_clear(qdma->eth, REG_GDM_INGRESS_CFG(port->id), ++ GDM_STAG_EN_MASK); ++ ++ airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG, ++ GLOBAL_CFG_TX_DMA_EN_MASK | ++ GLOBAL_CFG_RX_DMA_EN_MASK); ++ ++ return 0; ++} ++ ++static int airoha_dev_stop(struct net_device *dev) ++{ ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ struct airoha_qdma *qdma = port->qdma; ++ int i, err; ++ ++ netif_tx_disable(dev); ++ err = airoha_set_gdm_ports(qdma->eth, false); ++ if (err) ++ return err; ++ ++ airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG, ++ GLOBAL_CFG_TX_DMA_EN_MASK | ++ GLOBAL_CFG_RX_DMA_EN_MASK); ++ ++ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { ++ if (!qdma->q_tx[i].ndesc) ++ continue; ++ ++ airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]); ++ netdev_tx_reset_subqueue(dev, i); ++ } ++ ++ return 0; ++} ++ ++static int airoha_dev_set_macaddr(struct net_device *dev, void *p) ++{ ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ int err; ++ ++ err = eth_mac_addr(dev, p); ++ if (err) ++ return err; ++ ++ airoha_set_macaddr(port, dev->dev_addr); ++ ++ return 0; ++} ++ ++static int airoha_dev_init(struct net_device *dev) ++{ ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ ++ airoha_set_macaddr(port, dev->dev_addr); ++ ++ return 0; ++} ++ ++static void airoha_dev_get_stats64(struct net_device *dev, ++ struct rtnl_link_stats64 *storage) ++{ ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ unsigned int start; ++ ++ airoha_update_hw_stats(port); ++ do { ++ start = u64_stats_fetch_begin(&port->stats.syncp); ++ storage->rx_packets = port->stats.rx_ok_pkts; ++ storage->tx_packets = port->stats.tx_ok_pkts; ++ storage->rx_bytes = port->stats.rx_ok_bytes; ++ storage->tx_bytes = port->stats.tx_ok_bytes; ++ storage->multicast = port->stats.rx_multicast; ++ storage->rx_errors = port->stats.rx_errors; ++ storage->rx_dropped = port->stats.rx_drops; ++ storage->tx_dropped = port->stats.tx_drops; ++ storage->rx_crc_errors = port->stats.rx_crc_error; ++ storage->rx_over_errors = port->stats.rx_over_errors; ++ } while (u64_stats_fetch_retry(&port->stats.syncp, start)); ++} ++ ++static u16 airoha_dev_select_queue(struct net_device *dev, struct sk_buff *skb, ++ struct net_device *sb_dev) ++{ ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ int queue, channel; ++ ++ /* For dsa device select QoS channel according to the dsa user port ++ * index, rely on port id otherwise. Select QoS queue based on the ++ * skb priority. ++ */ ++ channel = netdev_uses_dsa(dev) ? skb_get_queue_mapping(skb) : port->id; ++ channel = channel % AIROHA_NUM_QOS_CHANNELS; ++ queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES; /* QoS queue */ ++ queue = channel * AIROHA_NUM_QOS_QUEUES + queue; ++ ++ return queue < dev->num_tx_queues ? queue : 0; ++} ++ ++static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, ++ struct net_device *dev) ++{ ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ u32 nr_frags = 1 + skb_shinfo(skb)->nr_frags; ++ u32 msg0, msg1, len = skb_headlen(skb); ++ struct airoha_qdma *qdma = port->qdma; ++ struct netdev_queue *txq; ++ struct airoha_queue *q; ++ void *data = skb->data; ++ int i, qid; ++ u16 index; ++ u8 fport; ++ ++ qid = skb_get_queue_mapping(skb) % ARRAY_SIZE(qdma->q_tx); ++ msg0 = FIELD_PREP(QDMA_ETH_TXMSG_CHAN_MASK, ++ qid / AIROHA_NUM_QOS_QUEUES) | ++ FIELD_PREP(QDMA_ETH_TXMSG_QUEUE_MASK, ++ qid % AIROHA_NUM_QOS_QUEUES); ++ if (skb->ip_summed == CHECKSUM_PARTIAL) ++ msg0 |= FIELD_PREP(QDMA_ETH_TXMSG_TCO_MASK, 1) | ++ FIELD_PREP(QDMA_ETH_TXMSG_UCO_MASK, 1) | ++ FIELD_PREP(QDMA_ETH_TXMSG_ICO_MASK, 1); ++ ++ /* TSO: fill MSS info in tcp checksum field */ ++ if (skb_is_gso(skb)) { ++ if (skb_cow_head(skb, 0)) ++ goto error; ++ ++ if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | ++ SKB_GSO_TCPV6)) { ++ __be16 csum = cpu_to_be16(skb_shinfo(skb)->gso_size); ++ ++ tcp_hdr(skb)->check = (__force __sum16)csum; ++ msg0 |= FIELD_PREP(QDMA_ETH_TXMSG_TSO_MASK, 1); ++ } ++ } ++ ++ fport = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id; ++ msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) | ++ FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f); ++ ++ q = &qdma->q_tx[qid]; ++ if (WARN_ON_ONCE(!q->ndesc)) ++ goto error; ++ ++ spin_lock_bh(&q->lock); ++ ++ txq = netdev_get_tx_queue(dev, qid); ++ if (q->queued + nr_frags > q->ndesc) { ++ /* not enough space in the queue */ ++ netif_tx_stop_queue(txq); ++ spin_unlock_bh(&q->lock); ++ return NETDEV_TX_BUSY; ++ } ++ ++ index = q->head; ++ for (i = 0; i < nr_frags; i++) { ++ struct airoha_qdma_desc *desc = &q->desc[index]; ++ struct airoha_queue_entry *e = &q->entry[index]; ++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; ++ dma_addr_t addr; ++ u32 val; ++ ++ addr = dma_map_single(dev->dev.parent, data, len, ++ DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(dev->dev.parent, addr))) ++ goto error_unmap; ++ ++ index = (index + 1) % q->ndesc; ++ ++ val = FIELD_PREP(QDMA_DESC_LEN_MASK, len); ++ if (i < nr_frags - 1) ++ val |= FIELD_PREP(QDMA_DESC_MORE_MASK, 1); ++ WRITE_ONCE(desc->ctrl, cpu_to_le32(val)); ++ WRITE_ONCE(desc->addr, cpu_to_le32(addr)); ++ val = FIELD_PREP(QDMA_DESC_NEXT_ID_MASK, index); ++ WRITE_ONCE(desc->data, cpu_to_le32(val)); ++ WRITE_ONCE(desc->msg0, cpu_to_le32(msg0)); ++ WRITE_ONCE(desc->msg1, cpu_to_le32(msg1)); ++ WRITE_ONCE(desc->msg2, cpu_to_le32(0xffff)); ++ ++ e->skb = i ? NULL : skb; ++ e->dma_addr = addr; ++ e->dma_len = len; ++ ++ data = skb_frag_address(frag); ++ len = skb_frag_size(frag); ++ } ++ ++ q->head = index; ++ q->queued += i; ++ ++ skb_tx_timestamp(skb); ++ netdev_tx_sent_queue(txq, skb->len); ++ ++ if (netif_xmit_stopped(txq) || !netdev_xmit_more()) ++ airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid), ++ TX_RING_CPU_IDX_MASK, ++ FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head)); ++ ++ if (q->ndesc - q->queued < q->free_thr) ++ netif_tx_stop_queue(txq); ++ ++ spin_unlock_bh(&q->lock); ++ ++ return NETDEV_TX_OK; ++ ++error_unmap: ++ for (i--; i >= 0; i--) { ++ index = (q->head + i) % q->ndesc; ++ dma_unmap_single(dev->dev.parent, q->entry[index].dma_addr, ++ q->entry[index].dma_len, DMA_TO_DEVICE); ++ } ++ ++ spin_unlock_bh(&q->lock); ++error: ++ dev_kfree_skb_any(skb); ++ dev->stats.tx_dropped++; ++ ++ return NETDEV_TX_OK; ++} ++ ++static void airoha_ethtool_get_drvinfo(struct net_device *dev, ++ struct ethtool_drvinfo *info) ++{ ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ struct airoha_eth *eth = port->qdma->eth; ++ ++ strscpy(info->driver, eth->dev->driver->name, sizeof(info->driver)); ++ strscpy(info->bus_info, dev_name(eth->dev), sizeof(info->bus_info)); ++} ++ ++static void airoha_ethtool_get_mac_stats(struct net_device *dev, ++ struct ethtool_eth_mac_stats *stats) ++{ ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ unsigned int start; ++ ++ airoha_update_hw_stats(port); ++ do { ++ start = u64_stats_fetch_begin(&port->stats.syncp); ++ stats->MulticastFramesXmittedOK = port->stats.tx_multicast; ++ stats->BroadcastFramesXmittedOK = port->stats.tx_broadcast; ++ stats->BroadcastFramesReceivedOK = port->stats.rx_broadcast; ++ } while (u64_stats_fetch_retry(&port->stats.syncp, start)); ++} ++ ++static const struct ethtool_rmon_hist_range airoha_ethtool_rmon_ranges[] = { ++ { 0, 64 }, ++ { 65, 127 }, ++ { 128, 255 }, ++ { 256, 511 }, ++ { 512, 1023 }, ++ { 1024, 1518 }, ++ { 1519, 10239 }, ++ {}, ++}; ++ ++static void ++airoha_ethtool_get_rmon_stats(struct net_device *dev, ++ struct ethtool_rmon_stats *stats, ++ const struct ethtool_rmon_hist_range **ranges) ++{ ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ struct airoha_hw_stats *hw_stats = &port->stats; ++ unsigned int start; ++ ++ BUILD_BUG_ON(ARRAY_SIZE(airoha_ethtool_rmon_ranges) != ++ ARRAY_SIZE(hw_stats->tx_len) + 1); ++ BUILD_BUG_ON(ARRAY_SIZE(airoha_ethtool_rmon_ranges) != ++ ARRAY_SIZE(hw_stats->rx_len) + 1); ++ ++ *ranges = airoha_ethtool_rmon_ranges; ++ airoha_update_hw_stats(port); ++ do { ++ int i; ++ ++ start = u64_stats_fetch_begin(&port->stats.syncp); ++ stats->fragments = hw_stats->rx_fragment; ++ stats->jabbers = hw_stats->rx_jabber; ++ for (i = 0; i < ARRAY_SIZE(airoha_ethtool_rmon_ranges) - 1; ++ i++) { ++ stats->hist[i] = hw_stats->rx_len[i]; ++ stats->hist_tx[i] = hw_stats->tx_len[i]; ++ } ++ } while (u64_stats_fetch_retry(&port->stats.syncp, start)); ++} ++ ++static int airoha_qdma_set_chan_tx_sched(struct airoha_gdm_port *port, ++ int channel, enum tx_sched_mode mode, ++ const u16 *weights, u8 n_weights) ++{ ++ int i; ++ ++ for (i = 0; i < AIROHA_NUM_TX_RING; i++) ++ airoha_qdma_clear(port->qdma, REG_QUEUE_CLOSE_CFG(channel), ++ TXQ_DISABLE_CHAN_QUEUE_MASK(channel, i)); ++ ++ for (i = 0; i < n_weights; i++) { ++ u32 status; ++ int err; ++ ++ airoha_qdma_wr(port->qdma, REG_TXWRR_WEIGHT_CFG, ++ TWRR_RW_CMD_MASK | ++ FIELD_PREP(TWRR_CHAN_IDX_MASK, channel) | ++ FIELD_PREP(TWRR_QUEUE_IDX_MASK, i) | ++ FIELD_PREP(TWRR_VALUE_MASK, weights[i])); ++ err = read_poll_timeout(airoha_qdma_rr, status, ++ status & TWRR_RW_CMD_DONE, ++ USEC_PER_MSEC, 10 * USEC_PER_MSEC, ++ true, port->qdma, ++ REG_TXWRR_WEIGHT_CFG); ++ if (err) ++ return err; ++ } ++ ++ airoha_qdma_rmw(port->qdma, REG_CHAN_QOS_MODE(channel >> 3), ++ CHAN_QOS_MODE_MASK(channel), ++ mode << __ffs(CHAN_QOS_MODE_MASK(channel))); ++ ++ return 0; ++} ++ ++static int airoha_qdma_set_tx_prio_sched(struct airoha_gdm_port *port, ++ int channel) ++{ ++ static const u16 w[AIROHA_NUM_QOS_QUEUES] = {}; ++ ++ return airoha_qdma_set_chan_tx_sched(port, channel, TC_SCH_SP, w, ++ ARRAY_SIZE(w)); ++} ++ ++static int airoha_qdma_set_tx_ets_sched(struct airoha_gdm_port *port, ++ int channel, ++ struct tc_ets_qopt_offload *opt) ++{ ++ struct tc_ets_qopt_offload_replace_params *p = &opt->replace_params; ++ enum tx_sched_mode mode = TC_SCH_SP; ++ u16 w[AIROHA_NUM_QOS_QUEUES] = {}; ++ int i, nstrict = 0, nwrr, qidx; ++ ++ if (p->bands > AIROHA_NUM_QOS_QUEUES) ++ return -EINVAL; ++ ++ for (i = 0; i < p->bands; i++) { ++ if (!p->quanta[i]) ++ nstrict++; ++ } ++ ++ /* this configuration is not supported by the hw */ ++ if (nstrict == AIROHA_NUM_QOS_QUEUES - 1) ++ return -EINVAL; ++ ++ /* EN7581 SoC supports fixed QoS band priority where WRR queues have ++ * lowest priorities with respect to SP ones. ++ * e.g: WRR0, WRR1, .., WRRm, SP0, SP1, .., SPn ++ */ ++ nwrr = p->bands - nstrict; ++ qidx = nstrict && nwrr ? nstrict : 0; ++ for (i = 1; i <= p->bands; i++) { ++ if (p->priomap[i % AIROHA_NUM_QOS_QUEUES] != qidx) ++ return -EINVAL; ++ ++ qidx = i == nwrr ? 0 : qidx + 1; ++ } ++ ++ for (i = 0; i < nwrr; i++) ++ w[i] = p->weights[nstrict + i]; ++ ++ if (!nstrict) ++ mode = TC_SCH_WRR8; ++ else if (nstrict < AIROHA_NUM_QOS_QUEUES - 1) ++ mode = nstrict + 1; ++ ++ return airoha_qdma_set_chan_tx_sched(port, channel, mode, w, ++ ARRAY_SIZE(w)); ++} ++ ++static int airoha_qdma_get_tx_ets_stats(struct airoha_gdm_port *port, ++ int channel, ++ struct tc_ets_qopt_offload *opt) ++{ ++ u64 cpu_tx_packets = airoha_qdma_rr(port->qdma, ++ REG_CNTR_VAL(channel << 1)); ++ u64 fwd_tx_packets = airoha_qdma_rr(port->qdma, ++ REG_CNTR_VAL((channel << 1) + 1)); ++ u64 tx_packets = (cpu_tx_packets - port->cpu_tx_packets) + ++ (fwd_tx_packets - port->fwd_tx_packets); ++ _bstats_update(opt->stats.bstats, 0, tx_packets); ++ ++ port->cpu_tx_packets = cpu_tx_packets; ++ port->fwd_tx_packets = fwd_tx_packets; ++ ++ return 0; ++} ++ ++static int airoha_tc_setup_qdisc_ets(struct airoha_gdm_port *port, ++ struct tc_ets_qopt_offload *opt) ++{ ++ int channel = TC_H_MAJ(opt->handle) >> 16; ++ ++ if (opt->parent == TC_H_ROOT) ++ return -EINVAL; ++ ++ switch (opt->command) { ++ case TC_ETS_REPLACE: ++ return airoha_qdma_set_tx_ets_sched(port, channel, opt); ++ case TC_ETS_DESTROY: ++ /* PRIO is default qdisc scheduler */ ++ return airoha_qdma_set_tx_prio_sched(port, channel); ++ case TC_ETS_STATS: ++ return airoha_qdma_get_tx_ets_stats(port, channel, opt); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static int airoha_qdma_get_trtcm_param(struct airoha_qdma *qdma, int channel, ++ u32 addr, enum trtcm_param_type param, ++ enum trtcm_mode_type mode, ++ u32 *val_low, u32 *val_high) ++{ ++ u32 idx = QDMA_METER_IDX(channel), group = QDMA_METER_GROUP(channel); ++ u32 val, config = FIELD_PREP(TRTCM_PARAM_TYPE_MASK, param) | ++ FIELD_PREP(TRTCM_METER_GROUP_MASK, group) | ++ FIELD_PREP(TRTCM_PARAM_INDEX_MASK, idx) | ++ FIELD_PREP(TRTCM_PARAM_RATE_TYPE_MASK, mode); ++ ++ airoha_qdma_wr(qdma, REG_TRTCM_CFG_PARAM(addr), config); ++ if (read_poll_timeout(airoha_qdma_rr, val, ++ val & TRTCM_PARAM_RW_DONE_MASK, ++ USEC_PER_MSEC, 10 * USEC_PER_MSEC, true, ++ qdma, REG_TRTCM_CFG_PARAM(addr))) ++ return -ETIMEDOUT; ++ ++ *val_low = airoha_qdma_rr(qdma, REG_TRTCM_DATA_LOW(addr)); ++ if (val_high) ++ *val_high = airoha_qdma_rr(qdma, REG_TRTCM_DATA_HIGH(addr)); ++ ++ return 0; ++} ++ ++static int airoha_qdma_set_trtcm_param(struct airoha_qdma *qdma, int channel, ++ u32 addr, enum trtcm_param_type param, ++ enum trtcm_mode_type mode, u32 val) ++{ ++ u32 idx = QDMA_METER_IDX(channel), group = QDMA_METER_GROUP(channel); ++ u32 config = TRTCM_PARAM_RW_MASK | ++ FIELD_PREP(TRTCM_PARAM_TYPE_MASK, param) | ++ FIELD_PREP(TRTCM_METER_GROUP_MASK, group) | ++ FIELD_PREP(TRTCM_PARAM_INDEX_MASK, idx) | ++ FIELD_PREP(TRTCM_PARAM_RATE_TYPE_MASK, mode); ++ ++ airoha_qdma_wr(qdma, REG_TRTCM_DATA_LOW(addr), val); ++ airoha_qdma_wr(qdma, REG_TRTCM_CFG_PARAM(addr), config); ++ ++ return read_poll_timeout(airoha_qdma_rr, val, ++ val & TRTCM_PARAM_RW_DONE_MASK, ++ USEC_PER_MSEC, 10 * USEC_PER_MSEC, true, ++ qdma, REG_TRTCM_CFG_PARAM(addr)); ++} ++ ++static int airoha_qdma_set_trtcm_config(struct airoha_qdma *qdma, int channel, ++ u32 addr, enum trtcm_mode_type mode, ++ bool enable, u32 enable_mask) ++{ ++ u32 val; ++ ++ if (airoha_qdma_get_trtcm_param(qdma, channel, addr, TRTCM_MISC_MODE, ++ mode, &val, NULL)) ++ return -EINVAL; ++ ++ val = enable ? val | enable_mask : val & ~enable_mask; ++ ++ return airoha_qdma_set_trtcm_param(qdma, channel, addr, TRTCM_MISC_MODE, ++ mode, val); ++} ++ ++static int airoha_qdma_set_trtcm_token_bucket(struct airoha_qdma *qdma, ++ int channel, u32 addr, ++ enum trtcm_mode_type mode, ++ u32 rate_val, u32 bucket_size) ++{ ++ u32 val, config, tick, unit, rate, rate_frac; ++ int err; ++ ++ if (airoha_qdma_get_trtcm_param(qdma, channel, addr, TRTCM_MISC_MODE, ++ mode, &config, NULL)) ++ return -EINVAL; ++ ++ val = airoha_qdma_rr(qdma, addr); ++ tick = FIELD_GET(INGRESS_FAST_TICK_MASK, val); ++ if (config & TRTCM_TICK_SEL) ++ tick *= FIELD_GET(INGRESS_SLOW_TICK_RATIO_MASK, val); ++ if (!tick) ++ return -EINVAL; ++ ++ unit = (config & TRTCM_PKT_MODE) ? 1000000 / tick : 8000 / tick; ++ if (!unit) ++ return -EINVAL; ++ ++ rate = rate_val / unit; ++ rate_frac = rate_val % unit; ++ rate_frac = FIELD_PREP(TRTCM_TOKEN_RATE_MASK, rate_frac) / unit; ++ rate = FIELD_PREP(TRTCM_TOKEN_RATE_MASK, rate) | ++ FIELD_PREP(TRTCM_TOKEN_RATE_FRACTION_MASK, rate_frac); ++ ++ err = airoha_qdma_set_trtcm_param(qdma, channel, addr, ++ TRTCM_TOKEN_RATE_MODE, mode, rate); ++ if (err) ++ return err; ++ ++ val = max_t(u32, bucket_size, MIN_TOKEN_SIZE); ++ val = min_t(u32, __fls(val), MAX_TOKEN_SIZE_OFFSET); ++ ++ return airoha_qdma_set_trtcm_param(qdma, channel, addr, ++ TRTCM_BUCKETSIZE_SHIFT_MODE, ++ mode, val); ++} ++ ++static int airoha_qdma_set_tx_rate_limit(struct airoha_gdm_port *port, ++ int channel, u32 rate, ++ u32 bucket_size) ++{ ++ int i, err; ++ ++ for (i = 0; i <= TRTCM_PEAK_MODE; i++) { ++ err = airoha_qdma_set_trtcm_config(port->qdma, channel, ++ REG_EGRESS_TRTCM_CFG, i, ++ !!rate, TRTCM_METER_MODE); ++ if (err) ++ return err; ++ ++ err = airoha_qdma_set_trtcm_token_bucket(port->qdma, channel, ++ REG_EGRESS_TRTCM_CFG, ++ i, rate, bucket_size); ++ if (err) ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int airoha_tc_htb_alloc_leaf_queue(struct airoha_gdm_port *port, ++ struct tc_htb_qopt_offload *opt) ++{ ++ u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; ++ u32 rate = div_u64(opt->rate, 1000) << 3; /* kbps */ ++ struct net_device *dev = port->dev; ++ int num_tx_queues = dev->real_num_tx_queues; ++ int err; ++ ++ if (opt->parent_classid != TC_HTB_CLASSID_ROOT) { ++ NL_SET_ERR_MSG_MOD(opt->extack, "invalid parent classid"); ++ return -EINVAL; ++ } ++ ++ err = airoha_qdma_set_tx_rate_limit(port, channel, rate, opt->quantum); ++ if (err) { ++ NL_SET_ERR_MSG_MOD(opt->extack, ++ "failed configuring htb offload"); ++ return err; ++ } ++ ++ if (opt->command == TC_HTB_NODE_MODIFY) ++ return 0; ++ ++ err = netif_set_real_num_tx_queues(dev, num_tx_queues + 1); ++ if (err) { ++ airoha_qdma_set_tx_rate_limit(port, channel, 0, opt->quantum); ++ NL_SET_ERR_MSG_MOD(opt->extack, ++ "failed setting real_num_tx_queues"); ++ return err; ++ } ++ ++ set_bit(channel, port->qos_sq_bmap); ++ opt->qid = AIROHA_NUM_TX_RING + channel; ++ ++ return 0; ++} ++ ++static void airoha_tc_remove_htb_queue(struct airoha_gdm_port *port, int queue) ++{ ++ struct net_device *dev = port->dev; ++ ++ netif_set_real_num_tx_queues(dev, dev->real_num_tx_queues - 1); ++ airoha_qdma_set_tx_rate_limit(port, queue + 1, 0, 0); ++ clear_bit(queue, port->qos_sq_bmap); ++} ++ ++static int airoha_tc_htb_delete_leaf_queue(struct airoha_gdm_port *port, ++ struct tc_htb_qopt_offload *opt) ++{ ++ u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; ++ ++ if (!test_bit(channel, port->qos_sq_bmap)) { ++ NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); ++ return -EINVAL; ++ } ++ ++ airoha_tc_remove_htb_queue(port, channel); ++ ++ return 0; ++} ++ ++static int airoha_tc_htb_destroy(struct airoha_gdm_port *port) ++{ ++ int q; ++ ++ for_each_set_bit(q, port->qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS) ++ airoha_tc_remove_htb_queue(port, q); ++ ++ return 0; ++} ++ ++static int airoha_tc_get_htb_get_leaf_queue(struct airoha_gdm_port *port, ++ struct tc_htb_qopt_offload *opt) ++{ ++ u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; ++ ++ if (!test_bit(channel, port->qos_sq_bmap)) { ++ NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); ++ return -EINVAL; ++ } ++ ++ opt->qid = channel; ++ ++ return 0; ++} ++ ++static int airoha_tc_setup_qdisc_htb(struct airoha_gdm_port *port, ++ struct tc_htb_qopt_offload *opt) ++{ ++ switch (opt->command) { ++ case TC_HTB_CREATE: ++ break; ++ case TC_HTB_DESTROY: ++ return airoha_tc_htb_destroy(port); ++ case TC_HTB_NODE_MODIFY: ++ case TC_HTB_LEAF_ALLOC_QUEUE: ++ return airoha_tc_htb_alloc_leaf_queue(port, opt); ++ case TC_HTB_LEAF_DEL: ++ case TC_HTB_LEAF_DEL_LAST: ++ case TC_HTB_LEAF_DEL_LAST_FORCE: ++ return airoha_tc_htb_delete_leaf_queue(port, opt); ++ case TC_HTB_LEAF_QUERY_QUEUE: ++ return airoha_tc_get_htb_get_leaf_queue(port, opt); ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ return 0; ++} ++ ++static int airoha_dev_tc_setup(struct net_device *dev, enum tc_setup_type type, ++ void *type_data) ++{ ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ ++ switch (type) { ++ case TC_SETUP_QDISC_ETS: ++ return airoha_tc_setup_qdisc_ets(port, type_data); ++ case TC_SETUP_QDISC_HTB: ++ return airoha_tc_setup_qdisc_htb(port, type_data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static const struct net_device_ops airoha_netdev_ops = { ++ .ndo_init = airoha_dev_init, ++ .ndo_open = airoha_dev_open, ++ .ndo_stop = airoha_dev_stop, ++ .ndo_select_queue = airoha_dev_select_queue, ++ .ndo_start_xmit = airoha_dev_xmit, ++ .ndo_get_stats64 = airoha_dev_get_stats64, ++ .ndo_set_mac_address = airoha_dev_set_macaddr, ++ .ndo_setup_tc = airoha_dev_tc_setup, ++}; ++ ++static const struct ethtool_ops airoha_ethtool_ops = { ++ .get_drvinfo = airoha_ethtool_get_drvinfo, ++ .get_eth_mac_stats = airoha_ethtool_get_mac_stats, ++ .get_rmon_stats = airoha_ethtool_get_rmon_stats, ++}; ++ ++static int airoha_alloc_gdm_port(struct airoha_eth *eth, struct device_node *np) ++{ ++ const __be32 *id_ptr = of_get_property(np, "reg", NULL); ++ struct airoha_gdm_port *port; ++ struct airoha_qdma *qdma; ++ struct net_device *dev; ++ int err, index; ++ u32 id; ++ ++ if (!id_ptr) { ++ dev_err(eth->dev, "missing gdm port id\n"); ++ return -EINVAL; ++ } ++ ++ id = be32_to_cpup(id_ptr); ++ index = id - 1; ++ ++ if (!id || id > ARRAY_SIZE(eth->ports)) { ++ dev_err(eth->dev, "invalid gdm port id: %d\n", id); ++ return -EINVAL; ++ } ++ ++ if (eth->ports[index]) { ++ dev_err(eth->dev, "duplicate gdm port id: %d\n", id); ++ return -EINVAL; ++ } ++ ++ dev = devm_alloc_etherdev_mqs(eth->dev, sizeof(*port), ++ AIROHA_NUM_NETDEV_TX_RINGS, ++ AIROHA_NUM_RX_RING); ++ if (!dev) { ++ dev_err(eth->dev, "alloc_etherdev failed\n"); ++ return -ENOMEM; ++ } ++ ++ qdma = ð->qdma[index % AIROHA_MAX_NUM_QDMA]; ++ dev->netdev_ops = &airoha_netdev_ops; ++ dev->ethtool_ops = &airoha_ethtool_ops; ++ dev->max_mtu = AIROHA_MAX_MTU; ++ dev->watchdog_timeo = 5 * HZ; ++ dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | ++ NETIF_F_TSO6 | NETIF_F_IPV6_CSUM | ++ NETIF_F_SG | NETIF_F_TSO | ++ NETIF_F_HW_TC; ++ dev->features |= dev->hw_features; ++ dev->dev.of_node = np; ++ dev->irq = qdma->irq; ++ SET_NETDEV_DEV(dev, eth->dev); ++ ++ /* reserve hw queues for HTB offloading */ ++ err = netif_set_real_num_tx_queues(dev, AIROHA_NUM_TX_RING); ++ if (err) ++ return err; ++ ++ err = of_get_ethdev_address(np, dev); ++ if (err) { ++ if (err == -EPROBE_DEFER) ++ return err; ++ ++ eth_hw_addr_random(dev); ++ dev_info(eth->dev, "generated random MAC address %pM\n", ++ dev->dev_addr); ++ } ++ ++ port = netdev_priv(dev); ++ u64_stats_init(&port->stats.syncp); ++ spin_lock_init(&port->stats.lock); ++ port->qdma = qdma; ++ port->dev = dev; ++ port->id = id; ++ eth->ports[index] = port; ++ ++ return register_netdev(dev); ++} ++ ++static int airoha_probe(struct platform_device *pdev) ++{ ++ struct device_node *np; ++ struct airoha_eth *eth; ++ int i, err; ++ ++ eth = devm_kzalloc(&pdev->dev, sizeof(*eth), GFP_KERNEL); ++ if (!eth) ++ return -ENOMEM; ++ ++ eth->dev = &pdev->dev; ++ ++ err = dma_set_mask_and_coherent(eth->dev, DMA_BIT_MASK(32)); ++ if (err) { ++ dev_err(eth->dev, "failed configuring DMA mask\n"); ++ return err; ++ } ++ ++ eth->fe_regs = devm_platform_ioremap_resource_byname(pdev, "fe"); ++ if (IS_ERR(eth->fe_regs)) ++ return dev_err_probe(eth->dev, PTR_ERR(eth->fe_regs), ++ "failed to iomap fe regs\n"); ++ ++ eth->rsts[0].id = "fe"; ++ eth->rsts[1].id = "pdma"; ++ eth->rsts[2].id = "qdma"; ++ err = devm_reset_control_bulk_get_exclusive(eth->dev, ++ ARRAY_SIZE(eth->rsts), ++ eth->rsts); ++ if (err) { ++ dev_err(eth->dev, "failed to get bulk reset lines\n"); ++ return err; ++ } ++ ++ eth->xsi_rsts[0].id = "xsi-mac"; ++ eth->xsi_rsts[1].id = "hsi0-mac"; ++ eth->xsi_rsts[2].id = "hsi1-mac"; ++ eth->xsi_rsts[3].id = "hsi-mac"; ++ eth->xsi_rsts[4].id = "xfp-mac"; ++ err = devm_reset_control_bulk_get_exclusive(eth->dev, ++ ARRAY_SIZE(eth->xsi_rsts), ++ eth->xsi_rsts); ++ if (err) { ++ dev_err(eth->dev, "failed to get bulk xsi reset lines\n"); ++ return err; ++ } ++ ++ eth->napi_dev = alloc_netdev_dummy(0); ++ if (!eth->napi_dev) ++ return -ENOMEM; ++ ++ /* Enable threaded NAPI by default */ ++ eth->napi_dev->threaded = true; ++ strscpy(eth->napi_dev->name, "qdma_eth", sizeof(eth->napi_dev->name)); ++ platform_set_drvdata(pdev, eth); ++ ++ err = airoha_hw_init(pdev, eth); ++ if (err) ++ goto error_hw_cleanup; ++ ++ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) ++ airoha_qdma_start_napi(ð->qdma[i]); ++ ++ for_each_child_of_node(pdev->dev.of_node, np) { ++ if (!of_device_is_compatible(np, "airoha,eth-mac")) ++ continue; ++ ++ if (!of_device_is_available(np)) ++ continue; ++ ++ err = airoha_alloc_gdm_port(eth, np); ++ if (err) { ++ of_node_put(np); ++ goto error_napi_stop; ++ } ++ } ++ ++ return 0; ++ ++error_napi_stop: ++ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) ++ airoha_qdma_stop_napi(ð->qdma[i]); ++error_hw_cleanup: ++ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) ++ airoha_hw_cleanup(ð->qdma[i]); ++ ++ for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { ++ struct airoha_gdm_port *port = eth->ports[i]; ++ ++ if (port && port->dev->reg_state == NETREG_REGISTERED) ++ unregister_netdev(port->dev); ++ } ++ free_netdev(eth->napi_dev); ++ platform_set_drvdata(pdev, NULL); ++ ++ return err; ++} ++ ++static void airoha_remove(struct platform_device *pdev) ++{ ++ struct airoha_eth *eth = platform_get_drvdata(pdev); ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) { ++ airoha_qdma_stop_napi(ð->qdma[i]); ++ airoha_hw_cleanup(ð->qdma[i]); ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { ++ struct airoha_gdm_port *port = eth->ports[i]; ++ ++ if (!port) ++ continue; ++ ++ airoha_dev_stop(port->dev); ++ unregister_netdev(port->dev); ++ } ++ free_netdev(eth->napi_dev); ++ ++ platform_set_drvdata(pdev, NULL); ++} ++ ++static const struct of_device_id of_airoha_match[] = { ++ { .compatible = "airoha,en7581-eth" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, of_airoha_match); ++ ++static struct platform_driver airoha_driver = { ++ .probe = airoha_probe, ++ .remove_new = airoha_remove, ++ .driver = { ++ .name = KBUILD_MODNAME, ++ .of_match_table = of_airoha_match, ++ }, ++}; ++module_platform_driver(airoha_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Lorenzo Bianconi "); ++MODULE_DESCRIPTION("Ethernet driver for Airoha SoC"); +--- a/drivers/net/ethernet/mediatek/airoha_eth.c ++++ /dev/null +@@ -1,3358 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-only +-/* +- * Copyright (c) 2024 AIROHA Inc +- * Author: Lorenzo Bianconi +- */ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#define AIROHA_MAX_NUM_GDM_PORTS 1 +-#define AIROHA_MAX_NUM_QDMA 2 +-#define AIROHA_MAX_NUM_RSTS 3 +-#define AIROHA_MAX_NUM_XSI_RSTS 5 +-#define AIROHA_MAX_MTU 2000 +-#define AIROHA_MAX_PACKET_SIZE 2048 +-#define AIROHA_NUM_QOS_CHANNELS 4 +-#define AIROHA_NUM_QOS_QUEUES 8 +-#define AIROHA_NUM_TX_RING 32 +-#define AIROHA_NUM_RX_RING 32 +-#define AIROHA_NUM_NETDEV_TX_RINGS (AIROHA_NUM_TX_RING + \ +- AIROHA_NUM_QOS_CHANNELS) +-#define AIROHA_FE_MC_MAX_VLAN_TABLE 64 +-#define AIROHA_FE_MC_MAX_VLAN_PORT 16 +-#define AIROHA_NUM_TX_IRQ 2 +-#define HW_DSCP_NUM 2048 +-#define IRQ_QUEUE_LEN(_n) ((_n) ? 1024 : 2048) +-#define TX_DSCP_NUM 1024 +-#define RX_DSCP_NUM(_n) \ +- ((_n) == 2 ? 128 : \ +- (_n) == 11 ? 128 : \ +- (_n) == 15 ? 128 : \ +- (_n) == 0 ? 1024 : 16) +- +-#define PSE_RSV_PAGES 128 +-#define PSE_QUEUE_RSV_PAGES 64 +- +-#define QDMA_METER_IDX(_n) ((_n) & 0xff) +-#define QDMA_METER_GROUP(_n) (((_n) >> 8) & 0x3) +- +-/* FE */ +-#define PSE_BASE 0x0100 +-#define CSR_IFC_BASE 0x0200 +-#define CDM1_BASE 0x0400 +-#define GDM1_BASE 0x0500 +-#define PPE1_BASE 0x0c00 +- +-#define CDM2_BASE 0x1400 +-#define GDM2_BASE 0x1500 +- +-#define GDM3_BASE 0x1100 +-#define GDM4_BASE 0x2500 +- +-#define GDM_BASE(_n) \ +- ((_n) == 4 ? GDM4_BASE : \ +- (_n) == 3 ? GDM3_BASE : \ +- (_n) == 2 ? GDM2_BASE : GDM1_BASE) +- +-#define REG_FE_DMA_GLO_CFG 0x0000 +-#define FE_DMA_GLO_L2_SPACE_MASK GENMASK(7, 4) +-#define FE_DMA_GLO_PG_SZ_MASK BIT(3) +- +-#define REG_FE_RST_GLO_CFG 0x0004 +-#define FE_RST_GDM4_MBI_ARB_MASK BIT(3) +-#define FE_RST_GDM3_MBI_ARB_MASK BIT(2) +-#define FE_RST_CORE_MASK BIT(0) +- +-#define REG_FE_WAN_MAC_H 0x0030 +-#define REG_FE_LAN_MAC_H 0x0040 +- +-#define REG_FE_MAC_LMIN(_n) ((_n) + 0x04) +-#define REG_FE_MAC_LMAX(_n) ((_n) + 0x08) +- +-#define REG_FE_CDM1_OQ_MAP0 0x0050 +-#define REG_FE_CDM1_OQ_MAP1 0x0054 +-#define REG_FE_CDM1_OQ_MAP2 0x0058 +-#define REG_FE_CDM1_OQ_MAP3 0x005c +- +-#define REG_FE_PCE_CFG 0x0070 +-#define PCE_DPI_EN_MASK BIT(2) +-#define PCE_KA_EN_MASK BIT(1) +-#define PCE_MC_EN_MASK BIT(0) +- +-#define REG_FE_PSE_QUEUE_CFG_WR 0x0080 +-#define PSE_CFG_PORT_ID_MASK GENMASK(27, 24) +-#define PSE_CFG_QUEUE_ID_MASK GENMASK(20, 16) +-#define PSE_CFG_WR_EN_MASK BIT(8) +-#define PSE_CFG_OQRSV_SEL_MASK BIT(0) +- +-#define REG_FE_PSE_QUEUE_CFG_VAL 0x0084 +-#define PSE_CFG_OQ_RSV_MASK GENMASK(13, 0) +- +-#define PSE_FQ_CFG 0x008c +-#define PSE_FQ_LIMIT_MASK GENMASK(14, 0) +- +-#define REG_FE_PSE_BUF_SET 0x0090 +-#define PSE_SHARE_USED_LTHD_MASK GENMASK(31, 16) +-#define PSE_ALLRSV_MASK GENMASK(14, 0) +- +-#define REG_PSE_SHARE_USED_THD 0x0094 +-#define PSE_SHARE_USED_MTHD_MASK GENMASK(31, 16) +-#define PSE_SHARE_USED_HTHD_MASK GENMASK(15, 0) +- +-#define REG_GDM_MISC_CFG 0x0148 +-#define GDM2_RDM_ACK_WAIT_PREF_MASK BIT(9) +-#define GDM2_CHN_VLD_MODE_MASK BIT(5) +- +-#define REG_FE_CSR_IFC_CFG CSR_IFC_BASE +-#define FE_IFC_EN_MASK BIT(0) +- +-#define REG_FE_VIP_PORT_EN 0x01f0 +-#define REG_FE_IFC_PORT_EN 0x01f4 +- +-#define REG_PSE_IQ_REV1 (PSE_BASE + 0x08) +-#define PSE_IQ_RES1_P2_MASK GENMASK(23, 16) +- +-#define REG_PSE_IQ_REV2 (PSE_BASE + 0x0c) +-#define PSE_IQ_RES2_P5_MASK GENMASK(15, 8) +-#define PSE_IQ_RES2_P4_MASK GENMASK(7, 0) +- +-#define REG_FE_VIP_EN(_n) (0x0300 + ((_n) << 3)) +-#define PATN_FCPU_EN_MASK BIT(7) +-#define PATN_SWP_EN_MASK BIT(6) +-#define PATN_DP_EN_MASK BIT(5) +-#define PATN_SP_EN_MASK BIT(4) +-#define PATN_TYPE_MASK GENMASK(3, 1) +-#define PATN_EN_MASK BIT(0) +- +-#define REG_FE_VIP_PATN(_n) (0x0304 + ((_n) << 3)) +-#define PATN_DP_MASK GENMASK(31, 16) +-#define PATN_SP_MASK GENMASK(15, 0) +- +-#define REG_CDM1_VLAN_CTRL CDM1_BASE +-#define CDM1_VLAN_MASK GENMASK(31, 16) +- +-#define REG_CDM1_FWD_CFG (CDM1_BASE + 0x08) +-#define CDM1_VIP_QSEL_MASK GENMASK(24, 20) +- +-#define REG_CDM1_CRSN_QSEL(_n) (CDM1_BASE + 0x10 + ((_n) << 2)) +-#define CDM1_CRSN_QSEL_REASON_MASK(_n) \ +- GENMASK(4 + (((_n) % 4) << 3), (((_n) % 4) << 3)) +- +-#define REG_CDM2_FWD_CFG (CDM2_BASE + 0x08) +-#define CDM2_OAM_QSEL_MASK GENMASK(31, 27) +-#define CDM2_VIP_QSEL_MASK GENMASK(24, 20) +- +-#define REG_CDM2_CRSN_QSEL(_n) (CDM2_BASE + 0x10 + ((_n) << 2)) +-#define CDM2_CRSN_QSEL_REASON_MASK(_n) \ +- GENMASK(4 + (((_n) % 4) << 3), (((_n) % 4) << 3)) +- +-#define REG_GDM_FWD_CFG(_n) GDM_BASE(_n) +-#define GDM_DROP_CRC_ERR BIT(23) +-#define GDM_IP4_CKSUM BIT(22) +-#define GDM_TCP_CKSUM BIT(21) +-#define GDM_UDP_CKSUM BIT(20) +-#define GDM_UCFQ_MASK GENMASK(15, 12) +-#define GDM_BCFQ_MASK GENMASK(11, 8) +-#define GDM_MCFQ_MASK GENMASK(7, 4) +-#define GDM_OCFQ_MASK GENMASK(3, 0) +- +-#define REG_GDM_INGRESS_CFG(_n) (GDM_BASE(_n) + 0x10) +-#define GDM_INGRESS_FC_EN_MASK BIT(1) +-#define GDM_STAG_EN_MASK BIT(0) +- +-#define REG_GDM_LEN_CFG(_n) (GDM_BASE(_n) + 0x14) +-#define GDM_SHORT_LEN_MASK GENMASK(13, 0) +-#define GDM_LONG_LEN_MASK GENMASK(29, 16) +- +-#define REG_FE_CPORT_CFG (GDM1_BASE + 0x40) +-#define FE_CPORT_PAD BIT(26) +-#define FE_CPORT_PORT_XFC_MASK BIT(25) +-#define FE_CPORT_QUEUE_XFC_MASK BIT(24) +- +-#define REG_FE_GDM_MIB_CLEAR(_n) (GDM_BASE(_n) + 0xf0) +-#define FE_GDM_MIB_RX_CLEAR_MASK BIT(1) +-#define FE_GDM_MIB_TX_CLEAR_MASK BIT(0) +- +-#define REG_FE_GDM1_MIB_CFG (GDM1_BASE + 0xf4) +-#define FE_STRICT_RFC2819_MODE_MASK BIT(31) +-#define FE_GDM1_TX_MIB_SPLIT_EN_MASK BIT(17) +-#define FE_GDM1_RX_MIB_SPLIT_EN_MASK BIT(16) +-#define FE_TX_MIB_ID_MASK GENMASK(15, 8) +-#define FE_RX_MIB_ID_MASK GENMASK(7, 0) +- +-#define REG_FE_GDM_TX_OK_PKT_CNT_L(_n) (GDM_BASE(_n) + 0x104) +-#define REG_FE_GDM_TX_OK_BYTE_CNT_L(_n) (GDM_BASE(_n) + 0x10c) +-#define REG_FE_GDM_TX_ETH_PKT_CNT_L(_n) (GDM_BASE(_n) + 0x110) +-#define REG_FE_GDM_TX_ETH_BYTE_CNT_L(_n) (GDM_BASE(_n) + 0x114) +-#define REG_FE_GDM_TX_ETH_DROP_CNT(_n) (GDM_BASE(_n) + 0x118) +-#define REG_FE_GDM_TX_ETH_BC_CNT(_n) (GDM_BASE(_n) + 0x11c) +-#define REG_FE_GDM_TX_ETH_MC_CNT(_n) (GDM_BASE(_n) + 0x120) +-#define REG_FE_GDM_TX_ETH_RUNT_CNT(_n) (GDM_BASE(_n) + 0x124) +-#define REG_FE_GDM_TX_ETH_LONG_CNT(_n) (GDM_BASE(_n) + 0x128) +-#define REG_FE_GDM_TX_ETH_E64_CNT_L(_n) (GDM_BASE(_n) + 0x12c) +-#define REG_FE_GDM_TX_ETH_L64_CNT_L(_n) (GDM_BASE(_n) + 0x130) +-#define REG_FE_GDM_TX_ETH_L127_CNT_L(_n) (GDM_BASE(_n) + 0x134) +-#define REG_FE_GDM_TX_ETH_L255_CNT_L(_n) (GDM_BASE(_n) + 0x138) +-#define REG_FE_GDM_TX_ETH_L511_CNT_L(_n) (GDM_BASE(_n) + 0x13c) +-#define REG_FE_GDM_TX_ETH_L1023_CNT_L(_n) (GDM_BASE(_n) + 0x140) +- +-#define REG_FE_GDM_RX_OK_PKT_CNT_L(_n) (GDM_BASE(_n) + 0x148) +-#define REG_FE_GDM_RX_FC_DROP_CNT(_n) (GDM_BASE(_n) + 0x14c) +-#define REG_FE_GDM_RX_RC_DROP_CNT(_n) (GDM_BASE(_n) + 0x150) +-#define REG_FE_GDM_RX_OVERFLOW_DROP_CNT(_n) (GDM_BASE(_n) + 0x154) +-#define REG_FE_GDM_RX_ERROR_DROP_CNT(_n) (GDM_BASE(_n) + 0x158) +-#define REG_FE_GDM_RX_OK_BYTE_CNT_L(_n) (GDM_BASE(_n) + 0x15c) +-#define REG_FE_GDM_RX_ETH_PKT_CNT_L(_n) (GDM_BASE(_n) + 0x160) +-#define REG_FE_GDM_RX_ETH_BYTE_CNT_L(_n) (GDM_BASE(_n) + 0x164) +-#define REG_FE_GDM_RX_ETH_DROP_CNT(_n) (GDM_BASE(_n) + 0x168) +-#define REG_FE_GDM_RX_ETH_BC_CNT(_n) (GDM_BASE(_n) + 0x16c) +-#define REG_FE_GDM_RX_ETH_MC_CNT(_n) (GDM_BASE(_n) + 0x170) +-#define REG_FE_GDM_RX_ETH_CRC_ERR_CNT(_n) (GDM_BASE(_n) + 0x174) +-#define REG_FE_GDM_RX_ETH_FRAG_CNT(_n) (GDM_BASE(_n) + 0x178) +-#define REG_FE_GDM_RX_ETH_JABBER_CNT(_n) (GDM_BASE(_n) + 0x17c) +-#define REG_FE_GDM_RX_ETH_RUNT_CNT(_n) (GDM_BASE(_n) + 0x180) +-#define REG_FE_GDM_RX_ETH_LONG_CNT(_n) (GDM_BASE(_n) + 0x184) +-#define REG_FE_GDM_RX_ETH_E64_CNT_L(_n) (GDM_BASE(_n) + 0x188) +-#define REG_FE_GDM_RX_ETH_L64_CNT_L(_n) (GDM_BASE(_n) + 0x18c) +-#define REG_FE_GDM_RX_ETH_L127_CNT_L(_n) (GDM_BASE(_n) + 0x190) +-#define REG_FE_GDM_RX_ETH_L255_CNT_L(_n) (GDM_BASE(_n) + 0x194) +-#define REG_FE_GDM_RX_ETH_L511_CNT_L(_n) (GDM_BASE(_n) + 0x198) +-#define REG_FE_GDM_RX_ETH_L1023_CNT_L(_n) (GDM_BASE(_n) + 0x19c) +- +-#define REG_PPE1_TB_HASH_CFG (PPE1_BASE + 0x250) +-#define PPE1_SRAM_TABLE_EN_MASK BIT(0) +-#define PPE1_SRAM_HASH1_EN_MASK BIT(8) +-#define PPE1_DRAM_TABLE_EN_MASK BIT(16) +-#define PPE1_DRAM_HASH1_EN_MASK BIT(24) +- +-#define REG_FE_GDM_TX_OK_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x280) +-#define REG_FE_GDM_TX_OK_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x284) +-#define REG_FE_GDM_TX_ETH_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x288) +-#define REG_FE_GDM_TX_ETH_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x28c) +- +-#define REG_FE_GDM_RX_OK_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x290) +-#define REG_FE_GDM_RX_OK_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x294) +-#define REG_FE_GDM_RX_ETH_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x298) +-#define REG_FE_GDM_RX_ETH_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x29c) +-#define REG_FE_GDM_TX_ETH_E64_CNT_H(_n) (GDM_BASE(_n) + 0x2b8) +-#define REG_FE_GDM_TX_ETH_L64_CNT_H(_n) (GDM_BASE(_n) + 0x2bc) +-#define REG_FE_GDM_TX_ETH_L127_CNT_H(_n) (GDM_BASE(_n) + 0x2c0) +-#define REG_FE_GDM_TX_ETH_L255_CNT_H(_n) (GDM_BASE(_n) + 0x2c4) +-#define REG_FE_GDM_TX_ETH_L511_CNT_H(_n) (GDM_BASE(_n) + 0x2c8) +-#define REG_FE_GDM_TX_ETH_L1023_CNT_H(_n) (GDM_BASE(_n) + 0x2cc) +-#define REG_FE_GDM_RX_ETH_E64_CNT_H(_n) (GDM_BASE(_n) + 0x2e8) +-#define REG_FE_GDM_RX_ETH_L64_CNT_H(_n) (GDM_BASE(_n) + 0x2ec) +-#define REG_FE_GDM_RX_ETH_L127_CNT_H(_n) (GDM_BASE(_n) + 0x2f0) +-#define REG_FE_GDM_RX_ETH_L255_CNT_H(_n) (GDM_BASE(_n) + 0x2f4) +-#define REG_FE_GDM_RX_ETH_L511_CNT_H(_n) (GDM_BASE(_n) + 0x2f8) +-#define REG_FE_GDM_RX_ETH_L1023_CNT_H(_n) (GDM_BASE(_n) + 0x2fc) +- +-#define REG_GDM2_CHN_RLS (GDM2_BASE + 0x20) +-#define MBI_RX_AGE_SEL_MASK GENMASK(26, 25) +-#define MBI_TX_AGE_SEL_MASK GENMASK(18, 17) +- +-#define REG_GDM3_FWD_CFG GDM3_BASE +-#define GDM3_PAD_EN_MASK BIT(28) +- +-#define REG_GDM4_FWD_CFG GDM4_BASE +-#define GDM4_PAD_EN_MASK BIT(28) +-#define GDM4_SPORT_OFFSET0_MASK GENMASK(11, 8) +- +-#define REG_GDM4_SRC_PORT_SET (GDM4_BASE + 0x23c) +-#define GDM4_SPORT_OFF2_MASK GENMASK(19, 16) +-#define GDM4_SPORT_OFF1_MASK GENMASK(15, 12) +-#define GDM4_SPORT_OFF0_MASK GENMASK(11, 8) +- +-#define REG_IP_FRAG_FP 0x2010 +-#define IP_ASSEMBLE_PORT_MASK GENMASK(24, 21) +-#define IP_ASSEMBLE_NBQ_MASK GENMASK(20, 16) +-#define IP_FRAGMENT_PORT_MASK GENMASK(8, 5) +-#define IP_FRAGMENT_NBQ_MASK GENMASK(4, 0) +- +-#define REG_MC_VLAN_EN 0x2100 +-#define MC_VLAN_EN_MASK BIT(0) +- +-#define REG_MC_VLAN_CFG 0x2104 +-#define MC_VLAN_CFG_CMD_DONE_MASK BIT(31) +-#define MC_VLAN_CFG_TABLE_ID_MASK GENMASK(21, 16) +-#define MC_VLAN_CFG_PORT_ID_MASK GENMASK(11, 8) +-#define MC_VLAN_CFG_TABLE_SEL_MASK BIT(4) +-#define MC_VLAN_CFG_RW_MASK BIT(0) +- +-#define REG_MC_VLAN_DATA 0x2108 +- +-#define REG_CDM5_RX_OQ1_DROP_CNT 0x29d4 +- +-/* QDMA */ +-#define REG_QDMA_GLOBAL_CFG 0x0004 +-#define GLOBAL_CFG_RX_2B_OFFSET_MASK BIT(31) +-#define GLOBAL_CFG_DMA_PREFERENCE_MASK GENMASK(30, 29) +-#define GLOBAL_CFG_CPU_TXR_RR_MASK BIT(28) +-#define GLOBAL_CFG_DSCP_BYTE_SWAP_MASK BIT(27) +-#define GLOBAL_CFG_PAYLOAD_BYTE_SWAP_MASK BIT(26) +-#define GLOBAL_CFG_MULTICAST_MODIFY_FP_MASK BIT(25) +-#define GLOBAL_CFG_OAM_MODIFY_MASK BIT(24) +-#define GLOBAL_CFG_RESET_MASK BIT(23) +-#define GLOBAL_CFG_RESET_DONE_MASK BIT(22) +-#define GLOBAL_CFG_MULTICAST_EN_MASK BIT(21) +-#define GLOBAL_CFG_IRQ1_EN_MASK BIT(20) +-#define GLOBAL_CFG_IRQ0_EN_MASK BIT(19) +-#define GLOBAL_CFG_LOOPCNT_EN_MASK BIT(18) +-#define GLOBAL_CFG_RD_BYPASS_WR_MASK BIT(17) +-#define GLOBAL_CFG_QDMA_LOOPBACK_MASK BIT(16) +-#define GLOBAL_CFG_LPBK_RXQ_SEL_MASK GENMASK(13, 8) +-#define GLOBAL_CFG_CHECK_DONE_MASK BIT(7) +-#define GLOBAL_CFG_TX_WB_DONE_MASK BIT(6) +-#define GLOBAL_CFG_MAX_ISSUE_NUM_MASK GENMASK(5, 4) +-#define GLOBAL_CFG_RX_DMA_BUSY_MASK BIT(3) +-#define GLOBAL_CFG_RX_DMA_EN_MASK BIT(2) +-#define GLOBAL_CFG_TX_DMA_BUSY_MASK BIT(1) +-#define GLOBAL_CFG_TX_DMA_EN_MASK BIT(0) +- +-#define REG_FWD_DSCP_BASE 0x0010 +-#define REG_FWD_BUF_BASE 0x0014 +- +-#define REG_HW_FWD_DSCP_CFG 0x0018 +-#define HW_FWD_DSCP_PAYLOAD_SIZE_MASK GENMASK(29, 28) +-#define HW_FWD_DSCP_SCATTER_LEN_MASK GENMASK(17, 16) +-#define HW_FWD_DSCP_MIN_SCATTER_LEN_MASK GENMASK(15, 0) +- +-#define REG_INT_STATUS(_n) \ +- (((_n) == 4) ? 0x0730 : \ +- ((_n) == 3) ? 0x0724 : \ +- ((_n) == 2) ? 0x0720 : \ +- ((_n) == 1) ? 0x0024 : 0x0020) +- +-#define REG_INT_ENABLE(_n) \ +- (((_n) == 4) ? 0x0750 : \ +- ((_n) == 3) ? 0x0744 : \ +- ((_n) == 2) ? 0x0740 : \ +- ((_n) == 1) ? 0x002c : 0x0028) +- +-/* QDMA_CSR_INT_ENABLE1 */ +-#define RX15_COHERENT_INT_MASK BIT(31) +-#define RX14_COHERENT_INT_MASK BIT(30) +-#define RX13_COHERENT_INT_MASK BIT(29) +-#define RX12_COHERENT_INT_MASK BIT(28) +-#define RX11_COHERENT_INT_MASK BIT(27) +-#define RX10_COHERENT_INT_MASK BIT(26) +-#define RX9_COHERENT_INT_MASK BIT(25) +-#define RX8_COHERENT_INT_MASK BIT(24) +-#define RX7_COHERENT_INT_MASK BIT(23) +-#define RX6_COHERENT_INT_MASK BIT(22) +-#define RX5_COHERENT_INT_MASK BIT(21) +-#define RX4_COHERENT_INT_MASK BIT(20) +-#define RX3_COHERENT_INT_MASK BIT(19) +-#define RX2_COHERENT_INT_MASK BIT(18) +-#define RX1_COHERENT_INT_MASK BIT(17) +-#define RX0_COHERENT_INT_MASK BIT(16) +-#define TX7_COHERENT_INT_MASK BIT(15) +-#define TX6_COHERENT_INT_MASK BIT(14) +-#define TX5_COHERENT_INT_MASK BIT(13) +-#define TX4_COHERENT_INT_MASK BIT(12) +-#define TX3_COHERENT_INT_MASK BIT(11) +-#define TX2_COHERENT_INT_MASK BIT(10) +-#define TX1_COHERENT_INT_MASK BIT(9) +-#define TX0_COHERENT_INT_MASK BIT(8) +-#define CNT_OVER_FLOW_INT_MASK BIT(7) +-#define IRQ1_FULL_INT_MASK BIT(5) +-#define IRQ1_INT_MASK BIT(4) +-#define HWFWD_DSCP_LOW_INT_MASK BIT(3) +-#define HWFWD_DSCP_EMPTY_INT_MASK BIT(2) +-#define IRQ0_FULL_INT_MASK BIT(1) +-#define IRQ0_INT_MASK BIT(0) +- +-#define TX_DONE_INT_MASK(_n) \ +- ((_n) ? IRQ1_INT_MASK | IRQ1_FULL_INT_MASK \ +- : IRQ0_INT_MASK | IRQ0_FULL_INT_MASK) +- +-#define INT_TX_MASK \ +- (IRQ1_INT_MASK | IRQ1_FULL_INT_MASK | \ +- IRQ0_INT_MASK | IRQ0_FULL_INT_MASK) +- +-#define INT_IDX0_MASK \ +- (TX0_COHERENT_INT_MASK | TX1_COHERENT_INT_MASK | \ +- TX2_COHERENT_INT_MASK | TX3_COHERENT_INT_MASK | \ +- TX4_COHERENT_INT_MASK | TX5_COHERENT_INT_MASK | \ +- TX6_COHERENT_INT_MASK | TX7_COHERENT_INT_MASK | \ +- RX0_COHERENT_INT_MASK | RX1_COHERENT_INT_MASK | \ +- RX2_COHERENT_INT_MASK | RX3_COHERENT_INT_MASK | \ +- RX4_COHERENT_INT_MASK | RX7_COHERENT_INT_MASK | \ +- RX8_COHERENT_INT_MASK | RX9_COHERENT_INT_MASK | \ +- RX15_COHERENT_INT_MASK | INT_TX_MASK) +- +-/* QDMA_CSR_INT_ENABLE2 */ +-#define RX15_NO_CPU_DSCP_INT_MASK BIT(31) +-#define RX14_NO_CPU_DSCP_INT_MASK BIT(30) +-#define RX13_NO_CPU_DSCP_INT_MASK BIT(29) +-#define RX12_NO_CPU_DSCP_INT_MASK BIT(28) +-#define RX11_NO_CPU_DSCP_INT_MASK BIT(27) +-#define RX10_NO_CPU_DSCP_INT_MASK BIT(26) +-#define RX9_NO_CPU_DSCP_INT_MASK BIT(25) +-#define RX8_NO_CPU_DSCP_INT_MASK BIT(24) +-#define RX7_NO_CPU_DSCP_INT_MASK BIT(23) +-#define RX6_NO_CPU_DSCP_INT_MASK BIT(22) +-#define RX5_NO_CPU_DSCP_INT_MASK BIT(21) +-#define RX4_NO_CPU_DSCP_INT_MASK BIT(20) +-#define RX3_NO_CPU_DSCP_INT_MASK BIT(19) +-#define RX2_NO_CPU_DSCP_INT_MASK BIT(18) +-#define RX1_NO_CPU_DSCP_INT_MASK BIT(17) +-#define RX0_NO_CPU_DSCP_INT_MASK BIT(16) +-#define RX15_DONE_INT_MASK BIT(15) +-#define RX14_DONE_INT_MASK BIT(14) +-#define RX13_DONE_INT_MASK BIT(13) +-#define RX12_DONE_INT_MASK BIT(12) +-#define RX11_DONE_INT_MASK BIT(11) +-#define RX10_DONE_INT_MASK BIT(10) +-#define RX9_DONE_INT_MASK BIT(9) +-#define RX8_DONE_INT_MASK BIT(8) +-#define RX7_DONE_INT_MASK BIT(7) +-#define RX6_DONE_INT_MASK BIT(6) +-#define RX5_DONE_INT_MASK BIT(5) +-#define RX4_DONE_INT_MASK BIT(4) +-#define RX3_DONE_INT_MASK BIT(3) +-#define RX2_DONE_INT_MASK BIT(2) +-#define RX1_DONE_INT_MASK BIT(1) +-#define RX0_DONE_INT_MASK BIT(0) +- +-#define RX_DONE_INT_MASK \ +- (RX0_DONE_INT_MASK | RX1_DONE_INT_MASK | \ +- RX2_DONE_INT_MASK | RX3_DONE_INT_MASK | \ +- RX4_DONE_INT_MASK | RX7_DONE_INT_MASK | \ +- RX8_DONE_INT_MASK | RX9_DONE_INT_MASK | \ +- RX15_DONE_INT_MASK) +-#define INT_IDX1_MASK \ +- (RX_DONE_INT_MASK | \ +- RX0_NO_CPU_DSCP_INT_MASK | RX1_NO_CPU_DSCP_INT_MASK | \ +- RX2_NO_CPU_DSCP_INT_MASK | RX3_NO_CPU_DSCP_INT_MASK | \ +- RX4_NO_CPU_DSCP_INT_MASK | RX7_NO_CPU_DSCP_INT_MASK | \ +- RX8_NO_CPU_DSCP_INT_MASK | RX9_NO_CPU_DSCP_INT_MASK | \ +- RX15_NO_CPU_DSCP_INT_MASK) +- +-/* QDMA_CSR_INT_ENABLE5 */ +-#define TX31_COHERENT_INT_MASK BIT(31) +-#define TX30_COHERENT_INT_MASK BIT(30) +-#define TX29_COHERENT_INT_MASK BIT(29) +-#define TX28_COHERENT_INT_MASK BIT(28) +-#define TX27_COHERENT_INT_MASK BIT(27) +-#define TX26_COHERENT_INT_MASK BIT(26) +-#define TX25_COHERENT_INT_MASK BIT(25) +-#define TX24_COHERENT_INT_MASK BIT(24) +-#define TX23_COHERENT_INT_MASK BIT(23) +-#define TX22_COHERENT_INT_MASK BIT(22) +-#define TX21_COHERENT_INT_MASK BIT(21) +-#define TX20_COHERENT_INT_MASK BIT(20) +-#define TX19_COHERENT_INT_MASK BIT(19) +-#define TX18_COHERENT_INT_MASK BIT(18) +-#define TX17_COHERENT_INT_MASK BIT(17) +-#define TX16_COHERENT_INT_MASK BIT(16) +-#define TX15_COHERENT_INT_MASK BIT(15) +-#define TX14_COHERENT_INT_MASK BIT(14) +-#define TX13_COHERENT_INT_MASK BIT(13) +-#define TX12_COHERENT_INT_MASK BIT(12) +-#define TX11_COHERENT_INT_MASK BIT(11) +-#define TX10_COHERENT_INT_MASK BIT(10) +-#define TX9_COHERENT_INT_MASK BIT(9) +-#define TX8_COHERENT_INT_MASK BIT(8) +- +-#define INT_IDX4_MASK \ +- (TX8_COHERENT_INT_MASK | TX9_COHERENT_INT_MASK | \ +- TX10_COHERENT_INT_MASK | TX11_COHERENT_INT_MASK | \ +- TX12_COHERENT_INT_MASK | TX13_COHERENT_INT_MASK | \ +- TX14_COHERENT_INT_MASK | TX15_COHERENT_INT_MASK | \ +- TX16_COHERENT_INT_MASK | TX17_COHERENT_INT_MASK | \ +- TX18_COHERENT_INT_MASK | TX19_COHERENT_INT_MASK | \ +- TX20_COHERENT_INT_MASK | TX21_COHERENT_INT_MASK | \ +- TX22_COHERENT_INT_MASK | TX23_COHERENT_INT_MASK | \ +- TX24_COHERENT_INT_MASK | TX25_COHERENT_INT_MASK | \ +- TX26_COHERENT_INT_MASK | TX27_COHERENT_INT_MASK | \ +- TX28_COHERENT_INT_MASK | TX29_COHERENT_INT_MASK | \ +- TX30_COHERENT_INT_MASK | TX31_COHERENT_INT_MASK) +- +-#define REG_TX_IRQ_BASE(_n) ((_n) ? 0x0048 : 0x0050) +- +-#define REG_TX_IRQ_CFG(_n) ((_n) ? 0x004c : 0x0054) +-#define TX_IRQ_THR_MASK GENMASK(27, 16) +-#define TX_IRQ_DEPTH_MASK GENMASK(11, 0) +- +-#define REG_IRQ_CLEAR_LEN(_n) ((_n) ? 0x0064 : 0x0058) +-#define IRQ_CLEAR_LEN_MASK GENMASK(7, 0) +- +-#define REG_IRQ_STATUS(_n) ((_n) ? 0x0068 : 0x005c) +-#define IRQ_ENTRY_LEN_MASK GENMASK(27, 16) +-#define IRQ_HEAD_IDX_MASK GENMASK(11, 0) +- +-#define REG_TX_RING_BASE(_n) \ +- (((_n) < 8) ? 0x0100 + ((_n) << 5) : 0x0b00 + (((_n) - 8) << 5)) +- +-#define REG_TX_RING_BLOCKING(_n) \ +- (((_n) < 8) ? 0x0104 + ((_n) << 5) : 0x0b04 + (((_n) - 8) << 5)) +- +-#define TX_RING_IRQ_BLOCKING_MAP_MASK BIT(6) +-#define TX_RING_IRQ_BLOCKING_CFG_MASK BIT(4) +-#define TX_RING_IRQ_BLOCKING_TX_DROP_EN_MASK BIT(2) +-#define TX_RING_IRQ_BLOCKING_MAX_TH_TXRING_EN_MASK BIT(1) +-#define TX_RING_IRQ_BLOCKING_MIN_TH_TXRING_EN_MASK BIT(0) +- +-#define REG_TX_CPU_IDX(_n) \ +- (((_n) < 8) ? 0x0108 + ((_n) << 5) : 0x0b08 + (((_n) - 8) << 5)) +- +-#define TX_RING_CPU_IDX_MASK GENMASK(15, 0) +- +-#define REG_TX_DMA_IDX(_n) \ +- (((_n) < 8) ? 0x010c + ((_n) << 5) : 0x0b0c + (((_n) - 8) << 5)) +- +-#define TX_RING_DMA_IDX_MASK GENMASK(15, 0) +- +-#define IRQ_RING_IDX_MASK GENMASK(20, 16) +-#define IRQ_DESC_IDX_MASK GENMASK(15, 0) +- +-#define REG_RX_RING_BASE(_n) \ +- (((_n) < 16) ? 0x0200 + ((_n) << 5) : 0x0e00 + (((_n) - 16) << 5)) +- +-#define REG_RX_RING_SIZE(_n) \ +- (((_n) < 16) ? 0x0204 + ((_n) << 5) : 0x0e04 + (((_n) - 16) << 5)) +- +-#define RX_RING_THR_MASK GENMASK(31, 16) +-#define RX_RING_SIZE_MASK GENMASK(15, 0) +- +-#define REG_RX_CPU_IDX(_n) \ +- (((_n) < 16) ? 0x0208 + ((_n) << 5) : 0x0e08 + (((_n) - 16) << 5)) +- +-#define RX_RING_CPU_IDX_MASK GENMASK(15, 0) +- +-#define REG_RX_DMA_IDX(_n) \ +- (((_n) < 16) ? 0x020c + ((_n) << 5) : 0x0e0c + (((_n) - 16) << 5)) +- +-#define REG_RX_DELAY_INT_IDX(_n) \ +- (((_n) < 16) ? 0x0210 + ((_n) << 5) : 0x0e10 + (((_n) - 16) << 5)) +- +-#define RX_DELAY_INT_MASK GENMASK(15, 0) +- +-#define RX_RING_DMA_IDX_MASK GENMASK(15, 0) +- +-#define REG_INGRESS_TRTCM_CFG 0x0070 +-#define INGRESS_TRTCM_EN_MASK BIT(31) +-#define INGRESS_TRTCM_MODE_MASK BIT(30) +-#define INGRESS_SLOW_TICK_RATIO_MASK GENMASK(29, 16) +-#define INGRESS_FAST_TICK_MASK GENMASK(15, 0) +- +-#define REG_QUEUE_CLOSE_CFG(_n) (0x00a0 + ((_n) & 0xfc)) +-#define TXQ_DISABLE_CHAN_QUEUE_MASK(_n, _m) BIT((_m) + (((_n) & 0x3) << 3)) +- +-#define REG_TXQ_DIS_CFG_BASE(_n) ((_n) ? 0x20a0 : 0x00a0) +-#define REG_TXQ_DIS_CFG(_n, _m) (REG_TXQ_DIS_CFG_BASE((_n)) + (_m) << 2) +- +-#define REG_CNTR_CFG(_n) (0x0400 + ((_n) << 3)) +-#define CNTR_EN_MASK BIT(31) +-#define CNTR_ALL_CHAN_EN_MASK BIT(30) +-#define CNTR_ALL_QUEUE_EN_MASK BIT(29) +-#define CNTR_ALL_DSCP_RING_EN_MASK BIT(28) +-#define CNTR_SRC_MASK GENMASK(27, 24) +-#define CNTR_DSCP_RING_MASK GENMASK(20, 16) +-#define CNTR_CHAN_MASK GENMASK(7, 3) +-#define CNTR_QUEUE_MASK GENMASK(2, 0) +- +-#define REG_CNTR_VAL(_n) (0x0404 + ((_n) << 3)) +- +-#define REG_LMGR_INIT_CFG 0x1000 +-#define LMGR_INIT_START BIT(31) +-#define LMGR_SRAM_MODE_MASK BIT(30) +-#define HW_FWD_PKTSIZE_OVERHEAD_MASK GENMASK(27, 20) +-#define HW_FWD_DESC_NUM_MASK GENMASK(16, 0) +- +-#define REG_FWD_DSCP_LOW_THR 0x1004 +-#define FWD_DSCP_LOW_THR_MASK GENMASK(17, 0) +- +-#define REG_EGRESS_RATE_METER_CFG 0x100c +-#define EGRESS_RATE_METER_EN_MASK BIT(31) +-#define EGRESS_RATE_METER_EQ_RATE_EN_MASK BIT(17) +-#define EGRESS_RATE_METER_WINDOW_SZ_MASK GENMASK(16, 12) +-#define EGRESS_RATE_METER_TIMESLICE_MASK GENMASK(10, 0) +- +-#define REG_EGRESS_TRTCM_CFG 0x1010 +-#define EGRESS_TRTCM_EN_MASK BIT(31) +-#define EGRESS_TRTCM_MODE_MASK BIT(30) +-#define EGRESS_SLOW_TICK_RATIO_MASK GENMASK(29, 16) +-#define EGRESS_FAST_TICK_MASK GENMASK(15, 0) +- +-#define TRTCM_PARAM_RW_MASK BIT(31) +-#define TRTCM_PARAM_RW_DONE_MASK BIT(30) +-#define TRTCM_PARAM_TYPE_MASK GENMASK(29, 28) +-#define TRTCM_METER_GROUP_MASK GENMASK(27, 26) +-#define TRTCM_PARAM_INDEX_MASK GENMASK(23, 17) +-#define TRTCM_PARAM_RATE_TYPE_MASK BIT(16) +- +-#define REG_TRTCM_CFG_PARAM(_n) ((_n) + 0x4) +-#define REG_TRTCM_DATA_LOW(_n) ((_n) + 0x8) +-#define REG_TRTCM_DATA_HIGH(_n) ((_n) + 0xc) +- +-#define REG_TXWRR_MODE_CFG 0x1020 +-#define TWRR_WEIGHT_SCALE_MASK BIT(31) +-#define TWRR_WEIGHT_BASE_MASK BIT(3) +- +-#define REG_TXWRR_WEIGHT_CFG 0x1024 +-#define TWRR_RW_CMD_MASK BIT(31) +-#define TWRR_RW_CMD_DONE BIT(30) +-#define TWRR_CHAN_IDX_MASK GENMASK(23, 19) +-#define TWRR_QUEUE_IDX_MASK GENMASK(18, 16) +-#define TWRR_VALUE_MASK GENMASK(15, 0) +- +-#define REG_PSE_BUF_USAGE_CFG 0x1028 +-#define PSE_BUF_ESTIMATE_EN_MASK BIT(29) +- +-#define REG_CHAN_QOS_MODE(_n) (0x1040 + ((_n) << 2)) +-#define CHAN_QOS_MODE_MASK(_n) GENMASK(2 + ((_n) << 2), (_n) << 2) +- +-#define REG_GLB_TRTCM_CFG 0x1080 +-#define GLB_TRTCM_EN_MASK BIT(31) +-#define GLB_TRTCM_MODE_MASK BIT(30) +-#define GLB_SLOW_TICK_RATIO_MASK GENMASK(29, 16) +-#define GLB_FAST_TICK_MASK GENMASK(15, 0) +- +-#define REG_TXQ_CNGST_CFG 0x10a0 +-#define TXQ_CNGST_DROP_EN BIT(31) +-#define TXQ_CNGST_DEI_DROP_EN BIT(30) +- +-#define REG_SLA_TRTCM_CFG 0x1150 +-#define SLA_TRTCM_EN_MASK BIT(31) +-#define SLA_TRTCM_MODE_MASK BIT(30) +-#define SLA_SLOW_TICK_RATIO_MASK GENMASK(29, 16) +-#define SLA_FAST_TICK_MASK GENMASK(15, 0) +- +-/* CTRL */ +-#define QDMA_DESC_DONE_MASK BIT(31) +-#define QDMA_DESC_DROP_MASK BIT(30) /* tx: drop - rx: overflow */ +-#define QDMA_DESC_MORE_MASK BIT(29) /* more SG elements */ +-#define QDMA_DESC_DEI_MASK BIT(25) +-#define QDMA_DESC_NO_DROP_MASK BIT(24) +-#define QDMA_DESC_LEN_MASK GENMASK(15, 0) +-/* DATA */ +-#define QDMA_DESC_NEXT_ID_MASK GENMASK(15, 0) +-/* TX MSG0 */ +-#define QDMA_ETH_TXMSG_MIC_IDX_MASK BIT(30) +-#define QDMA_ETH_TXMSG_SP_TAG_MASK GENMASK(29, 14) +-#define QDMA_ETH_TXMSG_ICO_MASK BIT(13) +-#define QDMA_ETH_TXMSG_UCO_MASK BIT(12) +-#define QDMA_ETH_TXMSG_TCO_MASK BIT(11) +-#define QDMA_ETH_TXMSG_TSO_MASK BIT(10) +-#define QDMA_ETH_TXMSG_FAST_MASK BIT(9) +-#define QDMA_ETH_TXMSG_OAM_MASK BIT(8) +-#define QDMA_ETH_TXMSG_CHAN_MASK GENMASK(7, 3) +-#define QDMA_ETH_TXMSG_QUEUE_MASK GENMASK(2, 0) +-/* TX MSG1 */ +-#define QDMA_ETH_TXMSG_NO_DROP BIT(31) +-#define QDMA_ETH_TXMSG_METER_MASK GENMASK(30, 24) /* 0x7f no meters */ +-#define QDMA_ETH_TXMSG_FPORT_MASK GENMASK(23, 20) +-#define QDMA_ETH_TXMSG_NBOQ_MASK GENMASK(19, 15) +-#define QDMA_ETH_TXMSG_HWF_MASK BIT(14) +-#define QDMA_ETH_TXMSG_HOP_MASK BIT(13) +-#define QDMA_ETH_TXMSG_PTP_MASK BIT(12) +-#define QDMA_ETH_TXMSG_ACNT_G1_MASK GENMASK(10, 6) /* 0x1f do not count */ +-#define QDMA_ETH_TXMSG_ACNT_G0_MASK GENMASK(5, 0) /* 0x3f do not count */ +- +-/* RX MSG1 */ +-#define QDMA_ETH_RXMSG_DEI_MASK BIT(31) +-#define QDMA_ETH_RXMSG_IP6_MASK BIT(30) +-#define QDMA_ETH_RXMSG_IP4_MASK BIT(29) +-#define QDMA_ETH_RXMSG_IP4F_MASK BIT(28) +-#define QDMA_ETH_RXMSG_L4_VALID_MASK BIT(27) +-#define QDMA_ETH_RXMSG_L4F_MASK BIT(26) +-#define QDMA_ETH_RXMSG_SPORT_MASK GENMASK(25, 21) +-#define QDMA_ETH_RXMSG_CRSN_MASK GENMASK(20, 16) +-#define QDMA_ETH_RXMSG_PPE_ENTRY_MASK GENMASK(15, 0) +- +-struct airoha_qdma_desc { +- __le32 rsv; +- __le32 ctrl; +- __le32 addr; +- __le32 data; +- __le32 msg0; +- __le32 msg1; +- __le32 msg2; +- __le32 msg3; +-}; +- +-/* CTRL0 */ +-#define QDMA_FWD_DESC_CTX_MASK BIT(31) +-#define QDMA_FWD_DESC_RING_MASK GENMASK(30, 28) +-#define QDMA_FWD_DESC_IDX_MASK GENMASK(27, 16) +-#define QDMA_FWD_DESC_LEN_MASK GENMASK(15, 0) +-/* CTRL1 */ +-#define QDMA_FWD_DESC_FIRST_IDX_MASK GENMASK(15, 0) +-/* CTRL2 */ +-#define QDMA_FWD_DESC_MORE_PKT_NUM_MASK GENMASK(2, 0) +- +-struct airoha_qdma_fwd_desc { +- __le32 addr; +- __le32 ctrl0; +- __le32 ctrl1; +- __le32 ctrl2; +- __le32 msg0; +- __le32 msg1; +- __le32 rsv0; +- __le32 rsv1; +-}; +- +-enum { +- QDMA_INT_REG_IDX0, +- QDMA_INT_REG_IDX1, +- QDMA_INT_REG_IDX2, +- QDMA_INT_REG_IDX3, +- QDMA_INT_REG_IDX4, +- QDMA_INT_REG_MAX +-}; +- +-enum { +- XSI_PCIE0_PORT, +- XSI_PCIE1_PORT, +- XSI_USB_PORT, +- XSI_AE_PORT, +- XSI_ETH_PORT, +-}; +- +-enum { +- XSI_PCIE0_VIP_PORT_MASK = BIT(22), +- XSI_PCIE1_VIP_PORT_MASK = BIT(23), +- XSI_USB_VIP_PORT_MASK = BIT(25), +- XSI_ETH_VIP_PORT_MASK = BIT(24), +-}; +- +-enum { +- DEV_STATE_INITIALIZED, +-}; +- +-enum { +- CDM_CRSN_QSEL_Q1 = 1, +- CDM_CRSN_QSEL_Q5 = 5, +- CDM_CRSN_QSEL_Q6 = 6, +- CDM_CRSN_QSEL_Q15 = 15, +-}; +- +-enum { +- CRSN_08 = 0x8, +- CRSN_21 = 0x15, /* KA */ +- CRSN_22 = 0x16, /* hit bind and force route to CPU */ +- CRSN_24 = 0x18, +- CRSN_25 = 0x19, +-}; +- +-enum { +- FE_PSE_PORT_CDM1, +- FE_PSE_PORT_GDM1, +- FE_PSE_PORT_GDM2, +- FE_PSE_PORT_GDM3, +- FE_PSE_PORT_PPE1, +- FE_PSE_PORT_CDM2, +- FE_PSE_PORT_CDM3, +- FE_PSE_PORT_CDM4, +- FE_PSE_PORT_PPE2, +- FE_PSE_PORT_GDM4, +- FE_PSE_PORT_CDM5, +- FE_PSE_PORT_DROP = 0xf, +-}; +- +-enum tx_sched_mode { +- TC_SCH_WRR8, +- TC_SCH_SP, +- TC_SCH_WRR7, +- TC_SCH_WRR6, +- TC_SCH_WRR5, +- TC_SCH_WRR4, +- TC_SCH_WRR3, +- TC_SCH_WRR2, +-}; +- +-enum trtcm_param_type { +- TRTCM_MISC_MODE, /* meter_en, pps_mode, tick_sel */ +- TRTCM_TOKEN_RATE_MODE, +- TRTCM_BUCKETSIZE_SHIFT_MODE, +- TRTCM_BUCKET_COUNTER_MODE, +-}; +- +-enum trtcm_mode_type { +- TRTCM_COMMIT_MODE, +- TRTCM_PEAK_MODE, +-}; +- +-enum trtcm_param { +- TRTCM_TICK_SEL = BIT(0), +- TRTCM_PKT_MODE = BIT(1), +- TRTCM_METER_MODE = BIT(2), +-}; +- +-#define MIN_TOKEN_SIZE 4096 +-#define MAX_TOKEN_SIZE_OFFSET 17 +-#define TRTCM_TOKEN_RATE_MASK GENMASK(23, 6) +-#define TRTCM_TOKEN_RATE_FRACTION_MASK GENMASK(5, 0) +- +-struct airoha_queue_entry { +- union { +- void *buf; +- struct sk_buff *skb; +- }; +- dma_addr_t dma_addr; +- u16 dma_len; +-}; +- +-struct airoha_queue { +- struct airoha_qdma *qdma; +- +- /* protect concurrent queue accesses */ +- spinlock_t lock; +- struct airoha_queue_entry *entry; +- struct airoha_qdma_desc *desc; +- u16 head; +- u16 tail; +- +- int queued; +- int ndesc; +- int free_thr; +- int buf_size; +- +- struct napi_struct napi; +- struct page_pool *page_pool; +-}; +- +-struct airoha_tx_irq_queue { +- struct airoha_qdma *qdma; +- +- struct napi_struct napi; +- +- int size; +- u32 *q; +-}; +- +-struct airoha_hw_stats { +- /* protect concurrent hw_stats accesses */ +- spinlock_t lock; +- struct u64_stats_sync syncp; +- +- /* get_stats64 */ +- u64 rx_ok_pkts; +- u64 tx_ok_pkts; +- u64 rx_ok_bytes; +- u64 tx_ok_bytes; +- u64 rx_multicast; +- u64 rx_errors; +- u64 rx_drops; +- u64 tx_drops; +- u64 rx_crc_error; +- u64 rx_over_errors; +- /* ethtool stats */ +- u64 tx_broadcast; +- u64 tx_multicast; +- u64 tx_len[7]; +- u64 rx_broadcast; +- u64 rx_fragment; +- u64 rx_jabber; +- u64 rx_len[7]; +-}; +- +-struct airoha_qdma { +- struct airoha_eth *eth; +- void __iomem *regs; +- +- /* protect concurrent irqmask accesses */ +- spinlock_t irq_lock; +- u32 irqmask[QDMA_INT_REG_MAX]; +- int irq; +- +- struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ]; +- +- struct airoha_queue q_tx[AIROHA_NUM_TX_RING]; +- struct airoha_queue q_rx[AIROHA_NUM_RX_RING]; +- +- /* descriptor and packet buffers for qdma hw forward */ +- struct { +- void *desc; +- void *q; +- } hfwd; +-}; +- +-struct airoha_gdm_port { +- struct airoha_qdma *qdma; +- struct net_device *dev; +- int id; +- +- struct airoha_hw_stats stats; +- +- DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); +- +- /* qos stats counters */ +- u64 cpu_tx_packets; +- u64 fwd_tx_packets; +-}; +- +-struct airoha_eth { +- struct device *dev; +- +- unsigned long state; +- void __iomem *fe_regs; +- +- struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS]; +- struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS]; +- +- struct net_device *napi_dev; +- +- struct airoha_qdma qdma[AIROHA_MAX_NUM_QDMA]; +- struct airoha_gdm_port *ports[AIROHA_MAX_NUM_GDM_PORTS]; +-}; +- +-static u32 airoha_rr(void __iomem *base, u32 offset) +-{ +- return readl(base + offset); +-} +- +-static void airoha_wr(void __iomem *base, u32 offset, u32 val) +-{ +- writel(val, base + offset); +-} +- +-static u32 airoha_rmw(void __iomem *base, u32 offset, u32 mask, u32 val) +-{ +- val |= (airoha_rr(base, offset) & ~mask); +- airoha_wr(base, offset, val); +- +- return val; +-} +- +-#define airoha_fe_rr(eth, offset) \ +- airoha_rr((eth)->fe_regs, (offset)) +-#define airoha_fe_wr(eth, offset, val) \ +- airoha_wr((eth)->fe_regs, (offset), (val)) +-#define airoha_fe_rmw(eth, offset, mask, val) \ +- airoha_rmw((eth)->fe_regs, (offset), (mask), (val)) +-#define airoha_fe_set(eth, offset, val) \ +- airoha_rmw((eth)->fe_regs, (offset), 0, (val)) +-#define airoha_fe_clear(eth, offset, val) \ +- airoha_rmw((eth)->fe_regs, (offset), (val), 0) +- +-#define airoha_qdma_rr(qdma, offset) \ +- airoha_rr((qdma)->regs, (offset)) +-#define airoha_qdma_wr(qdma, offset, val) \ +- airoha_wr((qdma)->regs, (offset), (val)) +-#define airoha_qdma_rmw(qdma, offset, mask, val) \ +- airoha_rmw((qdma)->regs, (offset), (mask), (val)) +-#define airoha_qdma_set(qdma, offset, val) \ +- airoha_rmw((qdma)->regs, (offset), 0, (val)) +-#define airoha_qdma_clear(qdma, offset, val) \ +- airoha_rmw((qdma)->regs, (offset), (val), 0) +- +-static void airoha_qdma_set_irqmask(struct airoha_qdma *qdma, int index, +- u32 clear, u32 set) +-{ +- unsigned long flags; +- +- if (WARN_ON_ONCE(index >= ARRAY_SIZE(qdma->irqmask))) +- return; +- +- spin_lock_irqsave(&qdma->irq_lock, flags); +- +- qdma->irqmask[index] &= ~clear; +- qdma->irqmask[index] |= set; +- airoha_qdma_wr(qdma, REG_INT_ENABLE(index), qdma->irqmask[index]); +- /* Read irq_enable register in order to guarantee the update above +- * completes in the spinlock critical section. +- */ +- airoha_qdma_rr(qdma, REG_INT_ENABLE(index)); +- +- spin_unlock_irqrestore(&qdma->irq_lock, flags); +-} +- +-static void airoha_qdma_irq_enable(struct airoha_qdma *qdma, int index, +- u32 mask) +-{ +- airoha_qdma_set_irqmask(qdma, index, 0, mask); +-} +- +-static void airoha_qdma_irq_disable(struct airoha_qdma *qdma, int index, +- u32 mask) +-{ +- airoha_qdma_set_irqmask(qdma, index, mask, 0); +-} +- +-static bool airhoa_is_lan_gdm_port(struct airoha_gdm_port *port) +-{ +- /* GDM1 port on EN7581 SoC is connected to the lan dsa switch. +- * GDM{2,3,4} can be used as wan port connected to an external +- * phy module. +- */ +- return port->id == 1; +-} +- +-static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr) +-{ +- struct airoha_eth *eth = port->qdma->eth; +- u32 val, reg; +- +- reg = airhoa_is_lan_gdm_port(port) ? REG_FE_LAN_MAC_H +- : REG_FE_WAN_MAC_H; +- val = (addr[0] << 16) | (addr[1] << 8) | addr[2]; +- airoha_fe_wr(eth, reg, val); +- +- val = (addr[3] << 16) | (addr[4] << 8) | addr[5]; +- airoha_fe_wr(eth, REG_FE_MAC_LMIN(reg), val); +- airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), val); +-} +- +-static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr, +- u32 val) +-{ +- airoha_fe_rmw(eth, addr, GDM_OCFQ_MASK, +- FIELD_PREP(GDM_OCFQ_MASK, val)); +- airoha_fe_rmw(eth, addr, GDM_MCFQ_MASK, +- FIELD_PREP(GDM_MCFQ_MASK, val)); +- airoha_fe_rmw(eth, addr, GDM_BCFQ_MASK, +- FIELD_PREP(GDM_BCFQ_MASK, val)); +- airoha_fe_rmw(eth, addr, GDM_UCFQ_MASK, +- FIELD_PREP(GDM_UCFQ_MASK, val)); +-} +- +-static int airoha_set_gdm_port(struct airoha_eth *eth, int port, bool enable) +-{ +- u32 val = enable ? FE_PSE_PORT_PPE1 : FE_PSE_PORT_DROP; +- u32 vip_port, cfg_addr; +- +- switch (port) { +- case XSI_PCIE0_PORT: +- vip_port = XSI_PCIE0_VIP_PORT_MASK; +- cfg_addr = REG_GDM_FWD_CFG(3); +- break; +- case XSI_PCIE1_PORT: +- vip_port = XSI_PCIE1_VIP_PORT_MASK; +- cfg_addr = REG_GDM_FWD_CFG(3); +- break; +- case XSI_USB_PORT: +- vip_port = XSI_USB_VIP_PORT_MASK; +- cfg_addr = REG_GDM_FWD_CFG(4); +- break; +- case XSI_ETH_PORT: +- vip_port = XSI_ETH_VIP_PORT_MASK; +- cfg_addr = REG_GDM_FWD_CFG(4); +- break; +- default: +- return -EINVAL; +- } +- +- if (enable) { +- airoha_fe_set(eth, REG_FE_VIP_PORT_EN, vip_port); +- airoha_fe_set(eth, REG_FE_IFC_PORT_EN, vip_port); +- } else { +- airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, vip_port); +- airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, vip_port); +- } +- +- airoha_set_gdm_port_fwd_cfg(eth, cfg_addr, val); +- +- return 0; +-} +- +-static int airoha_set_gdm_ports(struct airoha_eth *eth, bool enable) +-{ +- const int port_list[] = { +- XSI_PCIE0_PORT, +- XSI_PCIE1_PORT, +- XSI_USB_PORT, +- XSI_ETH_PORT +- }; +- int i, err; +- +- for (i = 0; i < ARRAY_SIZE(port_list); i++) { +- err = airoha_set_gdm_port(eth, port_list[i], enable); +- if (err) +- goto error; +- } +- +- return 0; +- +-error: +- for (i--; i >= 0; i--) +- airoha_set_gdm_port(eth, port_list[i], false); +- +- return err; +-} +- +-static void airoha_fe_maccr_init(struct airoha_eth *eth) +-{ +- int p; +- +- for (p = 1; p <= ARRAY_SIZE(eth->ports); p++) { +- airoha_fe_set(eth, REG_GDM_FWD_CFG(p), +- GDM_TCP_CKSUM | GDM_UDP_CKSUM | GDM_IP4_CKSUM | +- GDM_DROP_CRC_ERR); +- airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(p), +- FE_PSE_PORT_CDM1); +- airoha_fe_rmw(eth, REG_GDM_LEN_CFG(p), +- GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, +- FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | +- FIELD_PREP(GDM_LONG_LEN_MASK, 4004)); +- } +- +- airoha_fe_rmw(eth, REG_CDM1_VLAN_CTRL, CDM1_VLAN_MASK, +- FIELD_PREP(CDM1_VLAN_MASK, 0x8100)); +- +- airoha_fe_set(eth, REG_FE_CPORT_CFG, FE_CPORT_PAD); +-} +- +-static void airoha_fe_vip_setup(struct airoha_eth *eth) +-{ +- airoha_fe_wr(eth, REG_FE_VIP_PATN(3), ETH_P_PPP_DISC); +- airoha_fe_wr(eth, REG_FE_VIP_EN(3), PATN_FCPU_EN_MASK | PATN_EN_MASK); +- +- airoha_fe_wr(eth, REG_FE_VIP_PATN(4), PPP_LCP); +- airoha_fe_wr(eth, REG_FE_VIP_EN(4), +- PATN_FCPU_EN_MASK | FIELD_PREP(PATN_TYPE_MASK, 1) | +- PATN_EN_MASK); +- +- airoha_fe_wr(eth, REG_FE_VIP_PATN(6), PPP_IPCP); +- airoha_fe_wr(eth, REG_FE_VIP_EN(6), +- PATN_FCPU_EN_MASK | FIELD_PREP(PATN_TYPE_MASK, 1) | +- PATN_EN_MASK); +- +- airoha_fe_wr(eth, REG_FE_VIP_PATN(7), PPP_CHAP); +- airoha_fe_wr(eth, REG_FE_VIP_EN(7), +- PATN_FCPU_EN_MASK | FIELD_PREP(PATN_TYPE_MASK, 1) | +- PATN_EN_MASK); +- +- /* BOOTP (0x43) */ +- airoha_fe_wr(eth, REG_FE_VIP_PATN(8), 0x43); +- airoha_fe_wr(eth, REG_FE_VIP_EN(8), +- PATN_FCPU_EN_MASK | PATN_SP_EN_MASK | +- FIELD_PREP(PATN_TYPE_MASK, 4) | PATN_EN_MASK); +- +- /* BOOTP (0x44) */ +- airoha_fe_wr(eth, REG_FE_VIP_PATN(9), 0x44); +- airoha_fe_wr(eth, REG_FE_VIP_EN(9), +- PATN_FCPU_EN_MASK | PATN_SP_EN_MASK | +- FIELD_PREP(PATN_TYPE_MASK, 4) | PATN_EN_MASK); +- +- /* ISAKMP */ +- airoha_fe_wr(eth, REG_FE_VIP_PATN(10), 0x1f401f4); +- airoha_fe_wr(eth, REG_FE_VIP_EN(10), +- PATN_FCPU_EN_MASK | PATN_DP_EN_MASK | PATN_SP_EN_MASK | +- FIELD_PREP(PATN_TYPE_MASK, 4) | PATN_EN_MASK); +- +- airoha_fe_wr(eth, REG_FE_VIP_PATN(11), PPP_IPV6CP); +- airoha_fe_wr(eth, REG_FE_VIP_EN(11), +- PATN_FCPU_EN_MASK | FIELD_PREP(PATN_TYPE_MASK, 1) | +- PATN_EN_MASK); +- +- /* DHCPv6 */ +- airoha_fe_wr(eth, REG_FE_VIP_PATN(12), 0x2220223); +- airoha_fe_wr(eth, REG_FE_VIP_EN(12), +- PATN_FCPU_EN_MASK | PATN_DP_EN_MASK | PATN_SP_EN_MASK | +- FIELD_PREP(PATN_TYPE_MASK, 4) | PATN_EN_MASK); +- +- airoha_fe_wr(eth, REG_FE_VIP_PATN(19), PPP_PAP); +- airoha_fe_wr(eth, REG_FE_VIP_EN(19), +- PATN_FCPU_EN_MASK | FIELD_PREP(PATN_TYPE_MASK, 1) | +- PATN_EN_MASK); +- +- /* ETH->ETH_P_1905 (0x893a) */ +- airoha_fe_wr(eth, REG_FE_VIP_PATN(20), 0x893a); +- airoha_fe_wr(eth, REG_FE_VIP_EN(20), +- PATN_FCPU_EN_MASK | PATN_EN_MASK); +- +- airoha_fe_wr(eth, REG_FE_VIP_PATN(21), ETH_P_LLDP); +- airoha_fe_wr(eth, REG_FE_VIP_EN(21), +- PATN_FCPU_EN_MASK | PATN_EN_MASK); +-} +- +-static u32 airoha_fe_get_pse_queue_rsv_pages(struct airoha_eth *eth, +- u32 port, u32 queue) +-{ +- u32 val; +- +- airoha_fe_rmw(eth, REG_FE_PSE_QUEUE_CFG_WR, +- PSE_CFG_PORT_ID_MASK | PSE_CFG_QUEUE_ID_MASK, +- FIELD_PREP(PSE_CFG_PORT_ID_MASK, port) | +- FIELD_PREP(PSE_CFG_QUEUE_ID_MASK, queue)); +- val = airoha_fe_rr(eth, REG_FE_PSE_QUEUE_CFG_VAL); +- +- return FIELD_GET(PSE_CFG_OQ_RSV_MASK, val); +-} +- +-static void airoha_fe_set_pse_queue_rsv_pages(struct airoha_eth *eth, +- u32 port, u32 queue, u32 val) +-{ +- airoha_fe_rmw(eth, REG_FE_PSE_QUEUE_CFG_VAL, PSE_CFG_OQ_RSV_MASK, +- FIELD_PREP(PSE_CFG_OQ_RSV_MASK, val)); +- airoha_fe_rmw(eth, REG_FE_PSE_QUEUE_CFG_WR, +- PSE_CFG_PORT_ID_MASK | PSE_CFG_QUEUE_ID_MASK | +- PSE_CFG_WR_EN_MASK | PSE_CFG_OQRSV_SEL_MASK, +- FIELD_PREP(PSE_CFG_PORT_ID_MASK, port) | +- FIELD_PREP(PSE_CFG_QUEUE_ID_MASK, queue) | +- PSE_CFG_WR_EN_MASK | PSE_CFG_OQRSV_SEL_MASK); +-} +- +-static u32 airoha_fe_get_pse_all_rsv(struct airoha_eth *eth) +-{ +- u32 val = airoha_fe_rr(eth, REG_FE_PSE_BUF_SET); +- +- return FIELD_GET(PSE_ALLRSV_MASK, val); +-} +- +-static int airoha_fe_set_pse_oq_rsv(struct airoha_eth *eth, +- u32 port, u32 queue, u32 val) +-{ +- u32 orig_val = airoha_fe_get_pse_queue_rsv_pages(eth, port, queue); +- u32 tmp, all_rsv, fq_limit; +- +- airoha_fe_set_pse_queue_rsv_pages(eth, port, queue, val); +- +- /* modify all rsv */ +- all_rsv = airoha_fe_get_pse_all_rsv(eth); +- all_rsv += (val - orig_val); +- airoha_fe_rmw(eth, REG_FE_PSE_BUF_SET, PSE_ALLRSV_MASK, +- FIELD_PREP(PSE_ALLRSV_MASK, all_rsv)); +- +- /* modify hthd */ +- tmp = airoha_fe_rr(eth, PSE_FQ_CFG); +- fq_limit = FIELD_GET(PSE_FQ_LIMIT_MASK, tmp); +- tmp = fq_limit - all_rsv - 0x20; +- airoha_fe_rmw(eth, REG_PSE_SHARE_USED_THD, +- PSE_SHARE_USED_HTHD_MASK, +- FIELD_PREP(PSE_SHARE_USED_HTHD_MASK, tmp)); +- +- tmp = fq_limit - all_rsv - 0x100; +- airoha_fe_rmw(eth, REG_PSE_SHARE_USED_THD, +- PSE_SHARE_USED_MTHD_MASK, +- FIELD_PREP(PSE_SHARE_USED_MTHD_MASK, tmp)); +- tmp = (3 * tmp) >> 2; +- airoha_fe_rmw(eth, REG_FE_PSE_BUF_SET, +- PSE_SHARE_USED_LTHD_MASK, +- FIELD_PREP(PSE_SHARE_USED_LTHD_MASK, tmp)); +- +- return 0; +-} +- +-static void airoha_fe_pse_ports_init(struct airoha_eth *eth) +-{ +- const u32 pse_port_num_queues[] = { +- [FE_PSE_PORT_CDM1] = 6, +- [FE_PSE_PORT_GDM1] = 6, +- [FE_PSE_PORT_GDM2] = 32, +- [FE_PSE_PORT_GDM3] = 6, +- [FE_PSE_PORT_PPE1] = 4, +- [FE_PSE_PORT_CDM2] = 6, +- [FE_PSE_PORT_CDM3] = 8, +- [FE_PSE_PORT_CDM4] = 10, +- [FE_PSE_PORT_PPE2] = 4, +- [FE_PSE_PORT_GDM4] = 2, +- [FE_PSE_PORT_CDM5] = 2, +- }; +- u32 all_rsv; +- int q; +- +- all_rsv = airoha_fe_get_pse_all_rsv(eth); +- /* hw misses PPE2 oq rsv */ +- all_rsv += PSE_RSV_PAGES * pse_port_num_queues[FE_PSE_PORT_PPE2]; +- airoha_fe_set(eth, REG_FE_PSE_BUF_SET, all_rsv); +- +- /* CMD1 */ +- for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_CDM1]; q++) +- airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_CDM1, q, +- PSE_QUEUE_RSV_PAGES); +- /* GMD1 */ +- for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_GDM1]; q++) +- airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_GDM1, q, +- PSE_QUEUE_RSV_PAGES); +- /* GMD2 */ +- for (q = 6; q < pse_port_num_queues[FE_PSE_PORT_GDM2]; q++) +- airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_GDM2, q, 0); +- /* GMD3 */ +- for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_GDM3]; q++) +- airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_GDM3, q, +- PSE_QUEUE_RSV_PAGES); +- /* PPE1 */ +- for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_PPE1]; q++) { +- if (q < pse_port_num_queues[FE_PSE_PORT_PPE1]) +- airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE1, q, +- PSE_QUEUE_RSV_PAGES); +- else +- airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE1, q, 0); +- } +- /* CDM2 */ +- for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_CDM2]; q++) +- airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_CDM2, q, +- PSE_QUEUE_RSV_PAGES); +- /* CDM3 */ +- for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_CDM3] - 1; q++) +- airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_CDM3, q, 0); +- /* CDM4 */ +- for (q = 4; q < pse_port_num_queues[FE_PSE_PORT_CDM4]; q++) +- airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_CDM4, q, +- PSE_QUEUE_RSV_PAGES); +- /* PPE2 */ +- for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_PPE2]; q++) { +- if (q < pse_port_num_queues[FE_PSE_PORT_PPE2] / 2) +- airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE2, q, +- PSE_QUEUE_RSV_PAGES); +- else +- airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE2, q, 0); +- } +- /* GMD4 */ +- for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_GDM4]; q++) +- airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_GDM4, q, +- PSE_QUEUE_RSV_PAGES); +- /* CDM5 */ +- for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_CDM5]; q++) +- airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_CDM5, q, +- PSE_QUEUE_RSV_PAGES); +-} +- +-static int airoha_fe_mc_vlan_clear(struct airoha_eth *eth) +-{ +- int i; +- +- for (i = 0; i < AIROHA_FE_MC_MAX_VLAN_TABLE; i++) { +- int err, j; +- u32 val; +- +- airoha_fe_wr(eth, REG_MC_VLAN_DATA, 0x0); +- +- val = FIELD_PREP(MC_VLAN_CFG_TABLE_ID_MASK, i) | +- MC_VLAN_CFG_TABLE_SEL_MASK | MC_VLAN_CFG_RW_MASK; +- airoha_fe_wr(eth, REG_MC_VLAN_CFG, val); +- err = read_poll_timeout(airoha_fe_rr, val, +- val & MC_VLAN_CFG_CMD_DONE_MASK, +- USEC_PER_MSEC, 5 * USEC_PER_MSEC, +- false, eth, REG_MC_VLAN_CFG); +- if (err) +- return err; +- +- for (j = 0; j < AIROHA_FE_MC_MAX_VLAN_PORT; j++) { +- airoha_fe_wr(eth, REG_MC_VLAN_DATA, 0x0); +- +- val = FIELD_PREP(MC_VLAN_CFG_TABLE_ID_MASK, i) | +- FIELD_PREP(MC_VLAN_CFG_PORT_ID_MASK, j) | +- MC_VLAN_CFG_RW_MASK; +- airoha_fe_wr(eth, REG_MC_VLAN_CFG, val); +- err = read_poll_timeout(airoha_fe_rr, val, +- val & MC_VLAN_CFG_CMD_DONE_MASK, +- USEC_PER_MSEC, +- 5 * USEC_PER_MSEC, false, eth, +- REG_MC_VLAN_CFG); +- if (err) +- return err; +- } +- } +- +- return 0; +-} +- +-static void airoha_fe_crsn_qsel_init(struct airoha_eth *eth) +-{ +- /* CDM1_CRSN_QSEL */ +- airoha_fe_rmw(eth, REG_CDM1_CRSN_QSEL(CRSN_22 >> 2), +- CDM1_CRSN_QSEL_REASON_MASK(CRSN_22), +- FIELD_PREP(CDM1_CRSN_QSEL_REASON_MASK(CRSN_22), +- CDM_CRSN_QSEL_Q1)); +- airoha_fe_rmw(eth, REG_CDM1_CRSN_QSEL(CRSN_08 >> 2), +- CDM1_CRSN_QSEL_REASON_MASK(CRSN_08), +- FIELD_PREP(CDM1_CRSN_QSEL_REASON_MASK(CRSN_08), +- CDM_CRSN_QSEL_Q1)); +- airoha_fe_rmw(eth, REG_CDM1_CRSN_QSEL(CRSN_21 >> 2), +- CDM1_CRSN_QSEL_REASON_MASK(CRSN_21), +- FIELD_PREP(CDM1_CRSN_QSEL_REASON_MASK(CRSN_21), +- CDM_CRSN_QSEL_Q1)); +- airoha_fe_rmw(eth, REG_CDM1_CRSN_QSEL(CRSN_24 >> 2), +- CDM1_CRSN_QSEL_REASON_MASK(CRSN_24), +- FIELD_PREP(CDM1_CRSN_QSEL_REASON_MASK(CRSN_24), +- CDM_CRSN_QSEL_Q6)); +- airoha_fe_rmw(eth, REG_CDM1_CRSN_QSEL(CRSN_25 >> 2), +- CDM1_CRSN_QSEL_REASON_MASK(CRSN_25), +- FIELD_PREP(CDM1_CRSN_QSEL_REASON_MASK(CRSN_25), +- CDM_CRSN_QSEL_Q1)); +- /* CDM2_CRSN_QSEL */ +- airoha_fe_rmw(eth, REG_CDM2_CRSN_QSEL(CRSN_08 >> 2), +- CDM2_CRSN_QSEL_REASON_MASK(CRSN_08), +- FIELD_PREP(CDM2_CRSN_QSEL_REASON_MASK(CRSN_08), +- CDM_CRSN_QSEL_Q1)); +- airoha_fe_rmw(eth, REG_CDM2_CRSN_QSEL(CRSN_21 >> 2), +- CDM2_CRSN_QSEL_REASON_MASK(CRSN_21), +- FIELD_PREP(CDM2_CRSN_QSEL_REASON_MASK(CRSN_21), +- CDM_CRSN_QSEL_Q1)); +- airoha_fe_rmw(eth, REG_CDM2_CRSN_QSEL(CRSN_22 >> 2), +- CDM2_CRSN_QSEL_REASON_MASK(CRSN_22), +- FIELD_PREP(CDM2_CRSN_QSEL_REASON_MASK(CRSN_22), +- CDM_CRSN_QSEL_Q1)); +- airoha_fe_rmw(eth, REG_CDM2_CRSN_QSEL(CRSN_24 >> 2), +- CDM2_CRSN_QSEL_REASON_MASK(CRSN_24), +- FIELD_PREP(CDM2_CRSN_QSEL_REASON_MASK(CRSN_24), +- CDM_CRSN_QSEL_Q6)); +- airoha_fe_rmw(eth, REG_CDM2_CRSN_QSEL(CRSN_25 >> 2), +- CDM2_CRSN_QSEL_REASON_MASK(CRSN_25), +- FIELD_PREP(CDM2_CRSN_QSEL_REASON_MASK(CRSN_25), +- CDM_CRSN_QSEL_Q1)); +-} +- +-static int airoha_fe_init(struct airoha_eth *eth) +-{ +- airoha_fe_maccr_init(eth); +- +- /* PSE IQ reserve */ +- airoha_fe_rmw(eth, REG_PSE_IQ_REV1, PSE_IQ_RES1_P2_MASK, +- FIELD_PREP(PSE_IQ_RES1_P2_MASK, 0x10)); +- airoha_fe_rmw(eth, REG_PSE_IQ_REV2, +- PSE_IQ_RES2_P5_MASK | PSE_IQ_RES2_P4_MASK, +- FIELD_PREP(PSE_IQ_RES2_P5_MASK, 0x40) | +- FIELD_PREP(PSE_IQ_RES2_P4_MASK, 0x34)); +- +- /* enable FE copy engine for MC/KA/DPI */ +- airoha_fe_wr(eth, REG_FE_PCE_CFG, +- PCE_DPI_EN_MASK | PCE_KA_EN_MASK | PCE_MC_EN_MASK); +- /* set vip queue selection to ring 1 */ +- airoha_fe_rmw(eth, REG_CDM1_FWD_CFG, CDM1_VIP_QSEL_MASK, +- FIELD_PREP(CDM1_VIP_QSEL_MASK, 0x4)); +- airoha_fe_rmw(eth, REG_CDM2_FWD_CFG, CDM2_VIP_QSEL_MASK, +- FIELD_PREP(CDM2_VIP_QSEL_MASK, 0x4)); +- /* set GDM4 source interface offset to 8 */ +- airoha_fe_rmw(eth, REG_GDM4_SRC_PORT_SET, +- GDM4_SPORT_OFF2_MASK | +- GDM4_SPORT_OFF1_MASK | +- GDM4_SPORT_OFF0_MASK, +- FIELD_PREP(GDM4_SPORT_OFF2_MASK, 8) | +- FIELD_PREP(GDM4_SPORT_OFF1_MASK, 8) | +- FIELD_PREP(GDM4_SPORT_OFF0_MASK, 8)); +- +- /* set PSE Page as 128B */ +- airoha_fe_rmw(eth, REG_FE_DMA_GLO_CFG, +- FE_DMA_GLO_L2_SPACE_MASK | FE_DMA_GLO_PG_SZ_MASK, +- FIELD_PREP(FE_DMA_GLO_L2_SPACE_MASK, 2) | +- FE_DMA_GLO_PG_SZ_MASK); +- airoha_fe_wr(eth, REG_FE_RST_GLO_CFG, +- FE_RST_CORE_MASK | FE_RST_GDM3_MBI_ARB_MASK | +- FE_RST_GDM4_MBI_ARB_MASK); +- usleep_range(1000, 2000); +- +- /* connect RxRing1 and RxRing15 to PSE Port0 OQ-1 +- * connect other rings to PSE Port0 OQ-0 +- */ +- airoha_fe_wr(eth, REG_FE_CDM1_OQ_MAP0, BIT(4)); +- airoha_fe_wr(eth, REG_FE_CDM1_OQ_MAP1, BIT(28)); +- airoha_fe_wr(eth, REG_FE_CDM1_OQ_MAP2, BIT(4)); +- airoha_fe_wr(eth, REG_FE_CDM1_OQ_MAP3, BIT(28)); +- +- airoha_fe_vip_setup(eth); +- airoha_fe_pse_ports_init(eth); +- +- airoha_fe_set(eth, REG_GDM_MISC_CFG, +- GDM2_RDM_ACK_WAIT_PREF_MASK | +- GDM2_CHN_VLD_MODE_MASK); +- airoha_fe_rmw(eth, REG_CDM2_FWD_CFG, CDM2_OAM_QSEL_MASK, +- FIELD_PREP(CDM2_OAM_QSEL_MASK, 15)); +- +- /* init fragment and assemble Force Port */ +- /* NPU Core-3, NPU Bridge Channel-3 */ +- airoha_fe_rmw(eth, REG_IP_FRAG_FP, +- IP_FRAGMENT_PORT_MASK | IP_FRAGMENT_NBQ_MASK, +- FIELD_PREP(IP_FRAGMENT_PORT_MASK, 6) | +- FIELD_PREP(IP_FRAGMENT_NBQ_MASK, 3)); +- /* QDMA LAN, RX Ring-22 */ +- airoha_fe_rmw(eth, REG_IP_FRAG_FP, +- IP_ASSEMBLE_PORT_MASK | IP_ASSEMBLE_NBQ_MASK, +- FIELD_PREP(IP_ASSEMBLE_PORT_MASK, 0) | +- FIELD_PREP(IP_ASSEMBLE_NBQ_MASK, 22)); +- +- airoha_fe_set(eth, REG_GDM3_FWD_CFG, GDM3_PAD_EN_MASK); +- airoha_fe_set(eth, REG_GDM4_FWD_CFG, GDM4_PAD_EN_MASK); +- +- airoha_fe_crsn_qsel_init(eth); +- +- airoha_fe_clear(eth, REG_FE_CPORT_CFG, FE_CPORT_QUEUE_XFC_MASK); +- airoha_fe_set(eth, REG_FE_CPORT_CFG, FE_CPORT_PORT_XFC_MASK); +- +- /* default aging mode for mbi unlock issue */ +- airoha_fe_rmw(eth, REG_GDM2_CHN_RLS, +- MBI_RX_AGE_SEL_MASK | MBI_TX_AGE_SEL_MASK, +- FIELD_PREP(MBI_RX_AGE_SEL_MASK, 3) | +- FIELD_PREP(MBI_TX_AGE_SEL_MASK, 3)); +- +- /* disable IFC by default */ +- airoha_fe_clear(eth, REG_FE_CSR_IFC_CFG, FE_IFC_EN_MASK); +- +- /* enable 1:N vlan action, init vlan table */ +- airoha_fe_set(eth, REG_MC_VLAN_EN, MC_VLAN_EN_MASK); +- +- return airoha_fe_mc_vlan_clear(eth); +-} +- +-static int airoha_qdma_fill_rx_queue(struct airoha_queue *q) +-{ +- enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool); +- struct airoha_qdma *qdma = q->qdma; +- struct airoha_eth *eth = qdma->eth; +- int qid = q - &qdma->q_rx[0]; +- int nframes = 0; +- +- while (q->queued < q->ndesc - 1) { +- struct airoha_queue_entry *e = &q->entry[q->head]; +- struct airoha_qdma_desc *desc = &q->desc[q->head]; +- struct page *page; +- int offset; +- u32 val; +- +- page = page_pool_dev_alloc_frag(q->page_pool, &offset, +- q->buf_size); +- if (!page) +- break; +- +- q->head = (q->head + 1) % q->ndesc; +- q->queued++; +- nframes++; +- +- e->buf = page_address(page) + offset; +- e->dma_addr = page_pool_get_dma_addr(page) + offset; +- e->dma_len = SKB_WITH_OVERHEAD(q->buf_size); +- +- dma_sync_single_for_device(eth->dev, e->dma_addr, e->dma_len, +- dir); +- +- val = FIELD_PREP(QDMA_DESC_LEN_MASK, e->dma_len); +- WRITE_ONCE(desc->ctrl, cpu_to_le32(val)); +- WRITE_ONCE(desc->addr, cpu_to_le32(e->dma_addr)); +- val = FIELD_PREP(QDMA_DESC_NEXT_ID_MASK, q->head); +- WRITE_ONCE(desc->data, cpu_to_le32(val)); +- WRITE_ONCE(desc->msg0, 0); +- WRITE_ONCE(desc->msg1, 0); +- WRITE_ONCE(desc->msg2, 0); +- WRITE_ONCE(desc->msg3, 0); +- +- airoha_qdma_rmw(qdma, REG_RX_CPU_IDX(qid), +- RX_RING_CPU_IDX_MASK, +- FIELD_PREP(RX_RING_CPU_IDX_MASK, q->head)); +- } +- +- return nframes; +-} +- +-static int airoha_qdma_get_gdm_port(struct airoha_eth *eth, +- struct airoha_qdma_desc *desc) +-{ +- u32 port, sport, msg1 = le32_to_cpu(desc->msg1); +- +- sport = FIELD_GET(QDMA_ETH_RXMSG_SPORT_MASK, msg1); +- switch (sport) { +- case 0x10 ... 0x13: +- port = 0; +- break; +- case 0x2 ... 0x4: +- port = sport - 1; +- break; +- default: +- return -EINVAL; +- } +- +- return port >= ARRAY_SIZE(eth->ports) ? -EINVAL : port; +-} +- +-static int airoha_qdma_rx_process(struct airoha_queue *q, int budget) +-{ +- enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool); +- struct airoha_qdma *qdma = q->qdma; +- struct airoha_eth *eth = qdma->eth; +- int qid = q - &qdma->q_rx[0]; +- int done = 0; +- +- while (done < budget) { +- struct airoha_queue_entry *e = &q->entry[q->tail]; +- struct airoha_qdma_desc *desc = &q->desc[q->tail]; +- dma_addr_t dma_addr = le32_to_cpu(desc->addr); +- u32 desc_ctrl = le32_to_cpu(desc->ctrl); +- struct sk_buff *skb; +- int len, p; +- +- if (!(desc_ctrl & QDMA_DESC_DONE_MASK)) +- break; +- +- if (!dma_addr) +- break; +- +- len = FIELD_GET(QDMA_DESC_LEN_MASK, desc_ctrl); +- if (!len) +- break; +- +- q->tail = (q->tail + 1) % q->ndesc; +- q->queued--; +- +- dma_sync_single_for_cpu(eth->dev, dma_addr, +- SKB_WITH_OVERHEAD(q->buf_size), dir); +- +- p = airoha_qdma_get_gdm_port(eth, desc); +- if (p < 0 || !eth->ports[p]) { +- page_pool_put_full_page(q->page_pool, +- virt_to_head_page(e->buf), +- true); +- continue; +- } +- +- skb = napi_build_skb(e->buf, q->buf_size); +- if (!skb) { +- page_pool_put_full_page(q->page_pool, +- virt_to_head_page(e->buf), +- true); +- break; +- } +- +- skb_reserve(skb, 2); +- __skb_put(skb, len); +- skb_mark_for_recycle(skb); +- skb->dev = eth->ports[p]->dev; +- skb->protocol = eth_type_trans(skb, skb->dev); +- skb->ip_summed = CHECKSUM_UNNECESSARY; +- skb_record_rx_queue(skb, qid); +- napi_gro_receive(&q->napi, skb); +- +- done++; +- } +- airoha_qdma_fill_rx_queue(q); +- +- return done; +-} +- +-static int airoha_qdma_rx_napi_poll(struct napi_struct *napi, int budget) +-{ +- struct airoha_queue *q = container_of(napi, struct airoha_queue, napi); +- int cur, done = 0; +- +- do { +- cur = airoha_qdma_rx_process(q, budget - done); +- done += cur; +- } while (cur && done < budget); +- +- if (done < budget && napi_complete(napi)) +- airoha_qdma_irq_enable(q->qdma, QDMA_INT_REG_IDX1, +- RX_DONE_INT_MASK); +- +- return done; +-} +- +-static int airoha_qdma_init_rx_queue(struct airoha_queue *q, +- struct airoha_qdma *qdma, int ndesc) +-{ +- const struct page_pool_params pp_params = { +- .order = 0, +- .pool_size = 256, +- .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV, +- .dma_dir = DMA_FROM_DEVICE, +- .max_len = PAGE_SIZE, +- .nid = NUMA_NO_NODE, +- .dev = qdma->eth->dev, +- .napi = &q->napi, +- }; +- struct airoha_eth *eth = qdma->eth; +- int qid = q - &qdma->q_rx[0], thr; +- dma_addr_t dma_addr; +- +- q->buf_size = PAGE_SIZE / 2; +- q->ndesc = ndesc; +- q->qdma = qdma; +- +- q->entry = devm_kzalloc(eth->dev, q->ndesc * sizeof(*q->entry), +- GFP_KERNEL); +- if (!q->entry) +- return -ENOMEM; +- +- q->page_pool = page_pool_create(&pp_params); +- if (IS_ERR(q->page_pool)) { +- int err = PTR_ERR(q->page_pool); +- +- q->page_pool = NULL; +- return err; +- } +- +- q->desc = dmam_alloc_coherent(eth->dev, q->ndesc * sizeof(*q->desc), +- &dma_addr, GFP_KERNEL); +- if (!q->desc) +- return -ENOMEM; +- +- netif_napi_add(eth->napi_dev, &q->napi, airoha_qdma_rx_napi_poll); +- +- airoha_qdma_wr(qdma, REG_RX_RING_BASE(qid), dma_addr); +- airoha_qdma_rmw(qdma, REG_RX_RING_SIZE(qid), +- RX_RING_SIZE_MASK, +- FIELD_PREP(RX_RING_SIZE_MASK, ndesc)); +- +- thr = clamp(ndesc >> 3, 1, 32); +- airoha_qdma_rmw(qdma, REG_RX_RING_SIZE(qid), RX_RING_THR_MASK, +- FIELD_PREP(RX_RING_THR_MASK, thr)); +- airoha_qdma_rmw(qdma, REG_RX_DMA_IDX(qid), RX_RING_DMA_IDX_MASK, +- FIELD_PREP(RX_RING_DMA_IDX_MASK, q->head)); +- +- airoha_qdma_fill_rx_queue(q); +- +- return 0; +-} +- +-static void airoha_qdma_cleanup_rx_queue(struct airoha_queue *q) +-{ +- struct airoha_eth *eth = q->qdma->eth; +- +- while (q->queued) { +- struct airoha_queue_entry *e = &q->entry[q->tail]; +- struct page *page = virt_to_head_page(e->buf); +- +- dma_sync_single_for_cpu(eth->dev, e->dma_addr, e->dma_len, +- page_pool_get_dma_dir(q->page_pool)); +- page_pool_put_full_page(q->page_pool, page, false); +- q->tail = (q->tail + 1) % q->ndesc; +- q->queued--; +- } +-} +- +-static int airoha_qdma_init_rx(struct airoha_qdma *qdma) +-{ +- int i; +- +- for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { +- int err; +- +- if (!(RX_DONE_INT_MASK & BIT(i))) { +- /* rx-queue not binded to irq */ +- continue; +- } +- +- err = airoha_qdma_init_rx_queue(&qdma->q_rx[i], qdma, +- RX_DSCP_NUM(i)); +- if (err) +- return err; +- } +- +- return 0; +-} +- +-static int airoha_qdma_tx_napi_poll(struct napi_struct *napi, int budget) +-{ +- struct airoha_tx_irq_queue *irq_q; +- int id, done = 0, irq_queued; +- struct airoha_qdma *qdma; +- struct airoha_eth *eth; +- u32 status, head; +- +- irq_q = container_of(napi, struct airoha_tx_irq_queue, napi); +- qdma = irq_q->qdma; +- id = irq_q - &qdma->q_tx_irq[0]; +- eth = qdma->eth; +- +- status = airoha_qdma_rr(qdma, REG_IRQ_STATUS(id)); +- head = FIELD_GET(IRQ_HEAD_IDX_MASK, status); +- head = head % irq_q->size; +- irq_queued = FIELD_GET(IRQ_ENTRY_LEN_MASK, status); +- +- while (irq_queued > 0 && done < budget) { +- u32 qid, val = irq_q->q[head]; +- struct airoha_qdma_desc *desc; +- struct airoha_queue_entry *e; +- struct airoha_queue *q; +- u32 index, desc_ctrl; +- struct sk_buff *skb; +- +- if (val == 0xff) +- break; +- +- irq_q->q[head] = 0xff; /* mark as done */ +- head = (head + 1) % irq_q->size; +- irq_queued--; +- done++; +- +- qid = FIELD_GET(IRQ_RING_IDX_MASK, val); +- if (qid >= ARRAY_SIZE(qdma->q_tx)) +- continue; +- +- q = &qdma->q_tx[qid]; +- if (!q->ndesc) +- continue; +- +- index = FIELD_GET(IRQ_DESC_IDX_MASK, val); +- if (index >= q->ndesc) +- continue; +- +- spin_lock_bh(&q->lock); +- +- if (!q->queued) +- goto unlock; +- +- desc = &q->desc[index]; +- desc_ctrl = le32_to_cpu(desc->ctrl); +- +- if (!(desc_ctrl & QDMA_DESC_DONE_MASK) && +- !(desc_ctrl & QDMA_DESC_DROP_MASK)) +- goto unlock; +- +- e = &q->entry[index]; +- skb = e->skb; +- +- dma_unmap_single(eth->dev, e->dma_addr, e->dma_len, +- DMA_TO_DEVICE); +- memset(e, 0, sizeof(*e)); +- WRITE_ONCE(desc->msg0, 0); +- WRITE_ONCE(desc->msg1, 0); +- q->queued--; +- +- /* completion ring can report out-of-order indexes if hw QoS +- * is enabled and packets with different priority are queued +- * to same DMA ring. Take into account possible out-of-order +- * reports incrementing DMA ring tail pointer +- */ +- while (q->tail != q->head && !q->entry[q->tail].dma_addr) +- q->tail = (q->tail + 1) % q->ndesc; +- +- if (skb) { +- u16 queue = skb_get_queue_mapping(skb); +- struct netdev_queue *txq; +- +- txq = netdev_get_tx_queue(skb->dev, queue); +- netdev_tx_completed_queue(txq, 1, skb->len); +- if (netif_tx_queue_stopped(txq) && +- q->ndesc - q->queued >= q->free_thr) +- netif_tx_wake_queue(txq); +- +- dev_kfree_skb_any(skb); +- } +-unlock: +- spin_unlock_bh(&q->lock); +- } +- +- if (done) { +- int i, len = done >> 7; +- +- for (i = 0; i < len; i++) +- airoha_qdma_rmw(qdma, REG_IRQ_CLEAR_LEN(id), +- IRQ_CLEAR_LEN_MASK, 0x80); +- airoha_qdma_rmw(qdma, REG_IRQ_CLEAR_LEN(id), +- IRQ_CLEAR_LEN_MASK, (done & 0x7f)); +- } +- +- if (done < budget && napi_complete(napi)) +- airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX0, +- TX_DONE_INT_MASK(id)); +- +- return done; +-} +- +-static int airoha_qdma_init_tx_queue(struct airoha_queue *q, +- struct airoha_qdma *qdma, int size) +-{ +- struct airoha_eth *eth = qdma->eth; +- int i, qid = q - &qdma->q_tx[0]; +- dma_addr_t dma_addr; +- +- spin_lock_init(&q->lock); +- q->ndesc = size; +- q->qdma = qdma; +- q->free_thr = 1 + MAX_SKB_FRAGS; +- +- q->entry = devm_kzalloc(eth->dev, q->ndesc * sizeof(*q->entry), +- GFP_KERNEL); +- if (!q->entry) +- return -ENOMEM; +- +- q->desc = dmam_alloc_coherent(eth->dev, q->ndesc * sizeof(*q->desc), +- &dma_addr, GFP_KERNEL); +- if (!q->desc) +- return -ENOMEM; +- +- for (i = 0; i < q->ndesc; i++) { +- u32 val; +- +- val = FIELD_PREP(QDMA_DESC_DONE_MASK, 1); +- WRITE_ONCE(q->desc[i].ctrl, cpu_to_le32(val)); +- } +- +- /* xmit ring drop default setting */ +- airoha_qdma_set(qdma, REG_TX_RING_BLOCKING(qid), +- TX_RING_IRQ_BLOCKING_TX_DROP_EN_MASK); +- +- airoha_qdma_wr(qdma, REG_TX_RING_BASE(qid), dma_addr); +- airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK, +- FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head)); +- airoha_qdma_rmw(qdma, REG_TX_DMA_IDX(qid), TX_RING_DMA_IDX_MASK, +- FIELD_PREP(TX_RING_DMA_IDX_MASK, q->head)); +- +- return 0; +-} +- +-static int airoha_qdma_tx_irq_init(struct airoha_tx_irq_queue *irq_q, +- struct airoha_qdma *qdma, int size) +-{ +- int id = irq_q - &qdma->q_tx_irq[0]; +- struct airoha_eth *eth = qdma->eth; +- dma_addr_t dma_addr; +- +- netif_napi_add_tx(eth->napi_dev, &irq_q->napi, +- airoha_qdma_tx_napi_poll); +- irq_q->q = dmam_alloc_coherent(eth->dev, size * sizeof(u32), +- &dma_addr, GFP_KERNEL); +- if (!irq_q->q) +- return -ENOMEM; +- +- memset(irq_q->q, 0xff, size * sizeof(u32)); +- irq_q->size = size; +- irq_q->qdma = qdma; +- +- airoha_qdma_wr(qdma, REG_TX_IRQ_BASE(id), dma_addr); +- airoha_qdma_rmw(qdma, REG_TX_IRQ_CFG(id), TX_IRQ_DEPTH_MASK, +- FIELD_PREP(TX_IRQ_DEPTH_MASK, size)); +- airoha_qdma_rmw(qdma, REG_TX_IRQ_CFG(id), TX_IRQ_THR_MASK, +- FIELD_PREP(TX_IRQ_THR_MASK, 1)); +- +- return 0; +-} +- +-static int airoha_qdma_init_tx(struct airoha_qdma *qdma) +-{ +- int i, err; +- +- for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) { +- err = airoha_qdma_tx_irq_init(&qdma->q_tx_irq[i], qdma, +- IRQ_QUEUE_LEN(i)); +- if (err) +- return err; +- } +- +- for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { +- err = airoha_qdma_init_tx_queue(&qdma->q_tx[i], qdma, +- TX_DSCP_NUM); +- if (err) +- return err; +- } +- +- return 0; +-} +- +-static void airoha_qdma_cleanup_tx_queue(struct airoha_queue *q) +-{ +- struct airoha_eth *eth = q->qdma->eth; +- +- spin_lock_bh(&q->lock); +- while (q->queued) { +- struct airoha_queue_entry *e = &q->entry[q->tail]; +- +- dma_unmap_single(eth->dev, e->dma_addr, e->dma_len, +- DMA_TO_DEVICE); +- dev_kfree_skb_any(e->skb); +- e->skb = NULL; +- +- q->tail = (q->tail + 1) % q->ndesc; +- q->queued--; +- } +- spin_unlock_bh(&q->lock); +-} +- +-static int airoha_qdma_init_hfwd_queues(struct airoha_qdma *qdma) +-{ +- struct airoha_eth *eth = qdma->eth; +- dma_addr_t dma_addr; +- u32 status; +- int size; +- +- size = HW_DSCP_NUM * sizeof(struct airoha_qdma_fwd_desc); +- qdma->hfwd.desc = dmam_alloc_coherent(eth->dev, size, &dma_addr, +- GFP_KERNEL); +- if (!qdma->hfwd.desc) +- return -ENOMEM; +- +- airoha_qdma_wr(qdma, REG_FWD_DSCP_BASE, dma_addr); +- +- size = AIROHA_MAX_PACKET_SIZE * HW_DSCP_NUM; +- qdma->hfwd.q = dmam_alloc_coherent(eth->dev, size, &dma_addr, +- GFP_KERNEL); +- if (!qdma->hfwd.q) +- return -ENOMEM; +- +- airoha_qdma_wr(qdma, REG_FWD_BUF_BASE, dma_addr); +- +- airoha_qdma_rmw(qdma, REG_HW_FWD_DSCP_CFG, +- HW_FWD_DSCP_PAYLOAD_SIZE_MASK, +- FIELD_PREP(HW_FWD_DSCP_PAYLOAD_SIZE_MASK, 0)); +- airoha_qdma_rmw(qdma, REG_FWD_DSCP_LOW_THR, FWD_DSCP_LOW_THR_MASK, +- FIELD_PREP(FWD_DSCP_LOW_THR_MASK, 128)); +- airoha_qdma_rmw(qdma, REG_LMGR_INIT_CFG, +- LMGR_INIT_START | LMGR_SRAM_MODE_MASK | +- HW_FWD_DESC_NUM_MASK, +- FIELD_PREP(HW_FWD_DESC_NUM_MASK, HW_DSCP_NUM) | +- LMGR_INIT_START); +- +- return read_poll_timeout(airoha_qdma_rr, status, +- !(status & LMGR_INIT_START), USEC_PER_MSEC, +- 30 * USEC_PER_MSEC, true, qdma, +- REG_LMGR_INIT_CFG); +-} +- +-static void airoha_qdma_init_qos(struct airoha_qdma *qdma) +-{ +- airoha_qdma_clear(qdma, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_SCALE_MASK); +- airoha_qdma_set(qdma, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_BASE_MASK); +- +- airoha_qdma_clear(qdma, REG_PSE_BUF_USAGE_CFG, +- PSE_BUF_ESTIMATE_EN_MASK); +- +- airoha_qdma_set(qdma, REG_EGRESS_RATE_METER_CFG, +- EGRESS_RATE_METER_EN_MASK | +- EGRESS_RATE_METER_EQ_RATE_EN_MASK); +- /* 2047us x 31 = 63.457ms */ +- airoha_qdma_rmw(qdma, REG_EGRESS_RATE_METER_CFG, +- EGRESS_RATE_METER_WINDOW_SZ_MASK, +- FIELD_PREP(EGRESS_RATE_METER_WINDOW_SZ_MASK, 0x1f)); +- airoha_qdma_rmw(qdma, REG_EGRESS_RATE_METER_CFG, +- EGRESS_RATE_METER_TIMESLICE_MASK, +- FIELD_PREP(EGRESS_RATE_METER_TIMESLICE_MASK, 0x7ff)); +- +- /* ratelimit init */ +- airoha_qdma_set(qdma, REG_GLB_TRTCM_CFG, GLB_TRTCM_EN_MASK); +- /* fast-tick 25us */ +- airoha_qdma_rmw(qdma, REG_GLB_TRTCM_CFG, GLB_FAST_TICK_MASK, +- FIELD_PREP(GLB_FAST_TICK_MASK, 25)); +- airoha_qdma_rmw(qdma, REG_GLB_TRTCM_CFG, GLB_SLOW_TICK_RATIO_MASK, +- FIELD_PREP(GLB_SLOW_TICK_RATIO_MASK, 40)); +- +- airoha_qdma_set(qdma, REG_EGRESS_TRTCM_CFG, EGRESS_TRTCM_EN_MASK); +- airoha_qdma_rmw(qdma, REG_EGRESS_TRTCM_CFG, EGRESS_FAST_TICK_MASK, +- FIELD_PREP(EGRESS_FAST_TICK_MASK, 25)); +- airoha_qdma_rmw(qdma, REG_EGRESS_TRTCM_CFG, +- EGRESS_SLOW_TICK_RATIO_MASK, +- FIELD_PREP(EGRESS_SLOW_TICK_RATIO_MASK, 40)); +- +- airoha_qdma_set(qdma, REG_INGRESS_TRTCM_CFG, INGRESS_TRTCM_EN_MASK); +- airoha_qdma_clear(qdma, REG_INGRESS_TRTCM_CFG, +- INGRESS_TRTCM_MODE_MASK); +- airoha_qdma_rmw(qdma, REG_INGRESS_TRTCM_CFG, INGRESS_FAST_TICK_MASK, +- FIELD_PREP(INGRESS_FAST_TICK_MASK, 125)); +- airoha_qdma_rmw(qdma, REG_INGRESS_TRTCM_CFG, +- INGRESS_SLOW_TICK_RATIO_MASK, +- FIELD_PREP(INGRESS_SLOW_TICK_RATIO_MASK, 8)); +- +- airoha_qdma_set(qdma, REG_SLA_TRTCM_CFG, SLA_TRTCM_EN_MASK); +- airoha_qdma_rmw(qdma, REG_SLA_TRTCM_CFG, SLA_FAST_TICK_MASK, +- FIELD_PREP(SLA_FAST_TICK_MASK, 25)); +- airoha_qdma_rmw(qdma, REG_SLA_TRTCM_CFG, SLA_SLOW_TICK_RATIO_MASK, +- FIELD_PREP(SLA_SLOW_TICK_RATIO_MASK, 40)); +-} +- +-static void airoha_qdma_init_qos_stats(struct airoha_qdma *qdma) +-{ +- int i; +- +- for (i = 0; i < AIROHA_NUM_QOS_CHANNELS; i++) { +- /* Tx-cpu transferred count */ +- airoha_qdma_wr(qdma, REG_CNTR_VAL(i << 1), 0); +- airoha_qdma_wr(qdma, REG_CNTR_CFG(i << 1), +- CNTR_EN_MASK | CNTR_ALL_QUEUE_EN_MASK | +- CNTR_ALL_DSCP_RING_EN_MASK | +- FIELD_PREP(CNTR_CHAN_MASK, i)); +- /* Tx-fwd transferred count */ +- airoha_qdma_wr(qdma, REG_CNTR_VAL((i << 1) + 1), 0); +- airoha_qdma_wr(qdma, REG_CNTR_CFG(i << 1), +- CNTR_EN_MASK | CNTR_ALL_QUEUE_EN_MASK | +- CNTR_ALL_DSCP_RING_EN_MASK | +- FIELD_PREP(CNTR_SRC_MASK, 1) | +- FIELD_PREP(CNTR_CHAN_MASK, i)); +- } +-} +- +-static int airoha_qdma_hw_init(struct airoha_qdma *qdma) +-{ +- int i; +- +- /* clear pending irqs */ +- for (i = 0; i < ARRAY_SIZE(qdma->irqmask); i++) +- airoha_qdma_wr(qdma, REG_INT_STATUS(i), 0xffffffff); +- +- /* setup irqs */ +- airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX0, INT_IDX0_MASK); +- airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX1, INT_IDX1_MASK); +- airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX4, INT_IDX4_MASK); +- +- /* setup irq binding */ +- for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { +- if (!qdma->q_tx[i].ndesc) +- continue; +- +- if (TX_RING_IRQ_BLOCKING_MAP_MASK & BIT(i)) +- airoha_qdma_set(qdma, REG_TX_RING_BLOCKING(i), +- TX_RING_IRQ_BLOCKING_CFG_MASK); +- else +- airoha_qdma_clear(qdma, REG_TX_RING_BLOCKING(i), +- TX_RING_IRQ_BLOCKING_CFG_MASK); +- } +- +- airoha_qdma_wr(qdma, REG_QDMA_GLOBAL_CFG, +- GLOBAL_CFG_RX_2B_OFFSET_MASK | +- FIELD_PREP(GLOBAL_CFG_DMA_PREFERENCE_MASK, 3) | +- GLOBAL_CFG_CPU_TXR_RR_MASK | +- GLOBAL_CFG_PAYLOAD_BYTE_SWAP_MASK | +- GLOBAL_CFG_MULTICAST_MODIFY_FP_MASK | +- GLOBAL_CFG_MULTICAST_EN_MASK | +- GLOBAL_CFG_IRQ0_EN_MASK | GLOBAL_CFG_IRQ1_EN_MASK | +- GLOBAL_CFG_TX_WB_DONE_MASK | +- FIELD_PREP(GLOBAL_CFG_MAX_ISSUE_NUM_MASK, 2)); +- +- airoha_qdma_init_qos(qdma); +- +- /* disable qdma rx delay interrupt */ +- for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { +- if (!qdma->q_rx[i].ndesc) +- continue; +- +- airoha_qdma_clear(qdma, REG_RX_DELAY_INT_IDX(i), +- RX_DELAY_INT_MASK); +- } +- +- airoha_qdma_set(qdma, REG_TXQ_CNGST_CFG, +- TXQ_CNGST_DROP_EN | TXQ_CNGST_DEI_DROP_EN); +- airoha_qdma_init_qos_stats(qdma); +- +- return 0; +-} +- +-static irqreturn_t airoha_irq_handler(int irq, void *dev_instance) +-{ +- struct airoha_qdma *qdma = dev_instance; +- u32 intr[ARRAY_SIZE(qdma->irqmask)]; +- int i; +- +- for (i = 0; i < ARRAY_SIZE(qdma->irqmask); i++) { +- intr[i] = airoha_qdma_rr(qdma, REG_INT_STATUS(i)); +- intr[i] &= qdma->irqmask[i]; +- airoha_qdma_wr(qdma, REG_INT_STATUS(i), intr[i]); +- } +- +- if (!test_bit(DEV_STATE_INITIALIZED, &qdma->eth->state)) +- return IRQ_NONE; +- +- if (intr[1] & RX_DONE_INT_MASK) { +- airoha_qdma_irq_disable(qdma, QDMA_INT_REG_IDX1, +- RX_DONE_INT_MASK); +- +- for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { +- if (!qdma->q_rx[i].ndesc) +- continue; +- +- if (intr[1] & BIT(i)) +- napi_schedule(&qdma->q_rx[i].napi); +- } +- } +- +- if (intr[0] & INT_TX_MASK) { +- for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) { +- if (!(intr[0] & TX_DONE_INT_MASK(i))) +- continue; +- +- airoha_qdma_irq_disable(qdma, QDMA_INT_REG_IDX0, +- TX_DONE_INT_MASK(i)); +- napi_schedule(&qdma->q_tx_irq[i].napi); +- } +- } +- +- return IRQ_HANDLED; +-} +- +-static int airoha_qdma_init(struct platform_device *pdev, +- struct airoha_eth *eth, +- struct airoha_qdma *qdma) +-{ +- int err, id = qdma - ð->qdma[0]; +- const char *res; +- +- spin_lock_init(&qdma->irq_lock); +- qdma->eth = eth; +- +- res = devm_kasprintf(eth->dev, GFP_KERNEL, "qdma%d", id); +- if (!res) +- return -ENOMEM; +- +- qdma->regs = devm_platform_ioremap_resource_byname(pdev, res); +- if (IS_ERR(qdma->regs)) +- return dev_err_probe(eth->dev, PTR_ERR(qdma->regs), +- "failed to iomap qdma%d regs\n", id); +- +- qdma->irq = platform_get_irq(pdev, 4 * id); +- if (qdma->irq < 0) +- return qdma->irq; +- +- err = devm_request_irq(eth->dev, qdma->irq, airoha_irq_handler, +- IRQF_SHARED, KBUILD_MODNAME, qdma); +- if (err) +- return err; +- +- err = airoha_qdma_init_rx(qdma); +- if (err) +- return err; +- +- err = airoha_qdma_init_tx(qdma); +- if (err) +- return err; +- +- err = airoha_qdma_init_hfwd_queues(qdma); +- if (err) +- return err; +- +- return airoha_qdma_hw_init(qdma); +-} +- +-static int airoha_hw_init(struct platform_device *pdev, +- struct airoha_eth *eth) +-{ +- int err, i; +- +- /* disable xsi */ +- err = reset_control_bulk_assert(ARRAY_SIZE(eth->xsi_rsts), +- eth->xsi_rsts); +- if (err) +- return err; +- +- err = reset_control_bulk_assert(ARRAY_SIZE(eth->rsts), eth->rsts); +- if (err) +- return err; +- +- msleep(20); +- err = reset_control_bulk_deassert(ARRAY_SIZE(eth->rsts), eth->rsts); +- if (err) +- return err; +- +- msleep(20); +- err = airoha_fe_init(eth); +- if (err) +- return err; +- +- for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) { +- err = airoha_qdma_init(pdev, eth, ð->qdma[i]); +- if (err) +- return err; +- } +- +- set_bit(DEV_STATE_INITIALIZED, ð->state); +- +- return 0; +-} +- +-static void airoha_hw_cleanup(struct airoha_qdma *qdma) +-{ +- int i; +- +- for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { +- if (!qdma->q_rx[i].ndesc) +- continue; +- +- netif_napi_del(&qdma->q_rx[i].napi); +- airoha_qdma_cleanup_rx_queue(&qdma->q_rx[i]); +- if (qdma->q_rx[i].page_pool) +- page_pool_destroy(qdma->q_rx[i].page_pool); +- } +- +- for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) +- netif_napi_del(&qdma->q_tx_irq[i].napi); +- +- for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { +- if (!qdma->q_tx[i].ndesc) +- continue; +- +- airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]); +- } +-} +- +-static void airoha_qdma_start_napi(struct airoha_qdma *qdma) +-{ +- int i; +- +- for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) +- napi_enable(&qdma->q_tx_irq[i].napi); +- +- for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { +- if (!qdma->q_rx[i].ndesc) +- continue; +- +- napi_enable(&qdma->q_rx[i].napi); +- } +-} +- +-static void airoha_qdma_stop_napi(struct airoha_qdma *qdma) +-{ +- int i; +- +- for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) +- napi_disable(&qdma->q_tx_irq[i].napi); +- +- for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { +- if (!qdma->q_rx[i].ndesc) +- continue; +- +- napi_disable(&qdma->q_rx[i].napi); +- } +-} +- +-static void airoha_update_hw_stats(struct airoha_gdm_port *port) +-{ +- struct airoha_eth *eth = port->qdma->eth; +- u32 val, i = 0; +- +- spin_lock(&port->stats.lock); +- u64_stats_update_begin(&port->stats.syncp); +- +- /* TX */ +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_PKT_CNT_H(port->id)); +- port->stats.tx_ok_pkts += ((u64)val << 32); +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_PKT_CNT_L(port->id)); +- port->stats.tx_ok_pkts += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_BYTE_CNT_H(port->id)); +- port->stats.tx_ok_bytes += ((u64)val << 32); +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_OK_BYTE_CNT_L(port->id)); +- port->stats.tx_ok_bytes += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_DROP_CNT(port->id)); +- port->stats.tx_drops += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_BC_CNT(port->id)); +- port->stats.tx_broadcast += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_MC_CNT(port->id)); +- port->stats.tx_multicast += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_RUNT_CNT(port->id)); +- port->stats.tx_len[i] += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_E64_CNT_H(port->id)); +- port->stats.tx_len[i] += ((u64)val << 32); +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_E64_CNT_L(port->id)); +- port->stats.tx_len[i++] += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L64_CNT_H(port->id)); +- port->stats.tx_len[i] += ((u64)val << 32); +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L64_CNT_L(port->id)); +- port->stats.tx_len[i++] += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L127_CNT_H(port->id)); +- port->stats.tx_len[i] += ((u64)val << 32); +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L127_CNT_L(port->id)); +- port->stats.tx_len[i++] += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L255_CNT_H(port->id)); +- port->stats.tx_len[i] += ((u64)val << 32); +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L255_CNT_L(port->id)); +- port->stats.tx_len[i++] += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L511_CNT_H(port->id)); +- port->stats.tx_len[i] += ((u64)val << 32); +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L511_CNT_L(port->id)); +- port->stats.tx_len[i++] += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L1023_CNT_H(port->id)); +- port->stats.tx_len[i] += ((u64)val << 32); +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_L1023_CNT_L(port->id)); +- port->stats.tx_len[i++] += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_TX_ETH_LONG_CNT(port->id)); +- port->stats.tx_len[i++] += val; +- +- /* RX */ +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_PKT_CNT_H(port->id)); +- port->stats.rx_ok_pkts += ((u64)val << 32); +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_PKT_CNT_L(port->id)); +- port->stats.rx_ok_pkts += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_BYTE_CNT_H(port->id)); +- port->stats.rx_ok_bytes += ((u64)val << 32); +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_OK_BYTE_CNT_L(port->id)); +- port->stats.rx_ok_bytes += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_DROP_CNT(port->id)); +- port->stats.rx_drops += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_BC_CNT(port->id)); +- port->stats.rx_broadcast += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_MC_CNT(port->id)); +- port->stats.rx_multicast += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ERROR_DROP_CNT(port->id)); +- port->stats.rx_errors += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_CRC_ERR_CNT(port->id)); +- port->stats.rx_crc_error += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_OVERFLOW_DROP_CNT(port->id)); +- port->stats.rx_over_errors += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_FRAG_CNT(port->id)); +- port->stats.rx_fragment += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_JABBER_CNT(port->id)); +- port->stats.rx_jabber += val; +- +- i = 0; +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_RUNT_CNT(port->id)); +- port->stats.rx_len[i] += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_E64_CNT_H(port->id)); +- port->stats.rx_len[i] += ((u64)val << 32); +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_E64_CNT_L(port->id)); +- port->stats.rx_len[i++] += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L64_CNT_H(port->id)); +- port->stats.rx_len[i] += ((u64)val << 32); +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L64_CNT_L(port->id)); +- port->stats.rx_len[i++] += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L127_CNT_H(port->id)); +- port->stats.rx_len[i] += ((u64)val << 32); +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L127_CNT_L(port->id)); +- port->stats.rx_len[i++] += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L255_CNT_H(port->id)); +- port->stats.rx_len[i] += ((u64)val << 32); +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L255_CNT_L(port->id)); +- port->stats.rx_len[i++] += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L511_CNT_H(port->id)); +- port->stats.rx_len[i] += ((u64)val << 32); +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L511_CNT_L(port->id)); +- port->stats.rx_len[i++] += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L1023_CNT_H(port->id)); +- port->stats.rx_len[i] += ((u64)val << 32); +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_L1023_CNT_L(port->id)); +- port->stats.rx_len[i++] += val; +- +- val = airoha_fe_rr(eth, REG_FE_GDM_RX_ETH_LONG_CNT(port->id)); +- port->stats.rx_len[i++] += val; +- +- /* reset mib counters */ +- airoha_fe_set(eth, REG_FE_GDM_MIB_CLEAR(port->id), +- FE_GDM_MIB_RX_CLEAR_MASK | FE_GDM_MIB_TX_CLEAR_MASK); +- +- u64_stats_update_end(&port->stats.syncp); +- spin_unlock(&port->stats.lock); +-} +- +-static int airoha_dev_open(struct net_device *dev) +-{ +- struct airoha_gdm_port *port = netdev_priv(dev); +- struct airoha_qdma *qdma = port->qdma; +- int err; +- +- netif_tx_start_all_queues(dev); +- err = airoha_set_gdm_ports(qdma->eth, true); +- if (err) +- return err; +- +- if (netdev_uses_dsa(dev)) +- airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id), +- GDM_STAG_EN_MASK); +- else +- airoha_fe_clear(qdma->eth, REG_GDM_INGRESS_CFG(port->id), +- GDM_STAG_EN_MASK); +- +- airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG, +- GLOBAL_CFG_TX_DMA_EN_MASK | +- GLOBAL_CFG_RX_DMA_EN_MASK); +- +- return 0; +-} +- +-static int airoha_dev_stop(struct net_device *dev) +-{ +- struct airoha_gdm_port *port = netdev_priv(dev); +- struct airoha_qdma *qdma = port->qdma; +- int i, err; +- +- netif_tx_disable(dev); +- err = airoha_set_gdm_ports(qdma->eth, false); +- if (err) +- return err; +- +- airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG, +- GLOBAL_CFG_TX_DMA_EN_MASK | +- GLOBAL_CFG_RX_DMA_EN_MASK); +- +- for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { +- if (!qdma->q_tx[i].ndesc) +- continue; +- +- airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]); +- netdev_tx_reset_subqueue(dev, i); +- } +- +- return 0; +-} +- +-static int airoha_dev_set_macaddr(struct net_device *dev, void *p) +-{ +- struct airoha_gdm_port *port = netdev_priv(dev); +- int err; +- +- err = eth_mac_addr(dev, p); +- if (err) +- return err; +- +- airoha_set_macaddr(port, dev->dev_addr); +- +- return 0; +-} +- +-static int airoha_dev_init(struct net_device *dev) +-{ +- struct airoha_gdm_port *port = netdev_priv(dev); +- +- airoha_set_macaddr(port, dev->dev_addr); +- +- return 0; +-} +- +-static void airoha_dev_get_stats64(struct net_device *dev, +- struct rtnl_link_stats64 *storage) +-{ +- struct airoha_gdm_port *port = netdev_priv(dev); +- unsigned int start; +- +- airoha_update_hw_stats(port); +- do { +- start = u64_stats_fetch_begin(&port->stats.syncp); +- storage->rx_packets = port->stats.rx_ok_pkts; +- storage->tx_packets = port->stats.tx_ok_pkts; +- storage->rx_bytes = port->stats.rx_ok_bytes; +- storage->tx_bytes = port->stats.tx_ok_bytes; +- storage->multicast = port->stats.rx_multicast; +- storage->rx_errors = port->stats.rx_errors; +- storage->rx_dropped = port->stats.rx_drops; +- storage->tx_dropped = port->stats.tx_drops; +- storage->rx_crc_errors = port->stats.rx_crc_error; +- storage->rx_over_errors = port->stats.rx_over_errors; +- } while (u64_stats_fetch_retry(&port->stats.syncp, start)); +-} +- +-static u16 airoha_dev_select_queue(struct net_device *dev, struct sk_buff *skb, +- struct net_device *sb_dev) +-{ +- struct airoha_gdm_port *port = netdev_priv(dev); +- int queue, channel; +- +- /* For dsa device select QoS channel according to the dsa user port +- * index, rely on port id otherwise. Select QoS queue based on the +- * skb priority. +- */ +- channel = netdev_uses_dsa(dev) ? skb_get_queue_mapping(skb) : port->id; +- channel = channel % AIROHA_NUM_QOS_CHANNELS; +- queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES; /* QoS queue */ +- queue = channel * AIROHA_NUM_QOS_QUEUES + queue; +- +- return queue < dev->num_tx_queues ? queue : 0; +-} +- +-static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, +- struct net_device *dev) +-{ +- struct airoha_gdm_port *port = netdev_priv(dev); +- u32 nr_frags = 1 + skb_shinfo(skb)->nr_frags; +- u32 msg0, msg1, len = skb_headlen(skb); +- struct airoha_qdma *qdma = port->qdma; +- struct netdev_queue *txq; +- struct airoha_queue *q; +- void *data = skb->data; +- int i, qid; +- u16 index; +- u8 fport; +- +- qid = skb_get_queue_mapping(skb) % ARRAY_SIZE(qdma->q_tx); +- msg0 = FIELD_PREP(QDMA_ETH_TXMSG_CHAN_MASK, +- qid / AIROHA_NUM_QOS_QUEUES) | +- FIELD_PREP(QDMA_ETH_TXMSG_QUEUE_MASK, +- qid % AIROHA_NUM_QOS_QUEUES); +- if (skb->ip_summed == CHECKSUM_PARTIAL) +- msg0 |= FIELD_PREP(QDMA_ETH_TXMSG_TCO_MASK, 1) | +- FIELD_PREP(QDMA_ETH_TXMSG_UCO_MASK, 1) | +- FIELD_PREP(QDMA_ETH_TXMSG_ICO_MASK, 1); +- +- /* TSO: fill MSS info in tcp checksum field */ +- if (skb_is_gso(skb)) { +- if (skb_cow_head(skb, 0)) +- goto error; +- +- if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | +- SKB_GSO_TCPV6)) { +- __be16 csum = cpu_to_be16(skb_shinfo(skb)->gso_size); +- +- tcp_hdr(skb)->check = (__force __sum16)csum; +- msg0 |= FIELD_PREP(QDMA_ETH_TXMSG_TSO_MASK, 1); +- } +- } +- +- fport = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id; +- msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) | +- FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f); +- +- q = &qdma->q_tx[qid]; +- if (WARN_ON_ONCE(!q->ndesc)) +- goto error; +- +- spin_lock_bh(&q->lock); +- +- txq = netdev_get_tx_queue(dev, qid); +- if (q->queued + nr_frags > q->ndesc) { +- /* not enough space in the queue */ +- netif_tx_stop_queue(txq); +- spin_unlock_bh(&q->lock); +- return NETDEV_TX_BUSY; +- } +- +- index = q->head; +- for (i = 0; i < nr_frags; i++) { +- struct airoha_qdma_desc *desc = &q->desc[index]; +- struct airoha_queue_entry *e = &q->entry[index]; +- skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; +- dma_addr_t addr; +- u32 val; +- +- addr = dma_map_single(dev->dev.parent, data, len, +- DMA_TO_DEVICE); +- if (unlikely(dma_mapping_error(dev->dev.parent, addr))) +- goto error_unmap; +- +- index = (index + 1) % q->ndesc; +- +- val = FIELD_PREP(QDMA_DESC_LEN_MASK, len); +- if (i < nr_frags - 1) +- val |= FIELD_PREP(QDMA_DESC_MORE_MASK, 1); +- WRITE_ONCE(desc->ctrl, cpu_to_le32(val)); +- WRITE_ONCE(desc->addr, cpu_to_le32(addr)); +- val = FIELD_PREP(QDMA_DESC_NEXT_ID_MASK, index); +- WRITE_ONCE(desc->data, cpu_to_le32(val)); +- WRITE_ONCE(desc->msg0, cpu_to_le32(msg0)); +- WRITE_ONCE(desc->msg1, cpu_to_le32(msg1)); +- WRITE_ONCE(desc->msg2, cpu_to_le32(0xffff)); +- +- e->skb = i ? NULL : skb; +- e->dma_addr = addr; +- e->dma_len = len; +- +- data = skb_frag_address(frag); +- len = skb_frag_size(frag); +- } +- +- q->head = index; +- q->queued += i; +- +- skb_tx_timestamp(skb); +- netdev_tx_sent_queue(txq, skb->len); +- +- if (netif_xmit_stopped(txq) || !netdev_xmit_more()) +- airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid), +- TX_RING_CPU_IDX_MASK, +- FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head)); +- +- if (q->ndesc - q->queued < q->free_thr) +- netif_tx_stop_queue(txq); +- +- spin_unlock_bh(&q->lock); +- +- return NETDEV_TX_OK; +- +-error_unmap: +- for (i--; i >= 0; i--) { +- index = (q->head + i) % q->ndesc; +- dma_unmap_single(dev->dev.parent, q->entry[index].dma_addr, +- q->entry[index].dma_len, DMA_TO_DEVICE); +- } +- +- spin_unlock_bh(&q->lock); +-error: +- dev_kfree_skb_any(skb); +- dev->stats.tx_dropped++; +- +- return NETDEV_TX_OK; +-} +- +-static void airoha_ethtool_get_drvinfo(struct net_device *dev, +- struct ethtool_drvinfo *info) +-{ +- struct airoha_gdm_port *port = netdev_priv(dev); +- struct airoha_eth *eth = port->qdma->eth; +- +- strscpy(info->driver, eth->dev->driver->name, sizeof(info->driver)); +- strscpy(info->bus_info, dev_name(eth->dev), sizeof(info->bus_info)); +-} +- +-static void airoha_ethtool_get_mac_stats(struct net_device *dev, +- struct ethtool_eth_mac_stats *stats) +-{ +- struct airoha_gdm_port *port = netdev_priv(dev); +- unsigned int start; +- +- airoha_update_hw_stats(port); +- do { +- start = u64_stats_fetch_begin(&port->stats.syncp); +- stats->MulticastFramesXmittedOK = port->stats.tx_multicast; +- stats->BroadcastFramesXmittedOK = port->stats.tx_broadcast; +- stats->BroadcastFramesReceivedOK = port->stats.rx_broadcast; +- } while (u64_stats_fetch_retry(&port->stats.syncp, start)); +-} +- +-static const struct ethtool_rmon_hist_range airoha_ethtool_rmon_ranges[] = { +- { 0, 64 }, +- { 65, 127 }, +- { 128, 255 }, +- { 256, 511 }, +- { 512, 1023 }, +- { 1024, 1518 }, +- { 1519, 10239 }, +- {}, +-}; +- +-static void +-airoha_ethtool_get_rmon_stats(struct net_device *dev, +- struct ethtool_rmon_stats *stats, +- const struct ethtool_rmon_hist_range **ranges) +-{ +- struct airoha_gdm_port *port = netdev_priv(dev); +- struct airoha_hw_stats *hw_stats = &port->stats; +- unsigned int start; +- +- BUILD_BUG_ON(ARRAY_SIZE(airoha_ethtool_rmon_ranges) != +- ARRAY_SIZE(hw_stats->tx_len) + 1); +- BUILD_BUG_ON(ARRAY_SIZE(airoha_ethtool_rmon_ranges) != +- ARRAY_SIZE(hw_stats->rx_len) + 1); +- +- *ranges = airoha_ethtool_rmon_ranges; +- airoha_update_hw_stats(port); +- do { +- int i; +- +- start = u64_stats_fetch_begin(&port->stats.syncp); +- stats->fragments = hw_stats->rx_fragment; +- stats->jabbers = hw_stats->rx_jabber; +- for (i = 0; i < ARRAY_SIZE(airoha_ethtool_rmon_ranges) - 1; +- i++) { +- stats->hist[i] = hw_stats->rx_len[i]; +- stats->hist_tx[i] = hw_stats->tx_len[i]; +- } +- } while (u64_stats_fetch_retry(&port->stats.syncp, start)); +-} +- +-static int airoha_qdma_set_chan_tx_sched(struct airoha_gdm_port *port, +- int channel, enum tx_sched_mode mode, +- const u16 *weights, u8 n_weights) +-{ +- int i; +- +- for (i = 0; i < AIROHA_NUM_TX_RING; i++) +- airoha_qdma_clear(port->qdma, REG_QUEUE_CLOSE_CFG(channel), +- TXQ_DISABLE_CHAN_QUEUE_MASK(channel, i)); +- +- for (i = 0; i < n_weights; i++) { +- u32 status; +- int err; +- +- airoha_qdma_wr(port->qdma, REG_TXWRR_WEIGHT_CFG, +- TWRR_RW_CMD_MASK | +- FIELD_PREP(TWRR_CHAN_IDX_MASK, channel) | +- FIELD_PREP(TWRR_QUEUE_IDX_MASK, i) | +- FIELD_PREP(TWRR_VALUE_MASK, weights[i])); +- err = read_poll_timeout(airoha_qdma_rr, status, +- status & TWRR_RW_CMD_DONE, +- USEC_PER_MSEC, 10 * USEC_PER_MSEC, +- true, port->qdma, +- REG_TXWRR_WEIGHT_CFG); +- if (err) +- return err; +- } +- +- airoha_qdma_rmw(port->qdma, REG_CHAN_QOS_MODE(channel >> 3), +- CHAN_QOS_MODE_MASK(channel), +- mode << __ffs(CHAN_QOS_MODE_MASK(channel))); +- +- return 0; +-} +- +-static int airoha_qdma_set_tx_prio_sched(struct airoha_gdm_port *port, +- int channel) +-{ +- static const u16 w[AIROHA_NUM_QOS_QUEUES] = {}; +- +- return airoha_qdma_set_chan_tx_sched(port, channel, TC_SCH_SP, w, +- ARRAY_SIZE(w)); +-} +- +-static int airoha_qdma_set_tx_ets_sched(struct airoha_gdm_port *port, +- int channel, +- struct tc_ets_qopt_offload *opt) +-{ +- struct tc_ets_qopt_offload_replace_params *p = &opt->replace_params; +- enum tx_sched_mode mode = TC_SCH_SP; +- u16 w[AIROHA_NUM_QOS_QUEUES] = {}; +- int i, nstrict = 0, nwrr, qidx; +- +- if (p->bands > AIROHA_NUM_QOS_QUEUES) +- return -EINVAL; +- +- for (i = 0; i < p->bands; i++) { +- if (!p->quanta[i]) +- nstrict++; +- } +- +- /* this configuration is not supported by the hw */ +- if (nstrict == AIROHA_NUM_QOS_QUEUES - 1) +- return -EINVAL; +- +- /* EN7581 SoC supports fixed QoS band priority where WRR queues have +- * lowest priorities with respect to SP ones. +- * e.g: WRR0, WRR1, .., WRRm, SP0, SP1, .., SPn +- */ +- nwrr = p->bands - nstrict; +- qidx = nstrict && nwrr ? nstrict : 0; +- for (i = 1; i <= p->bands; i++) { +- if (p->priomap[i % AIROHA_NUM_QOS_QUEUES] != qidx) +- return -EINVAL; +- +- qidx = i == nwrr ? 0 : qidx + 1; +- } +- +- for (i = 0; i < nwrr; i++) +- w[i] = p->weights[nstrict + i]; +- +- if (!nstrict) +- mode = TC_SCH_WRR8; +- else if (nstrict < AIROHA_NUM_QOS_QUEUES - 1) +- mode = nstrict + 1; +- +- return airoha_qdma_set_chan_tx_sched(port, channel, mode, w, +- ARRAY_SIZE(w)); +-} +- +-static int airoha_qdma_get_tx_ets_stats(struct airoha_gdm_port *port, +- int channel, +- struct tc_ets_qopt_offload *opt) +-{ +- u64 cpu_tx_packets = airoha_qdma_rr(port->qdma, +- REG_CNTR_VAL(channel << 1)); +- u64 fwd_tx_packets = airoha_qdma_rr(port->qdma, +- REG_CNTR_VAL((channel << 1) + 1)); +- u64 tx_packets = (cpu_tx_packets - port->cpu_tx_packets) + +- (fwd_tx_packets - port->fwd_tx_packets); +- _bstats_update(opt->stats.bstats, 0, tx_packets); +- +- port->cpu_tx_packets = cpu_tx_packets; +- port->fwd_tx_packets = fwd_tx_packets; +- +- return 0; +-} +- +-static int airoha_tc_setup_qdisc_ets(struct airoha_gdm_port *port, +- struct tc_ets_qopt_offload *opt) +-{ +- int channel = TC_H_MAJ(opt->handle) >> 16; +- +- if (opt->parent == TC_H_ROOT) +- return -EINVAL; +- +- switch (opt->command) { +- case TC_ETS_REPLACE: +- return airoha_qdma_set_tx_ets_sched(port, channel, opt); +- case TC_ETS_DESTROY: +- /* PRIO is default qdisc scheduler */ +- return airoha_qdma_set_tx_prio_sched(port, channel); +- case TC_ETS_STATS: +- return airoha_qdma_get_tx_ets_stats(port, channel, opt); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-static int airoha_qdma_get_trtcm_param(struct airoha_qdma *qdma, int channel, +- u32 addr, enum trtcm_param_type param, +- enum trtcm_mode_type mode, +- u32 *val_low, u32 *val_high) +-{ +- u32 idx = QDMA_METER_IDX(channel), group = QDMA_METER_GROUP(channel); +- u32 val, config = FIELD_PREP(TRTCM_PARAM_TYPE_MASK, param) | +- FIELD_PREP(TRTCM_METER_GROUP_MASK, group) | +- FIELD_PREP(TRTCM_PARAM_INDEX_MASK, idx) | +- FIELD_PREP(TRTCM_PARAM_RATE_TYPE_MASK, mode); +- +- airoha_qdma_wr(qdma, REG_TRTCM_CFG_PARAM(addr), config); +- if (read_poll_timeout(airoha_qdma_rr, val, +- val & TRTCM_PARAM_RW_DONE_MASK, +- USEC_PER_MSEC, 10 * USEC_PER_MSEC, true, +- qdma, REG_TRTCM_CFG_PARAM(addr))) +- return -ETIMEDOUT; +- +- *val_low = airoha_qdma_rr(qdma, REG_TRTCM_DATA_LOW(addr)); +- if (val_high) +- *val_high = airoha_qdma_rr(qdma, REG_TRTCM_DATA_HIGH(addr)); +- +- return 0; +-} +- +-static int airoha_qdma_set_trtcm_param(struct airoha_qdma *qdma, int channel, +- u32 addr, enum trtcm_param_type param, +- enum trtcm_mode_type mode, u32 val) +-{ +- u32 idx = QDMA_METER_IDX(channel), group = QDMA_METER_GROUP(channel); +- u32 config = TRTCM_PARAM_RW_MASK | +- FIELD_PREP(TRTCM_PARAM_TYPE_MASK, param) | +- FIELD_PREP(TRTCM_METER_GROUP_MASK, group) | +- FIELD_PREP(TRTCM_PARAM_INDEX_MASK, idx) | +- FIELD_PREP(TRTCM_PARAM_RATE_TYPE_MASK, mode); +- +- airoha_qdma_wr(qdma, REG_TRTCM_DATA_LOW(addr), val); +- airoha_qdma_wr(qdma, REG_TRTCM_CFG_PARAM(addr), config); +- +- return read_poll_timeout(airoha_qdma_rr, val, +- val & TRTCM_PARAM_RW_DONE_MASK, +- USEC_PER_MSEC, 10 * USEC_PER_MSEC, true, +- qdma, REG_TRTCM_CFG_PARAM(addr)); +-} +- +-static int airoha_qdma_set_trtcm_config(struct airoha_qdma *qdma, int channel, +- u32 addr, enum trtcm_mode_type mode, +- bool enable, u32 enable_mask) +-{ +- u32 val; +- +- if (airoha_qdma_get_trtcm_param(qdma, channel, addr, TRTCM_MISC_MODE, +- mode, &val, NULL)) +- return -EINVAL; +- +- val = enable ? val | enable_mask : val & ~enable_mask; +- +- return airoha_qdma_set_trtcm_param(qdma, channel, addr, TRTCM_MISC_MODE, +- mode, val); +-} +- +-static int airoha_qdma_set_trtcm_token_bucket(struct airoha_qdma *qdma, +- int channel, u32 addr, +- enum trtcm_mode_type mode, +- u32 rate_val, u32 bucket_size) +-{ +- u32 val, config, tick, unit, rate, rate_frac; +- int err; +- +- if (airoha_qdma_get_trtcm_param(qdma, channel, addr, TRTCM_MISC_MODE, +- mode, &config, NULL)) +- return -EINVAL; +- +- val = airoha_qdma_rr(qdma, addr); +- tick = FIELD_GET(INGRESS_FAST_TICK_MASK, val); +- if (config & TRTCM_TICK_SEL) +- tick *= FIELD_GET(INGRESS_SLOW_TICK_RATIO_MASK, val); +- if (!tick) +- return -EINVAL; +- +- unit = (config & TRTCM_PKT_MODE) ? 1000000 / tick : 8000 / tick; +- if (!unit) +- return -EINVAL; +- +- rate = rate_val / unit; +- rate_frac = rate_val % unit; +- rate_frac = FIELD_PREP(TRTCM_TOKEN_RATE_MASK, rate_frac) / unit; +- rate = FIELD_PREP(TRTCM_TOKEN_RATE_MASK, rate) | +- FIELD_PREP(TRTCM_TOKEN_RATE_FRACTION_MASK, rate_frac); +- +- err = airoha_qdma_set_trtcm_param(qdma, channel, addr, +- TRTCM_TOKEN_RATE_MODE, mode, rate); +- if (err) +- return err; +- +- val = max_t(u32, bucket_size, MIN_TOKEN_SIZE); +- val = min_t(u32, __fls(val), MAX_TOKEN_SIZE_OFFSET); +- +- return airoha_qdma_set_trtcm_param(qdma, channel, addr, +- TRTCM_BUCKETSIZE_SHIFT_MODE, +- mode, val); +-} +- +-static int airoha_qdma_set_tx_rate_limit(struct airoha_gdm_port *port, +- int channel, u32 rate, +- u32 bucket_size) +-{ +- int i, err; +- +- for (i = 0; i <= TRTCM_PEAK_MODE; i++) { +- err = airoha_qdma_set_trtcm_config(port->qdma, channel, +- REG_EGRESS_TRTCM_CFG, i, +- !!rate, TRTCM_METER_MODE); +- if (err) +- return err; +- +- err = airoha_qdma_set_trtcm_token_bucket(port->qdma, channel, +- REG_EGRESS_TRTCM_CFG, +- i, rate, bucket_size); +- if (err) +- return err; +- } +- +- return 0; +-} +- +-static int airoha_tc_htb_alloc_leaf_queue(struct airoha_gdm_port *port, +- struct tc_htb_qopt_offload *opt) +-{ +- u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; +- u32 rate = div_u64(opt->rate, 1000) << 3; /* kbps */ +- struct net_device *dev = port->dev; +- int num_tx_queues = dev->real_num_tx_queues; +- int err; +- +- if (opt->parent_classid != TC_HTB_CLASSID_ROOT) { +- NL_SET_ERR_MSG_MOD(opt->extack, "invalid parent classid"); +- return -EINVAL; +- } +- +- err = airoha_qdma_set_tx_rate_limit(port, channel, rate, opt->quantum); +- if (err) { +- NL_SET_ERR_MSG_MOD(opt->extack, +- "failed configuring htb offload"); +- return err; +- } +- +- if (opt->command == TC_HTB_NODE_MODIFY) +- return 0; +- +- err = netif_set_real_num_tx_queues(dev, num_tx_queues + 1); +- if (err) { +- airoha_qdma_set_tx_rate_limit(port, channel, 0, opt->quantum); +- NL_SET_ERR_MSG_MOD(opt->extack, +- "failed setting real_num_tx_queues"); +- return err; +- } +- +- set_bit(channel, port->qos_sq_bmap); +- opt->qid = AIROHA_NUM_TX_RING + channel; +- +- return 0; +-} +- +-static void airoha_tc_remove_htb_queue(struct airoha_gdm_port *port, int queue) +-{ +- struct net_device *dev = port->dev; +- +- netif_set_real_num_tx_queues(dev, dev->real_num_tx_queues - 1); +- airoha_qdma_set_tx_rate_limit(port, queue + 1, 0, 0); +- clear_bit(queue, port->qos_sq_bmap); +-} +- +-static int airoha_tc_htb_delete_leaf_queue(struct airoha_gdm_port *port, +- struct tc_htb_qopt_offload *opt) +-{ +- u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; +- +- if (!test_bit(channel, port->qos_sq_bmap)) { +- NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); +- return -EINVAL; +- } +- +- airoha_tc_remove_htb_queue(port, channel); +- +- return 0; +-} +- +-static int airoha_tc_htb_destroy(struct airoha_gdm_port *port) +-{ +- int q; +- +- for_each_set_bit(q, port->qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS) +- airoha_tc_remove_htb_queue(port, q); +- +- return 0; +-} +- +-static int airoha_tc_get_htb_get_leaf_queue(struct airoha_gdm_port *port, +- struct tc_htb_qopt_offload *opt) +-{ +- u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS; +- +- if (!test_bit(channel, port->qos_sq_bmap)) { +- NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id"); +- return -EINVAL; +- } +- +- opt->qid = channel; +- +- return 0; +-} +- +-static int airoha_tc_setup_qdisc_htb(struct airoha_gdm_port *port, +- struct tc_htb_qopt_offload *opt) +-{ +- switch (opt->command) { +- case TC_HTB_CREATE: +- break; +- case TC_HTB_DESTROY: +- return airoha_tc_htb_destroy(port); +- case TC_HTB_NODE_MODIFY: +- case TC_HTB_LEAF_ALLOC_QUEUE: +- return airoha_tc_htb_alloc_leaf_queue(port, opt); +- case TC_HTB_LEAF_DEL: +- case TC_HTB_LEAF_DEL_LAST: +- case TC_HTB_LEAF_DEL_LAST_FORCE: +- return airoha_tc_htb_delete_leaf_queue(port, opt); +- case TC_HTB_LEAF_QUERY_QUEUE: +- return airoha_tc_get_htb_get_leaf_queue(port, opt); +- default: +- return -EOPNOTSUPP; +- } +- +- return 0; +-} +- +-static int airoha_dev_tc_setup(struct net_device *dev, enum tc_setup_type type, +- void *type_data) +-{ +- struct airoha_gdm_port *port = netdev_priv(dev); +- +- switch (type) { +- case TC_SETUP_QDISC_ETS: +- return airoha_tc_setup_qdisc_ets(port, type_data); +- case TC_SETUP_QDISC_HTB: +- return airoha_tc_setup_qdisc_htb(port, type_data); +- default: +- return -EOPNOTSUPP; +- } +-} +- +-static const struct net_device_ops airoha_netdev_ops = { +- .ndo_init = airoha_dev_init, +- .ndo_open = airoha_dev_open, +- .ndo_stop = airoha_dev_stop, +- .ndo_select_queue = airoha_dev_select_queue, +- .ndo_start_xmit = airoha_dev_xmit, +- .ndo_get_stats64 = airoha_dev_get_stats64, +- .ndo_set_mac_address = airoha_dev_set_macaddr, +- .ndo_setup_tc = airoha_dev_tc_setup, +-}; +- +-static const struct ethtool_ops airoha_ethtool_ops = { +- .get_drvinfo = airoha_ethtool_get_drvinfo, +- .get_eth_mac_stats = airoha_ethtool_get_mac_stats, +- .get_rmon_stats = airoha_ethtool_get_rmon_stats, +-}; +- +-static int airoha_alloc_gdm_port(struct airoha_eth *eth, struct device_node *np) +-{ +- const __be32 *id_ptr = of_get_property(np, "reg", NULL); +- struct airoha_gdm_port *port; +- struct airoha_qdma *qdma; +- struct net_device *dev; +- int err, index; +- u32 id; +- +- if (!id_ptr) { +- dev_err(eth->dev, "missing gdm port id\n"); +- return -EINVAL; +- } +- +- id = be32_to_cpup(id_ptr); +- index = id - 1; +- +- if (!id || id > ARRAY_SIZE(eth->ports)) { +- dev_err(eth->dev, "invalid gdm port id: %d\n", id); +- return -EINVAL; +- } +- +- if (eth->ports[index]) { +- dev_err(eth->dev, "duplicate gdm port id: %d\n", id); +- return -EINVAL; +- } +- +- dev = devm_alloc_etherdev_mqs(eth->dev, sizeof(*port), +- AIROHA_NUM_NETDEV_TX_RINGS, +- AIROHA_NUM_RX_RING); +- if (!dev) { +- dev_err(eth->dev, "alloc_etherdev failed\n"); +- return -ENOMEM; +- } +- +- qdma = ð->qdma[index % AIROHA_MAX_NUM_QDMA]; +- dev->netdev_ops = &airoha_netdev_ops; +- dev->ethtool_ops = &airoha_ethtool_ops; +- dev->max_mtu = AIROHA_MAX_MTU; +- dev->watchdog_timeo = 5 * HZ; +- dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | +- NETIF_F_TSO6 | NETIF_F_IPV6_CSUM | +- NETIF_F_SG | NETIF_F_TSO | +- NETIF_F_HW_TC; +- dev->features |= dev->hw_features; +- dev->dev.of_node = np; +- dev->irq = qdma->irq; +- SET_NETDEV_DEV(dev, eth->dev); +- +- /* reserve hw queues for HTB offloading */ +- err = netif_set_real_num_tx_queues(dev, AIROHA_NUM_TX_RING); +- if (err) +- return err; +- +- err = of_get_ethdev_address(np, dev); +- if (err) { +- if (err == -EPROBE_DEFER) +- return err; +- +- eth_hw_addr_random(dev); +- dev_info(eth->dev, "generated random MAC address %pM\n", +- dev->dev_addr); +- } +- +- port = netdev_priv(dev); +- u64_stats_init(&port->stats.syncp); +- spin_lock_init(&port->stats.lock); +- port->qdma = qdma; +- port->dev = dev; +- port->id = id; +- eth->ports[index] = port; +- +- return register_netdev(dev); +-} +- +-static int airoha_probe(struct platform_device *pdev) +-{ +- struct device_node *np; +- struct airoha_eth *eth; +- int i, err; +- +- eth = devm_kzalloc(&pdev->dev, sizeof(*eth), GFP_KERNEL); +- if (!eth) +- return -ENOMEM; +- +- eth->dev = &pdev->dev; +- +- err = dma_set_mask_and_coherent(eth->dev, DMA_BIT_MASK(32)); +- if (err) { +- dev_err(eth->dev, "failed configuring DMA mask\n"); +- return err; +- } +- +- eth->fe_regs = devm_platform_ioremap_resource_byname(pdev, "fe"); +- if (IS_ERR(eth->fe_regs)) +- return dev_err_probe(eth->dev, PTR_ERR(eth->fe_regs), +- "failed to iomap fe regs\n"); +- +- eth->rsts[0].id = "fe"; +- eth->rsts[1].id = "pdma"; +- eth->rsts[2].id = "qdma"; +- err = devm_reset_control_bulk_get_exclusive(eth->dev, +- ARRAY_SIZE(eth->rsts), +- eth->rsts); +- if (err) { +- dev_err(eth->dev, "failed to get bulk reset lines\n"); +- return err; +- } +- +- eth->xsi_rsts[0].id = "xsi-mac"; +- eth->xsi_rsts[1].id = "hsi0-mac"; +- eth->xsi_rsts[2].id = "hsi1-mac"; +- eth->xsi_rsts[3].id = "hsi-mac"; +- eth->xsi_rsts[4].id = "xfp-mac"; +- err = devm_reset_control_bulk_get_exclusive(eth->dev, +- ARRAY_SIZE(eth->xsi_rsts), +- eth->xsi_rsts); +- if (err) { +- dev_err(eth->dev, "failed to get bulk xsi reset lines\n"); +- return err; +- } +- +- eth->napi_dev = alloc_netdev_dummy(0); +- if (!eth->napi_dev) +- return -ENOMEM; +- +- /* Enable threaded NAPI by default */ +- eth->napi_dev->threaded = true; +- strscpy(eth->napi_dev->name, "qdma_eth", sizeof(eth->napi_dev->name)); +- platform_set_drvdata(pdev, eth); +- +- err = airoha_hw_init(pdev, eth); +- if (err) +- goto error_hw_cleanup; +- +- for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) +- airoha_qdma_start_napi(ð->qdma[i]); +- +- for_each_child_of_node(pdev->dev.of_node, np) { +- if (!of_device_is_compatible(np, "airoha,eth-mac")) +- continue; +- +- if (!of_device_is_available(np)) +- continue; +- +- err = airoha_alloc_gdm_port(eth, np); +- if (err) { +- of_node_put(np); +- goto error_napi_stop; +- } +- } +- +- return 0; +- +-error_napi_stop: +- for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) +- airoha_qdma_stop_napi(ð->qdma[i]); +-error_hw_cleanup: +- for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) +- airoha_hw_cleanup(ð->qdma[i]); +- +- for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { +- struct airoha_gdm_port *port = eth->ports[i]; +- +- if (port && port->dev->reg_state == NETREG_REGISTERED) +- unregister_netdev(port->dev); +- } +- free_netdev(eth->napi_dev); +- platform_set_drvdata(pdev, NULL); +- +- return err; +-} +- +-static void airoha_remove(struct platform_device *pdev) +-{ +- struct airoha_eth *eth = platform_get_drvdata(pdev); +- int i; +- +- for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) { +- airoha_qdma_stop_napi(ð->qdma[i]); +- airoha_hw_cleanup(ð->qdma[i]); +- } +- +- for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { +- struct airoha_gdm_port *port = eth->ports[i]; +- +- if (!port) +- continue; +- +- airoha_dev_stop(port->dev); +- unregister_netdev(port->dev); +- } +- free_netdev(eth->napi_dev); +- +- platform_set_drvdata(pdev, NULL); +-} +- +-static const struct of_device_id of_airoha_match[] = { +- { .compatible = "airoha,en7581-eth" }, +- { /* sentinel */ } +-}; +-MODULE_DEVICE_TABLE(of, of_airoha_match); +- +-static struct platform_driver airoha_driver = { +- .probe = airoha_probe, +- .remove_new = airoha_remove, +- .driver = { +- .name = KBUILD_MODNAME, +- .of_match_table = of_airoha_match, +- }, +-}; +-module_platform_driver(airoha_driver); +- +-MODULE_LICENSE("GPL"); +-MODULE_AUTHOR("Lorenzo Bianconi "); +-MODULE_DESCRIPTION("Ethernet driver for Airoha SoC"); diff --git a/lede/target/linux/airoha/patches-6.12/048-02-v6.15-net-airoha-Move-definitions-in-airoha_eth.h.patch b/lede/target/linux/airoha/patches-6.12/048-02-v6.15-net-airoha-Move-definitions-in-airoha_eth.h.patch new file mode 100644 index 0000000000..85391281a2 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/048-02-v6.15-net-airoha-Move-definitions-in-airoha_eth.h.patch @@ -0,0 +1,538 @@ +From b38f4ff0ceacd6ce8d333a8dc90f405a040968d3 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 28 Feb 2025 11:54:10 +0100 +Subject: [PATCH 02/15] net: airoha: Move definitions in airoha_eth.h + +Move common airoha_eth definitions in airoha_eth.h in order to reuse +them for Packet Processor Engine (PPE) codebase. +PPE module is used to enable support for flowtable hw offloading in +airoha_eth driver. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 240 +--------------------- + drivers/net/ethernet/airoha/airoha_eth.h | 251 +++++++++++++++++++++++ + 2 files changed, 252 insertions(+), 239 deletions(-) + create mode 100644 drivers/net/ethernet/airoha/airoha_eth.h + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -3,14 +3,9 @@ + * Copyright (c) 2024 AIROHA Inc + * Author: Lorenzo Bianconi + */ +-#include +-#include +-#include +-#include + #include + #include + #include +-#include + #include + #include + #include +@@ -18,35 +13,7 @@ + #include + #include + +-#define AIROHA_MAX_NUM_GDM_PORTS 1 +-#define AIROHA_MAX_NUM_QDMA 2 +-#define AIROHA_MAX_NUM_RSTS 3 +-#define AIROHA_MAX_NUM_XSI_RSTS 5 +-#define AIROHA_MAX_MTU 2000 +-#define AIROHA_MAX_PACKET_SIZE 2048 +-#define AIROHA_NUM_QOS_CHANNELS 4 +-#define AIROHA_NUM_QOS_QUEUES 8 +-#define AIROHA_NUM_TX_RING 32 +-#define AIROHA_NUM_RX_RING 32 +-#define AIROHA_NUM_NETDEV_TX_RINGS (AIROHA_NUM_TX_RING + \ +- AIROHA_NUM_QOS_CHANNELS) +-#define AIROHA_FE_MC_MAX_VLAN_TABLE 64 +-#define AIROHA_FE_MC_MAX_VLAN_PORT 16 +-#define AIROHA_NUM_TX_IRQ 2 +-#define HW_DSCP_NUM 2048 +-#define IRQ_QUEUE_LEN(_n) ((_n) ? 1024 : 2048) +-#define TX_DSCP_NUM 1024 +-#define RX_DSCP_NUM(_n) \ +- ((_n) == 2 ? 128 : \ +- (_n) == 11 ? 128 : \ +- (_n) == 15 ? 128 : \ +- (_n) == 0 ? 1024 : 16) +- +-#define PSE_RSV_PAGES 128 +-#define PSE_QUEUE_RSV_PAGES 64 +- +-#define QDMA_METER_IDX(_n) ((_n) & 0xff) +-#define QDMA_METER_GROUP(_n) (((_n) >> 8) & 0x3) ++#include "airoha_eth.h" + + /* FE */ + #define PSE_BASE 0x0100 +@@ -706,211 +673,6 @@ struct airoha_qdma_fwd_desc { + __le32 rsv1; + }; + +-enum { +- QDMA_INT_REG_IDX0, +- QDMA_INT_REG_IDX1, +- QDMA_INT_REG_IDX2, +- QDMA_INT_REG_IDX3, +- QDMA_INT_REG_IDX4, +- QDMA_INT_REG_MAX +-}; +- +-enum { +- XSI_PCIE0_PORT, +- XSI_PCIE1_PORT, +- XSI_USB_PORT, +- XSI_AE_PORT, +- XSI_ETH_PORT, +-}; +- +-enum { +- XSI_PCIE0_VIP_PORT_MASK = BIT(22), +- XSI_PCIE1_VIP_PORT_MASK = BIT(23), +- XSI_USB_VIP_PORT_MASK = BIT(25), +- XSI_ETH_VIP_PORT_MASK = BIT(24), +-}; +- +-enum { +- DEV_STATE_INITIALIZED, +-}; +- +-enum { +- CDM_CRSN_QSEL_Q1 = 1, +- CDM_CRSN_QSEL_Q5 = 5, +- CDM_CRSN_QSEL_Q6 = 6, +- CDM_CRSN_QSEL_Q15 = 15, +-}; +- +-enum { +- CRSN_08 = 0x8, +- CRSN_21 = 0x15, /* KA */ +- CRSN_22 = 0x16, /* hit bind and force route to CPU */ +- CRSN_24 = 0x18, +- CRSN_25 = 0x19, +-}; +- +-enum { +- FE_PSE_PORT_CDM1, +- FE_PSE_PORT_GDM1, +- FE_PSE_PORT_GDM2, +- FE_PSE_PORT_GDM3, +- FE_PSE_PORT_PPE1, +- FE_PSE_PORT_CDM2, +- FE_PSE_PORT_CDM3, +- FE_PSE_PORT_CDM4, +- FE_PSE_PORT_PPE2, +- FE_PSE_PORT_GDM4, +- FE_PSE_PORT_CDM5, +- FE_PSE_PORT_DROP = 0xf, +-}; +- +-enum tx_sched_mode { +- TC_SCH_WRR8, +- TC_SCH_SP, +- TC_SCH_WRR7, +- TC_SCH_WRR6, +- TC_SCH_WRR5, +- TC_SCH_WRR4, +- TC_SCH_WRR3, +- TC_SCH_WRR2, +-}; +- +-enum trtcm_param_type { +- TRTCM_MISC_MODE, /* meter_en, pps_mode, tick_sel */ +- TRTCM_TOKEN_RATE_MODE, +- TRTCM_BUCKETSIZE_SHIFT_MODE, +- TRTCM_BUCKET_COUNTER_MODE, +-}; +- +-enum trtcm_mode_type { +- TRTCM_COMMIT_MODE, +- TRTCM_PEAK_MODE, +-}; +- +-enum trtcm_param { +- TRTCM_TICK_SEL = BIT(0), +- TRTCM_PKT_MODE = BIT(1), +- TRTCM_METER_MODE = BIT(2), +-}; +- +-#define MIN_TOKEN_SIZE 4096 +-#define MAX_TOKEN_SIZE_OFFSET 17 +-#define TRTCM_TOKEN_RATE_MASK GENMASK(23, 6) +-#define TRTCM_TOKEN_RATE_FRACTION_MASK GENMASK(5, 0) +- +-struct airoha_queue_entry { +- union { +- void *buf; +- struct sk_buff *skb; +- }; +- dma_addr_t dma_addr; +- u16 dma_len; +-}; +- +-struct airoha_queue { +- struct airoha_qdma *qdma; +- +- /* protect concurrent queue accesses */ +- spinlock_t lock; +- struct airoha_queue_entry *entry; +- struct airoha_qdma_desc *desc; +- u16 head; +- u16 tail; +- +- int queued; +- int ndesc; +- int free_thr; +- int buf_size; +- +- struct napi_struct napi; +- struct page_pool *page_pool; +-}; +- +-struct airoha_tx_irq_queue { +- struct airoha_qdma *qdma; +- +- struct napi_struct napi; +- +- int size; +- u32 *q; +-}; +- +-struct airoha_hw_stats { +- /* protect concurrent hw_stats accesses */ +- spinlock_t lock; +- struct u64_stats_sync syncp; +- +- /* get_stats64 */ +- u64 rx_ok_pkts; +- u64 tx_ok_pkts; +- u64 rx_ok_bytes; +- u64 tx_ok_bytes; +- u64 rx_multicast; +- u64 rx_errors; +- u64 rx_drops; +- u64 tx_drops; +- u64 rx_crc_error; +- u64 rx_over_errors; +- /* ethtool stats */ +- u64 tx_broadcast; +- u64 tx_multicast; +- u64 tx_len[7]; +- u64 rx_broadcast; +- u64 rx_fragment; +- u64 rx_jabber; +- u64 rx_len[7]; +-}; +- +-struct airoha_qdma { +- struct airoha_eth *eth; +- void __iomem *regs; +- +- /* protect concurrent irqmask accesses */ +- spinlock_t irq_lock; +- u32 irqmask[QDMA_INT_REG_MAX]; +- int irq; +- +- struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ]; +- +- struct airoha_queue q_tx[AIROHA_NUM_TX_RING]; +- struct airoha_queue q_rx[AIROHA_NUM_RX_RING]; +- +- /* descriptor and packet buffers for qdma hw forward */ +- struct { +- void *desc; +- void *q; +- } hfwd; +-}; +- +-struct airoha_gdm_port { +- struct airoha_qdma *qdma; +- struct net_device *dev; +- int id; +- +- struct airoha_hw_stats stats; +- +- DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); +- +- /* qos stats counters */ +- u64 cpu_tx_packets; +- u64 fwd_tx_packets; +-}; +- +-struct airoha_eth { +- struct device *dev; +- +- unsigned long state; +- void __iomem *fe_regs; +- +- struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS]; +- struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS]; +- +- struct net_device *napi_dev; +- +- struct airoha_qdma qdma[AIROHA_MAX_NUM_QDMA]; +- struct airoha_gdm_port *ports[AIROHA_MAX_NUM_GDM_PORTS]; +-}; +- + static u32 airoha_rr(void __iomem *base, u32 offset) + { + return readl(base + offset); +--- /dev/null ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -0,0 +1,251 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2024 AIROHA Inc ++ * Author: Lorenzo Bianconi ++ */ ++ ++#ifndef AIROHA_ETH_H ++#define AIROHA_ETH_H ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define AIROHA_MAX_NUM_GDM_PORTS 1 ++#define AIROHA_MAX_NUM_QDMA 2 ++#define AIROHA_MAX_NUM_RSTS 3 ++#define AIROHA_MAX_NUM_XSI_RSTS 5 ++#define AIROHA_MAX_MTU 2000 ++#define AIROHA_MAX_PACKET_SIZE 2048 ++#define AIROHA_NUM_QOS_CHANNELS 4 ++#define AIROHA_NUM_QOS_QUEUES 8 ++#define AIROHA_NUM_TX_RING 32 ++#define AIROHA_NUM_RX_RING 32 ++#define AIROHA_NUM_NETDEV_TX_RINGS (AIROHA_NUM_TX_RING + \ ++ AIROHA_NUM_QOS_CHANNELS) ++#define AIROHA_FE_MC_MAX_VLAN_TABLE 64 ++#define AIROHA_FE_MC_MAX_VLAN_PORT 16 ++#define AIROHA_NUM_TX_IRQ 2 ++#define HW_DSCP_NUM 2048 ++#define IRQ_QUEUE_LEN(_n) ((_n) ? 1024 : 2048) ++#define TX_DSCP_NUM 1024 ++#define RX_DSCP_NUM(_n) \ ++ ((_n) == 2 ? 128 : \ ++ (_n) == 11 ? 128 : \ ++ (_n) == 15 ? 128 : \ ++ (_n) == 0 ? 1024 : 16) ++ ++#define PSE_RSV_PAGES 128 ++#define PSE_QUEUE_RSV_PAGES 64 ++ ++#define QDMA_METER_IDX(_n) ((_n) & 0xff) ++#define QDMA_METER_GROUP(_n) (((_n) >> 8) & 0x3) ++ ++enum { ++ QDMA_INT_REG_IDX0, ++ QDMA_INT_REG_IDX1, ++ QDMA_INT_REG_IDX2, ++ QDMA_INT_REG_IDX3, ++ QDMA_INT_REG_IDX4, ++ QDMA_INT_REG_MAX ++}; ++ ++enum { ++ XSI_PCIE0_PORT, ++ XSI_PCIE1_PORT, ++ XSI_USB_PORT, ++ XSI_AE_PORT, ++ XSI_ETH_PORT, ++}; ++ ++enum { ++ XSI_PCIE0_VIP_PORT_MASK = BIT(22), ++ XSI_PCIE1_VIP_PORT_MASK = BIT(23), ++ XSI_USB_VIP_PORT_MASK = BIT(25), ++ XSI_ETH_VIP_PORT_MASK = BIT(24), ++}; ++ ++enum { ++ DEV_STATE_INITIALIZED, ++}; ++ ++enum { ++ CDM_CRSN_QSEL_Q1 = 1, ++ CDM_CRSN_QSEL_Q5 = 5, ++ CDM_CRSN_QSEL_Q6 = 6, ++ CDM_CRSN_QSEL_Q15 = 15, ++}; ++ ++enum { ++ CRSN_08 = 0x8, ++ CRSN_21 = 0x15, /* KA */ ++ CRSN_22 = 0x16, /* hit bind and force route to CPU */ ++ CRSN_24 = 0x18, ++ CRSN_25 = 0x19, ++}; ++ ++enum { ++ FE_PSE_PORT_CDM1, ++ FE_PSE_PORT_GDM1, ++ FE_PSE_PORT_GDM2, ++ FE_PSE_PORT_GDM3, ++ FE_PSE_PORT_PPE1, ++ FE_PSE_PORT_CDM2, ++ FE_PSE_PORT_CDM3, ++ FE_PSE_PORT_CDM4, ++ FE_PSE_PORT_PPE2, ++ FE_PSE_PORT_GDM4, ++ FE_PSE_PORT_CDM5, ++ FE_PSE_PORT_DROP = 0xf, ++}; ++ ++enum tx_sched_mode { ++ TC_SCH_WRR8, ++ TC_SCH_SP, ++ TC_SCH_WRR7, ++ TC_SCH_WRR6, ++ TC_SCH_WRR5, ++ TC_SCH_WRR4, ++ TC_SCH_WRR3, ++ TC_SCH_WRR2, ++}; ++ ++enum trtcm_param_type { ++ TRTCM_MISC_MODE, /* meter_en, pps_mode, tick_sel */ ++ TRTCM_TOKEN_RATE_MODE, ++ TRTCM_BUCKETSIZE_SHIFT_MODE, ++ TRTCM_BUCKET_COUNTER_MODE, ++}; ++ ++enum trtcm_mode_type { ++ TRTCM_COMMIT_MODE, ++ TRTCM_PEAK_MODE, ++}; ++ ++enum trtcm_param { ++ TRTCM_TICK_SEL = BIT(0), ++ TRTCM_PKT_MODE = BIT(1), ++ TRTCM_METER_MODE = BIT(2), ++}; ++ ++#define MIN_TOKEN_SIZE 4096 ++#define MAX_TOKEN_SIZE_OFFSET 17 ++#define TRTCM_TOKEN_RATE_MASK GENMASK(23, 6) ++#define TRTCM_TOKEN_RATE_FRACTION_MASK GENMASK(5, 0) ++ ++struct airoha_queue_entry { ++ union { ++ void *buf; ++ struct sk_buff *skb; ++ }; ++ dma_addr_t dma_addr; ++ u16 dma_len; ++}; ++ ++struct airoha_queue { ++ struct airoha_qdma *qdma; ++ ++ /* protect concurrent queue accesses */ ++ spinlock_t lock; ++ struct airoha_queue_entry *entry; ++ struct airoha_qdma_desc *desc; ++ u16 head; ++ u16 tail; ++ ++ int queued; ++ int ndesc; ++ int free_thr; ++ int buf_size; ++ ++ struct napi_struct napi; ++ struct page_pool *page_pool; ++}; ++ ++struct airoha_tx_irq_queue { ++ struct airoha_qdma *qdma; ++ ++ struct napi_struct napi; ++ ++ int size; ++ u32 *q; ++}; ++ ++struct airoha_hw_stats { ++ /* protect concurrent hw_stats accesses */ ++ spinlock_t lock; ++ struct u64_stats_sync syncp; ++ ++ /* get_stats64 */ ++ u64 rx_ok_pkts; ++ u64 tx_ok_pkts; ++ u64 rx_ok_bytes; ++ u64 tx_ok_bytes; ++ u64 rx_multicast; ++ u64 rx_errors; ++ u64 rx_drops; ++ u64 tx_drops; ++ u64 rx_crc_error; ++ u64 rx_over_errors; ++ /* ethtool stats */ ++ u64 tx_broadcast; ++ u64 tx_multicast; ++ u64 tx_len[7]; ++ u64 rx_broadcast; ++ u64 rx_fragment; ++ u64 rx_jabber; ++ u64 rx_len[7]; ++}; ++ ++struct airoha_qdma { ++ struct airoha_eth *eth; ++ void __iomem *regs; ++ ++ /* protect concurrent irqmask accesses */ ++ spinlock_t irq_lock; ++ u32 irqmask[QDMA_INT_REG_MAX]; ++ int irq; ++ ++ struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ]; ++ ++ struct airoha_queue q_tx[AIROHA_NUM_TX_RING]; ++ struct airoha_queue q_rx[AIROHA_NUM_RX_RING]; ++ ++ /* descriptor and packet buffers for qdma hw forward */ ++ struct { ++ void *desc; ++ void *q; ++ } hfwd; ++}; ++ ++struct airoha_gdm_port { ++ struct airoha_qdma *qdma; ++ struct net_device *dev; ++ int id; ++ ++ struct airoha_hw_stats stats; ++ ++ DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); ++ ++ /* qos stats counters */ ++ u64 cpu_tx_packets; ++ u64 fwd_tx_packets; ++}; ++ ++struct airoha_eth { ++ struct device *dev; ++ ++ unsigned long state; ++ void __iomem *fe_regs; ++ ++ struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS]; ++ struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS]; ++ ++ struct net_device *napi_dev; ++ ++ struct airoha_qdma qdma[AIROHA_MAX_NUM_QDMA]; ++ struct airoha_gdm_port *ports[AIROHA_MAX_NUM_GDM_PORTS]; ++}; ++ ++#endif /* AIROHA_ETH_H */ diff --git a/lede/target/linux/airoha/patches-6.12/048-03-v6.15-net-airoha-Move-reg-write-utility-routines-in-airoha.patch b/lede/target/linux/airoha/patches-6.12/048-03-v6.15-net-airoha-Move-reg-write-utility-routines-in-airoha.patch new file mode 100644 index 0000000000..bf24638ec9 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/048-03-v6.15-net-airoha-Move-reg-write-utility-routines-in-airoha.patch @@ -0,0 +1,101 @@ +From e0758a8694fbaffdc72940774db295585e951119 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 28 Feb 2025 11:54:11 +0100 +Subject: [PATCH 03/15] net: airoha: Move reg/write utility routines in + airoha_eth.h + +This is a preliminary patch to introduce flowtable hw offloading +support for airoha_eth driver. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 28 +++--------------------- + drivers/net/ethernet/airoha/airoha_eth.h | 26 ++++++++++++++++++++++ + 2 files changed, 29 insertions(+), 25 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -673,17 +673,17 @@ struct airoha_qdma_fwd_desc { + __le32 rsv1; + }; + +-static u32 airoha_rr(void __iomem *base, u32 offset) ++u32 airoha_rr(void __iomem *base, u32 offset) + { + return readl(base + offset); + } + +-static void airoha_wr(void __iomem *base, u32 offset, u32 val) ++void airoha_wr(void __iomem *base, u32 offset, u32 val) + { + writel(val, base + offset); + } + +-static u32 airoha_rmw(void __iomem *base, u32 offset, u32 mask, u32 val) ++u32 airoha_rmw(void __iomem *base, u32 offset, u32 mask, u32 val) + { + val |= (airoha_rr(base, offset) & ~mask); + airoha_wr(base, offset, val); +@@ -691,28 +691,6 @@ static u32 airoha_rmw(void __iomem *base + return val; + } + +-#define airoha_fe_rr(eth, offset) \ +- airoha_rr((eth)->fe_regs, (offset)) +-#define airoha_fe_wr(eth, offset, val) \ +- airoha_wr((eth)->fe_regs, (offset), (val)) +-#define airoha_fe_rmw(eth, offset, mask, val) \ +- airoha_rmw((eth)->fe_regs, (offset), (mask), (val)) +-#define airoha_fe_set(eth, offset, val) \ +- airoha_rmw((eth)->fe_regs, (offset), 0, (val)) +-#define airoha_fe_clear(eth, offset, val) \ +- airoha_rmw((eth)->fe_regs, (offset), (val), 0) +- +-#define airoha_qdma_rr(qdma, offset) \ +- airoha_rr((qdma)->regs, (offset)) +-#define airoha_qdma_wr(qdma, offset, val) \ +- airoha_wr((qdma)->regs, (offset), (val)) +-#define airoha_qdma_rmw(qdma, offset, mask, val) \ +- airoha_rmw((qdma)->regs, (offset), (mask), (val)) +-#define airoha_qdma_set(qdma, offset, val) \ +- airoha_rmw((qdma)->regs, (offset), 0, (val)) +-#define airoha_qdma_clear(qdma, offset, val) \ +- airoha_rmw((qdma)->regs, (offset), (val), 0) +- + static void airoha_qdma_set_irqmask(struct airoha_qdma *qdma, int index, + u32 clear, u32 set) + { +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -248,4 +248,30 @@ struct airoha_eth { + struct airoha_gdm_port *ports[AIROHA_MAX_NUM_GDM_PORTS]; + }; + ++u32 airoha_rr(void __iomem *base, u32 offset); ++void airoha_wr(void __iomem *base, u32 offset, u32 val); ++u32 airoha_rmw(void __iomem *base, u32 offset, u32 mask, u32 val); ++ ++#define airoha_fe_rr(eth, offset) \ ++ airoha_rr((eth)->fe_regs, (offset)) ++#define airoha_fe_wr(eth, offset, val) \ ++ airoha_wr((eth)->fe_regs, (offset), (val)) ++#define airoha_fe_rmw(eth, offset, mask, val) \ ++ airoha_rmw((eth)->fe_regs, (offset), (mask), (val)) ++#define airoha_fe_set(eth, offset, val) \ ++ airoha_rmw((eth)->fe_regs, (offset), 0, (val)) ++#define airoha_fe_clear(eth, offset, val) \ ++ airoha_rmw((eth)->fe_regs, (offset), (val), 0) ++ ++#define airoha_qdma_rr(qdma, offset) \ ++ airoha_rr((qdma)->regs, (offset)) ++#define airoha_qdma_wr(qdma, offset, val) \ ++ airoha_wr((qdma)->regs, (offset), (val)) ++#define airoha_qdma_rmw(qdma, offset, mask, val) \ ++ airoha_rmw((qdma)->regs, (offset), (mask), (val)) ++#define airoha_qdma_set(qdma, offset, val) \ ++ airoha_rmw((qdma)->regs, (offset), 0, (val)) ++#define airoha_qdma_clear(qdma, offset, val) \ ++ airoha_rmw((qdma)->regs, (offset), (val), 0) ++ + #endif /* AIROHA_ETH_H */ diff --git a/lede/target/linux/airoha/patches-6.12/048-04-v6.15-net-airoha-Move-register-definitions-in-airoha_regs..patch b/lede/target/linux/airoha/patches-6.12/048-04-v6.15-net-airoha-Move-register-definitions-in-airoha_regs..patch new file mode 100644 index 0000000000..3b2b8bfe5d --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/048-04-v6.15-net-airoha-Move-register-definitions-in-airoha_regs..patch @@ -0,0 +1,1361 @@ +From ec663d9a82bf4d16721f6b1fc29df4892ba6c088 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 28 Feb 2025 11:54:12 +0100 +Subject: [PATCH 04/15] net: airoha: Move register definitions in airoha_regs.h + +Move common airoha_eth register definitions in airoha_regs.h in order +to reuse them for Packet Processor Engine (PPE) codebase. +PPE module is used to enable support for flowtable hw offloading in +airoha_eth driver. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 659 +-------------------- + drivers/net/ethernet/airoha/airoha_regs.h | 670 ++++++++++++++++++++++ + 2 files changed, 671 insertions(+), 658 deletions(-) + create mode 100644 drivers/net/ethernet/airoha/airoha_regs.h + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -13,666 +13,9 @@ + #include + #include + ++#include "airoha_regs.h" + #include "airoha_eth.h" + +-/* FE */ +-#define PSE_BASE 0x0100 +-#define CSR_IFC_BASE 0x0200 +-#define CDM1_BASE 0x0400 +-#define GDM1_BASE 0x0500 +-#define PPE1_BASE 0x0c00 +- +-#define CDM2_BASE 0x1400 +-#define GDM2_BASE 0x1500 +- +-#define GDM3_BASE 0x1100 +-#define GDM4_BASE 0x2500 +- +-#define GDM_BASE(_n) \ +- ((_n) == 4 ? GDM4_BASE : \ +- (_n) == 3 ? GDM3_BASE : \ +- (_n) == 2 ? GDM2_BASE : GDM1_BASE) +- +-#define REG_FE_DMA_GLO_CFG 0x0000 +-#define FE_DMA_GLO_L2_SPACE_MASK GENMASK(7, 4) +-#define FE_DMA_GLO_PG_SZ_MASK BIT(3) +- +-#define REG_FE_RST_GLO_CFG 0x0004 +-#define FE_RST_GDM4_MBI_ARB_MASK BIT(3) +-#define FE_RST_GDM3_MBI_ARB_MASK BIT(2) +-#define FE_RST_CORE_MASK BIT(0) +- +-#define REG_FE_WAN_MAC_H 0x0030 +-#define REG_FE_LAN_MAC_H 0x0040 +- +-#define REG_FE_MAC_LMIN(_n) ((_n) + 0x04) +-#define REG_FE_MAC_LMAX(_n) ((_n) + 0x08) +- +-#define REG_FE_CDM1_OQ_MAP0 0x0050 +-#define REG_FE_CDM1_OQ_MAP1 0x0054 +-#define REG_FE_CDM1_OQ_MAP2 0x0058 +-#define REG_FE_CDM1_OQ_MAP3 0x005c +- +-#define REG_FE_PCE_CFG 0x0070 +-#define PCE_DPI_EN_MASK BIT(2) +-#define PCE_KA_EN_MASK BIT(1) +-#define PCE_MC_EN_MASK BIT(0) +- +-#define REG_FE_PSE_QUEUE_CFG_WR 0x0080 +-#define PSE_CFG_PORT_ID_MASK GENMASK(27, 24) +-#define PSE_CFG_QUEUE_ID_MASK GENMASK(20, 16) +-#define PSE_CFG_WR_EN_MASK BIT(8) +-#define PSE_CFG_OQRSV_SEL_MASK BIT(0) +- +-#define REG_FE_PSE_QUEUE_CFG_VAL 0x0084 +-#define PSE_CFG_OQ_RSV_MASK GENMASK(13, 0) +- +-#define PSE_FQ_CFG 0x008c +-#define PSE_FQ_LIMIT_MASK GENMASK(14, 0) +- +-#define REG_FE_PSE_BUF_SET 0x0090 +-#define PSE_SHARE_USED_LTHD_MASK GENMASK(31, 16) +-#define PSE_ALLRSV_MASK GENMASK(14, 0) +- +-#define REG_PSE_SHARE_USED_THD 0x0094 +-#define PSE_SHARE_USED_MTHD_MASK GENMASK(31, 16) +-#define PSE_SHARE_USED_HTHD_MASK GENMASK(15, 0) +- +-#define REG_GDM_MISC_CFG 0x0148 +-#define GDM2_RDM_ACK_WAIT_PREF_MASK BIT(9) +-#define GDM2_CHN_VLD_MODE_MASK BIT(5) +- +-#define REG_FE_CSR_IFC_CFG CSR_IFC_BASE +-#define FE_IFC_EN_MASK BIT(0) +- +-#define REG_FE_VIP_PORT_EN 0x01f0 +-#define REG_FE_IFC_PORT_EN 0x01f4 +- +-#define REG_PSE_IQ_REV1 (PSE_BASE + 0x08) +-#define PSE_IQ_RES1_P2_MASK GENMASK(23, 16) +- +-#define REG_PSE_IQ_REV2 (PSE_BASE + 0x0c) +-#define PSE_IQ_RES2_P5_MASK GENMASK(15, 8) +-#define PSE_IQ_RES2_P4_MASK GENMASK(7, 0) +- +-#define REG_FE_VIP_EN(_n) (0x0300 + ((_n) << 3)) +-#define PATN_FCPU_EN_MASK BIT(7) +-#define PATN_SWP_EN_MASK BIT(6) +-#define PATN_DP_EN_MASK BIT(5) +-#define PATN_SP_EN_MASK BIT(4) +-#define PATN_TYPE_MASK GENMASK(3, 1) +-#define PATN_EN_MASK BIT(0) +- +-#define REG_FE_VIP_PATN(_n) (0x0304 + ((_n) << 3)) +-#define PATN_DP_MASK GENMASK(31, 16) +-#define PATN_SP_MASK GENMASK(15, 0) +- +-#define REG_CDM1_VLAN_CTRL CDM1_BASE +-#define CDM1_VLAN_MASK GENMASK(31, 16) +- +-#define REG_CDM1_FWD_CFG (CDM1_BASE + 0x08) +-#define CDM1_VIP_QSEL_MASK GENMASK(24, 20) +- +-#define REG_CDM1_CRSN_QSEL(_n) (CDM1_BASE + 0x10 + ((_n) << 2)) +-#define CDM1_CRSN_QSEL_REASON_MASK(_n) \ +- GENMASK(4 + (((_n) % 4) << 3), (((_n) % 4) << 3)) +- +-#define REG_CDM2_FWD_CFG (CDM2_BASE + 0x08) +-#define CDM2_OAM_QSEL_MASK GENMASK(31, 27) +-#define CDM2_VIP_QSEL_MASK GENMASK(24, 20) +- +-#define REG_CDM2_CRSN_QSEL(_n) (CDM2_BASE + 0x10 + ((_n) << 2)) +-#define CDM2_CRSN_QSEL_REASON_MASK(_n) \ +- GENMASK(4 + (((_n) % 4) << 3), (((_n) % 4) << 3)) +- +-#define REG_GDM_FWD_CFG(_n) GDM_BASE(_n) +-#define GDM_DROP_CRC_ERR BIT(23) +-#define GDM_IP4_CKSUM BIT(22) +-#define GDM_TCP_CKSUM BIT(21) +-#define GDM_UDP_CKSUM BIT(20) +-#define GDM_UCFQ_MASK GENMASK(15, 12) +-#define GDM_BCFQ_MASK GENMASK(11, 8) +-#define GDM_MCFQ_MASK GENMASK(7, 4) +-#define GDM_OCFQ_MASK GENMASK(3, 0) +- +-#define REG_GDM_INGRESS_CFG(_n) (GDM_BASE(_n) + 0x10) +-#define GDM_INGRESS_FC_EN_MASK BIT(1) +-#define GDM_STAG_EN_MASK BIT(0) +- +-#define REG_GDM_LEN_CFG(_n) (GDM_BASE(_n) + 0x14) +-#define GDM_SHORT_LEN_MASK GENMASK(13, 0) +-#define GDM_LONG_LEN_MASK GENMASK(29, 16) +- +-#define REG_FE_CPORT_CFG (GDM1_BASE + 0x40) +-#define FE_CPORT_PAD BIT(26) +-#define FE_CPORT_PORT_XFC_MASK BIT(25) +-#define FE_CPORT_QUEUE_XFC_MASK BIT(24) +- +-#define REG_FE_GDM_MIB_CLEAR(_n) (GDM_BASE(_n) + 0xf0) +-#define FE_GDM_MIB_RX_CLEAR_MASK BIT(1) +-#define FE_GDM_MIB_TX_CLEAR_MASK BIT(0) +- +-#define REG_FE_GDM1_MIB_CFG (GDM1_BASE + 0xf4) +-#define FE_STRICT_RFC2819_MODE_MASK BIT(31) +-#define FE_GDM1_TX_MIB_SPLIT_EN_MASK BIT(17) +-#define FE_GDM1_RX_MIB_SPLIT_EN_MASK BIT(16) +-#define FE_TX_MIB_ID_MASK GENMASK(15, 8) +-#define FE_RX_MIB_ID_MASK GENMASK(7, 0) +- +-#define REG_FE_GDM_TX_OK_PKT_CNT_L(_n) (GDM_BASE(_n) + 0x104) +-#define REG_FE_GDM_TX_OK_BYTE_CNT_L(_n) (GDM_BASE(_n) + 0x10c) +-#define REG_FE_GDM_TX_ETH_PKT_CNT_L(_n) (GDM_BASE(_n) + 0x110) +-#define REG_FE_GDM_TX_ETH_BYTE_CNT_L(_n) (GDM_BASE(_n) + 0x114) +-#define REG_FE_GDM_TX_ETH_DROP_CNT(_n) (GDM_BASE(_n) + 0x118) +-#define REG_FE_GDM_TX_ETH_BC_CNT(_n) (GDM_BASE(_n) + 0x11c) +-#define REG_FE_GDM_TX_ETH_MC_CNT(_n) (GDM_BASE(_n) + 0x120) +-#define REG_FE_GDM_TX_ETH_RUNT_CNT(_n) (GDM_BASE(_n) + 0x124) +-#define REG_FE_GDM_TX_ETH_LONG_CNT(_n) (GDM_BASE(_n) + 0x128) +-#define REG_FE_GDM_TX_ETH_E64_CNT_L(_n) (GDM_BASE(_n) + 0x12c) +-#define REG_FE_GDM_TX_ETH_L64_CNT_L(_n) (GDM_BASE(_n) + 0x130) +-#define REG_FE_GDM_TX_ETH_L127_CNT_L(_n) (GDM_BASE(_n) + 0x134) +-#define REG_FE_GDM_TX_ETH_L255_CNT_L(_n) (GDM_BASE(_n) + 0x138) +-#define REG_FE_GDM_TX_ETH_L511_CNT_L(_n) (GDM_BASE(_n) + 0x13c) +-#define REG_FE_GDM_TX_ETH_L1023_CNT_L(_n) (GDM_BASE(_n) + 0x140) +- +-#define REG_FE_GDM_RX_OK_PKT_CNT_L(_n) (GDM_BASE(_n) + 0x148) +-#define REG_FE_GDM_RX_FC_DROP_CNT(_n) (GDM_BASE(_n) + 0x14c) +-#define REG_FE_GDM_RX_RC_DROP_CNT(_n) (GDM_BASE(_n) + 0x150) +-#define REG_FE_GDM_RX_OVERFLOW_DROP_CNT(_n) (GDM_BASE(_n) + 0x154) +-#define REG_FE_GDM_RX_ERROR_DROP_CNT(_n) (GDM_BASE(_n) + 0x158) +-#define REG_FE_GDM_RX_OK_BYTE_CNT_L(_n) (GDM_BASE(_n) + 0x15c) +-#define REG_FE_GDM_RX_ETH_PKT_CNT_L(_n) (GDM_BASE(_n) + 0x160) +-#define REG_FE_GDM_RX_ETH_BYTE_CNT_L(_n) (GDM_BASE(_n) + 0x164) +-#define REG_FE_GDM_RX_ETH_DROP_CNT(_n) (GDM_BASE(_n) + 0x168) +-#define REG_FE_GDM_RX_ETH_BC_CNT(_n) (GDM_BASE(_n) + 0x16c) +-#define REG_FE_GDM_RX_ETH_MC_CNT(_n) (GDM_BASE(_n) + 0x170) +-#define REG_FE_GDM_RX_ETH_CRC_ERR_CNT(_n) (GDM_BASE(_n) + 0x174) +-#define REG_FE_GDM_RX_ETH_FRAG_CNT(_n) (GDM_BASE(_n) + 0x178) +-#define REG_FE_GDM_RX_ETH_JABBER_CNT(_n) (GDM_BASE(_n) + 0x17c) +-#define REG_FE_GDM_RX_ETH_RUNT_CNT(_n) (GDM_BASE(_n) + 0x180) +-#define REG_FE_GDM_RX_ETH_LONG_CNT(_n) (GDM_BASE(_n) + 0x184) +-#define REG_FE_GDM_RX_ETH_E64_CNT_L(_n) (GDM_BASE(_n) + 0x188) +-#define REG_FE_GDM_RX_ETH_L64_CNT_L(_n) (GDM_BASE(_n) + 0x18c) +-#define REG_FE_GDM_RX_ETH_L127_CNT_L(_n) (GDM_BASE(_n) + 0x190) +-#define REG_FE_GDM_RX_ETH_L255_CNT_L(_n) (GDM_BASE(_n) + 0x194) +-#define REG_FE_GDM_RX_ETH_L511_CNT_L(_n) (GDM_BASE(_n) + 0x198) +-#define REG_FE_GDM_RX_ETH_L1023_CNT_L(_n) (GDM_BASE(_n) + 0x19c) +- +-#define REG_PPE1_TB_HASH_CFG (PPE1_BASE + 0x250) +-#define PPE1_SRAM_TABLE_EN_MASK BIT(0) +-#define PPE1_SRAM_HASH1_EN_MASK BIT(8) +-#define PPE1_DRAM_TABLE_EN_MASK BIT(16) +-#define PPE1_DRAM_HASH1_EN_MASK BIT(24) +- +-#define REG_FE_GDM_TX_OK_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x280) +-#define REG_FE_GDM_TX_OK_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x284) +-#define REG_FE_GDM_TX_ETH_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x288) +-#define REG_FE_GDM_TX_ETH_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x28c) +- +-#define REG_FE_GDM_RX_OK_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x290) +-#define REG_FE_GDM_RX_OK_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x294) +-#define REG_FE_GDM_RX_ETH_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x298) +-#define REG_FE_GDM_RX_ETH_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x29c) +-#define REG_FE_GDM_TX_ETH_E64_CNT_H(_n) (GDM_BASE(_n) + 0x2b8) +-#define REG_FE_GDM_TX_ETH_L64_CNT_H(_n) (GDM_BASE(_n) + 0x2bc) +-#define REG_FE_GDM_TX_ETH_L127_CNT_H(_n) (GDM_BASE(_n) + 0x2c0) +-#define REG_FE_GDM_TX_ETH_L255_CNT_H(_n) (GDM_BASE(_n) + 0x2c4) +-#define REG_FE_GDM_TX_ETH_L511_CNT_H(_n) (GDM_BASE(_n) + 0x2c8) +-#define REG_FE_GDM_TX_ETH_L1023_CNT_H(_n) (GDM_BASE(_n) + 0x2cc) +-#define REG_FE_GDM_RX_ETH_E64_CNT_H(_n) (GDM_BASE(_n) + 0x2e8) +-#define REG_FE_GDM_RX_ETH_L64_CNT_H(_n) (GDM_BASE(_n) + 0x2ec) +-#define REG_FE_GDM_RX_ETH_L127_CNT_H(_n) (GDM_BASE(_n) + 0x2f0) +-#define REG_FE_GDM_RX_ETH_L255_CNT_H(_n) (GDM_BASE(_n) + 0x2f4) +-#define REG_FE_GDM_RX_ETH_L511_CNT_H(_n) (GDM_BASE(_n) + 0x2f8) +-#define REG_FE_GDM_RX_ETH_L1023_CNT_H(_n) (GDM_BASE(_n) + 0x2fc) +- +-#define REG_GDM2_CHN_RLS (GDM2_BASE + 0x20) +-#define MBI_RX_AGE_SEL_MASK GENMASK(26, 25) +-#define MBI_TX_AGE_SEL_MASK GENMASK(18, 17) +- +-#define REG_GDM3_FWD_CFG GDM3_BASE +-#define GDM3_PAD_EN_MASK BIT(28) +- +-#define REG_GDM4_FWD_CFG GDM4_BASE +-#define GDM4_PAD_EN_MASK BIT(28) +-#define GDM4_SPORT_OFFSET0_MASK GENMASK(11, 8) +- +-#define REG_GDM4_SRC_PORT_SET (GDM4_BASE + 0x23c) +-#define GDM4_SPORT_OFF2_MASK GENMASK(19, 16) +-#define GDM4_SPORT_OFF1_MASK GENMASK(15, 12) +-#define GDM4_SPORT_OFF0_MASK GENMASK(11, 8) +- +-#define REG_IP_FRAG_FP 0x2010 +-#define IP_ASSEMBLE_PORT_MASK GENMASK(24, 21) +-#define IP_ASSEMBLE_NBQ_MASK GENMASK(20, 16) +-#define IP_FRAGMENT_PORT_MASK GENMASK(8, 5) +-#define IP_FRAGMENT_NBQ_MASK GENMASK(4, 0) +- +-#define REG_MC_VLAN_EN 0x2100 +-#define MC_VLAN_EN_MASK BIT(0) +- +-#define REG_MC_VLAN_CFG 0x2104 +-#define MC_VLAN_CFG_CMD_DONE_MASK BIT(31) +-#define MC_VLAN_CFG_TABLE_ID_MASK GENMASK(21, 16) +-#define MC_VLAN_CFG_PORT_ID_MASK GENMASK(11, 8) +-#define MC_VLAN_CFG_TABLE_SEL_MASK BIT(4) +-#define MC_VLAN_CFG_RW_MASK BIT(0) +- +-#define REG_MC_VLAN_DATA 0x2108 +- +-#define REG_CDM5_RX_OQ1_DROP_CNT 0x29d4 +- +-/* QDMA */ +-#define REG_QDMA_GLOBAL_CFG 0x0004 +-#define GLOBAL_CFG_RX_2B_OFFSET_MASK BIT(31) +-#define GLOBAL_CFG_DMA_PREFERENCE_MASK GENMASK(30, 29) +-#define GLOBAL_CFG_CPU_TXR_RR_MASK BIT(28) +-#define GLOBAL_CFG_DSCP_BYTE_SWAP_MASK BIT(27) +-#define GLOBAL_CFG_PAYLOAD_BYTE_SWAP_MASK BIT(26) +-#define GLOBAL_CFG_MULTICAST_MODIFY_FP_MASK BIT(25) +-#define GLOBAL_CFG_OAM_MODIFY_MASK BIT(24) +-#define GLOBAL_CFG_RESET_MASK BIT(23) +-#define GLOBAL_CFG_RESET_DONE_MASK BIT(22) +-#define GLOBAL_CFG_MULTICAST_EN_MASK BIT(21) +-#define GLOBAL_CFG_IRQ1_EN_MASK BIT(20) +-#define GLOBAL_CFG_IRQ0_EN_MASK BIT(19) +-#define GLOBAL_CFG_LOOPCNT_EN_MASK BIT(18) +-#define GLOBAL_CFG_RD_BYPASS_WR_MASK BIT(17) +-#define GLOBAL_CFG_QDMA_LOOPBACK_MASK BIT(16) +-#define GLOBAL_CFG_LPBK_RXQ_SEL_MASK GENMASK(13, 8) +-#define GLOBAL_CFG_CHECK_DONE_MASK BIT(7) +-#define GLOBAL_CFG_TX_WB_DONE_MASK BIT(6) +-#define GLOBAL_CFG_MAX_ISSUE_NUM_MASK GENMASK(5, 4) +-#define GLOBAL_CFG_RX_DMA_BUSY_MASK BIT(3) +-#define GLOBAL_CFG_RX_DMA_EN_MASK BIT(2) +-#define GLOBAL_CFG_TX_DMA_BUSY_MASK BIT(1) +-#define GLOBAL_CFG_TX_DMA_EN_MASK BIT(0) +- +-#define REG_FWD_DSCP_BASE 0x0010 +-#define REG_FWD_BUF_BASE 0x0014 +- +-#define REG_HW_FWD_DSCP_CFG 0x0018 +-#define HW_FWD_DSCP_PAYLOAD_SIZE_MASK GENMASK(29, 28) +-#define HW_FWD_DSCP_SCATTER_LEN_MASK GENMASK(17, 16) +-#define HW_FWD_DSCP_MIN_SCATTER_LEN_MASK GENMASK(15, 0) +- +-#define REG_INT_STATUS(_n) \ +- (((_n) == 4) ? 0x0730 : \ +- ((_n) == 3) ? 0x0724 : \ +- ((_n) == 2) ? 0x0720 : \ +- ((_n) == 1) ? 0x0024 : 0x0020) +- +-#define REG_INT_ENABLE(_n) \ +- (((_n) == 4) ? 0x0750 : \ +- ((_n) == 3) ? 0x0744 : \ +- ((_n) == 2) ? 0x0740 : \ +- ((_n) == 1) ? 0x002c : 0x0028) +- +-/* QDMA_CSR_INT_ENABLE1 */ +-#define RX15_COHERENT_INT_MASK BIT(31) +-#define RX14_COHERENT_INT_MASK BIT(30) +-#define RX13_COHERENT_INT_MASK BIT(29) +-#define RX12_COHERENT_INT_MASK BIT(28) +-#define RX11_COHERENT_INT_MASK BIT(27) +-#define RX10_COHERENT_INT_MASK BIT(26) +-#define RX9_COHERENT_INT_MASK BIT(25) +-#define RX8_COHERENT_INT_MASK BIT(24) +-#define RX7_COHERENT_INT_MASK BIT(23) +-#define RX6_COHERENT_INT_MASK BIT(22) +-#define RX5_COHERENT_INT_MASK BIT(21) +-#define RX4_COHERENT_INT_MASK BIT(20) +-#define RX3_COHERENT_INT_MASK BIT(19) +-#define RX2_COHERENT_INT_MASK BIT(18) +-#define RX1_COHERENT_INT_MASK BIT(17) +-#define RX0_COHERENT_INT_MASK BIT(16) +-#define TX7_COHERENT_INT_MASK BIT(15) +-#define TX6_COHERENT_INT_MASK BIT(14) +-#define TX5_COHERENT_INT_MASK BIT(13) +-#define TX4_COHERENT_INT_MASK BIT(12) +-#define TX3_COHERENT_INT_MASK BIT(11) +-#define TX2_COHERENT_INT_MASK BIT(10) +-#define TX1_COHERENT_INT_MASK BIT(9) +-#define TX0_COHERENT_INT_MASK BIT(8) +-#define CNT_OVER_FLOW_INT_MASK BIT(7) +-#define IRQ1_FULL_INT_MASK BIT(5) +-#define IRQ1_INT_MASK BIT(4) +-#define HWFWD_DSCP_LOW_INT_MASK BIT(3) +-#define HWFWD_DSCP_EMPTY_INT_MASK BIT(2) +-#define IRQ0_FULL_INT_MASK BIT(1) +-#define IRQ0_INT_MASK BIT(0) +- +-#define TX_DONE_INT_MASK(_n) \ +- ((_n) ? IRQ1_INT_MASK | IRQ1_FULL_INT_MASK \ +- : IRQ0_INT_MASK | IRQ0_FULL_INT_MASK) +- +-#define INT_TX_MASK \ +- (IRQ1_INT_MASK | IRQ1_FULL_INT_MASK | \ +- IRQ0_INT_MASK | IRQ0_FULL_INT_MASK) +- +-#define INT_IDX0_MASK \ +- (TX0_COHERENT_INT_MASK | TX1_COHERENT_INT_MASK | \ +- TX2_COHERENT_INT_MASK | TX3_COHERENT_INT_MASK | \ +- TX4_COHERENT_INT_MASK | TX5_COHERENT_INT_MASK | \ +- TX6_COHERENT_INT_MASK | TX7_COHERENT_INT_MASK | \ +- RX0_COHERENT_INT_MASK | RX1_COHERENT_INT_MASK | \ +- RX2_COHERENT_INT_MASK | RX3_COHERENT_INT_MASK | \ +- RX4_COHERENT_INT_MASK | RX7_COHERENT_INT_MASK | \ +- RX8_COHERENT_INT_MASK | RX9_COHERENT_INT_MASK | \ +- RX15_COHERENT_INT_MASK | INT_TX_MASK) +- +-/* QDMA_CSR_INT_ENABLE2 */ +-#define RX15_NO_CPU_DSCP_INT_MASK BIT(31) +-#define RX14_NO_CPU_DSCP_INT_MASK BIT(30) +-#define RX13_NO_CPU_DSCP_INT_MASK BIT(29) +-#define RX12_NO_CPU_DSCP_INT_MASK BIT(28) +-#define RX11_NO_CPU_DSCP_INT_MASK BIT(27) +-#define RX10_NO_CPU_DSCP_INT_MASK BIT(26) +-#define RX9_NO_CPU_DSCP_INT_MASK BIT(25) +-#define RX8_NO_CPU_DSCP_INT_MASK BIT(24) +-#define RX7_NO_CPU_DSCP_INT_MASK BIT(23) +-#define RX6_NO_CPU_DSCP_INT_MASK BIT(22) +-#define RX5_NO_CPU_DSCP_INT_MASK BIT(21) +-#define RX4_NO_CPU_DSCP_INT_MASK BIT(20) +-#define RX3_NO_CPU_DSCP_INT_MASK BIT(19) +-#define RX2_NO_CPU_DSCP_INT_MASK BIT(18) +-#define RX1_NO_CPU_DSCP_INT_MASK BIT(17) +-#define RX0_NO_CPU_DSCP_INT_MASK BIT(16) +-#define RX15_DONE_INT_MASK BIT(15) +-#define RX14_DONE_INT_MASK BIT(14) +-#define RX13_DONE_INT_MASK BIT(13) +-#define RX12_DONE_INT_MASK BIT(12) +-#define RX11_DONE_INT_MASK BIT(11) +-#define RX10_DONE_INT_MASK BIT(10) +-#define RX9_DONE_INT_MASK BIT(9) +-#define RX8_DONE_INT_MASK BIT(8) +-#define RX7_DONE_INT_MASK BIT(7) +-#define RX6_DONE_INT_MASK BIT(6) +-#define RX5_DONE_INT_MASK BIT(5) +-#define RX4_DONE_INT_MASK BIT(4) +-#define RX3_DONE_INT_MASK BIT(3) +-#define RX2_DONE_INT_MASK BIT(2) +-#define RX1_DONE_INT_MASK BIT(1) +-#define RX0_DONE_INT_MASK BIT(0) +- +-#define RX_DONE_INT_MASK \ +- (RX0_DONE_INT_MASK | RX1_DONE_INT_MASK | \ +- RX2_DONE_INT_MASK | RX3_DONE_INT_MASK | \ +- RX4_DONE_INT_MASK | RX7_DONE_INT_MASK | \ +- RX8_DONE_INT_MASK | RX9_DONE_INT_MASK | \ +- RX15_DONE_INT_MASK) +-#define INT_IDX1_MASK \ +- (RX_DONE_INT_MASK | \ +- RX0_NO_CPU_DSCP_INT_MASK | RX1_NO_CPU_DSCP_INT_MASK | \ +- RX2_NO_CPU_DSCP_INT_MASK | RX3_NO_CPU_DSCP_INT_MASK | \ +- RX4_NO_CPU_DSCP_INT_MASK | RX7_NO_CPU_DSCP_INT_MASK | \ +- RX8_NO_CPU_DSCP_INT_MASK | RX9_NO_CPU_DSCP_INT_MASK | \ +- RX15_NO_CPU_DSCP_INT_MASK) +- +-/* QDMA_CSR_INT_ENABLE5 */ +-#define TX31_COHERENT_INT_MASK BIT(31) +-#define TX30_COHERENT_INT_MASK BIT(30) +-#define TX29_COHERENT_INT_MASK BIT(29) +-#define TX28_COHERENT_INT_MASK BIT(28) +-#define TX27_COHERENT_INT_MASK BIT(27) +-#define TX26_COHERENT_INT_MASK BIT(26) +-#define TX25_COHERENT_INT_MASK BIT(25) +-#define TX24_COHERENT_INT_MASK BIT(24) +-#define TX23_COHERENT_INT_MASK BIT(23) +-#define TX22_COHERENT_INT_MASK BIT(22) +-#define TX21_COHERENT_INT_MASK BIT(21) +-#define TX20_COHERENT_INT_MASK BIT(20) +-#define TX19_COHERENT_INT_MASK BIT(19) +-#define TX18_COHERENT_INT_MASK BIT(18) +-#define TX17_COHERENT_INT_MASK BIT(17) +-#define TX16_COHERENT_INT_MASK BIT(16) +-#define TX15_COHERENT_INT_MASK BIT(15) +-#define TX14_COHERENT_INT_MASK BIT(14) +-#define TX13_COHERENT_INT_MASK BIT(13) +-#define TX12_COHERENT_INT_MASK BIT(12) +-#define TX11_COHERENT_INT_MASK BIT(11) +-#define TX10_COHERENT_INT_MASK BIT(10) +-#define TX9_COHERENT_INT_MASK BIT(9) +-#define TX8_COHERENT_INT_MASK BIT(8) +- +-#define INT_IDX4_MASK \ +- (TX8_COHERENT_INT_MASK | TX9_COHERENT_INT_MASK | \ +- TX10_COHERENT_INT_MASK | TX11_COHERENT_INT_MASK | \ +- TX12_COHERENT_INT_MASK | TX13_COHERENT_INT_MASK | \ +- TX14_COHERENT_INT_MASK | TX15_COHERENT_INT_MASK | \ +- TX16_COHERENT_INT_MASK | TX17_COHERENT_INT_MASK | \ +- TX18_COHERENT_INT_MASK | TX19_COHERENT_INT_MASK | \ +- TX20_COHERENT_INT_MASK | TX21_COHERENT_INT_MASK | \ +- TX22_COHERENT_INT_MASK | TX23_COHERENT_INT_MASK | \ +- TX24_COHERENT_INT_MASK | TX25_COHERENT_INT_MASK | \ +- TX26_COHERENT_INT_MASK | TX27_COHERENT_INT_MASK | \ +- TX28_COHERENT_INT_MASK | TX29_COHERENT_INT_MASK | \ +- TX30_COHERENT_INT_MASK | TX31_COHERENT_INT_MASK) +- +-#define REG_TX_IRQ_BASE(_n) ((_n) ? 0x0048 : 0x0050) +- +-#define REG_TX_IRQ_CFG(_n) ((_n) ? 0x004c : 0x0054) +-#define TX_IRQ_THR_MASK GENMASK(27, 16) +-#define TX_IRQ_DEPTH_MASK GENMASK(11, 0) +- +-#define REG_IRQ_CLEAR_LEN(_n) ((_n) ? 0x0064 : 0x0058) +-#define IRQ_CLEAR_LEN_MASK GENMASK(7, 0) +- +-#define REG_IRQ_STATUS(_n) ((_n) ? 0x0068 : 0x005c) +-#define IRQ_ENTRY_LEN_MASK GENMASK(27, 16) +-#define IRQ_HEAD_IDX_MASK GENMASK(11, 0) +- +-#define REG_TX_RING_BASE(_n) \ +- (((_n) < 8) ? 0x0100 + ((_n) << 5) : 0x0b00 + (((_n) - 8) << 5)) +- +-#define REG_TX_RING_BLOCKING(_n) \ +- (((_n) < 8) ? 0x0104 + ((_n) << 5) : 0x0b04 + (((_n) - 8) << 5)) +- +-#define TX_RING_IRQ_BLOCKING_MAP_MASK BIT(6) +-#define TX_RING_IRQ_BLOCKING_CFG_MASK BIT(4) +-#define TX_RING_IRQ_BLOCKING_TX_DROP_EN_MASK BIT(2) +-#define TX_RING_IRQ_BLOCKING_MAX_TH_TXRING_EN_MASK BIT(1) +-#define TX_RING_IRQ_BLOCKING_MIN_TH_TXRING_EN_MASK BIT(0) +- +-#define REG_TX_CPU_IDX(_n) \ +- (((_n) < 8) ? 0x0108 + ((_n) << 5) : 0x0b08 + (((_n) - 8) << 5)) +- +-#define TX_RING_CPU_IDX_MASK GENMASK(15, 0) +- +-#define REG_TX_DMA_IDX(_n) \ +- (((_n) < 8) ? 0x010c + ((_n) << 5) : 0x0b0c + (((_n) - 8) << 5)) +- +-#define TX_RING_DMA_IDX_MASK GENMASK(15, 0) +- +-#define IRQ_RING_IDX_MASK GENMASK(20, 16) +-#define IRQ_DESC_IDX_MASK GENMASK(15, 0) +- +-#define REG_RX_RING_BASE(_n) \ +- (((_n) < 16) ? 0x0200 + ((_n) << 5) : 0x0e00 + (((_n) - 16) << 5)) +- +-#define REG_RX_RING_SIZE(_n) \ +- (((_n) < 16) ? 0x0204 + ((_n) << 5) : 0x0e04 + (((_n) - 16) << 5)) +- +-#define RX_RING_THR_MASK GENMASK(31, 16) +-#define RX_RING_SIZE_MASK GENMASK(15, 0) +- +-#define REG_RX_CPU_IDX(_n) \ +- (((_n) < 16) ? 0x0208 + ((_n) << 5) : 0x0e08 + (((_n) - 16) << 5)) +- +-#define RX_RING_CPU_IDX_MASK GENMASK(15, 0) +- +-#define REG_RX_DMA_IDX(_n) \ +- (((_n) < 16) ? 0x020c + ((_n) << 5) : 0x0e0c + (((_n) - 16) << 5)) +- +-#define REG_RX_DELAY_INT_IDX(_n) \ +- (((_n) < 16) ? 0x0210 + ((_n) << 5) : 0x0e10 + (((_n) - 16) << 5)) +- +-#define RX_DELAY_INT_MASK GENMASK(15, 0) +- +-#define RX_RING_DMA_IDX_MASK GENMASK(15, 0) +- +-#define REG_INGRESS_TRTCM_CFG 0x0070 +-#define INGRESS_TRTCM_EN_MASK BIT(31) +-#define INGRESS_TRTCM_MODE_MASK BIT(30) +-#define INGRESS_SLOW_TICK_RATIO_MASK GENMASK(29, 16) +-#define INGRESS_FAST_TICK_MASK GENMASK(15, 0) +- +-#define REG_QUEUE_CLOSE_CFG(_n) (0x00a0 + ((_n) & 0xfc)) +-#define TXQ_DISABLE_CHAN_QUEUE_MASK(_n, _m) BIT((_m) + (((_n) & 0x3) << 3)) +- +-#define REG_TXQ_DIS_CFG_BASE(_n) ((_n) ? 0x20a0 : 0x00a0) +-#define REG_TXQ_DIS_CFG(_n, _m) (REG_TXQ_DIS_CFG_BASE((_n)) + (_m) << 2) +- +-#define REG_CNTR_CFG(_n) (0x0400 + ((_n) << 3)) +-#define CNTR_EN_MASK BIT(31) +-#define CNTR_ALL_CHAN_EN_MASK BIT(30) +-#define CNTR_ALL_QUEUE_EN_MASK BIT(29) +-#define CNTR_ALL_DSCP_RING_EN_MASK BIT(28) +-#define CNTR_SRC_MASK GENMASK(27, 24) +-#define CNTR_DSCP_RING_MASK GENMASK(20, 16) +-#define CNTR_CHAN_MASK GENMASK(7, 3) +-#define CNTR_QUEUE_MASK GENMASK(2, 0) +- +-#define REG_CNTR_VAL(_n) (0x0404 + ((_n) << 3)) +- +-#define REG_LMGR_INIT_CFG 0x1000 +-#define LMGR_INIT_START BIT(31) +-#define LMGR_SRAM_MODE_MASK BIT(30) +-#define HW_FWD_PKTSIZE_OVERHEAD_MASK GENMASK(27, 20) +-#define HW_FWD_DESC_NUM_MASK GENMASK(16, 0) +- +-#define REG_FWD_DSCP_LOW_THR 0x1004 +-#define FWD_DSCP_LOW_THR_MASK GENMASK(17, 0) +- +-#define REG_EGRESS_RATE_METER_CFG 0x100c +-#define EGRESS_RATE_METER_EN_MASK BIT(31) +-#define EGRESS_RATE_METER_EQ_RATE_EN_MASK BIT(17) +-#define EGRESS_RATE_METER_WINDOW_SZ_MASK GENMASK(16, 12) +-#define EGRESS_RATE_METER_TIMESLICE_MASK GENMASK(10, 0) +- +-#define REG_EGRESS_TRTCM_CFG 0x1010 +-#define EGRESS_TRTCM_EN_MASK BIT(31) +-#define EGRESS_TRTCM_MODE_MASK BIT(30) +-#define EGRESS_SLOW_TICK_RATIO_MASK GENMASK(29, 16) +-#define EGRESS_FAST_TICK_MASK GENMASK(15, 0) +- +-#define TRTCM_PARAM_RW_MASK BIT(31) +-#define TRTCM_PARAM_RW_DONE_MASK BIT(30) +-#define TRTCM_PARAM_TYPE_MASK GENMASK(29, 28) +-#define TRTCM_METER_GROUP_MASK GENMASK(27, 26) +-#define TRTCM_PARAM_INDEX_MASK GENMASK(23, 17) +-#define TRTCM_PARAM_RATE_TYPE_MASK BIT(16) +- +-#define REG_TRTCM_CFG_PARAM(_n) ((_n) + 0x4) +-#define REG_TRTCM_DATA_LOW(_n) ((_n) + 0x8) +-#define REG_TRTCM_DATA_HIGH(_n) ((_n) + 0xc) +- +-#define REG_TXWRR_MODE_CFG 0x1020 +-#define TWRR_WEIGHT_SCALE_MASK BIT(31) +-#define TWRR_WEIGHT_BASE_MASK BIT(3) +- +-#define REG_TXWRR_WEIGHT_CFG 0x1024 +-#define TWRR_RW_CMD_MASK BIT(31) +-#define TWRR_RW_CMD_DONE BIT(30) +-#define TWRR_CHAN_IDX_MASK GENMASK(23, 19) +-#define TWRR_QUEUE_IDX_MASK GENMASK(18, 16) +-#define TWRR_VALUE_MASK GENMASK(15, 0) +- +-#define REG_PSE_BUF_USAGE_CFG 0x1028 +-#define PSE_BUF_ESTIMATE_EN_MASK BIT(29) +- +-#define REG_CHAN_QOS_MODE(_n) (0x1040 + ((_n) << 2)) +-#define CHAN_QOS_MODE_MASK(_n) GENMASK(2 + ((_n) << 2), (_n) << 2) +- +-#define REG_GLB_TRTCM_CFG 0x1080 +-#define GLB_TRTCM_EN_MASK BIT(31) +-#define GLB_TRTCM_MODE_MASK BIT(30) +-#define GLB_SLOW_TICK_RATIO_MASK GENMASK(29, 16) +-#define GLB_FAST_TICK_MASK GENMASK(15, 0) +- +-#define REG_TXQ_CNGST_CFG 0x10a0 +-#define TXQ_CNGST_DROP_EN BIT(31) +-#define TXQ_CNGST_DEI_DROP_EN BIT(30) +- +-#define REG_SLA_TRTCM_CFG 0x1150 +-#define SLA_TRTCM_EN_MASK BIT(31) +-#define SLA_TRTCM_MODE_MASK BIT(30) +-#define SLA_SLOW_TICK_RATIO_MASK GENMASK(29, 16) +-#define SLA_FAST_TICK_MASK GENMASK(15, 0) +- +-/* CTRL */ +-#define QDMA_DESC_DONE_MASK BIT(31) +-#define QDMA_DESC_DROP_MASK BIT(30) /* tx: drop - rx: overflow */ +-#define QDMA_DESC_MORE_MASK BIT(29) /* more SG elements */ +-#define QDMA_DESC_DEI_MASK BIT(25) +-#define QDMA_DESC_NO_DROP_MASK BIT(24) +-#define QDMA_DESC_LEN_MASK GENMASK(15, 0) +-/* DATA */ +-#define QDMA_DESC_NEXT_ID_MASK GENMASK(15, 0) +-/* TX MSG0 */ +-#define QDMA_ETH_TXMSG_MIC_IDX_MASK BIT(30) +-#define QDMA_ETH_TXMSG_SP_TAG_MASK GENMASK(29, 14) +-#define QDMA_ETH_TXMSG_ICO_MASK BIT(13) +-#define QDMA_ETH_TXMSG_UCO_MASK BIT(12) +-#define QDMA_ETH_TXMSG_TCO_MASK BIT(11) +-#define QDMA_ETH_TXMSG_TSO_MASK BIT(10) +-#define QDMA_ETH_TXMSG_FAST_MASK BIT(9) +-#define QDMA_ETH_TXMSG_OAM_MASK BIT(8) +-#define QDMA_ETH_TXMSG_CHAN_MASK GENMASK(7, 3) +-#define QDMA_ETH_TXMSG_QUEUE_MASK GENMASK(2, 0) +-/* TX MSG1 */ +-#define QDMA_ETH_TXMSG_NO_DROP BIT(31) +-#define QDMA_ETH_TXMSG_METER_MASK GENMASK(30, 24) /* 0x7f no meters */ +-#define QDMA_ETH_TXMSG_FPORT_MASK GENMASK(23, 20) +-#define QDMA_ETH_TXMSG_NBOQ_MASK GENMASK(19, 15) +-#define QDMA_ETH_TXMSG_HWF_MASK BIT(14) +-#define QDMA_ETH_TXMSG_HOP_MASK BIT(13) +-#define QDMA_ETH_TXMSG_PTP_MASK BIT(12) +-#define QDMA_ETH_TXMSG_ACNT_G1_MASK GENMASK(10, 6) /* 0x1f do not count */ +-#define QDMA_ETH_TXMSG_ACNT_G0_MASK GENMASK(5, 0) /* 0x3f do not count */ +- +-/* RX MSG1 */ +-#define QDMA_ETH_RXMSG_DEI_MASK BIT(31) +-#define QDMA_ETH_RXMSG_IP6_MASK BIT(30) +-#define QDMA_ETH_RXMSG_IP4_MASK BIT(29) +-#define QDMA_ETH_RXMSG_IP4F_MASK BIT(28) +-#define QDMA_ETH_RXMSG_L4_VALID_MASK BIT(27) +-#define QDMA_ETH_RXMSG_L4F_MASK BIT(26) +-#define QDMA_ETH_RXMSG_SPORT_MASK GENMASK(25, 21) +-#define QDMA_ETH_RXMSG_CRSN_MASK GENMASK(20, 16) +-#define QDMA_ETH_RXMSG_PPE_ENTRY_MASK GENMASK(15, 0) +- +-struct airoha_qdma_desc { +- __le32 rsv; +- __le32 ctrl; +- __le32 addr; +- __le32 data; +- __le32 msg0; +- __le32 msg1; +- __le32 msg2; +- __le32 msg3; +-}; +- +-/* CTRL0 */ +-#define QDMA_FWD_DESC_CTX_MASK BIT(31) +-#define QDMA_FWD_DESC_RING_MASK GENMASK(30, 28) +-#define QDMA_FWD_DESC_IDX_MASK GENMASK(27, 16) +-#define QDMA_FWD_DESC_LEN_MASK GENMASK(15, 0) +-/* CTRL1 */ +-#define QDMA_FWD_DESC_FIRST_IDX_MASK GENMASK(15, 0) +-/* CTRL2 */ +-#define QDMA_FWD_DESC_MORE_PKT_NUM_MASK GENMASK(2, 0) +- +-struct airoha_qdma_fwd_desc { +- __le32 addr; +- __le32 ctrl0; +- __le32 ctrl1; +- __le32 ctrl2; +- __le32 msg0; +- __le32 msg1; +- __le32 rsv0; +- __le32 rsv1; +-}; +- + u32 airoha_rr(void __iomem *base, u32 offset) + { + return readl(base + offset); +--- /dev/null ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -0,0 +1,670 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2024 AIROHA Inc ++ * Author: Lorenzo Bianconi ++ */ ++ ++#ifndef AIROHA_REGS_H ++#define AIROHA_REGS_H ++ ++#include ++ ++/* FE */ ++#define PSE_BASE 0x0100 ++#define CSR_IFC_BASE 0x0200 ++#define CDM1_BASE 0x0400 ++#define GDM1_BASE 0x0500 ++#define PPE1_BASE 0x0c00 ++ ++#define CDM2_BASE 0x1400 ++#define GDM2_BASE 0x1500 ++ ++#define GDM3_BASE 0x1100 ++#define GDM4_BASE 0x2500 ++ ++#define GDM_BASE(_n) \ ++ ((_n) == 4 ? GDM4_BASE : \ ++ (_n) == 3 ? GDM3_BASE : \ ++ (_n) == 2 ? GDM2_BASE : GDM1_BASE) ++ ++#define REG_FE_DMA_GLO_CFG 0x0000 ++#define FE_DMA_GLO_L2_SPACE_MASK GENMASK(7, 4) ++#define FE_DMA_GLO_PG_SZ_MASK BIT(3) ++ ++#define REG_FE_RST_GLO_CFG 0x0004 ++#define FE_RST_GDM4_MBI_ARB_MASK BIT(3) ++#define FE_RST_GDM3_MBI_ARB_MASK BIT(2) ++#define FE_RST_CORE_MASK BIT(0) ++ ++#define REG_FE_WAN_MAC_H 0x0030 ++#define REG_FE_LAN_MAC_H 0x0040 ++ ++#define REG_FE_MAC_LMIN(_n) ((_n) + 0x04) ++#define REG_FE_MAC_LMAX(_n) ((_n) + 0x08) ++ ++#define REG_FE_CDM1_OQ_MAP0 0x0050 ++#define REG_FE_CDM1_OQ_MAP1 0x0054 ++#define REG_FE_CDM1_OQ_MAP2 0x0058 ++#define REG_FE_CDM1_OQ_MAP3 0x005c ++ ++#define REG_FE_PCE_CFG 0x0070 ++#define PCE_DPI_EN_MASK BIT(2) ++#define PCE_KA_EN_MASK BIT(1) ++#define PCE_MC_EN_MASK BIT(0) ++ ++#define REG_FE_PSE_QUEUE_CFG_WR 0x0080 ++#define PSE_CFG_PORT_ID_MASK GENMASK(27, 24) ++#define PSE_CFG_QUEUE_ID_MASK GENMASK(20, 16) ++#define PSE_CFG_WR_EN_MASK BIT(8) ++#define PSE_CFG_OQRSV_SEL_MASK BIT(0) ++ ++#define REG_FE_PSE_QUEUE_CFG_VAL 0x0084 ++#define PSE_CFG_OQ_RSV_MASK GENMASK(13, 0) ++ ++#define PSE_FQ_CFG 0x008c ++#define PSE_FQ_LIMIT_MASK GENMASK(14, 0) ++ ++#define REG_FE_PSE_BUF_SET 0x0090 ++#define PSE_SHARE_USED_LTHD_MASK GENMASK(31, 16) ++#define PSE_ALLRSV_MASK GENMASK(14, 0) ++ ++#define REG_PSE_SHARE_USED_THD 0x0094 ++#define PSE_SHARE_USED_MTHD_MASK GENMASK(31, 16) ++#define PSE_SHARE_USED_HTHD_MASK GENMASK(15, 0) ++ ++#define REG_GDM_MISC_CFG 0x0148 ++#define GDM2_RDM_ACK_WAIT_PREF_MASK BIT(9) ++#define GDM2_CHN_VLD_MODE_MASK BIT(5) ++ ++#define REG_FE_CSR_IFC_CFG CSR_IFC_BASE ++#define FE_IFC_EN_MASK BIT(0) ++ ++#define REG_FE_VIP_PORT_EN 0x01f0 ++#define REG_FE_IFC_PORT_EN 0x01f4 ++ ++#define REG_PSE_IQ_REV1 (PSE_BASE + 0x08) ++#define PSE_IQ_RES1_P2_MASK GENMASK(23, 16) ++ ++#define REG_PSE_IQ_REV2 (PSE_BASE + 0x0c) ++#define PSE_IQ_RES2_P5_MASK GENMASK(15, 8) ++#define PSE_IQ_RES2_P4_MASK GENMASK(7, 0) ++ ++#define REG_FE_VIP_EN(_n) (0x0300 + ((_n) << 3)) ++#define PATN_FCPU_EN_MASK BIT(7) ++#define PATN_SWP_EN_MASK BIT(6) ++#define PATN_DP_EN_MASK BIT(5) ++#define PATN_SP_EN_MASK BIT(4) ++#define PATN_TYPE_MASK GENMASK(3, 1) ++#define PATN_EN_MASK BIT(0) ++ ++#define REG_FE_VIP_PATN(_n) (0x0304 + ((_n) << 3)) ++#define PATN_DP_MASK GENMASK(31, 16) ++#define PATN_SP_MASK GENMASK(15, 0) ++ ++#define REG_CDM1_VLAN_CTRL CDM1_BASE ++#define CDM1_VLAN_MASK GENMASK(31, 16) ++ ++#define REG_CDM1_FWD_CFG (CDM1_BASE + 0x08) ++#define CDM1_VIP_QSEL_MASK GENMASK(24, 20) ++ ++#define REG_CDM1_CRSN_QSEL(_n) (CDM1_BASE + 0x10 + ((_n) << 2)) ++#define CDM1_CRSN_QSEL_REASON_MASK(_n) \ ++ GENMASK(4 + (((_n) % 4) << 3), (((_n) % 4) << 3)) ++ ++#define REG_CDM2_FWD_CFG (CDM2_BASE + 0x08) ++#define CDM2_OAM_QSEL_MASK GENMASK(31, 27) ++#define CDM2_VIP_QSEL_MASK GENMASK(24, 20) ++ ++#define REG_CDM2_CRSN_QSEL(_n) (CDM2_BASE + 0x10 + ((_n) << 2)) ++#define CDM2_CRSN_QSEL_REASON_MASK(_n) \ ++ GENMASK(4 + (((_n) % 4) << 3), (((_n) % 4) << 3)) ++ ++#define REG_GDM_FWD_CFG(_n) GDM_BASE(_n) ++#define GDM_DROP_CRC_ERR BIT(23) ++#define GDM_IP4_CKSUM BIT(22) ++#define GDM_TCP_CKSUM BIT(21) ++#define GDM_UDP_CKSUM BIT(20) ++#define GDM_UCFQ_MASK GENMASK(15, 12) ++#define GDM_BCFQ_MASK GENMASK(11, 8) ++#define GDM_MCFQ_MASK GENMASK(7, 4) ++#define GDM_OCFQ_MASK GENMASK(3, 0) ++ ++#define REG_GDM_INGRESS_CFG(_n) (GDM_BASE(_n) + 0x10) ++#define GDM_INGRESS_FC_EN_MASK BIT(1) ++#define GDM_STAG_EN_MASK BIT(0) ++ ++#define REG_GDM_LEN_CFG(_n) (GDM_BASE(_n) + 0x14) ++#define GDM_SHORT_LEN_MASK GENMASK(13, 0) ++#define GDM_LONG_LEN_MASK GENMASK(29, 16) ++ ++#define REG_FE_CPORT_CFG (GDM1_BASE + 0x40) ++#define FE_CPORT_PAD BIT(26) ++#define FE_CPORT_PORT_XFC_MASK BIT(25) ++#define FE_CPORT_QUEUE_XFC_MASK BIT(24) ++ ++#define REG_FE_GDM_MIB_CLEAR(_n) (GDM_BASE(_n) + 0xf0) ++#define FE_GDM_MIB_RX_CLEAR_MASK BIT(1) ++#define FE_GDM_MIB_TX_CLEAR_MASK BIT(0) ++ ++#define REG_FE_GDM1_MIB_CFG (GDM1_BASE + 0xf4) ++#define FE_STRICT_RFC2819_MODE_MASK BIT(31) ++#define FE_GDM1_TX_MIB_SPLIT_EN_MASK BIT(17) ++#define FE_GDM1_RX_MIB_SPLIT_EN_MASK BIT(16) ++#define FE_TX_MIB_ID_MASK GENMASK(15, 8) ++#define FE_RX_MIB_ID_MASK GENMASK(7, 0) ++ ++#define REG_FE_GDM_TX_OK_PKT_CNT_L(_n) (GDM_BASE(_n) + 0x104) ++#define REG_FE_GDM_TX_OK_BYTE_CNT_L(_n) (GDM_BASE(_n) + 0x10c) ++#define REG_FE_GDM_TX_ETH_PKT_CNT_L(_n) (GDM_BASE(_n) + 0x110) ++#define REG_FE_GDM_TX_ETH_BYTE_CNT_L(_n) (GDM_BASE(_n) + 0x114) ++#define REG_FE_GDM_TX_ETH_DROP_CNT(_n) (GDM_BASE(_n) + 0x118) ++#define REG_FE_GDM_TX_ETH_BC_CNT(_n) (GDM_BASE(_n) + 0x11c) ++#define REG_FE_GDM_TX_ETH_MC_CNT(_n) (GDM_BASE(_n) + 0x120) ++#define REG_FE_GDM_TX_ETH_RUNT_CNT(_n) (GDM_BASE(_n) + 0x124) ++#define REG_FE_GDM_TX_ETH_LONG_CNT(_n) (GDM_BASE(_n) + 0x128) ++#define REG_FE_GDM_TX_ETH_E64_CNT_L(_n) (GDM_BASE(_n) + 0x12c) ++#define REG_FE_GDM_TX_ETH_L64_CNT_L(_n) (GDM_BASE(_n) + 0x130) ++#define REG_FE_GDM_TX_ETH_L127_CNT_L(_n) (GDM_BASE(_n) + 0x134) ++#define REG_FE_GDM_TX_ETH_L255_CNT_L(_n) (GDM_BASE(_n) + 0x138) ++#define REG_FE_GDM_TX_ETH_L511_CNT_L(_n) (GDM_BASE(_n) + 0x13c) ++#define REG_FE_GDM_TX_ETH_L1023_CNT_L(_n) (GDM_BASE(_n) + 0x140) ++ ++#define REG_FE_GDM_RX_OK_PKT_CNT_L(_n) (GDM_BASE(_n) + 0x148) ++#define REG_FE_GDM_RX_FC_DROP_CNT(_n) (GDM_BASE(_n) + 0x14c) ++#define REG_FE_GDM_RX_RC_DROP_CNT(_n) (GDM_BASE(_n) + 0x150) ++#define REG_FE_GDM_RX_OVERFLOW_DROP_CNT(_n) (GDM_BASE(_n) + 0x154) ++#define REG_FE_GDM_RX_ERROR_DROP_CNT(_n) (GDM_BASE(_n) + 0x158) ++#define REG_FE_GDM_RX_OK_BYTE_CNT_L(_n) (GDM_BASE(_n) + 0x15c) ++#define REG_FE_GDM_RX_ETH_PKT_CNT_L(_n) (GDM_BASE(_n) + 0x160) ++#define REG_FE_GDM_RX_ETH_BYTE_CNT_L(_n) (GDM_BASE(_n) + 0x164) ++#define REG_FE_GDM_RX_ETH_DROP_CNT(_n) (GDM_BASE(_n) + 0x168) ++#define REG_FE_GDM_RX_ETH_BC_CNT(_n) (GDM_BASE(_n) + 0x16c) ++#define REG_FE_GDM_RX_ETH_MC_CNT(_n) (GDM_BASE(_n) + 0x170) ++#define REG_FE_GDM_RX_ETH_CRC_ERR_CNT(_n) (GDM_BASE(_n) + 0x174) ++#define REG_FE_GDM_RX_ETH_FRAG_CNT(_n) (GDM_BASE(_n) + 0x178) ++#define REG_FE_GDM_RX_ETH_JABBER_CNT(_n) (GDM_BASE(_n) + 0x17c) ++#define REG_FE_GDM_RX_ETH_RUNT_CNT(_n) (GDM_BASE(_n) + 0x180) ++#define REG_FE_GDM_RX_ETH_LONG_CNT(_n) (GDM_BASE(_n) + 0x184) ++#define REG_FE_GDM_RX_ETH_E64_CNT_L(_n) (GDM_BASE(_n) + 0x188) ++#define REG_FE_GDM_RX_ETH_L64_CNT_L(_n) (GDM_BASE(_n) + 0x18c) ++#define REG_FE_GDM_RX_ETH_L127_CNT_L(_n) (GDM_BASE(_n) + 0x190) ++#define REG_FE_GDM_RX_ETH_L255_CNT_L(_n) (GDM_BASE(_n) + 0x194) ++#define REG_FE_GDM_RX_ETH_L511_CNT_L(_n) (GDM_BASE(_n) + 0x198) ++#define REG_FE_GDM_RX_ETH_L1023_CNT_L(_n) (GDM_BASE(_n) + 0x19c) ++ ++#define REG_PPE1_TB_HASH_CFG (PPE1_BASE + 0x250) ++#define PPE1_SRAM_TABLE_EN_MASK BIT(0) ++#define PPE1_SRAM_HASH1_EN_MASK BIT(8) ++#define PPE1_DRAM_TABLE_EN_MASK BIT(16) ++#define PPE1_DRAM_HASH1_EN_MASK BIT(24) ++ ++#define REG_FE_GDM_TX_OK_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x280) ++#define REG_FE_GDM_TX_OK_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x284) ++#define REG_FE_GDM_TX_ETH_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x288) ++#define REG_FE_GDM_TX_ETH_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x28c) ++ ++#define REG_FE_GDM_RX_OK_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x290) ++#define REG_FE_GDM_RX_OK_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x294) ++#define REG_FE_GDM_RX_ETH_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x298) ++#define REG_FE_GDM_RX_ETH_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x29c) ++#define REG_FE_GDM_TX_ETH_E64_CNT_H(_n) (GDM_BASE(_n) + 0x2b8) ++#define REG_FE_GDM_TX_ETH_L64_CNT_H(_n) (GDM_BASE(_n) + 0x2bc) ++#define REG_FE_GDM_TX_ETH_L127_CNT_H(_n) (GDM_BASE(_n) + 0x2c0) ++#define REG_FE_GDM_TX_ETH_L255_CNT_H(_n) (GDM_BASE(_n) + 0x2c4) ++#define REG_FE_GDM_TX_ETH_L511_CNT_H(_n) (GDM_BASE(_n) + 0x2c8) ++#define REG_FE_GDM_TX_ETH_L1023_CNT_H(_n) (GDM_BASE(_n) + 0x2cc) ++#define REG_FE_GDM_RX_ETH_E64_CNT_H(_n) (GDM_BASE(_n) + 0x2e8) ++#define REG_FE_GDM_RX_ETH_L64_CNT_H(_n) (GDM_BASE(_n) + 0x2ec) ++#define REG_FE_GDM_RX_ETH_L127_CNT_H(_n) (GDM_BASE(_n) + 0x2f0) ++#define REG_FE_GDM_RX_ETH_L255_CNT_H(_n) (GDM_BASE(_n) + 0x2f4) ++#define REG_FE_GDM_RX_ETH_L511_CNT_H(_n) (GDM_BASE(_n) + 0x2f8) ++#define REG_FE_GDM_RX_ETH_L1023_CNT_H(_n) (GDM_BASE(_n) + 0x2fc) ++ ++#define REG_GDM2_CHN_RLS (GDM2_BASE + 0x20) ++#define MBI_RX_AGE_SEL_MASK GENMASK(26, 25) ++#define MBI_TX_AGE_SEL_MASK GENMASK(18, 17) ++ ++#define REG_GDM3_FWD_CFG GDM3_BASE ++#define GDM3_PAD_EN_MASK BIT(28) ++ ++#define REG_GDM4_FWD_CFG GDM4_BASE ++#define GDM4_PAD_EN_MASK BIT(28) ++#define GDM4_SPORT_OFFSET0_MASK GENMASK(11, 8) ++ ++#define REG_GDM4_SRC_PORT_SET (GDM4_BASE + 0x23c) ++#define GDM4_SPORT_OFF2_MASK GENMASK(19, 16) ++#define GDM4_SPORT_OFF1_MASK GENMASK(15, 12) ++#define GDM4_SPORT_OFF0_MASK GENMASK(11, 8) ++ ++#define REG_IP_FRAG_FP 0x2010 ++#define IP_ASSEMBLE_PORT_MASK GENMASK(24, 21) ++#define IP_ASSEMBLE_NBQ_MASK GENMASK(20, 16) ++#define IP_FRAGMENT_PORT_MASK GENMASK(8, 5) ++#define IP_FRAGMENT_NBQ_MASK GENMASK(4, 0) ++ ++#define REG_MC_VLAN_EN 0x2100 ++#define MC_VLAN_EN_MASK BIT(0) ++ ++#define REG_MC_VLAN_CFG 0x2104 ++#define MC_VLAN_CFG_CMD_DONE_MASK BIT(31) ++#define MC_VLAN_CFG_TABLE_ID_MASK GENMASK(21, 16) ++#define MC_VLAN_CFG_PORT_ID_MASK GENMASK(11, 8) ++#define MC_VLAN_CFG_TABLE_SEL_MASK BIT(4) ++#define MC_VLAN_CFG_RW_MASK BIT(0) ++ ++#define REG_MC_VLAN_DATA 0x2108 ++ ++#define REG_CDM5_RX_OQ1_DROP_CNT 0x29d4 ++ ++/* QDMA */ ++#define REG_QDMA_GLOBAL_CFG 0x0004 ++#define GLOBAL_CFG_RX_2B_OFFSET_MASK BIT(31) ++#define GLOBAL_CFG_DMA_PREFERENCE_MASK GENMASK(30, 29) ++#define GLOBAL_CFG_CPU_TXR_RR_MASK BIT(28) ++#define GLOBAL_CFG_DSCP_BYTE_SWAP_MASK BIT(27) ++#define GLOBAL_CFG_PAYLOAD_BYTE_SWAP_MASK BIT(26) ++#define GLOBAL_CFG_MULTICAST_MODIFY_FP_MASK BIT(25) ++#define GLOBAL_CFG_OAM_MODIFY_MASK BIT(24) ++#define GLOBAL_CFG_RESET_MASK BIT(23) ++#define GLOBAL_CFG_RESET_DONE_MASK BIT(22) ++#define GLOBAL_CFG_MULTICAST_EN_MASK BIT(21) ++#define GLOBAL_CFG_IRQ1_EN_MASK BIT(20) ++#define GLOBAL_CFG_IRQ0_EN_MASK BIT(19) ++#define GLOBAL_CFG_LOOPCNT_EN_MASK BIT(18) ++#define GLOBAL_CFG_RD_BYPASS_WR_MASK BIT(17) ++#define GLOBAL_CFG_QDMA_LOOPBACK_MASK BIT(16) ++#define GLOBAL_CFG_LPBK_RXQ_SEL_MASK GENMASK(13, 8) ++#define GLOBAL_CFG_CHECK_DONE_MASK BIT(7) ++#define GLOBAL_CFG_TX_WB_DONE_MASK BIT(6) ++#define GLOBAL_CFG_MAX_ISSUE_NUM_MASK GENMASK(5, 4) ++#define GLOBAL_CFG_RX_DMA_BUSY_MASK BIT(3) ++#define GLOBAL_CFG_RX_DMA_EN_MASK BIT(2) ++#define GLOBAL_CFG_TX_DMA_BUSY_MASK BIT(1) ++#define GLOBAL_CFG_TX_DMA_EN_MASK BIT(0) ++ ++#define REG_FWD_DSCP_BASE 0x0010 ++#define REG_FWD_BUF_BASE 0x0014 ++ ++#define REG_HW_FWD_DSCP_CFG 0x0018 ++#define HW_FWD_DSCP_PAYLOAD_SIZE_MASK GENMASK(29, 28) ++#define HW_FWD_DSCP_SCATTER_LEN_MASK GENMASK(17, 16) ++#define HW_FWD_DSCP_MIN_SCATTER_LEN_MASK GENMASK(15, 0) ++ ++#define REG_INT_STATUS(_n) \ ++ (((_n) == 4) ? 0x0730 : \ ++ ((_n) == 3) ? 0x0724 : \ ++ ((_n) == 2) ? 0x0720 : \ ++ ((_n) == 1) ? 0x0024 : 0x0020) ++ ++#define REG_INT_ENABLE(_n) \ ++ (((_n) == 4) ? 0x0750 : \ ++ ((_n) == 3) ? 0x0744 : \ ++ ((_n) == 2) ? 0x0740 : \ ++ ((_n) == 1) ? 0x002c : 0x0028) ++ ++/* QDMA_CSR_INT_ENABLE1 */ ++#define RX15_COHERENT_INT_MASK BIT(31) ++#define RX14_COHERENT_INT_MASK BIT(30) ++#define RX13_COHERENT_INT_MASK BIT(29) ++#define RX12_COHERENT_INT_MASK BIT(28) ++#define RX11_COHERENT_INT_MASK BIT(27) ++#define RX10_COHERENT_INT_MASK BIT(26) ++#define RX9_COHERENT_INT_MASK BIT(25) ++#define RX8_COHERENT_INT_MASK BIT(24) ++#define RX7_COHERENT_INT_MASK BIT(23) ++#define RX6_COHERENT_INT_MASK BIT(22) ++#define RX5_COHERENT_INT_MASK BIT(21) ++#define RX4_COHERENT_INT_MASK BIT(20) ++#define RX3_COHERENT_INT_MASK BIT(19) ++#define RX2_COHERENT_INT_MASK BIT(18) ++#define RX1_COHERENT_INT_MASK BIT(17) ++#define RX0_COHERENT_INT_MASK BIT(16) ++#define TX7_COHERENT_INT_MASK BIT(15) ++#define TX6_COHERENT_INT_MASK BIT(14) ++#define TX5_COHERENT_INT_MASK BIT(13) ++#define TX4_COHERENT_INT_MASK BIT(12) ++#define TX3_COHERENT_INT_MASK BIT(11) ++#define TX2_COHERENT_INT_MASK BIT(10) ++#define TX1_COHERENT_INT_MASK BIT(9) ++#define TX0_COHERENT_INT_MASK BIT(8) ++#define CNT_OVER_FLOW_INT_MASK BIT(7) ++#define IRQ1_FULL_INT_MASK BIT(5) ++#define IRQ1_INT_MASK BIT(4) ++#define HWFWD_DSCP_LOW_INT_MASK BIT(3) ++#define HWFWD_DSCP_EMPTY_INT_MASK BIT(2) ++#define IRQ0_FULL_INT_MASK BIT(1) ++#define IRQ0_INT_MASK BIT(0) ++ ++#define TX_DONE_INT_MASK(_n) \ ++ ((_n) ? IRQ1_INT_MASK | IRQ1_FULL_INT_MASK \ ++ : IRQ0_INT_MASK | IRQ0_FULL_INT_MASK) ++ ++#define INT_TX_MASK \ ++ (IRQ1_INT_MASK | IRQ1_FULL_INT_MASK | \ ++ IRQ0_INT_MASK | IRQ0_FULL_INT_MASK) ++ ++#define INT_IDX0_MASK \ ++ (TX0_COHERENT_INT_MASK | TX1_COHERENT_INT_MASK | \ ++ TX2_COHERENT_INT_MASK | TX3_COHERENT_INT_MASK | \ ++ TX4_COHERENT_INT_MASK | TX5_COHERENT_INT_MASK | \ ++ TX6_COHERENT_INT_MASK | TX7_COHERENT_INT_MASK | \ ++ RX0_COHERENT_INT_MASK | RX1_COHERENT_INT_MASK | \ ++ RX2_COHERENT_INT_MASK | RX3_COHERENT_INT_MASK | \ ++ RX4_COHERENT_INT_MASK | RX7_COHERENT_INT_MASK | \ ++ RX8_COHERENT_INT_MASK | RX9_COHERENT_INT_MASK | \ ++ RX15_COHERENT_INT_MASK | INT_TX_MASK) ++ ++/* QDMA_CSR_INT_ENABLE2 */ ++#define RX15_NO_CPU_DSCP_INT_MASK BIT(31) ++#define RX14_NO_CPU_DSCP_INT_MASK BIT(30) ++#define RX13_NO_CPU_DSCP_INT_MASK BIT(29) ++#define RX12_NO_CPU_DSCP_INT_MASK BIT(28) ++#define RX11_NO_CPU_DSCP_INT_MASK BIT(27) ++#define RX10_NO_CPU_DSCP_INT_MASK BIT(26) ++#define RX9_NO_CPU_DSCP_INT_MASK BIT(25) ++#define RX8_NO_CPU_DSCP_INT_MASK BIT(24) ++#define RX7_NO_CPU_DSCP_INT_MASK BIT(23) ++#define RX6_NO_CPU_DSCP_INT_MASK BIT(22) ++#define RX5_NO_CPU_DSCP_INT_MASK BIT(21) ++#define RX4_NO_CPU_DSCP_INT_MASK BIT(20) ++#define RX3_NO_CPU_DSCP_INT_MASK BIT(19) ++#define RX2_NO_CPU_DSCP_INT_MASK BIT(18) ++#define RX1_NO_CPU_DSCP_INT_MASK BIT(17) ++#define RX0_NO_CPU_DSCP_INT_MASK BIT(16) ++#define RX15_DONE_INT_MASK BIT(15) ++#define RX14_DONE_INT_MASK BIT(14) ++#define RX13_DONE_INT_MASK BIT(13) ++#define RX12_DONE_INT_MASK BIT(12) ++#define RX11_DONE_INT_MASK BIT(11) ++#define RX10_DONE_INT_MASK BIT(10) ++#define RX9_DONE_INT_MASK BIT(9) ++#define RX8_DONE_INT_MASK BIT(8) ++#define RX7_DONE_INT_MASK BIT(7) ++#define RX6_DONE_INT_MASK BIT(6) ++#define RX5_DONE_INT_MASK BIT(5) ++#define RX4_DONE_INT_MASK BIT(4) ++#define RX3_DONE_INT_MASK BIT(3) ++#define RX2_DONE_INT_MASK BIT(2) ++#define RX1_DONE_INT_MASK BIT(1) ++#define RX0_DONE_INT_MASK BIT(0) ++ ++#define RX_DONE_INT_MASK \ ++ (RX0_DONE_INT_MASK | RX1_DONE_INT_MASK | \ ++ RX2_DONE_INT_MASK | RX3_DONE_INT_MASK | \ ++ RX4_DONE_INT_MASK | RX7_DONE_INT_MASK | \ ++ RX8_DONE_INT_MASK | RX9_DONE_INT_MASK | \ ++ RX15_DONE_INT_MASK) ++#define INT_IDX1_MASK \ ++ (RX_DONE_INT_MASK | \ ++ RX0_NO_CPU_DSCP_INT_MASK | RX1_NO_CPU_DSCP_INT_MASK | \ ++ RX2_NO_CPU_DSCP_INT_MASK | RX3_NO_CPU_DSCP_INT_MASK | \ ++ RX4_NO_CPU_DSCP_INT_MASK | RX7_NO_CPU_DSCP_INT_MASK | \ ++ RX8_NO_CPU_DSCP_INT_MASK | RX9_NO_CPU_DSCP_INT_MASK | \ ++ RX15_NO_CPU_DSCP_INT_MASK) ++ ++/* QDMA_CSR_INT_ENABLE5 */ ++#define TX31_COHERENT_INT_MASK BIT(31) ++#define TX30_COHERENT_INT_MASK BIT(30) ++#define TX29_COHERENT_INT_MASK BIT(29) ++#define TX28_COHERENT_INT_MASK BIT(28) ++#define TX27_COHERENT_INT_MASK BIT(27) ++#define TX26_COHERENT_INT_MASK BIT(26) ++#define TX25_COHERENT_INT_MASK BIT(25) ++#define TX24_COHERENT_INT_MASK BIT(24) ++#define TX23_COHERENT_INT_MASK BIT(23) ++#define TX22_COHERENT_INT_MASK BIT(22) ++#define TX21_COHERENT_INT_MASK BIT(21) ++#define TX20_COHERENT_INT_MASK BIT(20) ++#define TX19_COHERENT_INT_MASK BIT(19) ++#define TX18_COHERENT_INT_MASK BIT(18) ++#define TX17_COHERENT_INT_MASK BIT(17) ++#define TX16_COHERENT_INT_MASK BIT(16) ++#define TX15_COHERENT_INT_MASK BIT(15) ++#define TX14_COHERENT_INT_MASK BIT(14) ++#define TX13_COHERENT_INT_MASK BIT(13) ++#define TX12_COHERENT_INT_MASK BIT(12) ++#define TX11_COHERENT_INT_MASK BIT(11) ++#define TX10_COHERENT_INT_MASK BIT(10) ++#define TX9_COHERENT_INT_MASK BIT(9) ++#define TX8_COHERENT_INT_MASK BIT(8) ++ ++#define INT_IDX4_MASK \ ++ (TX8_COHERENT_INT_MASK | TX9_COHERENT_INT_MASK | \ ++ TX10_COHERENT_INT_MASK | TX11_COHERENT_INT_MASK | \ ++ TX12_COHERENT_INT_MASK | TX13_COHERENT_INT_MASK | \ ++ TX14_COHERENT_INT_MASK | TX15_COHERENT_INT_MASK | \ ++ TX16_COHERENT_INT_MASK | TX17_COHERENT_INT_MASK | \ ++ TX18_COHERENT_INT_MASK | TX19_COHERENT_INT_MASK | \ ++ TX20_COHERENT_INT_MASK | TX21_COHERENT_INT_MASK | \ ++ TX22_COHERENT_INT_MASK | TX23_COHERENT_INT_MASK | \ ++ TX24_COHERENT_INT_MASK | TX25_COHERENT_INT_MASK | \ ++ TX26_COHERENT_INT_MASK | TX27_COHERENT_INT_MASK | \ ++ TX28_COHERENT_INT_MASK | TX29_COHERENT_INT_MASK | \ ++ TX30_COHERENT_INT_MASK | TX31_COHERENT_INT_MASK) ++ ++#define REG_TX_IRQ_BASE(_n) ((_n) ? 0x0048 : 0x0050) ++ ++#define REG_TX_IRQ_CFG(_n) ((_n) ? 0x004c : 0x0054) ++#define TX_IRQ_THR_MASK GENMASK(27, 16) ++#define TX_IRQ_DEPTH_MASK GENMASK(11, 0) ++ ++#define REG_IRQ_CLEAR_LEN(_n) ((_n) ? 0x0064 : 0x0058) ++#define IRQ_CLEAR_LEN_MASK GENMASK(7, 0) ++ ++#define REG_IRQ_STATUS(_n) ((_n) ? 0x0068 : 0x005c) ++#define IRQ_ENTRY_LEN_MASK GENMASK(27, 16) ++#define IRQ_HEAD_IDX_MASK GENMASK(11, 0) ++ ++#define REG_TX_RING_BASE(_n) \ ++ (((_n) < 8) ? 0x0100 + ((_n) << 5) : 0x0b00 + (((_n) - 8) << 5)) ++ ++#define REG_TX_RING_BLOCKING(_n) \ ++ (((_n) < 8) ? 0x0104 + ((_n) << 5) : 0x0b04 + (((_n) - 8) << 5)) ++ ++#define TX_RING_IRQ_BLOCKING_MAP_MASK BIT(6) ++#define TX_RING_IRQ_BLOCKING_CFG_MASK BIT(4) ++#define TX_RING_IRQ_BLOCKING_TX_DROP_EN_MASK BIT(2) ++#define TX_RING_IRQ_BLOCKING_MAX_TH_TXRING_EN_MASK BIT(1) ++#define TX_RING_IRQ_BLOCKING_MIN_TH_TXRING_EN_MASK BIT(0) ++ ++#define REG_TX_CPU_IDX(_n) \ ++ (((_n) < 8) ? 0x0108 + ((_n) << 5) : 0x0b08 + (((_n) - 8) << 5)) ++ ++#define TX_RING_CPU_IDX_MASK GENMASK(15, 0) ++ ++#define REG_TX_DMA_IDX(_n) \ ++ (((_n) < 8) ? 0x010c + ((_n) << 5) : 0x0b0c + (((_n) - 8) << 5)) ++ ++#define TX_RING_DMA_IDX_MASK GENMASK(15, 0) ++ ++#define IRQ_RING_IDX_MASK GENMASK(20, 16) ++#define IRQ_DESC_IDX_MASK GENMASK(15, 0) ++ ++#define REG_RX_RING_BASE(_n) \ ++ (((_n) < 16) ? 0x0200 + ((_n) << 5) : 0x0e00 + (((_n) - 16) << 5)) ++ ++#define REG_RX_RING_SIZE(_n) \ ++ (((_n) < 16) ? 0x0204 + ((_n) << 5) : 0x0e04 + (((_n) - 16) << 5)) ++ ++#define RX_RING_THR_MASK GENMASK(31, 16) ++#define RX_RING_SIZE_MASK GENMASK(15, 0) ++ ++#define REG_RX_CPU_IDX(_n) \ ++ (((_n) < 16) ? 0x0208 + ((_n) << 5) : 0x0e08 + (((_n) - 16) << 5)) ++ ++#define RX_RING_CPU_IDX_MASK GENMASK(15, 0) ++ ++#define REG_RX_DMA_IDX(_n) \ ++ (((_n) < 16) ? 0x020c + ((_n) << 5) : 0x0e0c + (((_n) - 16) << 5)) ++ ++#define REG_RX_DELAY_INT_IDX(_n) \ ++ (((_n) < 16) ? 0x0210 + ((_n) << 5) : 0x0e10 + (((_n) - 16) << 5)) ++ ++#define RX_DELAY_INT_MASK GENMASK(15, 0) ++ ++#define RX_RING_DMA_IDX_MASK GENMASK(15, 0) ++ ++#define REG_INGRESS_TRTCM_CFG 0x0070 ++#define INGRESS_TRTCM_EN_MASK BIT(31) ++#define INGRESS_TRTCM_MODE_MASK BIT(30) ++#define INGRESS_SLOW_TICK_RATIO_MASK GENMASK(29, 16) ++#define INGRESS_FAST_TICK_MASK GENMASK(15, 0) ++ ++#define REG_QUEUE_CLOSE_CFG(_n) (0x00a0 + ((_n) & 0xfc)) ++#define TXQ_DISABLE_CHAN_QUEUE_MASK(_n, _m) BIT((_m) + (((_n) & 0x3) << 3)) ++ ++#define REG_TXQ_DIS_CFG_BASE(_n) ((_n) ? 0x20a0 : 0x00a0) ++#define REG_TXQ_DIS_CFG(_n, _m) (REG_TXQ_DIS_CFG_BASE((_n)) + (_m) << 2) ++ ++#define REG_CNTR_CFG(_n) (0x0400 + ((_n) << 3)) ++#define CNTR_EN_MASK BIT(31) ++#define CNTR_ALL_CHAN_EN_MASK BIT(30) ++#define CNTR_ALL_QUEUE_EN_MASK BIT(29) ++#define CNTR_ALL_DSCP_RING_EN_MASK BIT(28) ++#define CNTR_SRC_MASK GENMASK(27, 24) ++#define CNTR_DSCP_RING_MASK GENMASK(20, 16) ++#define CNTR_CHAN_MASK GENMASK(7, 3) ++#define CNTR_QUEUE_MASK GENMASK(2, 0) ++ ++#define REG_CNTR_VAL(_n) (0x0404 + ((_n) << 3)) ++ ++#define REG_LMGR_INIT_CFG 0x1000 ++#define LMGR_INIT_START BIT(31) ++#define LMGR_SRAM_MODE_MASK BIT(30) ++#define HW_FWD_PKTSIZE_OVERHEAD_MASK GENMASK(27, 20) ++#define HW_FWD_DESC_NUM_MASK GENMASK(16, 0) ++ ++#define REG_FWD_DSCP_LOW_THR 0x1004 ++#define FWD_DSCP_LOW_THR_MASK GENMASK(17, 0) ++ ++#define REG_EGRESS_RATE_METER_CFG 0x100c ++#define EGRESS_RATE_METER_EN_MASK BIT(31) ++#define EGRESS_RATE_METER_EQ_RATE_EN_MASK BIT(17) ++#define EGRESS_RATE_METER_WINDOW_SZ_MASK GENMASK(16, 12) ++#define EGRESS_RATE_METER_TIMESLICE_MASK GENMASK(10, 0) ++ ++#define REG_EGRESS_TRTCM_CFG 0x1010 ++#define EGRESS_TRTCM_EN_MASK BIT(31) ++#define EGRESS_TRTCM_MODE_MASK BIT(30) ++#define EGRESS_SLOW_TICK_RATIO_MASK GENMASK(29, 16) ++#define EGRESS_FAST_TICK_MASK GENMASK(15, 0) ++ ++#define TRTCM_PARAM_RW_MASK BIT(31) ++#define TRTCM_PARAM_RW_DONE_MASK BIT(30) ++#define TRTCM_PARAM_TYPE_MASK GENMASK(29, 28) ++#define TRTCM_METER_GROUP_MASK GENMASK(27, 26) ++#define TRTCM_PARAM_INDEX_MASK GENMASK(23, 17) ++#define TRTCM_PARAM_RATE_TYPE_MASK BIT(16) ++ ++#define REG_TRTCM_CFG_PARAM(_n) ((_n) + 0x4) ++#define REG_TRTCM_DATA_LOW(_n) ((_n) + 0x8) ++#define REG_TRTCM_DATA_HIGH(_n) ((_n) + 0xc) ++ ++#define REG_TXWRR_MODE_CFG 0x1020 ++#define TWRR_WEIGHT_SCALE_MASK BIT(31) ++#define TWRR_WEIGHT_BASE_MASK BIT(3) ++ ++#define REG_TXWRR_WEIGHT_CFG 0x1024 ++#define TWRR_RW_CMD_MASK BIT(31) ++#define TWRR_RW_CMD_DONE BIT(30) ++#define TWRR_CHAN_IDX_MASK GENMASK(23, 19) ++#define TWRR_QUEUE_IDX_MASK GENMASK(18, 16) ++#define TWRR_VALUE_MASK GENMASK(15, 0) ++ ++#define REG_PSE_BUF_USAGE_CFG 0x1028 ++#define PSE_BUF_ESTIMATE_EN_MASK BIT(29) ++ ++#define REG_CHAN_QOS_MODE(_n) (0x1040 + ((_n) << 2)) ++#define CHAN_QOS_MODE_MASK(_n) GENMASK(2 + ((_n) << 2), (_n) << 2) ++ ++#define REG_GLB_TRTCM_CFG 0x1080 ++#define GLB_TRTCM_EN_MASK BIT(31) ++#define GLB_TRTCM_MODE_MASK BIT(30) ++#define GLB_SLOW_TICK_RATIO_MASK GENMASK(29, 16) ++#define GLB_FAST_TICK_MASK GENMASK(15, 0) ++ ++#define REG_TXQ_CNGST_CFG 0x10a0 ++#define TXQ_CNGST_DROP_EN BIT(31) ++#define TXQ_CNGST_DEI_DROP_EN BIT(30) ++ ++#define REG_SLA_TRTCM_CFG 0x1150 ++#define SLA_TRTCM_EN_MASK BIT(31) ++#define SLA_TRTCM_MODE_MASK BIT(30) ++#define SLA_SLOW_TICK_RATIO_MASK GENMASK(29, 16) ++#define SLA_FAST_TICK_MASK GENMASK(15, 0) ++ ++/* CTRL */ ++#define QDMA_DESC_DONE_MASK BIT(31) ++#define QDMA_DESC_DROP_MASK BIT(30) /* tx: drop - rx: overflow */ ++#define QDMA_DESC_MORE_MASK BIT(29) /* more SG elements */ ++#define QDMA_DESC_DEI_MASK BIT(25) ++#define QDMA_DESC_NO_DROP_MASK BIT(24) ++#define QDMA_DESC_LEN_MASK GENMASK(15, 0) ++/* DATA */ ++#define QDMA_DESC_NEXT_ID_MASK GENMASK(15, 0) ++/* TX MSG0 */ ++#define QDMA_ETH_TXMSG_MIC_IDX_MASK BIT(30) ++#define QDMA_ETH_TXMSG_SP_TAG_MASK GENMASK(29, 14) ++#define QDMA_ETH_TXMSG_ICO_MASK BIT(13) ++#define QDMA_ETH_TXMSG_UCO_MASK BIT(12) ++#define QDMA_ETH_TXMSG_TCO_MASK BIT(11) ++#define QDMA_ETH_TXMSG_TSO_MASK BIT(10) ++#define QDMA_ETH_TXMSG_FAST_MASK BIT(9) ++#define QDMA_ETH_TXMSG_OAM_MASK BIT(8) ++#define QDMA_ETH_TXMSG_CHAN_MASK GENMASK(7, 3) ++#define QDMA_ETH_TXMSG_QUEUE_MASK GENMASK(2, 0) ++/* TX MSG1 */ ++#define QDMA_ETH_TXMSG_NO_DROP BIT(31) ++#define QDMA_ETH_TXMSG_METER_MASK GENMASK(30, 24) /* 0x7f no meters */ ++#define QDMA_ETH_TXMSG_FPORT_MASK GENMASK(23, 20) ++#define QDMA_ETH_TXMSG_NBOQ_MASK GENMASK(19, 15) ++#define QDMA_ETH_TXMSG_HWF_MASK BIT(14) ++#define QDMA_ETH_TXMSG_HOP_MASK BIT(13) ++#define QDMA_ETH_TXMSG_PTP_MASK BIT(12) ++#define QDMA_ETH_TXMSG_ACNT_G1_MASK GENMASK(10, 6) /* 0x1f do not count */ ++#define QDMA_ETH_TXMSG_ACNT_G0_MASK GENMASK(5, 0) /* 0x3f do not count */ ++ ++/* RX MSG1 */ ++#define QDMA_ETH_RXMSG_DEI_MASK BIT(31) ++#define QDMA_ETH_RXMSG_IP6_MASK BIT(30) ++#define QDMA_ETH_RXMSG_IP4_MASK BIT(29) ++#define QDMA_ETH_RXMSG_IP4F_MASK BIT(28) ++#define QDMA_ETH_RXMSG_L4_VALID_MASK BIT(27) ++#define QDMA_ETH_RXMSG_L4F_MASK BIT(26) ++#define QDMA_ETH_RXMSG_SPORT_MASK GENMASK(25, 21) ++#define QDMA_ETH_RXMSG_CRSN_MASK GENMASK(20, 16) ++#define QDMA_ETH_RXMSG_PPE_ENTRY_MASK GENMASK(15, 0) ++ ++struct airoha_qdma_desc { ++ __le32 rsv; ++ __le32 ctrl; ++ __le32 addr; ++ __le32 data; ++ __le32 msg0; ++ __le32 msg1; ++ __le32 msg2; ++ __le32 msg3; ++}; ++ ++/* CTRL0 */ ++#define QDMA_FWD_DESC_CTX_MASK BIT(31) ++#define QDMA_FWD_DESC_RING_MASK GENMASK(30, 28) ++#define QDMA_FWD_DESC_IDX_MASK GENMASK(27, 16) ++#define QDMA_FWD_DESC_LEN_MASK GENMASK(15, 0) ++/* CTRL1 */ ++#define QDMA_FWD_DESC_FIRST_IDX_MASK GENMASK(15, 0) ++/* CTRL2 */ ++#define QDMA_FWD_DESC_MORE_PKT_NUM_MASK GENMASK(2, 0) ++ ++struct airoha_qdma_fwd_desc { ++ __le32 addr; ++ __le32 ctrl0; ++ __le32 ctrl1; ++ __le32 ctrl2; ++ __le32 msg0; ++ __le32 msg1; ++ __le32 rsv0; ++ __le32 rsv1; ++}; ++ ++#endif /* AIROHA_REGS_H */ diff --git a/lede/target/linux/airoha/patches-6.12/048-05-v6.15-net-airoha-Move-DSA-tag-in-DMA-descriptor.patch b/lede/target/linux/airoha/patches-6.12/048-05-v6.15-net-airoha-Move-DSA-tag-in-DMA-descriptor.patch new file mode 100644 index 0000000000..45f5fe327d --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/048-05-v6.15-net-airoha-Move-DSA-tag-in-DMA-descriptor.patch @@ -0,0 +1,287 @@ +From af3cf757d5c99011b9b94ea8d78aeaccc0153fdc Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 28 Feb 2025 11:54:13 +0100 +Subject: [PATCH 05/15] net: airoha: Move DSA tag in DMA descriptor + +Packet Processor Engine (PPE) module reads DSA tags from the DMA descriptor +and requires untagged DSA packets to properly parse them. Move DSA tag +in the DMA descriptor on TX side and read DSA tag from DMA descriptor +on RX side. In order to avoid skb reallocation, store tag in skb_dst on +RX side. +This is a preliminary patch to enable netfilter flowtable hw offloading +on EN7581 SoC. + +Tested-by: Sayantan Nandy +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 125 ++++++++++++++++++++-- + drivers/net/ethernet/airoha/airoha_eth.h | 7 ++ + drivers/net/ethernet/airoha/airoha_regs.h | 2 + + 3 files changed, 128 insertions(+), 6 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -656,6 +657,7 @@ static int airoha_qdma_rx_process(struct + struct airoha_qdma_desc *desc = &q->desc[q->tail]; + dma_addr_t dma_addr = le32_to_cpu(desc->addr); + u32 desc_ctrl = le32_to_cpu(desc->ctrl); ++ struct airoha_gdm_port *port; + struct sk_buff *skb; + int len, p; + +@@ -683,6 +685,7 @@ static int airoha_qdma_rx_process(struct + continue; + } + ++ port = eth->ports[p]; + skb = napi_build_skb(e->buf, q->buf_size); + if (!skb) { + page_pool_put_full_page(q->page_pool, +@@ -694,10 +697,26 @@ static int airoha_qdma_rx_process(struct + skb_reserve(skb, 2); + __skb_put(skb, len); + skb_mark_for_recycle(skb); +- skb->dev = eth->ports[p]->dev; ++ skb->dev = port->dev; + skb->protocol = eth_type_trans(skb, skb->dev); + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb_record_rx_queue(skb, qid); ++ ++ if (netdev_uses_dsa(port->dev)) { ++ /* PPE module requires untagged packets to work ++ * properly and it provides DSA port index via the ++ * DMA descriptor. Report DSA tag to the DSA stack ++ * via skb dst info. ++ */ ++ u32 sptag = FIELD_GET(QDMA_ETH_RXMSG_SPTAG, ++ le32_to_cpu(desc->msg0)); ++ ++ if (sptag < ARRAY_SIZE(port->dsa_meta) && ++ port->dsa_meta[sptag]) ++ skb_dst_set_noref(skb, ++ &port->dsa_meta[sptag]->dst); ++ } ++ + napi_gro_receive(&q->napi, skb); + + done++; +@@ -1636,25 +1655,76 @@ static u16 airoha_dev_select_queue(struc + return queue < dev->num_tx_queues ? queue : 0; + } + ++static u32 airoha_get_dsa_tag(struct sk_buff *skb, struct net_device *dev) ++{ ++#if IS_ENABLED(CONFIG_NET_DSA) ++ struct ethhdr *ehdr; ++ struct dsa_port *dp; ++ u8 xmit_tpid; ++ u16 tag; ++ ++ if (!netdev_uses_dsa(dev)) ++ return 0; ++ ++ dp = dev->dsa_ptr; ++ if (IS_ERR(dp)) ++ return 0; ++ ++ if (dp->tag_ops->proto != DSA_TAG_PROTO_MTK) ++ return 0; ++ ++ if (skb_cow_head(skb, 0)) ++ return 0; ++ ++ ehdr = (struct ethhdr *)skb->data; ++ tag = be16_to_cpu(ehdr->h_proto); ++ xmit_tpid = tag >> 8; ++ ++ switch (xmit_tpid) { ++ case MTK_HDR_XMIT_TAGGED_TPID_8100: ++ ehdr->h_proto = cpu_to_be16(ETH_P_8021Q); ++ tag &= ~(MTK_HDR_XMIT_TAGGED_TPID_8100 << 8); ++ break; ++ case MTK_HDR_XMIT_TAGGED_TPID_88A8: ++ ehdr->h_proto = cpu_to_be16(ETH_P_8021AD); ++ tag &= ~(MTK_HDR_XMIT_TAGGED_TPID_88A8 << 8); ++ break; ++ default: ++ /* PPE module requires untagged DSA packets to work properly, ++ * so move DSA tag to DMA descriptor. ++ */ ++ memmove(skb->data + MTK_HDR_LEN, skb->data, 2 * ETH_ALEN); ++ __skb_pull(skb, MTK_HDR_LEN); ++ break; ++ } ++ ++ return tag; ++#else ++ return 0; ++#endif ++} ++ + static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, + struct net_device *dev) + { + struct airoha_gdm_port *port = netdev_priv(dev); +- u32 nr_frags = 1 + skb_shinfo(skb)->nr_frags; +- u32 msg0, msg1, len = skb_headlen(skb); + struct airoha_qdma *qdma = port->qdma; ++ u32 nr_frags, tag, msg0, msg1, len; + struct netdev_queue *txq; + struct airoha_queue *q; +- void *data = skb->data; ++ void *data; + int i, qid; + u16 index; + u8 fport; + + qid = skb_get_queue_mapping(skb) % ARRAY_SIZE(qdma->q_tx); ++ tag = airoha_get_dsa_tag(skb, dev); ++ + msg0 = FIELD_PREP(QDMA_ETH_TXMSG_CHAN_MASK, + qid / AIROHA_NUM_QOS_QUEUES) | + FIELD_PREP(QDMA_ETH_TXMSG_QUEUE_MASK, +- qid % AIROHA_NUM_QOS_QUEUES); ++ qid % AIROHA_NUM_QOS_QUEUES) | ++ FIELD_PREP(QDMA_ETH_TXMSG_SP_TAG_MASK, tag); + if (skb->ip_summed == CHECKSUM_PARTIAL) + msg0 |= FIELD_PREP(QDMA_ETH_TXMSG_TCO_MASK, 1) | + FIELD_PREP(QDMA_ETH_TXMSG_UCO_MASK, 1) | +@@ -1685,6 +1755,8 @@ static netdev_tx_t airoha_dev_xmit(struc + spin_lock_bh(&q->lock); + + txq = netdev_get_tx_queue(dev, qid); ++ nr_frags = 1 + skb_shinfo(skb)->nr_frags; ++ + if (q->queued + nr_frags > q->ndesc) { + /* not enough space in the queue */ + netif_tx_stop_queue(txq); +@@ -1692,7 +1764,10 @@ static netdev_tx_t airoha_dev_xmit(struc + return NETDEV_TX_BUSY; + } + ++ len = skb_headlen(skb); ++ data = skb->data; + index = q->head; ++ + for (i = 0; i < nr_frags; i++) { + struct airoha_qdma_desc *desc = &q->desc[index]; + struct airoha_queue_entry *e = &q->entry[index]; +@@ -2223,6 +2298,37 @@ static const struct ethtool_ops airoha_e + .get_rmon_stats = airoha_ethtool_get_rmon_stats, + }; + ++static int airoha_metadata_dst_alloc(struct airoha_gdm_port *port) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(port->dsa_meta); i++) { ++ struct metadata_dst *md_dst; ++ ++ md_dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, ++ GFP_KERNEL); ++ if (!md_dst) ++ return -ENOMEM; ++ ++ md_dst->u.port_info.port_id = i; ++ port->dsa_meta[i] = md_dst; ++ } ++ ++ return 0; ++} ++ ++static void airoha_metadata_dst_free(struct airoha_gdm_port *port) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(port->dsa_meta); i++) { ++ if (!port->dsa_meta[i]) ++ continue; ++ ++ metadata_dst_free(port->dsa_meta[i]); ++ } ++} ++ + static int airoha_alloc_gdm_port(struct airoha_eth *eth, struct device_node *np) + { + const __be32 *id_ptr = of_get_property(np, "reg", NULL); +@@ -2295,6 +2401,10 @@ static int airoha_alloc_gdm_port(struct + port->id = id; + eth->ports[index] = port; + ++ err = airoha_metadata_dst_alloc(port); ++ if (err) ++ return err; ++ + return register_netdev(dev); + } + +@@ -2387,8 +2497,10 @@ error_hw_cleanup: + for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { + struct airoha_gdm_port *port = eth->ports[i]; + +- if (port && port->dev->reg_state == NETREG_REGISTERED) ++ if (port && port->dev->reg_state == NETREG_REGISTERED) { + unregister_netdev(port->dev); ++ airoha_metadata_dst_free(port); ++ } + } + free_netdev(eth->napi_dev); + platform_set_drvdata(pdev, NULL); +@@ -2414,6 +2526,7 @@ static void airoha_remove(struct platfor + + airoha_dev_stop(port->dev); + unregister_netdev(port->dev); ++ airoha_metadata_dst_free(port); + } + free_netdev(eth->napi_dev); + +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -15,6 +15,7 @@ + + #define AIROHA_MAX_NUM_GDM_PORTS 1 + #define AIROHA_MAX_NUM_QDMA 2 ++#define AIROHA_MAX_DSA_PORTS 7 + #define AIROHA_MAX_NUM_RSTS 3 + #define AIROHA_MAX_NUM_XSI_RSTS 5 + #define AIROHA_MAX_MTU 2000 +@@ -43,6 +44,10 @@ + #define QDMA_METER_IDX(_n) ((_n) & 0xff) + #define QDMA_METER_GROUP(_n) (((_n) >> 8) & 0x3) + ++#define MTK_HDR_LEN 4 ++#define MTK_HDR_XMIT_TAGGED_TPID_8100 1 ++#define MTK_HDR_XMIT_TAGGED_TPID_88A8 2 ++ + enum { + QDMA_INT_REG_IDX0, + QDMA_INT_REG_IDX1, +@@ -231,6 +236,8 @@ struct airoha_gdm_port { + /* qos stats counters */ + u64 cpu_tx_packets; + u64 fwd_tx_packets; ++ ++ struct metadata_dst *dsa_meta[AIROHA_MAX_DSA_PORTS]; + }; + + struct airoha_eth { +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -624,6 +624,8 @@ + #define QDMA_ETH_TXMSG_ACNT_G1_MASK GENMASK(10, 6) /* 0x1f do not count */ + #define QDMA_ETH_TXMSG_ACNT_G0_MASK GENMASK(5, 0) /* 0x3f do not count */ + ++/* RX MSG0 */ ++#define QDMA_ETH_RXMSG_SPTAG GENMASK(21, 14) + /* RX MSG1 */ + #define QDMA_ETH_RXMSG_DEI_MASK BIT(31) + #define QDMA_ETH_RXMSG_IP6_MASK BIT(30) diff --git a/lede/target/linux/airoha/patches-6.12/048-06-v6.15-net-dsa-mt7530-Enable-Rx-sptag-for-EN7581-SoC.patch b/lede/target/linux/airoha/patches-6.12/048-06-v6.15-net-dsa-mt7530-Enable-Rx-sptag-for-EN7581-SoC.patch new file mode 100644 index 0000000000..27956d553a --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/048-06-v6.15-net-dsa-mt7530-Enable-Rx-sptag-for-EN7581-SoC.patch @@ -0,0 +1,46 @@ +From ab667db1e6014634c6607ebdddc16c1b8394a935 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 28 Feb 2025 11:54:14 +0100 +Subject: [PATCH 06/15] net: dsa: mt7530: Enable Rx sptag for EN7581 SoC + +Packet Processor Engine (PPE) module used for hw acceleration on EN7581 +mac block, in order to properly parse packets, requires DSA untagged +packets on TX side and read DSA tag from DMA descriptor on RX side. +For this reason, enable RX Special Tag (SPTAG) for EN7581 SoC. +This is a preliminary patch to enable netfilter flowtable hw offloading +on EN7581 SoC. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 5 +++++ + drivers/net/dsa/mt7530.h | 4 ++++ + 2 files changed, 9 insertions(+) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2588,6 +2588,11 @@ mt7531_setup_common(struct dsa_switch *d + /* Allow mirroring frames received on the local port (monitor port). */ + mt7530_set(priv, MT753X_AGC, LOCAL_EN); + ++ /* Enable Special Tag for rx frames */ ++ if (priv->id == ID_EN7581) ++ mt7530_write(priv, MT753X_CPORT_SPTAG_CFG, ++ CPORT_SW2FE_STAG_EN | CPORT_FE2SW_STAG_EN); ++ + /* Flush the FDB table */ + ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL); + if (ret < 0) +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -615,6 +615,10 @@ enum mt7531_xtal_fsel { + #define MT7531_GPIO12_RG_RXD3_MASK GENMASK(19, 16) + #define MT7531_EXT_P_MDIO_12 (2 << 16) + ++#define MT753X_CPORT_SPTAG_CFG 0x7c10 ++#define CPORT_SW2FE_STAG_EN BIT(1) ++#define CPORT_FE2SW_STAG_EN BIT(0) ++ + /* Registers for LED GPIO control (MT7530 only) + * All registers follow this pattern: + * [ 2: 0] port 0 diff --git a/lede/target/linux/airoha/patches-6.12/048-07-v6.15-net-airoha-Enable-support-for-multiple-net_devices.patch b/lede/target/linux/airoha/patches-6.12/048-07-v6.15-net-airoha-Enable-support-for-multiple-net_devices.patch new file mode 100644 index 0000000000..4b78255ba3 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/048-07-v6.15-net-airoha-Enable-support-for-multiple-net_devices.patch @@ -0,0 +1,144 @@ +From 80369686737fe07c233a1152da0b84372dabdcd6 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 28 Feb 2025 11:54:15 +0100 +Subject: [PATCH 07/15] net: airoha: Enable support for multiple net_devices + +In the current codebase airoha_eth driver supports just a single +net_device connected to the Packet Switch Engine (PSE) lan port (GDM1). +As shown in commit 23020f049327 ("net: airoha: Introduce ethernet +support for EN7581 SoC"), PSE can switch packets between four GDM ports. +Enable the capability to create a net_device for each GDM port of the +PSE module. Moreover, since the QDMA blocks can be shared between +net_devices, do not stop TX/RX DMA in airoha_dev_stop() if there are +active net_devices for this QDMA block. +This is a preliminary patch to enable flowtable hw offloading for EN7581 +SoC. + +Co-developed-by: Christian Marangi +Signed-off-by: Christian Marangi +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 35 ++++++++++++++---------- + drivers/net/ethernet/airoha/airoha_eth.h | 4 ++- + 2 files changed, 24 insertions(+), 15 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1562,6 +1562,7 @@ static int airoha_dev_open(struct net_de + airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG, + GLOBAL_CFG_TX_DMA_EN_MASK | + GLOBAL_CFG_RX_DMA_EN_MASK); ++ atomic_inc(&qdma->users); + + return 0; + } +@@ -1577,16 +1578,20 @@ static int airoha_dev_stop(struct net_de + if (err) + return err; + +- airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG, +- GLOBAL_CFG_TX_DMA_EN_MASK | +- GLOBAL_CFG_RX_DMA_EN_MASK); ++ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) ++ netdev_tx_reset_subqueue(dev, i); + +- for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { +- if (!qdma->q_tx[i].ndesc) +- continue; ++ if (atomic_dec_and_test(&qdma->users)) { ++ airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG, ++ GLOBAL_CFG_TX_DMA_EN_MASK | ++ GLOBAL_CFG_RX_DMA_EN_MASK); ++ ++ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { ++ if (!qdma->q_tx[i].ndesc) ++ continue; + +- airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]); +- netdev_tx_reset_subqueue(dev, i); ++ airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]); ++ } + } + + return 0; +@@ -2329,13 +2334,14 @@ static void airoha_metadata_dst_free(str + } + } + +-static int airoha_alloc_gdm_port(struct airoha_eth *eth, struct device_node *np) ++static int airoha_alloc_gdm_port(struct airoha_eth *eth, ++ struct device_node *np, int index) + { + const __be32 *id_ptr = of_get_property(np, "reg", NULL); + struct airoha_gdm_port *port; + struct airoha_qdma *qdma; + struct net_device *dev; +- int err, index; ++ int err, p; + u32 id; + + if (!id_ptr) { +@@ -2344,14 +2350,14 @@ static int airoha_alloc_gdm_port(struct + } + + id = be32_to_cpup(id_ptr); +- index = id - 1; ++ p = id - 1; + + if (!id || id > ARRAY_SIZE(eth->ports)) { + dev_err(eth->dev, "invalid gdm port id: %d\n", id); + return -EINVAL; + } + +- if (eth->ports[index]) { ++ if (eth->ports[p]) { + dev_err(eth->dev, "duplicate gdm port id: %d\n", id); + return -EINVAL; + } +@@ -2399,7 +2405,7 @@ static int airoha_alloc_gdm_port(struct + port->qdma = qdma; + port->dev = dev; + port->id = id; +- eth->ports[index] = port; ++ eth->ports[p] = port; + + err = airoha_metadata_dst_alloc(port); + if (err) +@@ -2471,6 +2477,7 @@ static int airoha_probe(struct platform_ + for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) + airoha_qdma_start_napi(ð->qdma[i]); + ++ i = 0; + for_each_child_of_node(pdev->dev.of_node, np) { + if (!of_device_is_compatible(np, "airoha,eth-mac")) + continue; +@@ -2478,7 +2485,7 @@ static int airoha_probe(struct platform_ + if (!of_device_is_available(np)) + continue; + +- err = airoha_alloc_gdm_port(eth, np); ++ err = airoha_alloc_gdm_port(eth, np, i++); + if (err) { + of_node_put(np); + goto error_napi_stop; +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -13,7 +13,7 @@ + #include + #include + +-#define AIROHA_MAX_NUM_GDM_PORTS 1 ++#define AIROHA_MAX_NUM_GDM_PORTS 4 + #define AIROHA_MAX_NUM_QDMA 2 + #define AIROHA_MAX_DSA_PORTS 7 + #define AIROHA_MAX_NUM_RSTS 3 +@@ -212,6 +212,8 @@ struct airoha_qdma { + u32 irqmask[QDMA_INT_REG_MAX]; + int irq; + ++ atomic_t users; ++ + struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ]; + + struct airoha_queue q_tx[AIROHA_NUM_TX_RING]; diff --git a/lede/target/linux/airoha/patches-6.12/048-08-v6.15-net-airoha-Move-REG_GDM_FWD_CFG-initialization-in-ai.patch b/lede/target/linux/airoha/patches-6.12/048-08-v6.15-net-airoha-Move-REG_GDM_FWD_CFG-initialization-in-ai.patch new file mode 100644 index 0000000000..c4079f45d4 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/048-08-v6.15-net-airoha-Move-REG_GDM_FWD_CFG-initialization-in-ai.patch @@ -0,0 +1,77 @@ +From 67fde5d58cd43d129a979e918ec9cd5d2e2fbcfb Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 28 Feb 2025 11:54:16 +0100 +Subject: [PATCH 08/15] net: airoha: Move REG_GDM_FWD_CFG() initialization in + airoha_dev_init() + +Move REG_GDM_FWD_CFG() register initialization in airoha_dev_init +routine. Moreover, always send traffic PPE module in order to be +processed by hw accelerator. +This is a preliminary patch to enable netfilter flowtable hw offloading +on EN7581 SoC. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 14 ++++---------- + 1 file changed, 4 insertions(+), 10 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -107,25 +107,20 @@ static void airoha_set_gdm_port_fwd_cfg( + + static int airoha_set_gdm_port(struct airoha_eth *eth, int port, bool enable) + { +- u32 val = enable ? FE_PSE_PORT_PPE1 : FE_PSE_PORT_DROP; +- u32 vip_port, cfg_addr; ++ u32 vip_port; + + switch (port) { + case XSI_PCIE0_PORT: + vip_port = XSI_PCIE0_VIP_PORT_MASK; +- cfg_addr = REG_GDM_FWD_CFG(3); + break; + case XSI_PCIE1_PORT: + vip_port = XSI_PCIE1_VIP_PORT_MASK; +- cfg_addr = REG_GDM_FWD_CFG(3); + break; + case XSI_USB_PORT: + vip_port = XSI_USB_VIP_PORT_MASK; +- cfg_addr = REG_GDM_FWD_CFG(4); + break; + case XSI_ETH_PORT: + vip_port = XSI_ETH_VIP_PORT_MASK; +- cfg_addr = REG_GDM_FWD_CFG(4); + break; + default: + return -EINVAL; +@@ -139,8 +134,6 @@ static int airoha_set_gdm_port(struct ai + airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, vip_port); + } + +- airoha_set_gdm_port_fwd_cfg(eth, cfg_addr, val); +- + return 0; + } + +@@ -177,8 +170,6 @@ static void airoha_fe_maccr_init(struct + airoha_fe_set(eth, REG_GDM_FWD_CFG(p), + GDM_TCP_CKSUM | GDM_UDP_CKSUM | GDM_IP4_CKSUM | + GDM_DROP_CRC_ERR); +- airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(p), +- FE_PSE_PORT_CDM1); + airoha_fe_rmw(eth, REG_GDM_LEN_CFG(p), + GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, + FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | +@@ -1614,8 +1605,11 @@ static int airoha_dev_set_macaddr(struct + static int airoha_dev_init(struct net_device *dev) + { + struct airoha_gdm_port *port = netdev_priv(dev); ++ struct airoha_eth *eth = port->qdma->eth; + + airoha_set_macaddr(port, dev->dev_addr); ++ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), ++ FE_PSE_PORT_PPE1); + + return 0; + } diff --git a/lede/target/linux/airoha/patches-6.12/048-09-v6.15-net-airoha-Rename-airoha_set_gdm_port_fwd_cfg-in-air.patch b/lede/target/linux/airoha/patches-6.12/048-09-v6.15-net-airoha-Rename-airoha_set_gdm_port_fwd_cfg-in-air.patch new file mode 100644 index 0000000000..3edeacfbd0 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/048-09-v6.15-net-airoha-Rename-airoha_set_gdm_port_fwd_cfg-in-air.patch @@ -0,0 +1,120 @@ +From c28b8375f6d02ef3b5e8c51234cc3f6d47d9fb7f Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 28 Feb 2025 11:54:17 +0100 +Subject: [PATCH 09/15] net: airoha: Rename airoha_set_gdm_port_fwd_cfg() in + airoha_set_vip_for_gdm_port() + +Rename airoha_set_gdm_port() in airoha_set_vip_for_gdm_port(). +Get rid of airoha_set_gdm_ports routine. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 49 ++++++------------------ + drivers/net/ethernet/airoha/airoha_eth.h | 8 ---- + 2 files changed, 11 insertions(+), 46 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -105,25 +105,23 @@ static void airoha_set_gdm_port_fwd_cfg( + FIELD_PREP(GDM_UCFQ_MASK, val)); + } + +-static int airoha_set_gdm_port(struct airoha_eth *eth, int port, bool enable) ++static int airoha_set_vip_for_gdm_port(struct airoha_gdm_port *port, ++ bool enable) + { ++ struct airoha_eth *eth = port->qdma->eth; + u32 vip_port; + +- switch (port) { +- case XSI_PCIE0_PORT: ++ switch (port->id) { ++ case 3: ++ /* FIXME: handle XSI_PCIE1_PORT */ + vip_port = XSI_PCIE0_VIP_PORT_MASK; + break; +- case XSI_PCIE1_PORT: +- vip_port = XSI_PCIE1_VIP_PORT_MASK; +- break; +- case XSI_USB_PORT: +- vip_port = XSI_USB_VIP_PORT_MASK; +- break; +- case XSI_ETH_PORT: ++ case 4: ++ /* FIXME: handle XSI_USB_PORT */ + vip_port = XSI_ETH_VIP_PORT_MASK; + break; + default: +- return -EINVAL; ++ return 0; + } + + if (enable) { +@@ -137,31 +135,6 @@ static int airoha_set_gdm_port(struct ai + return 0; + } + +-static int airoha_set_gdm_ports(struct airoha_eth *eth, bool enable) +-{ +- const int port_list[] = { +- XSI_PCIE0_PORT, +- XSI_PCIE1_PORT, +- XSI_USB_PORT, +- XSI_ETH_PORT +- }; +- int i, err; +- +- for (i = 0; i < ARRAY_SIZE(port_list); i++) { +- err = airoha_set_gdm_port(eth, port_list[i], enable); +- if (err) +- goto error; +- } +- +- return 0; +- +-error: +- for (i--; i >= 0; i--) +- airoha_set_gdm_port(eth, port_list[i], false); +- +- return err; +-} +- + static void airoha_fe_maccr_init(struct airoha_eth *eth) + { + int p; +@@ -1539,7 +1512,7 @@ static int airoha_dev_open(struct net_de + int err; + + netif_tx_start_all_queues(dev); +- err = airoha_set_gdm_ports(qdma->eth, true); ++ err = airoha_set_vip_for_gdm_port(port, true); + if (err) + return err; + +@@ -1565,7 +1538,7 @@ static int airoha_dev_stop(struct net_de + int i, err; + + netif_tx_disable(dev); +- err = airoha_set_gdm_ports(qdma->eth, false); ++ err = airoha_set_vip_for_gdm_port(port, false); + if (err) + return err; + +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -58,14 +58,6 @@ enum { + }; + + enum { +- XSI_PCIE0_PORT, +- XSI_PCIE1_PORT, +- XSI_USB_PORT, +- XSI_AE_PORT, +- XSI_ETH_PORT, +-}; +- +-enum { + XSI_PCIE0_VIP_PORT_MASK = BIT(22), + XSI_PCIE1_VIP_PORT_MASK = BIT(23), + XSI_USB_VIP_PORT_MASK = BIT(25), diff --git a/lede/target/linux/airoha/patches-6.12/048-12-v6.15-net-airoha-Introduce-Airoha-NPU-support.patch b/lede/target/linux/airoha/patches-6.12/048-12-v6.15-net-airoha-Introduce-Airoha-NPU-support.patch new file mode 100644 index 0000000000..41c5622304 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/048-12-v6.15-net-airoha-Introduce-Airoha-NPU-support.patch @@ -0,0 +1,627 @@ +From 23290c7bc190def4e1ca61610992d9b7c32e33f3 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 28 Feb 2025 11:54:20 +0100 +Subject: [PATCH 12/15] net: airoha: Introduce Airoha NPU support + +Packet Processor Engine (PPE) module available on EN7581 SoC populates +the PPE table with 5-tuples flower rules learned from traffic forwarded +between the GDM ports connected to the Packet Switch Engine (PSE) module. +The airoha_eth driver can enable hw acceleration of learned 5-tuples +rules if the user configure them in netfilter flowtable (netfilter +flowtable support will be added with subsequent patches). +airoha_eth driver configures and collects data from the PPE module via a +Network Processor Unit (NPU) RISC-V module available on the EN7581 SoC. +Introduce basic support for Airoha NPU module. + +Tested-by: Sayantan Nandy +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/Kconfig | 9 + + drivers/net/ethernet/airoha/Makefile | 1 + + drivers/net/ethernet/airoha/airoha_eth.h | 2 + + drivers/net/ethernet/airoha/airoha_npu.c | 520 +++++++++++++++++++++++ + drivers/net/ethernet/airoha/airoha_npu.h | 34 ++ + 5 files changed, 566 insertions(+) + create mode 100644 drivers/net/ethernet/airoha/airoha_npu.c + create mode 100644 drivers/net/ethernet/airoha/airoha_npu.h + +--- a/drivers/net/ethernet/airoha/Kconfig ++++ b/drivers/net/ethernet/airoha/Kconfig +@@ -7,9 +7,18 @@ config NET_VENDOR_AIROHA + + if NET_VENDOR_AIROHA + ++config NET_AIROHA_NPU ++ tristate "Airoha NPU support" ++ select WANT_DEV_COREDUMP ++ select REGMAP_MMIO ++ help ++ This driver supports Airoha Network Processor (NPU) available ++ on the Airoha Soc family. ++ + config NET_AIROHA + tristate "Airoha SoC Gigabit Ethernet support" + depends on NET_DSA || !NET_DSA ++ select NET_AIROHA_NPU + select PAGE_POOL + help + This driver supports the gigabit ethernet MACs in the +--- a/drivers/net/ethernet/airoha/Makefile ++++ b/drivers/net/ethernet/airoha/Makefile +@@ -4,3 +4,4 @@ + # + + obj-$(CONFIG_NET_AIROHA) += airoha_eth.o ++obj-$(CONFIG_NET_AIROHA_NPU) += airoha_npu.o +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -240,6 +240,8 @@ struct airoha_eth { + unsigned long state; + void __iomem *fe_regs; + ++ struct airoha_npu __rcu *npu; ++ + struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS]; + struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS]; + +--- /dev/null ++++ b/drivers/net/ethernet/airoha/airoha_npu.c +@@ -0,0 +1,520 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2025 AIROHA Inc ++ * Author: Lorenzo Bianconi ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "airoha_npu.h" ++ ++#define NPU_EN7581_FIRMWARE_DATA "airoha/en7581_npu_data.bin" ++#define NPU_EN7581_FIRMWARE_RV32 "airoha/en7581_npu_rv32.bin" ++#define NPU_EN7581_FIRMWARE_RV32_MAX_SIZE 0x200000 ++#define NPU_EN7581_FIRMWARE_DATA_MAX_SIZE 0x10000 ++#define NPU_DUMP_SIZE 512 ++ ++#define REG_NPU_LOCAL_SRAM 0x0 ++ ++#define NPU_PC_BASE_ADDR 0x305000 ++#define REG_PC_DBG(_n) (0x305000 + ((_n) * 0x100)) ++ ++#define NPU_CLUSTER_BASE_ADDR 0x306000 ++ ++#define REG_CR_BOOT_TRIGGER (NPU_CLUSTER_BASE_ADDR + 0x000) ++#define REG_CR_BOOT_CONFIG (NPU_CLUSTER_BASE_ADDR + 0x004) ++#define REG_CR_BOOT_BASE(_n) (NPU_CLUSTER_BASE_ADDR + 0x020 + ((_n) << 2)) ++ ++#define NPU_MBOX_BASE_ADDR 0x30c000 ++ ++#define REG_CR_MBOX_INT_STATUS (NPU_MBOX_BASE_ADDR + 0x000) ++#define MBOX_INT_STATUS_MASK BIT(8) ++ ++#define REG_CR_MBOX_INT_MASK(_n) (NPU_MBOX_BASE_ADDR + 0x004 + ((_n) << 2)) ++#define REG_CR_MBQ0_CTRL(_n) (NPU_MBOX_BASE_ADDR + 0x030 + ((_n) << 2)) ++#define REG_CR_MBQ8_CTRL(_n) (NPU_MBOX_BASE_ADDR + 0x0b0 + ((_n) << 2)) ++#define REG_CR_NPU_MIB(_n) (NPU_MBOX_BASE_ADDR + 0x140 + ((_n) << 2)) ++ ++#define NPU_TIMER_BASE_ADDR 0x310100 ++#define REG_WDT_TIMER_CTRL(_n) (NPU_TIMER_BASE_ADDR + ((_n) * 0x100)) ++#define WDT_EN_MASK BIT(25) ++#define WDT_INTR_MASK BIT(21) ++ ++enum { ++ NPU_OP_SET = 1, ++ NPU_OP_SET_NO_WAIT, ++ NPU_OP_GET, ++ NPU_OP_GET_NO_WAIT, ++}; ++ ++enum { ++ NPU_FUNC_WIFI, ++ NPU_FUNC_TUNNEL, ++ NPU_FUNC_NOTIFY, ++ NPU_FUNC_DBA, ++ NPU_FUNC_TR471, ++ NPU_FUNC_PPE, ++}; ++ ++enum { ++ NPU_MBOX_ERROR, ++ NPU_MBOX_SUCCESS, ++}; ++ ++enum { ++ PPE_FUNC_SET_WAIT, ++ PPE_FUNC_SET_WAIT_HWNAT_INIT, ++ PPE_FUNC_SET_WAIT_HWNAT_DEINIT, ++ PPE_FUNC_SET_WAIT_API, ++}; ++ ++enum { ++ PPE2_SRAM_SET_ENTRY, ++ PPE_SRAM_SET_ENTRY, ++ PPE_SRAM_SET_VAL, ++ PPE_SRAM_RESET_VAL, ++}; ++ ++enum { ++ QDMA_WAN_ETHER = 1, ++ QDMA_WAN_PON_XDSL, ++}; ++ ++#define MBOX_MSG_FUNC_ID GENMASK(14, 11) ++#define MBOX_MSG_STATIC_BUF BIT(5) ++#define MBOX_MSG_STATUS GENMASK(4, 2) ++#define MBOX_MSG_DONE BIT(1) ++#define MBOX_MSG_WAIT_RSP BIT(0) ++ ++#define PPE_TYPE_L2B_IPV4 2 ++#define PPE_TYPE_L2B_IPV4_IPV6 3 ++ ++struct ppe_mbox_data { ++ u32 func_type; ++ u32 func_id; ++ union { ++ struct { ++ u8 cds; ++ u8 xpon_hal_api; ++ u8 wan_xsi; ++ u8 ct_joyme4; ++ int ppe_type; ++ int wan_mode; ++ int wan_sel; ++ } init_info; ++ struct { ++ int func_id; ++ u32 size; ++ u32 data; ++ } set_info; ++ }; ++}; ++ ++static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id, ++ void *p, int size) ++{ ++ u16 core = 0; /* FIXME */ ++ u32 val, offset = core << 4; ++ dma_addr_t dma_addr; ++ void *addr; ++ int ret; ++ ++ addr = kmemdup(p, size, GFP_ATOMIC); ++ if (!addr) ++ return -ENOMEM; ++ ++ dma_addr = dma_map_single(npu->dev, addr, size, DMA_TO_DEVICE); ++ ret = dma_mapping_error(npu->dev, dma_addr); ++ if (ret) ++ goto out; ++ ++ spin_lock_bh(&npu->cores[core].lock); ++ ++ regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(0) + offset, dma_addr); ++ regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(1) + offset, size); ++ regmap_read(npu->regmap, REG_CR_MBQ0_CTRL(2) + offset, &val); ++ regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(2) + offset, val + 1); ++ val = FIELD_PREP(MBOX_MSG_FUNC_ID, func_id) | MBOX_MSG_WAIT_RSP; ++ regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(3) + offset, val); ++ ++ ret = regmap_read_poll_timeout_atomic(npu->regmap, ++ REG_CR_MBQ0_CTRL(3) + offset, ++ val, (val & MBOX_MSG_DONE), ++ 100, 100 * MSEC_PER_SEC); ++ if (!ret && FIELD_GET(MBOX_MSG_STATUS, val) != NPU_MBOX_SUCCESS) ++ ret = -EINVAL; ++ ++ spin_unlock_bh(&npu->cores[core].lock); ++ ++ dma_unmap_single(npu->dev, dma_addr, size, DMA_TO_DEVICE); ++out: ++ kfree(addr); ++ ++ return ret; ++} ++ ++static int airoha_npu_run_firmware(struct device *dev, void __iomem *base, ++ struct reserved_mem *rmem) ++{ ++ const struct firmware *fw; ++ void __iomem *addr; ++ int ret; ++ ++ ret = request_firmware(&fw, NPU_EN7581_FIRMWARE_RV32, dev); ++ if (ret) ++ return ret == -ENOENT ? -EPROBE_DEFER : ret; ++ ++ if (fw->size > NPU_EN7581_FIRMWARE_RV32_MAX_SIZE) { ++ dev_err(dev, "%s: fw size too overlimit (%zu)\n", ++ NPU_EN7581_FIRMWARE_RV32, fw->size); ++ ret = -E2BIG; ++ goto out; ++ } ++ ++ addr = devm_ioremap(dev, rmem->base, rmem->size); ++ if (!addr) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ memcpy_toio(addr, fw->data, fw->size); ++ release_firmware(fw); ++ ++ ret = request_firmware(&fw, NPU_EN7581_FIRMWARE_DATA, dev); ++ if (ret) ++ return ret == -ENOENT ? -EPROBE_DEFER : ret; ++ ++ if (fw->size > NPU_EN7581_FIRMWARE_DATA_MAX_SIZE) { ++ dev_err(dev, "%s: fw size too overlimit (%zu)\n", ++ NPU_EN7581_FIRMWARE_DATA, fw->size); ++ ret = -E2BIG; ++ goto out; ++ } ++ ++ memcpy_toio(base + REG_NPU_LOCAL_SRAM, fw->data, fw->size); ++out: ++ release_firmware(fw); ++ ++ return ret; ++} ++ ++static irqreturn_t airoha_npu_mbox_handler(int irq, void *npu_instance) ++{ ++ struct airoha_npu *npu = npu_instance; ++ ++ /* clear mbox interrupt status */ ++ regmap_write(npu->regmap, REG_CR_MBOX_INT_STATUS, ++ MBOX_INT_STATUS_MASK); ++ ++ /* acknowledge npu */ ++ regmap_update_bits(npu->regmap, REG_CR_MBQ8_CTRL(3), ++ MBOX_MSG_STATUS | MBOX_MSG_DONE, MBOX_MSG_DONE); ++ ++ return IRQ_HANDLED; ++} ++ ++static void airoha_npu_wdt_work(struct work_struct *work) ++{ ++ struct airoha_npu_core *core; ++ struct airoha_npu *npu; ++ void *dump; ++ u32 val[3]; ++ int c; ++ ++ core = container_of(work, struct airoha_npu_core, wdt_work); ++ npu = core->npu; ++ ++ dump = vzalloc(NPU_DUMP_SIZE); ++ if (!dump) ++ return; ++ ++ c = core - &npu->cores[0]; ++ regmap_bulk_read(npu->regmap, REG_PC_DBG(c), val, ARRAY_SIZE(val)); ++ snprintf(dump, NPU_DUMP_SIZE, "PC: %08x SP: %08x LR: %08x\n", ++ val[0], val[1], val[2]); ++ ++ dev_coredumpv(npu->dev, dump, NPU_DUMP_SIZE, GFP_KERNEL); ++} ++ ++static irqreturn_t airoha_npu_wdt_handler(int irq, void *core_instance) ++{ ++ struct airoha_npu_core *core = core_instance; ++ struct airoha_npu *npu = core->npu; ++ int c = core - &npu->cores[0]; ++ u32 val; ++ ++ regmap_set_bits(npu->regmap, REG_WDT_TIMER_CTRL(c), WDT_INTR_MASK); ++ if (!regmap_read(npu->regmap, REG_WDT_TIMER_CTRL(c), &val) && ++ FIELD_GET(WDT_EN_MASK, val)) ++ schedule_work(&core->wdt_work); ++ ++ return IRQ_HANDLED; ++} ++ ++static int airoha_npu_ppe_init(struct airoha_npu *npu) ++{ ++ struct ppe_mbox_data ppe_data = { ++ .func_type = NPU_OP_SET, ++ .func_id = PPE_FUNC_SET_WAIT_HWNAT_INIT, ++ .init_info = { ++ .ppe_type = PPE_TYPE_L2B_IPV4_IPV6, ++ .wan_mode = QDMA_WAN_ETHER, ++ }, ++ }; ++ ++ return airoha_npu_send_msg(npu, NPU_FUNC_PPE, &ppe_data, ++ sizeof(struct ppe_mbox_data)); ++} ++ ++static int airoha_npu_ppe_deinit(struct airoha_npu *npu) ++{ ++ struct ppe_mbox_data ppe_data = { ++ .func_type = NPU_OP_SET, ++ .func_id = PPE_FUNC_SET_WAIT_HWNAT_DEINIT, ++ }; ++ ++ return airoha_npu_send_msg(npu, NPU_FUNC_PPE, &ppe_data, ++ sizeof(struct ppe_mbox_data)); ++} ++ ++static int airoha_npu_ppe_flush_sram_entries(struct airoha_npu *npu, ++ dma_addr_t foe_addr, ++ int sram_num_entries) ++{ ++ struct ppe_mbox_data ppe_data = { ++ .func_type = NPU_OP_SET, ++ .func_id = PPE_FUNC_SET_WAIT_API, ++ .set_info = { ++ .func_id = PPE_SRAM_RESET_VAL, ++ .data = foe_addr, ++ .size = sram_num_entries, ++ }, ++ }; ++ ++ return airoha_npu_send_msg(npu, NPU_FUNC_PPE, &ppe_data, ++ sizeof(struct ppe_mbox_data)); ++} ++ ++static int airoha_npu_foe_commit_entry(struct airoha_npu *npu, ++ dma_addr_t foe_addr, ++ u32 entry_size, u32 hash, bool ppe2) ++{ ++ struct ppe_mbox_data ppe_data = { ++ .func_type = NPU_OP_SET, ++ .func_id = PPE_FUNC_SET_WAIT_API, ++ .set_info = { ++ .data = foe_addr, ++ .size = entry_size, ++ }, ++ }; ++ int err; ++ ++ ppe_data.set_info.func_id = ppe2 ? PPE2_SRAM_SET_ENTRY ++ : PPE_SRAM_SET_ENTRY; ++ ++ err = airoha_npu_send_msg(npu, NPU_FUNC_PPE, &ppe_data, ++ sizeof(struct ppe_mbox_data)); ++ if (err) ++ return err; ++ ++ ppe_data.set_info.func_id = PPE_SRAM_SET_VAL; ++ ppe_data.set_info.data = hash; ++ ppe_data.set_info.size = sizeof(u32); ++ ++ return airoha_npu_send_msg(npu, NPU_FUNC_PPE, &ppe_data, ++ sizeof(struct ppe_mbox_data)); ++} ++ ++struct airoha_npu *airoha_npu_get(struct device *dev) ++{ ++ struct platform_device *pdev; ++ struct device_node *np; ++ struct airoha_npu *npu; ++ ++ np = of_parse_phandle(dev->of_node, "airoha,npu", 0); ++ if (!np) ++ return ERR_PTR(-ENODEV); ++ ++ pdev = of_find_device_by_node(np); ++ of_node_put(np); ++ ++ if (!pdev) { ++ dev_err(dev, "cannot find device node %s\n", np->name); ++ return ERR_PTR(-ENODEV); ++ } ++ ++ if (!try_module_get(THIS_MODULE)) { ++ dev_err(dev, "failed to get the device driver module\n"); ++ npu = ERR_PTR(-ENODEV); ++ goto error_pdev_put; ++ } ++ ++ npu = platform_get_drvdata(pdev); ++ if (!npu) { ++ npu = ERR_PTR(-ENODEV); ++ goto error_module_put; ++ } ++ ++ if (!device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER)) { ++ dev_err(&pdev->dev, ++ "failed to create device link to consumer %s\n", ++ dev_name(dev)); ++ npu = ERR_PTR(-EINVAL); ++ goto error_module_put; ++ } ++ ++ return npu; ++ ++error_module_put: ++ module_put(THIS_MODULE); ++error_pdev_put: ++ platform_device_put(pdev); ++ ++ return npu; ++} ++EXPORT_SYMBOL_GPL(airoha_npu_get); ++ ++void airoha_npu_put(struct airoha_npu *npu) ++{ ++ module_put(THIS_MODULE); ++ put_device(npu->dev); ++} ++EXPORT_SYMBOL_GPL(airoha_npu_put); ++ ++static const struct of_device_id of_airoha_npu_match[] = { ++ { .compatible = "airoha,en7581-npu" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, of_airoha_npu_match); ++ ++static const struct regmap_config regmap_config = { ++ .name = "npu", ++ .reg_bits = 32, ++ .val_bits = 32, ++ .reg_stride = 4, ++ .disable_locking = true, ++}; ++ ++static int airoha_npu_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct reserved_mem *rmem; ++ struct airoha_npu *npu; ++ struct device_node *np; ++ void __iomem *base; ++ int i, irq, err; ++ ++ base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ npu = devm_kzalloc(dev, sizeof(*npu), GFP_KERNEL); ++ if (!npu) ++ return -ENOMEM; ++ ++ npu->dev = dev; ++ npu->ops.ppe_init = airoha_npu_ppe_init; ++ npu->ops.ppe_deinit = airoha_npu_ppe_deinit; ++ npu->ops.ppe_flush_sram_entries = airoha_npu_ppe_flush_sram_entries; ++ npu->ops.ppe_foe_commit_entry = airoha_npu_foe_commit_entry; ++ ++ npu->regmap = devm_regmap_init_mmio(dev, base, ®map_config); ++ if (IS_ERR(npu->regmap)) ++ return PTR_ERR(npu->regmap); ++ ++ np = of_parse_phandle(dev->of_node, "memory-region", 0); ++ if (!np) ++ return -ENODEV; ++ ++ rmem = of_reserved_mem_lookup(np); ++ of_node_put(np); ++ ++ if (!rmem) ++ return -ENODEV; ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) ++ return irq; ++ ++ err = devm_request_irq(dev, irq, airoha_npu_mbox_handler, ++ IRQF_SHARED, "airoha-npu-mbox", npu); ++ if (err) ++ return err; ++ ++ for (i = 0; i < ARRAY_SIZE(npu->cores); i++) { ++ struct airoha_npu_core *core = &npu->cores[i]; ++ ++ spin_lock_init(&core->lock); ++ core->npu = npu; ++ ++ irq = platform_get_irq(pdev, i + 1); ++ if (irq < 0) ++ return irq; ++ ++ err = devm_request_irq(dev, irq, airoha_npu_wdt_handler, ++ IRQF_SHARED, "airoha-npu-wdt", core); ++ if (err) ++ return err; ++ ++ INIT_WORK(&core->wdt_work, airoha_npu_wdt_work); ++ } ++ ++ err = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); ++ if (err) ++ return err; ++ ++ err = airoha_npu_run_firmware(dev, base, rmem); ++ if (err) ++ return dev_err_probe(dev, err, "failed to run npu firmware\n"); ++ ++ regmap_write(npu->regmap, REG_CR_NPU_MIB(10), ++ rmem->base + NPU_EN7581_FIRMWARE_RV32_MAX_SIZE); ++ regmap_write(npu->regmap, REG_CR_NPU_MIB(11), 0x40000); /* SRAM 256K */ ++ regmap_write(npu->regmap, REG_CR_NPU_MIB(12), 0); ++ regmap_write(npu->regmap, REG_CR_NPU_MIB(21), 1); ++ msleep(100); ++ ++ /* setting booting address */ ++ for (i = 0; i < NPU_NUM_CORES; i++) ++ regmap_write(npu->regmap, REG_CR_BOOT_BASE(i), rmem->base); ++ usleep_range(1000, 2000); ++ ++ /* enable NPU cores */ ++ /* do not start core3 since it is used for WiFi offloading */ ++ regmap_write(npu->regmap, REG_CR_BOOT_CONFIG, 0xf7); ++ regmap_write(npu->regmap, REG_CR_BOOT_TRIGGER, 0x1); ++ msleep(100); ++ ++ platform_set_drvdata(pdev, npu); ++ ++ return 0; ++} ++ ++static void airoha_npu_remove(struct platform_device *pdev) ++{ ++ struct airoha_npu *npu = platform_get_drvdata(pdev); ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(npu->cores); i++) ++ cancel_work_sync(&npu->cores[i].wdt_work); ++} ++ ++static struct platform_driver airoha_npu_driver = { ++ .probe = airoha_npu_probe, ++ .remove_new = airoha_npu_remove, ++ .driver = { ++ .name = "airoha-npu", ++ .of_match_table = of_airoha_npu_match, ++ }, ++}; ++module_platform_driver(airoha_npu_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Lorenzo Bianconi "); ++MODULE_DESCRIPTION("Airoha Network Processor Unit driver"); +--- /dev/null ++++ b/drivers/net/ethernet/airoha/airoha_npu.h +@@ -0,0 +1,34 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2025 AIROHA Inc ++ * Author: Lorenzo Bianconi ++ */ ++ ++#define NPU_NUM_CORES 8 ++ ++struct airoha_npu { ++ struct device *dev; ++ struct regmap *regmap; ++ ++ struct airoha_npu_core { ++ struct airoha_npu *npu; ++ /* protect concurrent npu memory accesses */ ++ spinlock_t lock; ++ struct work_struct wdt_work; ++ } cores[NPU_NUM_CORES]; ++ ++ struct { ++ int (*ppe_init)(struct airoha_npu *npu); ++ int (*ppe_deinit)(struct airoha_npu *npu); ++ int (*ppe_flush_sram_entries)(struct airoha_npu *npu, ++ dma_addr_t foe_addr, ++ int sram_num_entries); ++ int (*ppe_foe_commit_entry)(struct airoha_npu *npu, ++ dma_addr_t foe_addr, ++ u32 entry_size, u32 hash, ++ bool ppe2); ++ } ops; ++}; ++ ++struct airoha_npu *airoha_npu_get(struct device *dev); ++void airoha_npu_put(struct airoha_npu *npu); diff --git a/lede/target/linux/airoha/patches-6.12/048-13-v6.15-net-airoha-Introduce-flowtable-offload-support.patch b/lede/target/linux/airoha/patches-6.12/048-13-v6.15-net-airoha-Introduce-flowtable-offload-support.patch new file mode 100644 index 0000000000..ca7925304e --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/048-13-v6.15-net-airoha-Introduce-flowtable-offload-support.patch @@ -0,0 +1,1481 @@ +From 00a7678310fe3d3f408513e55d9a0b67f0db380f Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 28 Feb 2025 11:54:21 +0100 +Subject: [PATCH 13/15] net: airoha: Introduce flowtable offload support + +Introduce netfilter flowtable integration in order to allow airoha_eth +driver to offload 5-tuple flower rules learned by the PPE module if the +user accelerates them using a nft configuration similar to the one reported +below: + +table inet filter { + flowtable ft { + hook ingress priority filter + devices = { lan1, lan2, lan3, lan4, eth1 } + flags offload; + } + chain forward { + type filter hook forward priority filter; policy accept; + meta l4proto { tcp, udp } flow add @ft + } +} + +Tested-by: Sayantan Nandy +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/Makefile | 3 +- + drivers/net/ethernet/airoha/airoha_eth.c | 60 +- + drivers/net/ethernet/airoha/airoha_eth.h | 250 ++++++ + drivers/net/ethernet/airoha/airoha_ppe.c | 901 ++++++++++++++++++++++ + drivers/net/ethernet/airoha/airoha_regs.h | 107 ++- + 5 files changed, 1314 insertions(+), 7 deletions(-) + create mode 100644 drivers/net/ethernet/airoha/airoha_ppe.c + +--- a/drivers/net/ethernet/airoha/Makefile ++++ b/drivers/net/ethernet/airoha/Makefile +@@ -3,5 +3,6 @@ + # Airoha for the Mediatek SoCs built-in ethernet macs + # + +-obj-$(CONFIG_NET_AIROHA) += airoha_eth.o ++obj-$(CONFIG_NET_AIROHA) += airoha-eth.o ++airoha-eth-y := airoha_eth.o airoha_ppe.o + obj-$(CONFIG_NET_AIROHA_NPU) += airoha_npu.o +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -8,7 +8,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -619,6 +618,7 @@ static int airoha_qdma_rx_process(struct + while (done < budget) { + struct airoha_queue_entry *e = &q->entry[q->tail]; + struct airoha_qdma_desc *desc = &q->desc[q->tail]; ++ u32 hash, reason, msg1 = le32_to_cpu(desc->msg1); + dma_addr_t dma_addr = le32_to_cpu(desc->addr); + u32 desc_ctrl = le32_to_cpu(desc->ctrl); + struct airoha_gdm_port *port; +@@ -681,6 +681,15 @@ static int airoha_qdma_rx_process(struct + &port->dsa_meta[sptag]->dst); + } + ++ hash = FIELD_GET(AIROHA_RXD4_FOE_ENTRY, msg1); ++ if (hash != AIROHA_RXD4_FOE_ENTRY) ++ skb_set_hash(skb, jhash_1word(hash, 0), ++ PKT_HASH_TYPE_L4); ++ ++ reason = FIELD_GET(AIROHA_RXD4_PPE_CPU_REASON, msg1); ++ if (reason == PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) ++ airoha_ppe_check_skb(eth->ppe, hash); ++ + napi_gro_receive(&q->napi, skb); + + done++; +@@ -1301,6 +1310,10 @@ static int airoha_hw_init(struct platfor + return err; + } + ++ err = airoha_ppe_init(eth); ++ if (err) ++ return err; ++ + set_bit(DEV_STATE_INITIALIZED, ð->state); + + return 0; +@@ -2165,6 +2178,47 @@ static int airoha_tc_htb_alloc_leaf_queu + return 0; + } + ++static int airoha_dev_setup_tc_block(struct airoha_gdm_port *port, ++ struct flow_block_offload *f) ++{ ++ flow_setup_cb_t *cb = airoha_ppe_setup_tc_block_cb; ++ static LIST_HEAD(block_cb_list); ++ struct flow_block_cb *block_cb; ++ ++ if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) ++ return -EOPNOTSUPP; ++ ++ f->driver_block_list = &block_cb_list; ++ switch (f->command) { ++ case FLOW_BLOCK_BIND: ++ block_cb = flow_block_cb_lookup(f->block, cb, port->dev); ++ if (block_cb) { ++ flow_block_cb_incref(block_cb); ++ return 0; ++ } ++ block_cb = flow_block_cb_alloc(cb, port->dev, port->dev, NULL); ++ if (IS_ERR(block_cb)) ++ return PTR_ERR(block_cb); ++ ++ flow_block_cb_incref(block_cb); ++ flow_block_cb_add(block_cb, f); ++ list_add_tail(&block_cb->driver_list, &block_cb_list); ++ return 0; ++ case FLOW_BLOCK_UNBIND: ++ block_cb = flow_block_cb_lookup(f->block, cb, port->dev); ++ if (!block_cb) ++ return -ENOENT; ++ ++ if (!flow_block_cb_decref(block_cb)) { ++ flow_block_cb_remove(block_cb, f); ++ list_del(&block_cb->driver_list); ++ } ++ return 0; ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ + static void airoha_tc_remove_htb_queue(struct airoha_gdm_port *port, int queue) + { + struct net_device *dev = port->dev; +@@ -2248,6 +2302,9 @@ static int airoha_dev_tc_setup(struct ne + return airoha_tc_setup_qdisc_ets(port, type_data); + case TC_SETUP_QDISC_HTB: + return airoha_tc_setup_qdisc_htb(port, type_data); ++ case TC_SETUP_BLOCK: ++ case TC_SETUP_FT: ++ return airoha_dev_setup_tc_block(port, type_data); + default: + return -EOPNOTSUPP; + } +@@ -2504,6 +2561,7 @@ static void airoha_remove(struct platfor + } + free_netdev(eth->napi_dev); + ++ airoha_ppe_deinit(eth); + platform_set_drvdata(pdev, NULL); + } + +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + + #define AIROHA_MAX_NUM_GDM_PORTS 4 + #define AIROHA_MAX_NUM_QDMA 2 +@@ -44,6 +45,15 @@ + #define QDMA_METER_IDX(_n) ((_n) & 0xff) + #define QDMA_METER_GROUP(_n) (((_n) >> 8) & 0x3) + ++#define PPE_NUM 2 ++#define PPE1_SRAM_NUM_ENTRIES (8 * 1024) ++#define PPE_SRAM_NUM_ENTRIES (2 * PPE1_SRAM_NUM_ENTRIES) ++#define PPE_DRAM_NUM_ENTRIES (16 * 1024) ++#define PPE_NUM_ENTRIES (PPE_SRAM_NUM_ENTRIES + PPE_DRAM_NUM_ENTRIES) ++#define PPE_HASH_MASK (PPE_NUM_ENTRIES - 1) ++#define PPE_ENTRY_SIZE 80 ++#define PPE_RAM_NUM_ENTRIES_SHIFT(_n) (__ffs((_n) >> 10)) ++ + #define MTK_HDR_LEN 4 + #define MTK_HDR_XMIT_TAGGED_TPID_8100 1 + #define MTK_HDR_XMIT_TAGGED_TPID_88A8 2 +@@ -195,6 +205,224 @@ struct airoha_hw_stats { + u64 rx_len[7]; + }; + ++enum { ++ PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED = 0x0f, ++}; ++ ++enum { ++ AIROHA_FOE_STATE_INVALID, ++ AIROHA_FOE_STATE_UNBIND, ++ AIROHA_FOE_STATE_BIND, ++ AIROHA_FOE_STATE_FIN ++}; ++ ++enum { ++ PPE_PKT_TYPE_IPV4_HNAPT = 0, ++ PPE_PKT_TYPE_IPV4_ROUTE = 1, ++ PPE_PKT_TYPE_BRIDGE = 2, ++ PPE_PKT_TYPE_IPV4_DSLITE = 3, ++ PPE_PKT_TYPE_IPV6_ROUTE_3T = 4, ++ PPE_PKT_TYPE_IPV6_ROUTE_5T = 5, ++ PPE_PKT_TYPE_IPV6_6RD = 7, ++}; ++ ++#define AIROHA_FOE_MAC_SMAC_ID GENMASK(20, 16) ++#define AIROHA_FOE_MAC_PPPOE_ID GENMASK(15, 0) ++ ++struct airoha_foe_mac_info_common { ++ u16 vlan1; ++ u16 etype; ++ ++ u32 dest_mac_hi; ++ ++ u16 vlan2; ++ u16 dest_mac_lo; ++ ++ u32 src_mac_hi; ++}; ++ ++struct airoha_foe_mac_info { ++ struct airoha_foe_mac_info_common common; ++ ++ u16 pppoe_id; ++ u16 src_mac_lo; ++}; ++ ++#define AIROHA_FOE_IB1_UNBIND_PREBIND BIT(24) ++#define AIROHA_FOE_IB1_UNBIND_PACKETS GENMASK(23, 8) ++#define AIROHA_FOE_IB1_UNBIND_TIMESTAMP GENMASK(7, 0) ++ ++#define AIROHA_FOE_IB1_BIND_STATIC BIT(31) ++#define AIROHA_FOE_IB1_BIND_UDP BIT(30) ++#define AIROHA_FOE_IB1_BIND_STATE GENMASK(29, 28) ++#define AIROHA_FOE_IB1_BIND_PACKET_TYPE GENMASK(27, 25) ++#define AIROHA_FOE_IB1_BIND_TTL BIT(24) ++#define AIROHA_FOE_IB1_BIND_TUNNEL_DECAP BIT(23) ++#define AIROHA_FOE_IB1_BIND_PPPOE BIT(22) ++#define AIROHA_FOE_IB1_BIND_VPM GENMASK(21, 20) ++#define AIROHA_FOE_IB1_BIND_VLAN_LAYER GENMASK(19, 16) ++#define AIROHA_FOE_IB1_BIND_KEEPALIVE BIT(15) ++#define AIROHA_FOE_IB1_BIND_TIMESTAMP GENMASK(14, 0) ++ ++#define AIROHA_FOE_IB2_DSCP GENMASK(31, 24) ++#define AIROHA_FOE_IB2_PORT_AG GENMASK(23, 13) ++#define AIROHA_FOE_IB2_PCP BIT(12) ++#define AIROHA_FOE_IB2_MULTICAST BIT(11) ++#define AIROHA_FOE_IB2_FAST_PATH BIT(10) ++#define AIROHA_FOE_IB2_PSE_QOS BIT(9) ++#define AIROHA_FOE_IB2_PSE_PORT GENMASK(8, 5) ++#define AIROHA_FOE_IB2_NBQ GENMASK(4, 0) ++ ++#define AIROHA_FOE_ACTDP GENMASK(31, 24) ++#define AIROHA_FOE_SHAPER_ID GENMASK(23, 16) ++#define AIROHA_FOE_CHANNEL GENMASK(15, 11) ++#define AIROHA_FOE_QID GENMASK(10, 8) ++#define AIROHA_FOE_DPI BIT(7) ++#define AIROHA_FOE_TUNNEL BIT(6) ++#define AIROHA_FOE_TUNNEL_ID GENMASK(5, 0) ++ ++struct airoha_foe_bridge { ++ u32 dest_mac_hi; ++ ++ u16 src_mac_hi; ++ u16 dest_mac_lo; ++ ++ u32 src_mac_lo; ++ ++ u32 ib2; ++ ++ u32 rsv[5]; ++ ++ u32 data; ++ ++ struct airoha_foe_mac_info l2; ++}; ++ ++struct airoha_foe_ipv4_tuple { ++ u32 src_ip; ++ u32 dest_ip; ++ union { ++ struct { ++ u16 dest_port; ++ u16 src_port; ++ }; ++ struct { ++ u8 protocol; ++ u8 _pad[3]; /* fill with 0xa5a5a5 */ ++ }; ++ u32 ports; ++ }; ++}; ++ ++struct airoha_foe_ipv4 { ++ struct airoha_foe_ipv4_tuple orig_tuple; ++ ++ u32 ib2; ++ ++ struct airoha_foe_ipv4_tuple new_tuple; ++ ++ u32 rsv[2]; ++ ++ u32 data; ++ ++ struct airoha_foe_mac_info l2; ++}; ++ ++struct airoha_foe_ipv4_dslite { ++ struct airoha_foe_ipv4_tuple ip4; ++ ++ u32 ib2; ++ ++ u8 flow_label[3]; ++ u8 priority; ++ ++ u32 rsv[4]; ++ ++ u32 data; ++ ++ struct airoha_foe_mac_info l2; ++}; ++ ++struct airoha_foe_ipv6 { ++ u32 src_ip[4]; ++ u32 dest_ip[4]; ++ ++ union { ++ struct { ++ u16 dest_port; ++ u16 src_port; ++ }; ++ struct { ++ u8 protocol; ++ u8 pad[3]; ++ }; ++ u32 ports; ++ }; ++ ++ u32 data; ++ ++ u32 ib2; ++ ++ struct airoha_foe_mac_info_common l2; ++}; ++ ++struct airoha_foe_entry { ++ union { ++ struct { ++ u32 ib1; ++ union { ++ struct airoha_foe_bridge bridge; ++ struct airoha_foe_ipv4 ipv4; ++ struct airoha_foe_ipv4_dslite dslite; ++ struct airoha_foe_ipv6 ipv6; ++ DECLARE_FLEX_ARRAY(u32, d); ++ }; ++ }; ++ u8 data[PPE_ENTRY_SIZE]; ++ }; ++}; ++ ++struct airoha_flow_data { ++ struct ethhdr eth; ++ ++ union { ++ struct { ++ __be32 src_addr; ++ __be32 dst_addr; ++ } v4; ++ ++ struct { ++ struct in6_addr src_addr; ++ struct in6_addr dst_addr; ++ } v6; ++ }; ++ ++ __be16 src_port; ++ __be16 dst_port; ++ ++ struct { ++ struct { ++ u16 id; ++ __be16 proto; ++ } hdr[2]; ++ u8 num; ++ } vlan; ++ struct { ++ u16 sid; ++ u8 num; ++ } pppoe; ++}; ++ ++struct airoha_flow_table_entry { ++ struct hlist_node list; ++ ++ struct airoha_foe_entry data; ++ u32 hash; ++ ++ struct rhash_head node; ++ unsigned long cookie; ++}; ++ + struct airoha_qdma { + struct airoha_eth *eth; + void __iomem *regs; +@@ -234,6 +462,19 @@ struct airoha_gdm_port { + struct metadata_dst *dsa_meta[AIROHA_MAX_DSA_PORTS]; + }; + ++#define AIROHA_RXD4_PPE_CPU_REASON GENMASK(20, 16) ++#define AIROHA_RXD4_FOE_ENTRY GENMASK(15, 0) ++ ++struct airoha_ppe { ++ struct airoha_eth *eth; ++ ++ void *foe; ++ dma_addr_t foe_dma; ++ ++ struct hlist_head *foe_flow; ++ u16 foe_check_time[PPE_NUM_ENTRIES]; ++}; ++ + struct airoha_eth { + struct device *dev; + +@@ -242,6 +483,9 @@ struct airoha_eth { + + struct airoha_npu __rcu *npu; + ++ struct airoha_ppe *ppe; ++ struct rhashtable flow_table; ++ + struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS]; + struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS]; + +@@ -277,4 +521,10 @@ u32 airoha_rmw(void __iomem *base, u32 o + #define airoha_qdma_clear(qdma, offset, val) \ + airoha_rmw((qdma)->regs, (offset), (val), 0) + ++void airoha_ppe_check_skb(struct airoha_ppe *ppe, u16 hash); ++int airoha_ppe_setup_tc_block_cb(enum tc_setup_type type, void *type_data, ++ void *cb_priv); ++int airoha_ppe_init(struct airoha_eth *eth); ++void airoha_ppe_deinit(struct airoha_eth *eth); ++ + #endif /* AIROHA_ETH_H */ +--- /dev/null ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -0,0 +1,901 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2025 AIROHA Inc ++ * Author: Lorenzo Bianconi ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "airoha_npu.h" ++#include "airoha_regs.h" ++#include "airoha_eth.h" ++ ++static DEFINE_MUTEX(flow_offload_mutex); ++static DEFINE_SPINLOCK(ppe_lock); ++ ++static const struct rhashtable_params airoha_flow_table_params = { ++ .head_offset = offsetof(struct airoha_flow_table_entry, node), ++ .key_offset = offsetof(struct airoha_flow_table_entry, cookie), ++ .key_len = sizeof(unsigned long), ++ .automatic_shrinking = true, ++}; ++ ++static bool airoha_ppe2_is_enabled(struct airoha_eth *eth) ++{ ++ return airoha_fe_rr(eth, REG_PPE_GLO_CFG(1)) & PPE_GLO_CFG_EN_MASK; ++} ++ ++static u32 airoha_ppe_get_timestamp(struct airoha_ppe *ppe) ++{ ++ u16 timestamp = airoha_fe_rr(ppe->eth, REG_FE_FOE_TS); ++ ++ return FIELD_GET(AIROHA_FOE_IB1_BIND_TIMESTAMP, timestamp); ++} ++ ++static void airoha_ppe_hw_init(struct airoha_ppe *ppe) ++{ ++ u32 sram_tb_size, sram_num_entries, dram_num_entries; ++ struct airoha_eth *eth = ppe->eth; ++ int i; ++ ++ sram_tb_size = PPE_SRAM_NUM_ENTRIES * sizeof(struct airoha_foe_entry); ++ dram_num_entries = PPE_RAM_NUM_ENTRIES_SHIFT(PPE_DRAM_NUM_ENTRIES); ++ ++ for (i = 0; i < PPE_NUM; i++) { ++ int p; ++ ++ airoha_fe_wr(eth, REG_PPE_TB_BASE(i), ++ ppe->foe_dma + sram_tb_size); ++ ++ airoha_fe_rmw(eth, REG_PPE_BND_AGE0(i), ++ PPE_BIND_AGE0_DELTA_NON_L4 | ++ PPE_BIND_AGE0_DELTA_UDP, ++ FIELD_PREP(PPE_BIND_AGE0_DELTA_NON_L4, 1) | ++ FIELD_PREP(PPE_BIND_AGE0_DELTA_UDP, 12)); ++ airoha_fe_rmw(eth, REG_PPE_BND_AGE1(i), ++ PPE_BIND_AGE1_DELTA_TCP_FIN | ++ PPE_BIND_AGE1_DELTA_TCP, ++ FIELD_PREP(PPE_BIND_AGE1_DELTA_TCP_FIN, 1) | ++ FIELD_PREP(PPE_BIND_AGE1_DELTA_TCP, 7)); ++ ++ airoha_fe_rmw(eth, REG_PPE_TB_HASH_CFG(i), ++ PPE_SRAM_TABLE_EN_MASK | ++ PPE_SRAM_HASH1_EN_MASK | ++ PPE_DRAM_TABLE_EN_MASK | ++ PPE_SRAM_HASH0_MODE_MASK | ++ PPE_SRAM_HASH1_MODE_MASK | ++ PPE_DRAM_HASH0_MODE_MASK | ++ PPE_DRAM_HASH1_MODE_MASK, ++ FIELD_PREP(PPE_SRAM_TABLE_EN_MASK, 1) | ++ FIELD_PREP(PPE_SRAM_HASH1_EN_MASK, 1) | ++ FIELD_PREP(PPE_SRAM_HASH1_MODE_MASK, 1) | ++ FIELD_PREP(PPE_DRAM_HASH1_MODE_MASK, 3)); ++ ++ airoha_fe_rmw(eth, REG_PPE_TB_CFG(i), ++ PPE_TB_CFG_SEARCH_MISS_MASK | ++ PPE_TB_ENTRY_SIZE_MASK, ++ FIELD_PREP(PPE_TB_CFG_SEARCH_MISS_MASK, 3) | ++ FIELD_PREP(PPE_TB_ENTRY_SIZE_MASK, 0)); ++ ++ airoha_fe_wr(eth, REG_PPE_HASH_SEED(i), PPE_HASH_SEED); ++ ++ for (p = 0; p < ARRAY_SIZE(eth->ports); p++) ++ airoha_fe_rmw(eth, REG_PPE_MTU(i, p), ++ FP0_EGRESS_MTU_MASK | ++ FP1_EGRESS_MTU_MASK, ++ FIELD_PREP(FP0_EGRESS_MTU_MASK, ++ AIROHA_MAX_MTU) | ++ FIELD_PREP(FP1_EGRESS_MTU_MASK, ++ AIROHA_MAX_MTU)); ++ } ++ ++ if (airoha_ppe2_is_enabled(eth)) { ++ sram_num_entries = ++ PPE_RAM_NUM_ENTRIES_SHIFT(PPE1_SRAM_NUM_ENTRIES); ++ airoha_fe_rmw(eth, REG_PPE_TB_CFG(0), ++ PPE_SRAM_TB_NUM_ENTRY_MASK | ++ PPE_DRAM_TB_NUM_ENTRY_MASK, ++ FIELD_PREP(PPE_SRAM_TB_NUM_ENTRY_MASK, ++ sram_num_entries) | ++ FIELD_PREP(PPE_DRAM_TB_NUM_ENTRY_MASK, ++ dram_num_entries)); ++ airoha_fe_rmw(eth, REG_PPE_TB_CFG(1), ++ PPE_SRAM_TB_NUM_ENTRY_MASK | ++ PPE_DRAM_TB_NUM_ENTRY_MASK, ++ FIELD_PREP(PPE_SRAM_TB_NUM_ENTRY_MASK, ++ sram_num_entries) | ++ FIELD_PREP(PPE_DRAM_TB_NUM_ENTRY_MASK, ++ dram_num_entries)); ++ } else { ++ sram_num_entries = ++ PPE_RAM_NUM_ENTRIES_SHIFT(PPE_SRAM_NUM_ENTRIES); ++ airoha_fe_rmw(eth, REG_PPE_TB_CFG(0), ++ PPE_SRAM_TB_NUM_ENTRY_MASK | ++ PPE_DRAM_TB_NUM_ENTRY_MASK, ++ FIELD_PREP(PPE_SRAM_TB_NUM_ENTRY_MASK, ++ sram_num_entries) | ++ FIELD_PREP(PPE_DRAM_TB_NUM_ENTRY_MASK, ++ dram_num_entries)); ++ } ++} ++ ++static void airoha_ppe_flow_mangle_eth(const struct flow_action_entry *act, void *eth) ++{ ++ void *dest = eth + act->mangle.offset; ++ const void *src = &act->mangle.val; ++ ++ if (act->mangle.offset > 8) ++ return; ++ ++ if (act->mangle.mask == 0xffff) { ++ src += 2; ++ dest += 2; ++ } ++ ++ memcpy(dest, src, act->mangle.mask ? 2 : 4); ++} ++ ++static int airoha_ppe_flow_mangle_ports(const struct flow_action_entry *act, ++ struct airoha_flow_data *data) ++{ ++ u32 val = be32_to_cpu((__force __be32)act->mangle.val); ++ ++ switch (act->mangle.offset) { ++ case 0: ++ if ((__force __be32)act->mangle.mask == ~cpu_to_be32(0xffff)) ++ data->dst_port = cpu_to_be16(val); ++ else ++ data->src_port = cpu_to_be16(val >> 16); ++ break; ++ case 2: ++ data->dst_port = cpu_to_be16(val); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int airoha_ppe_flow_mangle_ipv4(const struct flow_action_entry *act, ++ struct airoha_flow_data *data) ++{ ++ __be32 *dest; ++ ++ switch (act->mangle.offset) { ++ case offsetof(struct iphdr, saddr): ++ dest = &data->v4.src_addr; ++ break; ++ case offsetof(struct iphdr, daddr): ++ dest = &data->v4.dst_addr; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ memcpy(dest, &act->mangle.val, sizeof(u32)); ++ ++ return 0; ++} ++ ++static int airoha_get_dsa_port(struct net_device **dev) ++{ ++#if IS_ENABLED(CONFIG_NET_DSA) ++ struct dsa_port *dp = dsa_port_from_netdev(*dev); ++ ++ if (IS_ERR(dp)) ++ return -ENODEV; ++ ++ *dev = dsa_port_to_conduit(dp); ++ return dp->index; ++#else ++ return -ENODEV; ++#endif ++} ++ ++static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe, ++ struct net_device *dev, int type, ++ struct airoha_flow_data *data, ++ int l4proto) ++{ ++ int dsa_port = airoha_get_dsa_port(&dev); ++ struct airoha_foe_mac_info_common *l2; ++ u32 qdata, ports_pad, val; ++ ++ memset(hwe, 0, sizeof(*hwe)); ++ ++ val = FIELD_PREP(AIROHA_FOE_IB1_BIND_STATE, AIROHA_FOE_STATE_BIND) | ++ FIELD_PREP(AIROHA_FOE_IB1_BIND_PACKET_TYPE, type) | ++ FIELD_PREP(AIROHA_FOE_IB1_BIND_UDP, l4proto == IPPROTO_UDP) | ++ FIELD_PREP(AIROHA_FOE_IB1_BIND_VLAN_LAYER, data->vlan.num) | ++ FIELD_PREP(AIROHA_FOE_IB1_BIND_VPM, data->vlan.num) | ++ AIROHA_FOE_IB1_BIND_TTL; ++ hwe->ib1 = val; ++ ++ val = FIELD_PREP(AIROHA_FOE_IB2_PORT_AG, 0x1f); ++ if (dsa_port >= 0) ++ val |= FIELD_PREP(AIROHA_FOE_IB2_NBQ, dsa_port); ++ ++ if (dev) { ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ u8 pse_port; ++ ++ pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id; ++ val |= FIELD_PREP(AIROHA_FOE_IB2_PSE_PORT, pse_port); ++ } ++ ++ /* FIXME: implement QoS support setting pse_port to 2 (loopback) ++ * for uplink and setting qos bit in ib2 ++ */ ++ ++ if (is_multicast_ether_addr(data->eth.h_dest)) ++ val |= AIROHA_FOE_IB2_MULTICAST; ++ ++ ports_pad = 0xa5a5a500 | (l4proto & 0xff); ++ if (type == PPE_PKT_TYPE_IPV4_ROUTE) ++ hwe->ipv4.orig_tuple.ports = ports_pad; ++ if (type == PPE_PKT_TYPE_IPV6_ROUTE_3T) ++ hwe->ipv6.ports = ports_pad; ++ ++ qdata = FIELD_PREP(AIROHA_FOE_SHAPER_ID, 0x7f); ++ if (type == PPE_PKT_TYPE_BRIDGE) { ++ hwe->bridge.dest_mac_hi = get_unaligned_be32(data->eth.h_dest); ++ hwe->bridge.dest_mac_lo = ++ get_unaligned_be16(data->eth.h_dest + 4); ++ hwe->bridge.src_mac_hi = ++ get_unaligned_be16(data->eth.h_source); ++ hwe->bridge.src_mac_lo = ++ get_unaligned_be32(data->eth.h_source + 2); ++ hwe->bridge.data = qdata; ++ hwe->bridge.ib2 = val; ++ l2 = &hwe->bridge.l2.common; ++ } else if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T) { ++ hwe->ipv6.data = qdata; ++ hwe->ipv6.ib2 = val; ++ l2 = &hwe->ipv6.l2; ++ } else { ++ hwe->ipv4.data = qdata; ++ hwe->ipv4.ib2 = val; ++ l2 = &hwe->ipv4.l2.common; ++ } ++ ++ l2->dest_mac_hi = get_unaligned_be32(data->eth.h_dest); ++ l2->dest_mac_lo = get_unaligned_be16(data->eth.h_dest + 4); ++ if (type <= PPE_PKT_TYPE_IPV4_DSLITE) { ++ l2->src_mac_hi = get_unaligned_be32(data->eth.h_source); ++ hwe->ipv4.l2.src_mac_lo = ++ get_unaligned_be16(data->eth.h_source + 4); ++ } else { ++ l2->src_mac_hi = FIELD_PREP(AIROHA_FOE_MAC_SMAC_ID, 0xf); ++ } ++ ++ if (data->vlan.num) { ++ l2->etype = dsa_port >= 0 ? BIT(dsa_port) : 0; ++ l2->vlan1 = data->vlan.hdr[0].id; ++ if (data->vlan.num == 2) ++ l2->vlan2 = data->vlan.hdr[1].id; ++ } else if (dsa_port >= 0) { ++ l2->etype = BIT(15) | BIT(dsa_port); ++ } else if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T) { ++ l2->etype = ETH_P_IPV6; ++ } else { ++ l2->etype = ETH_P_IP; ++ } ++ ++ return 0; ++} ++ ++static int airoha_ppe_foe_entry_set_ipv4_tuple(struct airoha_foe_entry *hwe, ++ struct airoha_flow_data *data, ++ bool egress) ++{ ++ int type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe->ib1); ++ struct airoha_foe_ipv4_tuple *t; ++ ++ switch (type) { ++ case PPE_PKT_TYPE_IPV4_HNAPT: ++ if (egress) { ++ t = &hwe->ipv4.new_tuple; ++ break; ++ } ++ fallthrough; ++ case PPE_PKT_TYPE_IPV4_DSLITE: ++ case PPE_PKT_TYPE_IPV4_ROUTE: ++ t = &hwe->ipv4.orig_tuple; ++ break; ++ default: ++ WARN_ON_ONCE(1); ++ return -EINVAL; ++ } ++ ++ t->src_ip = be32_to_cpu(data->v4.src_addr); ++ t->dest_ip = be32_to_cpu(data->v4.dst_addr); ++ ++ if (type != PPE_PKT_TYPE_IPV4_ROUTE) { ++ t->src_port = be16_to_cpu(data->src_port); ++ t->dest_port = be16_to_cpu(data->dst_port); ++ } ++ ++ return 0; ++} ++ ++static int airoha_ppe_foe_entry_set_ipv6_tuple(struct airoha_foe_entry *hwe, ++ struct airoha_flow_data *data) ++ ++{ ++ int type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe->ib1); ++ u32 *src, *dest; ++ ++ switch (type) { ++ case PPE_PKT_TYPE_IPV6_ROUTE_5T: ++ case PPE_PKT_TYPE_IPV6_6RD: ++ hwe->ipv6.src_port = be16_to_cpu(data->src_port); ++ hwe->ipv6.dest_port = be16_to_cpu(data->dst_port); ++ fallthrough; ++ case PPE_PKT_TYPE_IPV6_ROUTE_3T: ++ src = hwe->ipv6.src_ip; ++ dest = hwe->ipv6.dest_ip; ++ break; ++ default: ++ WARN_ON_ONCE(1); ++ return -EINVAL; ++ } ++ ++ ipv6_addr_be32_to_cpu(src, data->v6.src_addr.s6_addr32); ++ ipv6_addr_be32_to_cpu(dest, data->v6.dst_addr.s6_addr32); ++ ++ return 0; ++} ++ ++static u32 airoha_ppe_foe_get_entry_hash(struct airoha_foe_entry *hwe) ++{ ++ int type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe->ib1); ++ u32 hash, hv1, hv2, hv3; ++ ++ switch (type) { ++ case PPE_PKT_TYPE_IPV4_ROUTE: ++ case PPE_PKT_TYPE_IPV4_HNAPT: ++ hv1 = hwe->ipv4.orig_tuple.ports; ++ hv2 = hwe->ipv4.orig_tuple.dest_ip; ++ hv3 = hwe->ipv4.orig_tuple.src_ip; ++ break; ++ case PPE_PKT_TYPE_IPV6_ROUTE_3T: ++ case PPE_PKT_TYPE_IPV6_ROUTE_5T: ++ hv1 = hwe->ipv6.src_ip[3] ^ hwe->ipv6.dest_ip[3]; ++ hv1 ^= hwe->ipv6.ports; ++ ++ hv2 = hwe->ipv6.src_ip[2] ^ hwe->ipv6.dest_ip[2]; ++ hv2 ^= hwe->ipv6.dest_ip[0]; ++ ++ hv3 = hwe->ipv6.src_ip[1] ^ hwe->ipv6.dest_ip[1]; ++ hv3 ^= hwe->ipv6.src_ip[0]; ++ break; ++ case PPE_PKT_TYPE_IPV4_DSLITE: ++ case PPE_PKT_TYPE_IPV6_6RD: ++ default: ++ WARN_ON_ONCE(1); ++ return PPE_HASH_MASK; ++ } ++ ++ hash = (hv1 & hv2) | ((~hv1) & hv3); ++ hash = (hash >> 24) | ((hash & 0xffffff) << 8); ++ hash ^= hv1 ^ hv2 ^ hv3; ++ hash ^= hash >> 16; ++ hash &= PPE_NUM_ENTRIES - 1; ++ ++ return hash; ++} ++ ++static struct airoha_foe_entry * ++airoha_ppe_foe_get_entry(struct airoha_ppe *ppe, u32 hash) ++{ ++ if (hash < PPE_SRAM_NUM_ENTRIES) { ++ u32 *hwe = ppe->foe + hash * sizeof(struct airoha_foe_entry); ++ struct airoha_eth *eth = ppe->eth; ++ bool ppe2; ++ u32 val; ++ int i; ++ ++ ppe2 = airoha_ppe2_is_enabled(ppe->eth) && ++ hash >= PPE1_SRAM_NUM_ENTRIES; ++ airoha_fe_wr(ppe->eth, REG_PPE_RAM_CTRL(ppe2), ++ FIELD_PREP(PPE_SRAM_CTRL_ENTRY_MASK, hash) | ++ PPE_SRAM_CTRL_REQ_MASK); ++ if (read_poll_timeout_atomic(airoha_fe_rr, val, ++ val & PPE_SRAM_CTRL_ACK_MASK, ++ 10, 100, false, eth, ++ REG_PPE_RAM_CTRL(ppe2))) ++ return NULL; ++ ++ for (i = 0; i < sizeof(struct airoha_foe_entry) / 4; i++) ++ hwe[i] = airoha_fe_rr(eth, ++ REG_PPE_RAM_ENTRY(ppe2, i)); ++ } ++ ++ return ppe->foe + hash * sizeof(struct airoha_foe_entry); ++} ++ ++static bool airoha_ppe_foe_compare_entry(struct airoha_flow_table_entry *e, ++ struct airoha_foe_entry *hwe) ++{ ++ int type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, e->data.ib1); ++ int len; ++ ++ if ((hwe->ib1 ^ e->data.ib1) & AIROHA_FOE_IB1_BIND_UDP) ++ return false; ++ ++ if (type > PPE_PKT_TYPE_IPV4_DSLITE) ++ len = offsetof(struct airoha_foe_entry, ipv6.data); ++ else ++ len = offsetof(struct airoha_foe_entry, ipv4.ib2); ++ ++ return !memcmp(&e->data.d, &hwe->d, len - sizeof(hwe->ib1)); ++} ++ ++static int airoha_ppe_foe_commit_entry(struct airoha_ppe *ppe, ++ struct airoha_foe_entry *e, ++ u32 hash) ++{ ++ struct airoha_foe_entry *hwe = ppe->foe + hash * sizeof(*hwe); ++ u32 ts = airoha_ppe_get_timestamp(ppe); ++ struct airoha_eth *eth = ppe->eth; ++ ++ memcpy(&hwe->d, &e->d, sizeof(*hwe) - sizeof(hwe->ib1)); ++ wmb(); ++ ++ e->ib1 &= ~AIROHA_FOE_IB1_BIND_TIMESTAMP; ++ e->ib1 |= FIELD_PREP(AIROHA_FOE_IB1_BIND_TIMESTAMP, ts); ++ hwe->ib1 = e->ib1; ++ ++ if (hash < PPE_SRAM_NUM_ENTRIES) { ++ dma_addr_t addr = ppe->foe_dma + hash * sizeof(*hwe); ++ bool ppe2 = airoha_ppe2_is_enabled(eth) && ++ hash >= PPE1_SRAM_NUM_ENTRIES; ++ struct airoha_npu *npu; ++ int err = -ENODEV; ++ ++ rcu_read_lock(); ++ npu = rcu_dereference(eth->npu); ++ if (npu) ++ err = npu->ops.ppe_foe_commit_entry(npu, addr, ++ sizeof(*hwe), hash, ++ ppe2); ++ rcu_read_unlock(); ++ ++ return err; ++ } ++ ++ return 0; ++} ++ ++static void airoha_ppe_foe_insert_entry(struct airoha_ppe *ppe, u32 hash) ++{ ++ struct airoha_flow_table_entry *e; ++ struct airoha_foe_entry *hwe; ++ struct hlist_node *n; ++ u32 index, state; ++ ++ spin_lock_bh(&ppe_lock); ++ ++ hwe = airoha_ppe_foe_get_entry(ppe, hash); ++ if (!hwe) ++ goto unlock; ++ ++ state = FIELD_GET(AIROHA_FOE_IB1_BIND_STATE, hwe->ib1); ++ if (state == AIROHA_FOE_STATE_BIND) ++ goto unlock; ++ ++ index = airoha_ppe_foe_get_entry_hash(hwe); ++ hlist_for_each_entry_safe(e, n, &ppe->foe_flow[index], list) { ++ if (airoha_ppe_foe_compare_entry(e, hwe)) { ++ airoha_ppe_foe_commit_entry(ppe, &e->data, hash); ++ e->hash = hash; ++ break; ++ } ++ } ++unlock: ++ spin_unlock_bh(&ppe_lock); ++} ++ ++static int airoha_ppe_foe_flow_commit_entry(struct airoha_ppe *ppe, ++ struct airoha_flow_table_entry *e) ++{ ++ u32 hash = airoha_ppe_foe_get_entry_hash(&e->data); ++ ++ e->hash = 0xffff; ++ ++ spin_lock_bh(&ppe_lock); ++ hlist_add_head(&e->list, &ppe->foe_flow[hash]); ++ spin_unlock_bh(&ppe_lock); ++ ++ return 0; ++} ++ ++static void airoha_ppe_foe_flow_remove_entry(struct airoha_ppe *ppe, ++ struct airoha_flow_table_entry *e) ++{ ++ spin_lock_bh(&ppe_lock); ++ ++ hlist_del_init(&e->list); ++ if (e->hash != 0xffff) { ++ e->data.ib1 &= ~AIROHA_FOE_IB1_BIND_STATE; ++ e->data.ib1 |= FIELD_PREP(AIROHA_FOE_IB1_BIND_STATE, ++ AIROHA_FOE_STATE_INVALID); ++ airoha_ppe_foe_commit_entry(ppe, &e->data, e->hash); ++ e->hash = 0xffff; ++ } ++ ++ spin_unlock_bh(&ppe_lock); ++} ++ ++static int airoha_ppe_flow_offload_replace(struct airoha_gdm_port *port, ++ struct flow_cls_offload *f) ++{ ++ struct flow_rule *rule = flow_cls_offload_flow_rule(f); ++ struct airoha_eth *eth = port->qdma->eth; ++ struct airoha_flow_table_entry *e; ++ struct airoha_flow_data data = {}; ++ struct net_device *odev = NULL; ++ struct flow_action_entry *act; ++ struct airoha_foe_entry hwe; ++ int err, i, offload_type; ++ u16 addr_type = 0; ++ u8 l4proto = 0; ++ ++ if (rhashtable_lookup(ð->flow_table, &f->cookie, ++ airoha_flow_table_params)) ++ return -EEXIST; ++ ++ if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) ++ return -EOPNOTSUPP; ++ ++ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { ++ struct flow_match_control match; ++ ++ flow_rule_match_control(rule, &match); ++ addr_type = match.key->addr_type; ++ if (flow_rule_has_control_flags(match.mask->flags, ++ f->common.extack)) ++ return -EOPNOTSUPP; ++ } else { ++ return -EOPNOTSUPP; ++ } ++ ++ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { ++ struct flow_match_basic match; ++ ++ flow_rule_match_basic(rule, &match); ++ l4proto = match.key->ip_proto; ++ } else { ++ return -EOPNOTSUPP; ++ } ++ ++ switch (addr_type) { ++ case 0: ++ offload_type = PPE_PKT_TYPE_BRIDGE; ++ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { ++ struct flow_match_eth_addrs match; ++ ++ flow_rule_match_eth_addrs(rule, &match); ++ memcpy(data.eth.h_dest, match.key->dst, ETH_ALEN); ++ memcpy(data.eth.h_source, match.key->src, ETH_ALEN); ++ } else { ++ return -EOPNOTSUPP; ++ } ++ break; ++ case FLOW_DISSECTOR_KEY_IPV4_ADDRS: ++ offload_type = PPE_PKT_TYPE_IPV4_HNAPT; ++ break; ++ case FLOW_DISSECTOR_KEY_IPV6_ADDRS: ++ offload_type = PPE_PKT_TYPE_IPV6_ROUTE_5T; ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ flow_action_for_each(i, act, &rule->action) { ++ switch (act->id) { ++ case FLOW_ACTION_MANGLE: ++ if (offload_type == PPE_PKT_TYPE_BRIDGE) ++ return -EOPNOTSUPP; ++ ++ if (act->mangle.htype == FLOW_ACT_MANGLE_HDR_TYPE_ETH) ++ airoha_ppe_flow_mangle_eth(act, &data.eth); ++ break; ++ case FLOW_ACTION_REDIRECT: ++ odev = act->dev; ++ break; ++ case FLOW_ACTION_CSUM: ++ break; ++ case FLOW_ACTION_VLAN_PUSH: ++ if (data.vlan.num == 2 || ++ act->vlan.proto != htons(ETH_P_8021Q)) ++ return -EOPNOTSUPP; ++ ++ data.vlan.hdr[data.vlan.num].id = act->vlan.vid; ++ data.vlan.hdr[data.vlan.num].proto = act->vlan.proto; ++ data.vlan.num++; ++ break; ++ case FLOW_ACTION_VLAN_POP: ++ break; ++ case FLOW_ACTION_PPPOE_PUSH: ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ } ++ ++ if (!is_valid_ether_addr(data.eth.h_source) || ++ !is_valid_ether_addr(data.eth.h_dest)) ++ return -EINVAL; ++ ++ err = airoha_ppe_foe_entry_prepare(&hwe, odev, offload_type, ++ &data, l4proto); ++ if (err) ++ return err; ++ ++ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { ++ struct flow_match_ports ports; ++ ++ if (offload_type == PPE_PKT_TYPE_BRIDGE) ++ return -EOPNOTSUPP; ++ ++ flow_rule_match_ports(rule, &ports); ++ data.src_port = ports.key->src; ++ data.dst_port = ports.key->dst; ++ } else if (offload_type != PPE_PKT_TYPE_BRIDGE) { ++ return -EOPNOTSUPP; ++ } ++ ++ if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) { ++ struct flow_match_ipv4_addrs addrs; ++ ++ flow_rule_match_ipv4_addrs(rule, &addrs); ++ data.v4.src_addr = addrs.key->src; ++ data.v4.dst_addr = addrs.key->dst; ++ airoha_ppe_foe_entry_set_ipv4_tuple(&hwe, &data, false); ++ } ++ ++ if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) { ++ struct flow_match_ipv6_addrs addrs; ++ ++ flow_rule_match_ipv6_addrs(rule, &addrs); ++ ++ data.v6.src_addr = addrs.key->src; ++ data.v6.dst_addr = addrs.key->dst; ++ airoha_ppe_foe_entry_set_ipv6_tuple(&hwe, &data); ++ } ++ ++ flow_action_for_each(i, act, &rule->action) { ++ if (act->id != FLOW_ACTION_MANGLE) ++ continue; ++ ++ if (offload_type == PPE_PKT_TYPE_BRIDGE) ++ return -EOPNOTSUPP; ++ ++ switch (act->mangle.htype) { ++ case FLOW_ACT_MANGLE_HDR_TYPE_TCP: ++ case FLOW_ACT_MANGLE_HDR_TYPE_UDP: ++ err = airoha_ppe_flow_mangle_ports(act, &data); ++ break; ++ case FLOW_ACT_MANGLE_HDR_TYPE_IP4: ++ err = airoha_ppe_flow_mangle_ipv4(act, &data); ++ break; ++ case FLOW_ACT_MANGLE_HDR_TYPE_ETH: ++ /* handled earlier */ ++ break; ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ if (err) ++ return err; ++ } ++ ++ if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) { ++ err = airoha_ppe_foe_entry_set_ipv4_tuple(&hwe, &data, true); ++ if (err) ++ return err; ++ } ++ ++ e = kzalloc(sizeof(*e), GFP_KERNEL); ++ if (!e) ++ return -ENOMEM; ++ ++ e->cookie = f->cookie; ++ memcpy(&e->data, &hwe, sizeof(e->data)); ++ ++ err = airoha_ppe_foe_flow_commit_entry(eth->ppe, e); ++ if (err) ++ goto free_entry; ++ ++ err = rhashtable_insert_fast(ð->flow_table, &e->node, ++ airoha_flow_table_params); ++ if (err < 0) ++ goto remove_foe_entry; ++ ++ return 0; ++ ++remove_foe_entry: ++ airoha_ppe_foe_flow_remove_entry(eth->ppe, e); ++free_entry: ++ kfree(e); ++ ++ return err; ++} ++ ++static int airoha_ppe_flow_offload_destroy(struct airoha_gdm_port *port, ++ struct flow_cls_offload *f) ++{ ++ struct airoha_eth *eth = port->qdma->eth; ++ struct airoha_flow_table_entry *e; ++ ++ e = rhashtable_lookup(ð->flow_table, &f->cookie, ++ airoha_flow_table_params); ++ if (!e) ++ return -ENOENT; ++ ++ airoha_ppe_foe_flow_remove_entry(eth->ppe, e); ++ rhashtable_remove_fast(ð->flow_table, &e->node, ++ airoha_flow_table_params); ++ kfree(e); ++ ++ return 0; ++} ++ ++static int airoha_ppe_flow_offload_cmd(struct airoha_gdm_port *port, ++ struct flow_cls_offload *f) ++{ ++ switch (f->command) { ++ case FLOW_CLS_REPLACE: ++ return airoha_ppe_flow_offload_replace(port, f); ++ case FLOW_CLS_DESTROY: ++ return airoha_ppe_flow_offload_destroy(port, f); ++ default: ++ break; ++ } ++ ++ return -EOPNOTSUPP; ++} ++ ++static int airoha_ppe_flush_sram_entries(struct airoha_ppe *ppe, ++ struct airoha_npu *npu) ++{ ++ int i, sram_num_entries = PPE_SRAM_NUM_ENTRIES; ++ struct airoha_foe_entry *hwe = ppe->foe; ++ ++ if (airoha_ppe2_is_enabled(ppe->eth)) ++ sram_num_entries = sram_num_entries / 2; ++ ++ for (i = 0; i < sram_num_entries; i++) ++ memset(&hwe[i], 0, sizeof(*hwe)); ++ ++ return npu->ops.ppe_flush_sram_entries(npu, ppe->foe_dma, ++ PPE_SRAM_NUM_ENTRIES); ++} ++ ++static struct airoha_npu *airoha_ppe_npu_get(struct airoha_eth *eth) ++{ ++ struct airoha_npu *npu = airoha_npu_get(eth->dev); ++ ++ if (IS_ERR(npu)) { ++ request_module("airoha-npu"); ++ npu = airoha_npu_get(eth->dev); ++ } ++ ++ return npu; ++} ++ ++static int airoha_ppe_offload_setup(struct airoha_eth *eth) ++{ ++ struct airoha_npu *npu = airoha_ppe_npu_get(eth); ++ int err; ++ ++ if (IS_ERR(npu)) ++ return PTR_ERR(npu); ++ ++ err = npu->ops.ppe_init(npu); ++ if (err) ++ goto error_npu_put; ++ ++ airoha_ppe_hw_init(eth->ppe); ++ err = airoha_ppe_flush_sram_entries(eth->ppe, npu); ++ if (err) ++ goto error_npu_put; ++ ++ rcu_assign_pointer(eth->npu, npu); ++ synchronize_rcu(); ++ ++ return 0; ++ ++error_npu_put: ++ airoha_npu_put(npu); ++ ++ return err; ++} ++ ++int airoha_ppe_setup_tc_block_cb(enum tc_setup_type type, void *type_data, ++ void *cb_priv) ++{ ++ struct flow_cls_offload *cls = type_data; ++ struct net_device *dev = cb_priv; ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ struct airoha_eth *eth = port->qdma->eth; ++ int err = 0; ++ ++ if (!tc_can_offload(dev) || type != TC_SETUP_CLSFLOWER) ++ return -EOPNOTSUPP; ++ ++ mutex_lock(&flow_offload_mutex); ++ ++ if (!eth->npu) ++ err = airoha_ppe_offload_setup(eth); ++ if (!err) ++ err = airoha_ppe_flow_offload_cmd(port, cls); ++ ++ mutex_unlock(&flow_offload_mutex); ++ ++ return err; ++} ++ ++void airoha_ppe_check_skb(struct airoha_ppe *ppe, u16 hash) ++{ ++ u16 now, diff; ++ ++ if (hash > PPE_HASH_MASK) ++ return; ++ ++ now = (u16)jiffies; ++ diff = now - ppe->foe_check_time[hash]; ++ if (diff < HZ / 10) ++ return; ++ ++ ppe->foe_check_time[hash] = now; ++ airoha_ppe_foe_insert_entry(ppe, hash); ++} ++ ++int airoha_ppe_init(struct airoha_eth *eth) ++{ ++ struct airoha_ppe *ppe; ++ int foe_size; ++ ++ ppe = devm_kzalloc(eth->dev, sizeof(*ppe), GFP_KERNEL); ++ if (!ppe) ++ return -ENOMEM; ++ ++ foe_size = PPE_NUM_ENTRIES * sizeof(struct airoha_foe_entry); ++ ppe->foe = dmam_alloc_coherent(eth->dev, foe_size, &ppe->foe_dma, ++ GFP_KERNEL); ++ if (!ppe->foe) ++ return -ENOMEM; ++ ++ ppe->eth = eth; ++ eth->ppe = ppe; ++ ++ ppe->foe_flow = devm_kzalloc(eth->dev, ++ PPE_NUM_ENTRIES * sizeof(*ppe->foe_flow), ++ GFP_KERNEL); ++ if (!ppe->foe_flow) ++ return -ENOMEM; ++ ++ return rhashtable_init(ð->flow_table, &airoha_flow_table_params); ++} ++ ++void airoha_ppe_deinit(struct airoha_eth *eth) ++{ ++ struct airoha_npu *npu; ++ ++ rcu_read_lock(); ++ npu = rcu_dereference(eth->npu); ++ if (npu) { ++ npu->ops.ppe_deinit(npu); ++ airoha_npu_put(npu); ++ } ++ rcu_read_unlock(); ++ ++ rhashtable_destroy(ð->flow_table); ++} +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -15,6 +15,7 @@ + #define CDM1_BASE 0x0400 + #define GDM1_BASE 0x0500 + #define PPE1_BASE 0x0c00 ++#define PPE2_BASE 0x1c00 + + #define CDM2_BASE 0x1400 + #define GDM2_BASE 0x1500 +@@ -36,6 +37,7 @@ + #define FE_RST_GDM3_MBI_ARB_MASK BIT(2) + #define FE_RST_CORE_MASK BIT(0) + ++#define REG_FE_FOE_TS 0x0010 + #define REG_FE_WAN_MAC_H 0x0030 + #define REG_FE_LAN_MAC_H 0x0040 + +@@ -192,11 +194,106 @@ + #define REG_FE_GDM_RX_ETH_L511_CNT_L(_n) (GDM_BASE(_n) + 0x198) + #define REG_FE_GDM_RX_ETH_L1023_CNT_L(_n) (GDM_BASE(_n) + 0x19c) + +-#define REG_PPE1_TB_HASH_CFG (PPE1_BASE + 0x250) +-#define PPE1_SRAM_TABLE_EN_MASK BIT(0) +-#define PPE1_SRAM_HASH1_EN_MASK BIT(8) +-#define PPE1_DRAM_TABLE_EN_MASK BIT(16) +-#define PPE1_DRAM_HASH1_EN_MASK BIT(24) ++#define REG_PPE_GLO_CFG(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x200) ++#define PPE_GLO_CFG_BUSY_MASK BIT(31) ++#define PPE_GLO_CFG_FLOW_DROP_UPDATE_MASK BIT(9) ++#define PPE_GLO_CFG_PSE_HASH_OFS_MASK BIT(6) ++#define PPE_GLO_CFG_PPE_BSWAP_MASK BIT(5) ++#define PPE_GLO_CFG_TTL_DROP_MASK BIT(4) ++#define PPE_GLO_CFG_IP4_CS_DROP_MASK BIT(3) ++#define PPE_GLO_CFG_IP4_L4_CS_DROP_MASK BIT(2) ++#define PPE_GLO_CFG_EN_MASK BIT(0) ++ ++#define REG_PPE_PPE_FLOW_CFG(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x204) ++#define PPE_FLOW_CFG_IP6_HASH_GRE_KEY_MASK BIT(20) ++#define PPE_FLOW_CFG_IP4_HASH_GRE_KEY_MASK BIT(19) ++#define PPE_FLOW_CFG_IP4_HASH_FLOW_LABEL_MASK BIT(18) ++#define PPE_FLOW_CFG_IP4_NAT_FRAG_MASK BIT(17) ++#define PPE_FLOW_CFG_IP_PROTO_BLACKLIST_MASK BIT(16) ++#define PPE_FLOW_CFG_IP4_DSLITE_MASK BIT(14) ++#define PPE_FLOW_CFG_IP4_NAPT_MASK BIT(13) ++#define PPE_FLOW_CFG_IP4_NAT_MASK BIT(12) ++#define PPE_FLOW_CFG_IP6_6RD_MASK BIT(10) ++#define PPE_FLOW_CFG_IP6_5T_ROUTE_MASK BIT(9) ++#define PPE_FLOW_CFG_IP6_3T_ROUTE_MASK BIT(8) ++#define PPE_FLOW_CFG_IP4_UDP_FRAG_MASK BIT(7) ++#define PPE_FLOW_CFG_IP4_TCP_FRAG_MASK BIT(6) ++ ++#define REG_PPE_IP_PROTO_CHK(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x208) ++#define PPE_IP_PROTO_CHK_IPV4_MASK GENMASK(15, 0) ++#define PPE_IP_PROTO_CHK_IPV6_MASK GENMASK(31, 16) ++ ++#define REG_PPE_TB_CFG(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x21c) ++#define PPE_SRAM_TB_NUM_ENTRY_MASK GENMASK(26, 24) ++#define PPE_TB_CFG_KEEPALIVE_MASK GENMASK(13, 12) ++#define PPE_TB_CFG_AGE_TCP_FIN_MASK BIT(11) ++#define PPE_TB_CFG_AGE_UDP_MASK BIT(10) ++#define PPE_TB_CFG_AGE_TCP_MASK BIT(9) ++#define PPE_TB_CFG_AGE_UNBIND_MASK BIT(8) ++#define PPE_TB_CFG_AGE_NON_L4_MASK BIT(7) ++#define PPE_TB_CFG_AGE_PREBIND_MASK BIT(6) ++#define PPE_TB_CFG_SEARCH_MISS_MASK GENMASK(5, 4) ++#define PPE_TB_ENTRY_SIZE_MASK BIT(3) ++#define PPE_DRAM_TB_NUM_ENTRY_MASK GENMASK(2, 0) ++ ++#define REG_PPE_TB_BASE(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x220) ++ ++#define REG_PPE_BIND_RATE(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x228) ++#define PPE_BIND_RATE_L2B_BIND_MASK GENMASK(31, 16) ++#define PPE_BIND_RATE_BIND_MASK GENMASK(15, 0) ++ ++#define REG_PPE_BIND_LIMIT0(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x22c) ++#define PPE_BIND_LIMIT0_HALF_MASK GENMASK(29, 16) ++#define PPE_BIND_LIMIT0_QUARTER_MASK GENMASK(13, 0) ++ ++#define REG_PPE_BIND_LIMIT1(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x230) ++#define PPE_BIND_LIMIT1_NON_L4_MASK GENMASK(23, 16) ++#define PPE_BIND_LIMIT1_FULL_MASK GENMASK(13, 0) ++ ++#define REG_PPE_BND_AGE0(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x23c) ++#define PPE_BIND_AGE0_DELTA_NON_L4 GENMASK(30, 16) ++#define PPE_BIND_AGE0_DELTA_UDP GENMASK(14, 0) ++ ++#define REG_PPE_UNBIND_AGE(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x238) ++#define PPE_UNBIND_AGE_MIN_PACKETS_MASK GENMASK(31, 16) ++#define PPE_UNBIND_AGE_DELTA_MASK GENMASK(7, 0) ++ ++#define REG_PPE_BND_AGE1(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x240) ++#define PPE_BIND_AGE1_DELTA_TCP_FIN GENMASK(30, 16) ++#define PPE_BIND_AGE1_DELTA_TCP GENMASK(14, 0) ++ ++#define REG_PPE_HASH_SEED(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x244) ++#define PPE_HASH_SEED 0x12345678 ++ ++#define REG_PPE_DFT_CPORT0(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x248) ++ ++#define REG_PPE_DFT_CPORT1(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x24c) ++ ++#define REG_PPE_TB_HASH_CFG(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x250) ++#define PPE_DRAM_HASH1_MODE_MASK GENMASK(31, 28) ++#define PPE_DRAM_HASH1_EN_MASK BIT(24) ++#define PPE_DRAM_HASH0_MODE_MASK GENMASK(23, 20) ++#define PPE_DRAM_TABLE_EN_MASK BIT(16) ++#define PPE_SRAM_HASH1_MODE_MASK GENMASK(15, 12) ++#define PPE_SRAM_HASH1_EN_MASK BIT(8) ++#define PPE_SRAM_HASH0_MODE_MASK GENMASK(7, 4) ++#define PPE_SRAM_TABLE_EN_MASK BIT(0) ++ ++#define REG_PPE_MTU_BASE(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x304) ++#define REG_PPE_MTU(_m, _n) (REG_PPE_MTU_BASE(_m) + ((_n) << 2)) ++#define FP1_EGRESS_MTU_MASK GENMASK(29, 16) ++#define FP0_EGRESS_MTU_MASK GENMASK(13, 0) ++ ++#define REG_PPE_RAM_CTRL(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x31c) ++#define PPE_SRAM_CTRL_ACK_MASK BIT(31) ++#define PPE_SRAM_CTRL_DUAL_SUCESS_MASK BIT(30) ++#define PPE_SRAM_CTRL_ENTRY_MASK GENMASK(23, 8) ++#define PPE_SRAM_WR_DUAL_DIRECTION_MASK BIT(2) ++#define PPE_SRAM_CTRL_WR_MASK BIT(1) ++#define PPE_SRAM_CTRL_REQ_MASK BIT(0) ++ ++#define REG_PPE_RAM_BASE(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x320) ++#define REG_PPE_RAM_ENTRY(_m, _n) (REG_PPE_RAM_BASE(_m) + ((_n) << 2)) + + #define REG_FE_GDM_TX_OK_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x280) + #define REG_FE_GDM_TX_OK_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x284) diff --git a/lede/target/linux/airoha/patches-6.12/048-14-v6.15-net-airoha-Add-loopback-support-for-GDM2.patch b/lede/target/linux/airoha/patches-6.12/048-14-v6.15-net-airoha-Add-loopback-support-for-GDM2.patch new file mode 100644 index 0000000000..e91501eeb0 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/048-14-v6.15-net-airoha-Add-loopback-support-for-GDM2.patch @@ -0,0 +1,210 @@ +From 9cd451d414f6e29f507a216fb3b19fa68c011f8c Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 28 Feb 2025 11:54:22 +0100 +Subject: [PATCH 14/15] net: airoha: Add loopback support for GDM2 + +Enable hw redirection for traffic received on GDM2 port to GDM{3,4}. +This is required to apply Qdisc offloading (HTB or ETS) for traffic to +and from GDM{3,4} port. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 71 ++++++++++++++++++++++- + drivers/net/ethernet/airoha/airoha_eth.h | 7 +++ + drivers/net/ethernet/airoha/airoha_ppe.c | 12 ++-- + drivers/net/ethernet/airoha/airoha_regs.h | 29 +++++++++ + 4 files changed, 111 insertions(+), 8 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1588,14 +1588,81 @@ static int airoha_dev_set_macaddr(struct + return 0; + } + ++static void airhoha_set_gdm2_loopback(struct airoha_gdm_port *port) ++{ ++ u32 pse_port = port->id == 3 ? FE_PSE_PORT_GDM3 : FE_PSE_PORT_GDM4; ++ struct airoha_eth *eth = port->qdma->eth; ++ u32 chan = port->id == 3 ? 4 : 0; ++ ++ /* Forward the traffic to the proper GDM port */ ++ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(2), pse_port); ++ airoha_fe_clear(eth, REG_GDM_FWD_CFG(2), GDM_STRIP_CRC); ++ ++ /* Enable GDM2 loopback */ ++ airoha_fe_wr(eth, REG_GDM_TXCHN_EN(2), 0xffffffff); ++ airoha_fe_wr(eth, REG_GDM_RXCHN_EN(2), 0xffff); ++ airoha_fe_rmw(eth, REG_GDM_LPBK_CFG(2), ++ LPBK_CHAN_MASK | LPBK_MODE_MASK | LPBK_EN_MASK, ++ FIELD_PREP(LPBK_CHAN_MASK, chan) | LPBK_EN_MASK); ++ airoha_fe_rmw(eth, REG_GDM_LEN_CFG(2), ++ GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, ++ FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | ++ FIELD_PREP(GDM_LONG_LEN_MASK, AIROHA_MAX_MTU)); ++ ++ /* Disable VIP and IFC for GDM2 */ ++ airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(2)); ++ airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(2)); ++ ++ if (port->id == 3) { ++ /* FIXME: handle XSI_PCE1_PORT */ ++ airoha_fe_wr(eth, REG_PPE_DFT_CPORT0(0), 0x5500); ++ airoha_fe_rmw(eth, REG_FE_WAN_PORT, ++ WAN1_EN_MASK | WAN1_MASK | WAN0_MASK, ++ FIELD_PREP(WAN0_MASK, HSGMII_LAN_PCIE0_SRCPORT)); ++ airoha_fe_rmw(eth, ++ REG_SP_DFT_CPORT(HSGMII_LAN_PCIE0_SRCPORT >> 3), ++ SP_CPORT_PCIE0_MASK, ++ FIELD_PREP(SP_CPORT_PCIE0_MASK, ++ FE_PSE_PORT_CDM2)); ++ } else { ++ /* FIXME: handle XSI_USB_PORT */ ++ airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6, ++ FC_ID_OF_SRC_PORT24_MASK, ++ FIELD_PREP(FC_ID_OF_SRC_PORT24_MASK, 2)); ++ airoha_fe_rmw(eth, REG_FE_WAN_PORT, ++ WAN1_EN_MASK | WAN1_MASK | WAN0_MASK, ++ FIELD_PREP(WAN0_MASK, HSGMII_LAN_ETH_SRCPORT)); ++ airoha_fe_rmw(eth, ++ REG_SP_DFT_CPORT(HSGMII_LAN_ETH_SRCPORT >> 3), ++ SP_CPORT_ETH_MASK, ++ FIELD_PREP(SP_CPORT_ETH_MASK, FE_PSE_PORT_CDM2)); ++ } ++} ++ + static int airoha_dev_init(struct net_device *dev) + { + struct airoha_gdm_port *port = netdev_priv(dev); + struct airoha_eth *eth = port->qdma->eth; ++ u32 pse_port; + + airoha_set_macaddr(port, dev->dev_addr); +- airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), +- FE_PSE_PORT_PPE1); ++ ++ switch (port->id) { ++ case 3: ++ case 4: ++ /* If GDM2 is active we can't enable loopback */ ++ if (!eth->ports[1]) ++ airhoha_set_gdm2_loopback(port); ++ fallthrough; ++ case 2: ++ pse_port = FE_PSE_PORT_PPE2; ++ break; ++ default: ++ pse_port = FE_PSE_PORT_PPE1; ++ break; ++ } ++ ++ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), pse_port); + + return 0; + } +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -68,6 +68,13 @@ enum { + }; + + enum { ++ HSGMII_LAN_PCIE0_SRCPORT = 0x16, ++ HSGMII_LAN_PCIE1_SRCPORT, ++ HSGMII_LAN_ETH_SRCPORT, ++ HSGMII_LAN_USB_SRCPORT, ++}; ++ ++enum { + XSI_PCIE0_VIP_PORT_MASK = BIT(22), + XSI_PCIE1_VIP_PORT_MASK = BIT(23), + XSI_USB_VIP_PORT_MASK = BIT(25), +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -216,7 +216,8 @@ static int airoha_ppe_foe_entry_prepare( + AIROHA_FOE_IB1_BIND_TTL; + hwe->ib1 = val; + +- val = FIELD_PREP(AIROHA_FOE_IB2_PORT_AG, 0x1f); ++ val = FIELD_PREP(AIROHA_FOE_IB2_PORT_AG, 0x1f) | ++ AIROHA_FOE_IB2_PSE_QOS; + if (dsa_port >= 0) + val |= FIELD_PREP(AIROHA_FOE_IB2_NBQ, dsa_port); + +@@ -224,14 +225,13 @@ static int airoha_ppe_foe_entry_prepare( + struct airoha_gdm_port *port = netdev_priv(dev); + u8 pse_port; + +- pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id; ++ if (dsa_port >= 0) ++ pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id; ++ else ++ pse_port = 2; /* uplink relies on GDM2 loopback */ + val |= FIELD_PREP(AIROHA_FOE_IB2_PSE_PORT, pse_port); + } + +- /* FIXME: implement QoS support setting pse_port to 2 (loopback) +- * for uplink and setting qos bit in ib2 +- */ +- + if (is_multicast_ether_addr(data->eth.h_dest)) + val |= AIROHA_FOE_IB2_MULTICAST; + +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -38,6 +38,12 @@ + #define FE_RST_CORE_MASK BIT(0) + + #define REG_FE_FOE_TS 0x0010 ++ ++#define REG_FE_WAN_PORT 0x0024 ++#define WAN1_EN_MASK BIT(16) ++#define WAN1_MASK GENMASK(12, 8) ++#define WAN0_MASK GENMASK(4, 0) ++ + #define REG_FE_WAN_MAC_H 0x0030 + #define REG_FE_LAN_MAC_H 0x0040 + +@@ -126,6 +132,7 @@ + #define GDM_IP4_CKSUM BIT(22) + #define GDM_TCP_CKSUM BIT(21) + #define GDM_UDP_CKSUM BIT(20) ++#define GDM_STRIP_CRC BIT(16) + #define GDM_UCFQ_MASK GENMASK(15, 12) + #define GDM_BCFQ_MASK GENMASK(11, 8) + #define GDM_MCFQ_MASK GENMASK(7, 4) +@@ -139,6 +146,16 @@ + #define GDM_SHORT_LEN_MASK GENMASK(13, 0) + #define GDM_LONG_LEN_MASK GENMASK(29, 16) + ++#define REG_GDM_LPBK_CFG(_n) (GDM_BASE(_n) + 0x1c) ++#define LPBK_GAP_MASK GENMASK(31, 24) ++#define LPBK_LEN_MASK GENMASK(23, 10) ++#define LPBK_CHAN_MASK GENMASK(8, 4) ++#define LPBK_MODE_MASK GENMASK(3, 1) ++#define LPBK_EN_MASK BIT(0) ++ ++#define REG_GDM_TXCHN_EN(_n) (GDM_BASE(_n) + 0x24) ++#define REG_GDM_RXCHN_EN(_n) (GDM_BASE(_n) + 0x28) ++ + #define REG_FE_CPORT_CFG (GDM1_BASE + 0x40) + #define FE_CPORT_PAD BIT(26) + #define FE_CPORT_PORT_XFC_MASK BIT(25) +@@ -351,6 +368,18 @@ + + #define REG_MC_VLAN_DATA 0x2108 + ++#define REG_SP_DFT_CPORT(_n) (0x20e0 + ((_n) << 2)) ++#define SP_CPORT_PCIE1_MASK GENMASK(31, 28) ++#define SP_CPORT_PCIE0_MASK GENMASK(27, 24) ++#define SP_CPORT_USB_MASK GENMASK(7, 4) ++#define SP_CPORT_ETH_MASK GENMASK(7, 4) ++ ++#define REG_SRC_PORT_FC_MAP6 0x2298 ++#define FC_ID_OF_SRC_PORT27_MASK GENMASK(28, 24) ++#define FC_ID_OF_SRC_PORT26_MASK GENMASK(20, 16) ++#define FC_ID_OF_SRC_PORT25_MASK GENMASK(12, 8) ++#define FC_ID_OF_SRC_PORT24_MASK GENMASK(4, 0) ++ + #define REG_CDM5_RX_OQ1_DROP_CNT 0x29d4 + + /* QDMA */ diff --git a/lede/target/linux/airoha/patches-6.12/048-15-v6.15-net-airoha-Introduce-PPE-debugfs-support.patch b/lede/target/linux/airoha/patches-6.12/048-15-v6.15-net-airoha-Introduce-PPE-debugfs-support.patch new file mode 100644 index 0000000000..50d7fa1266 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/048-15-v6.15-net-airoha-Introduce-PPE-debugfs-support.patch @@ -0,0 +1,291 @@ +From 3fe15c640f3808c3faf235553c67c867d1389e5c Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 28 Feb 2025 11:54:23 +0100 +Subject: [PATCH 15/15] net: airoha: Introduce PPE debugfs support + +Similar to PPE support for Mediatek devices, introduce PPE debugfs +in order to dump binded and unbinded flows. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/Makefile | 1 + + drivers/net/ethernet/airoha/airoha_eth.h | 14 ++ + drivers/net/ethernet/airoha/airoha_ppe.c | 17 +- + .../net/ethernet/airoha/airoha_ppe_debugfs.c | 181 ++++++++++++++++++ + 4 files changed, 209 insertions(+), 4 deletions(-) + create mode 100644 drivers/net/ethernet/airoha/airoha_ppe_debugfs.c + +--- a/drivers/net/ethernet/airoha/Makefile ++++ b/drivers/net/ethernet/airoha/Makefile +@@ -5,4 +5,5 @@ + + obj-$(CONFIG_NET_AIROHA) += airoha-eth.o + airoha-eth-y := airoha_eth.o airoha_ppe.o ++airoha-eth-$(CONFIG_DEBUG_FS) += airoha_ppe_debugfs.o + obj-$(CONFIG_NET_AIROHA_NPU) += airoha_npu.o +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -7,6 +7,7 @@ + #ifndef AIROHA_ETH_H + #define AIROHA_ETH_H + ++#include + #include + #include + #include +@@ -480,6 +481,8 @@ struct airoha_ppe { + + struct hlist_head *foe_flow; + u16 foe_check_time[PPE_NUM_ENTRIES]; ++ ++ struct dentry *debugfs_dir; + }; + + struct airoha_eth { +@@ -533,5 +536,16 @@ int airoha_ppe_setup_tc_block_cb(enum tc + void *cb_priv); + int airoha_ppe_init(struct airoha_eth *eth); + void airoha_ppe_deinit(struct airoha_eth *eth); ++struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe, ++ u32 hash); ++ ++#if CONFIG_DEBUG_FS ++int airoha_ppe_debugfs_init(struct airoha_ppe *ppe); ++#else ++static inline int airoha_ppe_debugfs_init(struct airoha_ppe *ppe) ++{ ++ return 0; ++} ++#endif + + #endif /* AIROHA_ETH_H */ +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -390,8 +390,8 @@ static u32 airoha_ppe_foe_get_entry_hash + return hash; + } + +-static struct airoha_foe_entry * +-airoha_ppe_foe_get_entry(struct airoha_ppe *ppe, u32 hash) ++struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe, ++ u32 hash) + { + if (hash < PPE_SRAM_NUM_ENTRIES) { + u32 *hwe = ppe->foe + hash * sizeof(struct airoha_foe_entry); +@@ -861,7 +861,7 @@ void airoha_ppe_check_skb(struct airoha_ + int airoha_ppe_init(struct airoha_eth *eth) + { + struct airoha_ppe *ppe; +- int foe_size; ++ int foe_size, err; + + ppe = devm_kzalloc(eth->dev, sizeof(*ppe), GFP_KERNEL); + if (!ppe) +@@ -882,7 +882,15 @@ int airoha_ppe_init(struct airoha_eth *e + if (!ppe->foe_flow) + return -ENOMEM; + +- return rhashtable_init(ð->flow_table, &airoha_flow_table_params); ++ err = rhashtable_init(ð->flow_table, &airoha_flow_table_params); ++ if (err) ++ return err; ++ ++ err = airoha_ppe_debugfs_init(ppe); ++ if (err) ++ rhashtable_destroy(ð->flow_table); ++ ++ return err; + } + + void airoha_ppe_deinit(struct airoha_eth *eth) +@@ -898,4 +906,5 @@ void airoha_ppe_deinit(struct airoha_eth + rcu_read_unlock(); + + rhashtable_destroy(ð->flow_table); ++ debugfs_remove(eth->ppe->debugfs_dir); + } +--- /dev/null ++++ b/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c +@@ -0,0 +1,181 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2025 AIROHA Inc ++ * Author: Lorenzo Bianconi ++ */ ++ ++#include "airoha_eth.h" ++ ++static void airoha_debugfs_ppe_print_tuple(struct seq_file *m, ++ void *src_addr, void *dest_addr, ++ u16 *src_port, u16 *dest_port, ++ bool ipv6) ++{ ++ __be32 n_addr[IPV6_ADDR_WORDS]; ++ ++ if (ipv6) { ++ ipv6_addr_cpu_to_be32(n_addr, src_addr); ++ seq_printf(m, "%pI6", n_addr); ++ } else { ++ seq_printf(m, "%pI4h", src_addr); ++ } ++ if (src_port) ++ seq_printf(m, ":%d", *src_port); ++ ++ seq_puts(m, "->"); ++ ++ if (ipv6) { ++ ipv6_addr_cpu_to_be32(n_addr, dest_addr); ++ seq_printf(m, "%pI6", n_addr); ++ } else { ++ seq_printf(m, "%pI4h", dest_addr); ++ } ++ if (dest_port) ++ seq_printf(m, ":%d", *dest_port); ++} ++ ++static int airoha_ppe_debugfs_foe_show(struct seq_file *m, void *private, ++ bool bind) ++{ ++ static const char *const ppe_type_str[] = { ++ [PPE_PKT_TYPE_IPV4_HNAPT] = "IPv4 5T", ++ [PPE_PKT_TYPE_IPV4_ROUTE] = "IPv4 3T", ++ [PPE_PKT_TYPE_BRIDGE] = "L2B", ++ [PPE_PKT_TYPE_IPV4_DSLITE] = "DS-LITE", ++ [PPE_PKT_TYPE_IPV6_ROUTE_3T] = "IPv6 3T", ++ [PPE_PKT_TYPE_IPV6_ROUTE_5T] = "IPv6 5T", ++ [PPE_PKT_TYPE_IPV6_6RD] = "6RD", ++ }; ++ static const char *const ppe_state_str[] = { ++ [AIROHA_FOE_STATE_INVALID] = "INV", ++ [AIROHA_FOE_STATE_UNBIND] = "UNB", ++ [AIROHA_FOE_STATE_BIND] = "BND", ++ [AIROHA_FOE_STATE_FIN] = "FIN", ++ }; ++ struct airoha_ppe *ppe = m->private; ++ int i; ++ ++ for (i = 0; i < PPE_NUM_ENTRIES; i++) { ++ const char *state_str, *type_str = "UNKNOWN"; ++ void *src_addr = NULL, *dest_addr = NULL; ++ u16 *src_port = NULL, *dest_port = NULL; ++ struct airoha_foe_mac_info_common *l2; ++ unsigned char h_source[ETH_ALEN] = {}; ++ unsigned char h_dest[ETH_ALEN]; ++ struct airoha_foe_entry *hwe; ++ u32 type, state, ib2, data; ++ bool ipv6 = false; ++ ++ hwe = airoha_ppe_foe_get_entry(ppe, i); ++ if (!hwe) ++ continue; ++ ++ state = FIELD_GET(AIROHA_FOE_IB1_BIND_STATE, hwe->ib1); ++ if (!state) ++ continue; ++ ++ if (bind && state != AIROHA_FOE_STATE_BIND) ++ continue; ++ ++ state_str = ppe_state_str[state % ARRAY_SIZE(ppe_state_str)]; ++ type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe->ib1); ++ if (type < ARRAY_SIZE(ppe_type_str) && ppe_type_str[type]) ++ type_str = ppe_type_str[type]; ++ ++ seq_printf(m, "%05x %s %7s", i, state_str, type_str); ++ ++ switch (type) { ++ case PPE_PKT_TYPE_IPV4_HNAPT: ++ case PPE_PKT_TYPE_IPV4_DSLITE: ++ src_port = &hwe->ipv4.orig_tuple.src_port; ++ dest_port = &hwe->ipv4.orig_tuple.dest_port; ++ fallthrough; ++ case PPE_PKT_TYPE_IPV4_ROUTE: ++ src_addr = &hwe->ipv4.orig_tuple.src_ip; ++ dest_addr = &hwe->ipv4.orig_tuple.dest_ip; ++ break; ++ case PPE_PKT_TYPE_IPV6_ROUTE_5T: ++ src_port = &hwe->ipv6.src_port; ++ dest_port = &hwe->ipv6.dest_port; ++ fallthrough; ++ case PPE_PKT_TYPE_IPV6_ROUTE_3T: ++ case PPE_PKT_TYPE_IPV6_6RD: ++ src_addr = &hwe->ipv6.src_ip; ++ dest_addr = &hwe->ipv6.dest_ip; ++ ipv6 = true; ++ break; ++ default: ++ break; ++ } ++ ++ if (src_addr && dest_addr) { ++ seq_puts(m, " orig="); ++ airoha_debugfs_ppe_print_tuple(m, src_addr, dest_addr, ++ src_port, dest_port, ipv6); ++ } ++ ++ switch (type) { ++ case PPE_PKT_TYPE_IPV4_HNAPT: ++ case PPE_PKT_TYPE_IPV4_DSLITE: ++ src_port = &hwe->ipv4.new_tuple.src_port; ++ dest_port = &hwe->ipv4.new_tuple.dest_port; ++ fallthrough; ++ case PPE_PKT_TYPE_IPV4_ROUTE: ++ src_addr = &hwe->ipv4.new_tuple.src_ip; ++ dest_addr = &hwe->ipv4.new_tuple.dest_ip; ++ seq_puts(m, " new="); ++ airoha_debugfs_ppe_print_tuple(m, src_addr, dest_addr, ++ src_port, dest_port, ++ ipv6); ++ break; ++ default: ++ break; ++ } ++ ++ if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T) { ++ data = hwe->ipv6.data; ++ ib2 = hwe->ipv6.ib2; ++ l2 = &hwe->ipv6.l2; ++ } else { ++ data = hwe->ipv4.data; ++ ib2 = hwe->ipv4.ib2; ++ l2 = &hwe->ipv4.l2.common; ++ *((__be16 *)&h_source[4]) = ++ cpu_to_be16(hwe->ipv4.l2.src_mac_lo); ++ } ++ ++ *((__be32 *)h_dest) = cpu_to_be32(l2->dest_mac_hi); ++ *((__be16 *)&h_dest[4]) = cpu_to_be16(l2->dest_mac_lo); ++ *((__be32 *)h_source) = cpu_to_be32(l2->src_mac_hi); ++ ++ seq_printf(m, " eth=%pM->%pM etype=%04x data=%08x" ++ " vlan=%d,%d ib1=%08x ib2=%08x\n", ++ h_source, h_dest, l2->etype, data, ++ l2->vlan1, l2->vlan2, hwe->ib1, ib2); ++ } ++ ++ return 0; ++} ++ ++static int airoha_ppe_debugfs_foe_all_show(struct seq_file *m, void *private) ++{ ++ return airoha_ppe_debugfs_foe_show(m, private, false); ++} ++DEFINE_SHOW_ATTRIBUTE(airoha_ppe_debugfs_foe_all); ++ ++static int airoha_ppe_debugfs_foe_bind_show(struct seq_file *m, void *private) ++{ ++ return airoha_ppe_debugfs_foe_show(m, private, true); ++} ++DEFINE_SHOW_ATTRIBUTE(airoha_ppe_debugfs_foe_bind); ++ ++int airoha_ppe_debugfs_init(struct airoha_ppe *ppe) ++{ ++ ppe->debugfs_dir = debugfs_create_dir("ppe", NULL); ++ debugfs_create_file("entries", 0444, ppe->debugfs_dir, ppe, ++ &airoha_ppe_debugfs_foe_all_fops); ++ debugfs_create_file("bind", 0444, ppe->debugfs_dir, ppe, ++ &airoha_ppe_debugfs_foe_bind_fops); ++ ++ return 0; ++} diff --git a/lede/target/linux/airoha/patches-6.12/049-01-v6.16-thermal-drivers-Add-support-for-Airoha-EN7581-therma.patch b/lede/target/linux/airoha/patches-6.12/049-01-v6.16-thermal-drivers-Add-support-for-Airoha-EN7581-therma.patch new file mode 100644 index 0000000000..ea68cab33e --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/049-01-v6.16-thermal-drivers-Add-support-for-Airoha-EN7581-therma.patch @@ -0,0 +1,550 @@ +From 42de37f40e1bc818df216dfa0918c114cfb5941d Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sun, 11 May 2025 20:49:55 +0200 +Subject: [PATCH] thermal/drivers: Add support for Airoha EN7581 thermal sensor + +Add support for Airoha EN7581 thermal sensor. This provide support for +reading the CPU or SoC Package sensor and to setup trip points for hot +and critical condition. An interrupt is fired to react on this and +doesn't require passive poll to read the temperature. + +The thermal regs provide a way to read the ADC value from an external +register placed in the Chip SCU regs. Monitor will read this value and +fire an interrupt if the trip condition configured is reached. + +The Thermal Trip and Interrupt logic is conceptually similar to Mediatek +LVTS Thermal but differ in register mapping and actual function/bug +workaround. The implementation only share some register names but from +functionality observation it's very different and used only for the +basic function of periodically poll the temp and trip the interrupt. + +Signed-off-by: Christian Marangi +Link: https://lore.kernel.org/r/20250511185003.3754495-2-ansuelsmth@gmail.com +Signed-off-by: Daniel Lezcano +--- + drivers/thermal/Kconfig | 9 + + drivers/thermal/Makefile | 1 + + drivers/thermal/airoha_thermal.c | 489 +++++++++++++++++++++++++++++++ + 3 files changed, 499 insertions(+) + create mode 100644 drivers/thermal/airoha_thermal.c + +--- a/drivers/thermal/Kconfig ++++ b/drivers/thermal/Kconfig +@@ -318,6 +318,15 @@ config QORIQ_THERMAL + cpufreq is used as the cooling device to throttle CPUs when the + passive trip is crossed. + ++config AIROHA_THERMAL ++ tristate "Airoha thermal sensor driver" ++ depends on ARCH_AIROHA || COMPILE_TEST ++ depends on MFD_SYSCON ++ depends on OF ++ help ++ Enable this to plug the Airoha thermal sensor driver into the Linux ++ thermal framework. ++ + config SPEAR_THERMAL + tristate "SPEAr thermal sensor driver" + depends on PLAT_SPEAR || COMPILE_TEST +--- a/drivers/thermal/Makefile ++++ b/drivers/thermal/Makefile +@@ -35,6 +35,7 @@ obj-$(CONFIG_K3_THERMAL) += k3_bandgap.o + # platform thermal drivers + obj-y += broadcom/ + obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o ++obj-$(CONFIG_AIROHA_THERMAL) += airoha_thermal.o + obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o + obj-$(CONFIG_SUN8I_THERMAL) += sun8i_thermal.o + obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o +--- /dev/null ++++ b/drivers/thermal/airoha_thermal.c +@@ -0,0 +1,489 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* SCU regs */ ++#define EN7581_PLLRG_PROTECT 0x268 ++#define EN7581_PWD_TADC 0x2ec ++#define EN7581_MUX_TADC GENMASK(3, 1) ++#define EN7581_DOUT_TADC 0x2f8 ++#define EN7581_DOUT_TADC_MASK GENMASK(15, 0) ++ ++/* PTP_THERMAL regs */ ++#define EN7581_TEMPMONCTL0 0x800 ++#define EN7581_SENSE3_EN BIT(3) ++#define EN7581_SENSE2_EN BIT(2) ++#define EN7581_SENSE1_EN BIT(1) ++#define EN7581_SENSE0_EN BIT(0) ++#define EN7581_TEMPMONCTL1 0x804 ++/* period unit calculated in BUS clock * 256 scaling-up */ ++#define EN7581_PERIOD_UNIT GENMASK(9, 0) ++#define EN7581_TEMPMONCTL2 0x808 ++#define EN7581_FILT_INTERVAL GENMASK(25, 16) ++#define EN7581_SEN_INTERVAL GENMASK(9, 0) ++#define EN7581_TEMPMONINT 0x80C ++#define EN7581_STAGE3_INT_EN BIT(31) ++#define EN7581_STAGE2_INT_EN BIT(30) ++#define EN7581_STAGE1_INT_EN BIT(29) ++#define EN7581_FILTER_INT_EN_3 BIT(28) ++#define EN7581_IMMD_INT_EN3 BIT(27) ++#define EN7581_NOHOTINTEN3 BIT(26) ++#define EN7581_HOFSINTEN3 BIT(25) ++#define EN7581_LOFSINTEN3 BIT(24) ++#define EN7581_HINTEN3 BIT(23) ++#define EN7581_CINTEN3 BIT(22) ++#define EN7581_FILTER_INT_EN_2 BIT(21) ++#define EN7581_FILTER_INT_EN_1 BIT(20) ++#define EN7581_FILTER_INT_EN_0 BIT(19) ++#define EN7581_IMMD_INT_EN2 BIT(18) ++#define EN7581_IMMD_INT_EN1 BIT(17) ++#define EN7581_IMMD_INT_EN0 BIT(16) ++#define EN7581_TIME_OUT_INT_EN BIT(15) ++#define EN7581_NOHOTINTEN2 BIT(14) ++#define EN7581_HOFSINTEN2 BIT(13) ++#define EN7581_LOFSINTEN2 BIT(12) ++#define EN7581_HINTEN2 BIT(11) ++#define EN7581_CINTEN2 BIT(10) ++#define EN7581_NOHOTINTEN1 BIT(9) ++#define EN7581_HOFSINTEN1 BIT(8) ++#define EN7581_LOFSINTEN1 BIT(7) ++#define EN7581_HINTEN1 BIT(6) ++#define EN7581_CINTEN1 BIT(5) ++#define EN7581_NOHOTINTEN0 BIT(4) ++/* Similar to COLD and HOT also these seems to be swapped in documentation */ ++#define EN7581_LOFSINTEN0 BIT(3) /* In documentation: BIT(2) */ ++#define EN7581_HOFSINTEN0 BIT(2) /* In documentation: BIT(3) */ ++/* It seems documentation have these swapped as the HW ++ * - Fire BIT(1) when lower than EN7581_COLD_THRE ++ * - Fire BIT(0) and BIT(5) when higher than EN7581_HOT2NORMAL_THRE or ++ * EN7581_HOT_THRE ++ */ ++#define EN7581_CINTEN0 BIT(1) /* In documentation: BIT(0) */ ++#define EN7581_HINTEN0 BIT(0) /* In documentation: BIT(1) */ ++#define EN7581_TEMPMONINTSTS 0x810 ++#define EN7581_STAGE3_INT_STAT BIT(31) ++#define EN7581_STAGE2_INT_STAT BIT(30) ++#define EN7581_STAGE1_INT_STAT BIT(29) ++#define EN7581_FILTER_INT_STAT_3 BIT(28) ++#define EN7581_IMMD_INT_STS3 BIT(27) ++#define EN7581_NOHOTINTSTS3 BIT(26) ++#define EN7581_HOFSINTSTS3 BIT(25) ++#define EN7581_LOFSINTSTS3 BIT(24) ++#define EN7581_HINTSTS3 BIT(23) ++#define EN7581_CINTSTS3 BIT(22) ++#define EN7581_FILTER_INT_STAT_2 BIT(21) ++#define EN7581_FILTER_INT_STAT_1 BIT(20) ++#define EN7581_FILTER_INT_STAT_0 BIT(19) ++#define EN7581_IMMD_INT_STS2 BIT(18) ++#define EN7581_IMMD_INT_STS1 BIT(17) ++#define EN7581_IMMD_INT_STS0 BIT(16) ++#define EN7581_TIME_OUT_INT_STAT BIT(15) ++#define EN7581_NOHOTINTSTS2 BIT(14) ++#define EN7581_HOFSINTSTS2 BIT(13) ++#define EN7581_LOFSINTSTS2 BIT(12) ++#define EN7581_HINTSTS2 BIT(11) ++#define EN7581_CINTSTS2 BIT(10) ++#define EN7581_NOHOTINTSTS1 BIT(9) ++#define EN7581_HOFSINTSTS1 BIT(8) ++#define EN7581_LOFSINTSTS1 BIT(7) ++#define EN7581_HINTSTS1 BIT(6) ++#define EN7581_CINTSTS1 BIT(5) ++#define EN7581_NOHOTINTSTS0 BIT(4) ++/* Similar to COLD and HOT also these seems to be swapped in documentation */ ++#define EN7581_LOFSINTSTS0 BIT(3) /* In documentation: BIT(2) */ ++#define EN7581_HOFSINTSTS0 BIT(2) /* In documentation: BIT(3) */ ++/* It seems documentation have these swapped as the HW ++ * - Fire BIT(1) when lower than EN7581_COLD_THRE ++ * - Fire BIT(0) and BIT(5) when higher than EN7581_HOT2NORMAL_THRE or ++ * EN7581_HOT_THRE ++ * ++ * To clear things, we swap the define but we keep them documented here. ++ */ ++#define EN7581_CINTSTS0 BIT(1) /* In documentation: BIT(0) */ ++#define EN7581_HINTSTS0 BIT(0) /* In documentation: BIT(1)*/ ++/* Monitor will take the bigger threshold between HOT2NORMAL and HOT ++ * and will fire both HOT2NORMAL and HOT interrupt when higher than the 2 ++ * ++ * It has also been observed that not setting HOT2NORMAL makes the monitor ++ * treat COLD threshold as HOT2NORMAL. ++ */ ++#define EN7581_TEMPH2NTHRE 0x824 ++/* It seems HOT2NORMAL is actually NORMAL2HOT */ ++#define EN7581_HOT2NORMAL_THRE GENMASK(11, 0) ++#define EN7581_TEMPHTHRE 0x828 ++#define EN7581_HOT_THRE GENMASK(11, 0) ++/* Monitor will use this as HOT2NORMAL (fire interrupt when lower than...)*/ ++#define EN7581_TEMPCTHRE 0x82c ++#define EN7581_COLD_THRE GENMASK(11, 0) ++/* Also LOW and HIGH offset register are swapped */ ++#define EN7581_TEMPOFFSETL 0x830 /* In documentation: 0x834 */ ++#define EN7581_LOW_OFFSET GENMASK(11, 0) ++#define EN7581_TEMPOFFSETH 0x834 /* In documentation: 0x830 */ ++#define EN7581_HIGH_OFFSET GENMASK(11, 0) ++#define EN7581_TEMPMSRCTL0 0x838 ++#define EN7581_MSRCTL3 GENMASK(11, 9) ++#define EN7581_MSRCTL2 GENMASK(8, 6) ++#define EN7581_MSRCTL1 GENMASK(5, 3) ++#define EN7581_MSRCTL0 GENMASK(2, 0) ++#define EN7581_TEMPADCVALIDADDR 0x878 ++#define EN7581_ADC_VALID_ADDR GENMASK(31, 0) ++#define EN7581_TEMPADCVOLTADDR 0x87c ++#define EN7581_ADC_VOLT_ADDR GENMASK(31, 0) ++#define EN7581_TEMPRDCTRL 0x880 ++/* ++ * NOTICE: AHB have this set to 0 by default. Means that ++ * the same addr is used for ADC volt and valid reading. ++ * In such case, VALID ADDR is used and volt addr is ignored. ++ */ ++#define EN7581_RD_CTRL_DIFF BIT(0) ++#define EN7581_TEMPADCVALIDMASK 0x884 ++#define EN7581_ADV_RD_VALID_POLARITY BIT(5) ++#define EN7581_ADV_RD_VALID_POS GENMASK(4, 0) ++#define EN7581_TEMPADCVOLTAGESHIFT 0x888 ++#define EN7581_ADC_VOLTAGE_SHIFT GENMASK(4, 0) ++/* ++ * Same values for each CTL. ++ * Can operate in: ++ * - 1 sample ++ * - 2 sample and make average of them ++ * - 4,6,10,16 sample, drop max and min and make avgerage of them ++ */ ++#define EN7581_MSRCTL_1SAMPLE 0x0 ++#define EN7581_MSRCTL_AVG2SAMPLE 0x1 ++#define EN7581_MSRCTL_4SAMPLE_MAX_MIX_AVG2 0x2 ++#define EN7581_MSRCTL_6SAMPLE_MAX_MIX_AVG4 0x3 ++#define EN7581_MSRCTL_10SAMPLE_MAX_MIX_AVG8 0x4 ++#define EN7581_MSRCTL_18SAMPLE_MAX_MIX_AVG16 0x5 ++#define EN7581_TEMPAHBPOLL 0x840 ++#define EN7581_ADC_POLL_INTVL GENMASK(31, 0) ++/* PTPSPARE0,2 reg are used to store efuse info for calibrated temp offset */ ++#define EN7581_EFUSE_TEMP_OFFSET_REG 0xf20 /* PTPSPARE0 */ ++#define EN7581_EFUSE_TEMP_OFFSET GENMASK(31, 16) ++#define EN7581_PTPSPARE1 0xf24 /* PTPSPARE1 */ ++#define EN7581_EFUSE_TEMP_CPU_SENSOR_REG 0xf28 /* PTPSPARE2 */ ++ ++#define EN7581_SLOPE_X100_DIO_DEFAULT 5645 ++#define EN7581_SLOPE_X100_DIO_AVS 5645 ++ ++#define EN7581_INIT_TEMP_CPK_X10 300 ++#define EN7581_INIT_TEMP_FTK_X10 620 ++#define EN7581_INIT_TEMP_NONK_X10 550 ++ ++#define EN7581_SCU_THERMAL_PROTECT_KEY 0x12 ++#define EN7581_SCU_THERMAL_MUX_DIODE1 0x7 ++ ++/* Convert temp to raw value as read from ADC ((((temp / 100) - init) * slope) / 1000) + offset */ ++#define TEMP_TO_RAW(priv, temp) ((((((temp) / 100) - (priv)->init_temp) * \ ++ (priv)->default_slope) / 1000) + \ ++ (priv)->default_offset) ++ ++/* Convert raw to temp ((((temp - offset) * 1000) / slope + init) * 100) */ ++#define RAW_TO_TEMP(priv, raw) (((((raw) - (priv)->default_offset) * 1000) / \ ++ (priv)->default_slope + \ ++ (priv)->init_temp) * 100) ++ ++#define AIROHA_MAX_SAMPLES 6 ++ ++struct airoha_thermal_priv { ++ void __iomem *base; ++ struct regmap *chip_scu; ++ struct resource scu_adc_res; ++ ++ struct thermal_zone_device *tz; ++ int init_temp; ++ int default_slope; ++ int default_offset; ++}; ++ ++static int airoha_get_thermal_ADC(struct airoha_thermal_priv *priv) ++{ ++ u32 val; ++ ++ regmap_read(priv->chip_scu, EN7581_DOUT_TADC, &val); ++ return FIELD_GET(EN7581_DOUT_TADC_MASK, val); ++} ++ ++static void airoha_init_thermal_ADC_mode(struct airoha_thermal_priv *priv) ++{ ++ u32 adc_mux, pllrg; ++ ++ /* Save PLLRG current value */ ++ regmap_read(priv->chip_scu, EN7581_PLLRG_PROTECT, &pllrg); ++ ++ /* Give access to thermal regs */ ++ regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT, EN7581_SCU_THERMAL_PROTECT_KEY); ++ adc_mux = FIELD_PREP(EN7581_MUX_TADC, EN7581_SCU_THERMAL_MUX_DIODE1); ++ regmap_write(priv->chip_scu, EN7581_PWD_TADC, adc_mux); ++ ++ /* Restore PLLRG value on exit */ ++ regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT, pllrg); ++} ++ ++static int airoha_thermal_get_temp(struct thermal_zone_device *tz, int *temp) ++{ ++ struct airoha_thermal_priv *priv = thermal_zone_device_priv(tz); ++ int min_value, max_value, avg_value, value; ++ int i; ++ ++ avg_value = 0; ++ min_value = INT_MAX; ++ max_value = INT_MIN; ++ ++ for (i = 0; i < AIROHA_MAX_SAMPLES; i++) { ++ value = airoha_get_thermal_ADC(priv); ++ min_value = min(value, min_value); ++ max_value = max(value, max_value); ++ avg_value += value; ++ } ++ ++ /* Drop min and max and average for the remaining sample */ ++ avg_value -= (min_value + max_value); ++ avg_value /= AIROHA_MAX_SAMPLES - 2; ++ ++ *temp = RAW_TO_TEMP(priv, avg_value); ++ return 0; ++} ++ ++static int airoha_thermal_set_trips(struct thermal_zone_device *tz, int low, ++ int high) ++{ ++ struct airoha_thermal_priv *priv = thermal_zone_device_priv(tz); ++ bool enable_monitor = false; ++ ++ if (high != INT_MAX) { ++ /* Validate high and clamp it a supported value */ ++ high = clamp_t(int, high, RAW_TO_TEMP(priv, 0), ++ RAW_TO_TEMP(priv, FIELD_MAX(EN7581_DOUT_TADC_MASK))); ++ ++ /* We offset the high temp of 1°C to trigger correct event */ ++ writel(TEMP_TO_RAW(priv, high) >> 4, ++ priv->base + EN7581_TEMPOFFSETH); ++ ++ enable_monitor = true; ++ } ++ ++ if (low != -INT_MAX) { ++ /* Validate low and clamp it to a supported value */ ++ low = clamp_t(int, high, RAW_TO_TEMP(priv, 0), ++ RAW_TO_TEMP(priv, FIELD_MAX(EN7581_DOUT_TADC_MASK))); ++ ++ /* We offset the low temp of 1°C to trigger correct event */ ++ writel(TEMP_TO_RAW(priv, low) >> 4, ++ priv->base + EN7581_TEMPOFFSETL); ++ ++ enable_monitor = true; ++ } ++ ++ /* Enable sensor 0 monitor after trip are set */ ++ if (enable_monitor) ++ writel(EN7581_SENSE0_EN, priv->base + EN7581_TEMPMONCTL0); ++ ++ return 0; ++} ++ ++static const struct thermal_zone_device_ops thdev_ops = { ++ .get_temp = airoha_thermal_get_temp, ++ .set_trips = airoha_thermal_set_trips, ++}; ++ ++static irqreturn_t airoha_thermal_irq(int irq, void *data) ++{ ++ struct airoha_thermal_priv *priv = data; ++ enum thermal_notify_event event; ++ bool update = false; ++ u32 status; ++ ++ status = readl(priv->base + EN7581_TEMPMONINTSTS); ++ switch (status & (EN7581_HOFSINTSTS0 | EN7581_LOFSINTSTS0)) { ++ case EN7581_HOFSINTSTS0: ++ event = THERMAL_TRIP_VIOLATED; ++ update = true; ++ break; ++ case EN7581_LOFSINTSTS0: ++ event = THERMAL_EVENT_UNSPECIFIED; ++ update = true; ++ break; ++ default: ++ /* Should be impossible as we enable only these Interrupt */ ++ break; ++ } ++ ++ /* Reset Interrupt */ ++ writel(status, priv->base + EN7581_TEMPMONINTSTS); ++ ++ if (update) ++ thermal_zone_device_update(priv->tz, event); ++ ++ return IRQ_HANDLED; ++} ++ ++static void airoha_thermal_setup_adc_val(struct device *dev, ++ struct airoha_thermal_priv *priv) ++{ ++ u32 efuse_calib_info, cpu_sensor; ++ ++ /* Setup thermal sensor to ADC mode and setup the mux to DIODE1 */ ++ airoha_init_thermal_ADC_mode(priv); ++ /* sleep 10 ms for ADC to enable */ ++ usleep_range(10 * USEC_PER_MSEC, 11 * USEC_PER_MSEC); ++ ++ efuse_calib_info = readl(priv->base + EN7581_EFUSE_TEMP_OFFSET_REG); ++ if (efuse_calib_info) { ++ priv->default_offset = FIELD_GET(EN7581_EFUSE_TEMP_OFFSET, efuse_calib_info); ++ /* Different slope are applied if the sensor is used for CPU or for package */ ++ cpu_sensor = readl(priv->base + EN7581_EFUSE_TEMP_CPU_SENSOR_REG); ++ if (cpu_sensor) { ++ priv->default_slope = EN7581_SLOPE_X100_DIO_DEFAULT; ++ priv->init_temp = EN7581_INIT_TEMP_FTK_X10; ++ } else { ++ priv->default_slope = EN7581_SLOPE_X100_DIO_AVS; ++ priv->init_temp = EN7581_INIT_TEMP_CPK_X10; ++ } ++ } else { ++ priv->default_offset = airoha_get_thermal_ADC(priv); ++ priv->default_slope = EN7581_SLOPE_X100_DIO_DEFAULT; ++ priv->init_temp = EN7581_INIT_TEMP_NONK_X10; ++ dev_info(dev, "missing thermal calibrarion EFUSE, using non calibrated value\n"); ++ } ++} ++ ++static void airoha_thermal_setup_monitor(struct airoha_thermal_priv *priv) ++{ ++ /* Set measure mode */ ++ writel(FIELD_PREP(EN7581_MSRCTL0, EN7581_MSRCTL_6SAMPLE_MAX_MIX_AVG4), ++ priv->base + EN7581_TEMPMSRCTL0); ++ ++ /* ++ * Configure ADC valid reading addr ++ * The AHB temp monitor system doesn't have direct access to the ++ * thermal sensor. It does instead work by providing all kind of ++ * address to configure how to access and setup an ADC for the ++ * sensor. EN7581 supports only one sensor hence the ++ * implementation is greatly simplified but the AHB supports ++ * up to 4 different sensor from the same ADC that can be ++ * switched by tuning the ADC mux or wiriting address. ++ * ++ * We set valid instead of volt as we don't enable valid/volt ++ * split reading and AHB read valid addr in such case. ++ */ ++ writel(priv->scu_adc_res.start + EN7581_DOUT_TADC, ++ priv->base + EN7581_TEMPADCVALIDADDR); ++ ++ /* ++ * Configure valid bit on a fake value of bit 16. The ADC outputs ++ * max of 2 bytes for voltage. ++ */ ++ writel(FIELD_PREP(EN7581_ADV_RD_VALID_POS, 16), ++ priv->base + EN7581_TEMPADCVALIDMASK); ++ ++ /* ++ * AHB supports max 12 bytes for ADC voltage. Shift the read ++ * value 4 bit to the right. Precision lost by this is minimal ++ * in the order of half a °C and is acceptable in the context ++ * of triggering interrupt in critical condition. ++ */ ++ writel(FIELD_PREP(EN7581_ADC_VOLTAGE_SHIFT, 4), ++ priv->base + EN7581_TEMPADCVOLTAGESHIFT); ++ ++ /* BUS clock is 300MHz counting unit is 3 * 68.64 * 256 = 52.715us */ ++ writel(FIELD_PREP(EN7581_PERIOD_UNIT, 3), ++ priv->base + EN7581_TEMPMONCTL1); ++ ++ /* ++ * filt interval is 1 * 52.715us = 52.715us, ++ * sen interval is 379 * 52.715us = 19.97ms ++ */ ++ writel(FIELD_PREP(EN7581_FILT_INTERVAL, 1) | ++ FIELD_PREP(EN7581_FILT_INTERVAL, 379), ++ priv->base + EN7581_TEMPMONCTL2); ++ ++ /* AHB poll is set to 146 * 68.64 = 10.02us */ ++ writel(FIELD_PREP(EN7581_ADC_POLL_INTVL, 146), ++ priv->base + EN7581_TEMPAHBPOLL); ++} ++ ++static int airoha_thermal_probe(struct platform_device *pdev) ++{ ++ struct airoha_thermal_priv *priv; ++ struct device_node *chip_scu_np; ++ struct device *dev = &pdev->dev; ++ int irq, ret; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(priv->base)) ++ return PTR_ERR(priv->base); ++ ++ chip_scu_np = of_parse_phandle(dev->of_node, "airoha,chip-scu", 0); ++ if (!chip_scu_np) ++ return -EINVAL; ++ ++ priv->chip_scu = syscon_node_to_regmap(chip_scu_np); ++ if (IS_ERR(priv->chip_scu)) ++ return PTR_ERR(priv->chip_scu); ++ ++ of_address_to_resource(chip_scu_np, 0, &priv->scu_adc_res); ++ of_node_put(chip_scu_np); ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) ++ return irq; ++ ++ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, ++ airoha_thermal_irq, IRQF_ONESHOT, ++ pdev->name, priv); ++ if (ret) { ++ dev_err(dev, "Can't get interrupt working.\n"); ++ return ret; ++ } ++ ++ airoha_thermal_setup_monitor(priv); ++ airoha_thermal_setup_adc_val(dev, priv); ++ ++ /* register of thermal sensor and get info from DT */ ++ priv->tz = devm_thermal_of_zone_register(dev, 0, priv, &thdev_ops); ++ if (IS_ERR(priv->tz)) { ++ dev_err(dev, "register thermal zone sensor failed\n"); ++ return PTR_ERR(priv->tz); ++ } ++ ++ platform_set_drvdata(pdev, priv); ++ ++ /* Enable LOW and HIGH interrupt */ ++ writel(EN7581_HOFSINTEN0 | EN7581_LOFSINTEN0, ++ priv->base + EN7581_TEMPMONINT); ++ ++ return 0; ++} ++ ++static const struct of_device_id airoha_thermal_match[] = { ++ { .compatible = "airoha,en7581-thermal" }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, airoha_thermal_match); ++ ++static struct platform_driver airoha_thermal_driver = { ++ .driver = { ++ .name = "airoha-thermal", ++ .of_match_table = airoha_thermal_match, ++ }, ++ .probe = airoha_thermal_probe, ++}; ++ ++module_platform_driver(airoha_thermal_driver); ++ ++MODULE_AUTHOR("Christian Marangi "); ++MODULE_DESCRIPTION("Airoha thermal driver"); ++MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/airoha/patches-6.12/049-02-v6.16-thermal-drivers-airoha-Fix-spelling-mistake.patch b/lede/target/linux/airoha/patches-6.12/049-02-v6.16-thermal-drivers-airoha-Fix-spelling-mistake.patch new file mode 100644 index 0000000000..7b1b9478c3 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/049-02-v6.16-thermal-drivers-airoha-Fix-spelling-mistake.patch @@ -0,0 +1,44 @@ +From e23cba0ab49a9cf95e9bc3a86cfbf336b0e285f6 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 14 May 2025 23:39:12 +0200 +Subject: [PATCH] thermal/drivers/airoha: Fix spelling mistake + +Fix various spelling mistake in airoha_thermal_setup_monitor() and +define. + +Reported-by: Alok Tiwari +Signed-off-by: Christian Marangi +Link: https://lore.kernel.org/r/20250514213919.2321490-1-ansuelsmth@gmail.com +Signed-off-by: Daniel Lezcano +--- + drivers/thermal/airoha_thermal.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/thermal/airoha_thermal.c ++++ b/drivers/thermal/airoha_thermal.c +@@ -155,7 +155,7 @@ + * Can operate in: + * - 1 sample + * - 2 sample and make average of them +- * - 4,6,10,16 sample, drop max and min and make avgerage of them ++ * - 4,6,10,16 sample, drop max and min and make average of them + */ + #define EN7581_MSRCTL_1SAMPLE 0x0 + #define EN7581_MSRCTL_AVG2SAMPLE 0x1 +@@ -365,12 +365,12 @@ static void airoha_thermal_setup_monitor + /* + * Configure ADC valid reading addr + * The AHB temp monitor system doesn't have direct access to the +- * thermal sensor. It does instead work by providing all kind of +- * address to configure how to access and setup an ADC for the ++ * thermal sensor. It does instead work by providing various ++ * addresses to configure how to access and setup an ADC for the + * sensor. EN7581 supports only one sensor hence the + * implementation is greatly simplified but the AHB supports +- * up to 4 different sensor from the same ADC that can be +- * switched by tuning the ADC mux or wiriting address. ++ * up to 4 different sensors from the same ADC that can be ++ * switched by tuning the ADC mux or writing address. + * + * We set valid instead of volt as we don't enable valid/volt + * split reading and AHB read valid addr in such case. diff --git a/lede/target/linux/airoha/patches-6.12/051-v6.15-pinctrl-airoha-fix-wrong-PHY-LED-mapping-and-PHY2-LE.patch b/lede/target/linux/airoha/patches-6.12/051-v6.15-pinctrl-airoha-fix-wrong-PHY-LED-mapping-and-PHY2-LE.patch new file mode 100644 index 0000000000..15bbee2a24 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/051-v6.15-pinctrl-airoha-fix-wrong-PHY-LED-mapping-and-PHY2-LE.patch @@ -0,0 +1,435 @@ +From 457d9772e8a5cdae64f66b5f7d5b0247365191ec Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 1 Apr 2025 15:50:21 +0200 +Subject: [PATCH] pinctrl: airoha: fix wrong PHY LED mapping and PHY2 LED + defines + +The current PHY2 LED define are wrong and actually set BITs outside the +related mask. Fix it and set the correct value. While at it, also use +FIELD_PREP_CONST macro to make it simple to understand what values are +actually applied for the mask. + +Also fix wrong PHY LED mapping. The SoC Switch supports up to 4 port but +the register define mapping for 5 PHY port, starting from 0. The mapping +was wrongly defined starting from PHY1. Reorder the function group to +start from PHY0. PHY4 is actually never supported as we don't have a +GPIO pin to assign. + +Cc: stable@vger.kernel.org +Fixes: 1c8ace2d0725 ("pinctrl: airoha: Add support for EN7581 SoC") +Reviewed-by: Benjamin Larsson +Signed-off-by: Christian Marangi +Acked-by: Lorenzo Bianconi +Link: https://lore.kernel.org/20250401135026.18018-1-ansuelsmth@gmail.com +Signed-off-by: Linus Walleij +--- + drivers/pinctrl/mediatek/pinctrl-airoha.c | 159 ++++++++++------------ + 1 file changed, 70 insertions(+), 89 deletions(-) + +--- a/drivers/pinctrl/mediatek/pinctrl-airoha.c ++++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c +@@ -6,6 +6,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -112,39 +113,19 @@ + #define REG_LAN_LED1_MAPPING 0x0280 + + #define LAN4_LED_MAPPING_MASK GENMASK(18, 16) +-#define LAN4_PHY4_LED_MAP BIT(18) +-#define LAN4_PHY2_LED_MAP BIT(17) +-#define LAN4_PHY1_LED_MAP BIT(16) +-#define LAN4_PHY0_LED_MAP 0 +-#define LAN4_PHY3_LED_MAP GENMASK(17, 16) ++#define LAN4_PHY_LED_MAP(_n) FIELD_PREP_CONST(LAN4_LED_MAPPING_MASK, (_n)) + + #define LAN3_LED_MAPPING_MASK GENMASK(14, 12) +-#define LAN3_PHY4_LED_MAP BIT(14) +-#define LAN3_PHY2_LED_MAP BIT(13) +-#define LAN3_PHY1_LED_MAP BIT(12) +-#define LAN3_PHY0_LED_MAP 0 +-#define LAN3_PHY3_LED_MAP GENMASK(13, 12) ++#define LAN3_PHY_LED_MAP(_n) FIELD_PREP_CONST(LAN3_LED_MAPPING_MASK, (_n)) + + #define LAN2_LED_MAPPING_MASK GENMASK(10, 8) +-#define LAN2_PHY4_LED_MAP BIT(12) +-#define LAN2_PHY2_LED_MAP BIT(11) +-#define LAN2_PHY1_LED_MAP BIT(10) +-#define LAN2_PHY0_LED_MAP 0 +-#define LAN2_PHY3_LED_MAP GENMASK(11, 10) ++#define LAN2_PHY_LED_MAP(_n) FIELD_PREP_CONST(LAN2_LED_MAPPING_MASK, (_n)) + + #define LAN1_LED_MAPPING_MASK GENMASK(6, 4) +-#define LAN1_PHY4_LED_MAP BIT(6) +-#define LAN1_PHY2_LED_MAP BIT(5) +-#define LAN1_PHY1_LED_MAP BIT(4) +-#define LAN1_PHY0_LED_MAP 0 +-#define LAN1_PHY3_LED_MAP GENMASK(5, 4) ++#define LAN1_PHY_LED_MAP(_n) FIELD_PREP_CONST(LAN1_LED_MAPPING_MASK, (_n)) + + #define LAN0_LED_MAPPING_MASK GENMASK(2, 0) +-#define LAN0_PHY4_LED_MAP BIT(3) +-#define LAN0_PHY2_LED_MAP BIT(2) +-#define LAN0_PHY1_LED_MAP BIT(1) +-#define LAN0_PHY0_LED_MAP 0 +-#define LAN0_PHY3_LED_MAP GENMASK(2, 1) ++#define LAN0_PHY_LED_MAP(_n) FIELD_PREP_CONST(LAN0_LED_MAPPING_MASK, (_n)) + + /* CONF */ + #define REG_I2C_SDA_E2 0x001c +@@ -1476,8 +1457,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, +- LAN1_LED_MAPPING_MASK, +- LAN1_PHY1_LED_MAP ++ LAN0_LED_MAPPING_MASK, ++ LAN0_PHY_LED_MAP(0) + }, + .regmap_size = 2, + }, { +@@ -1491,8 +1472,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, +- LAN2_LED_MAPPING_MASK, +- LAN2_PHY1_LED_MAP ++ LAN1_LED_MAPPING_MASK, ++ LAN1_PHY_LED_MAP(0) + }, + .regmap_size = 2, + }, { +@@ -1506,8 +1487,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, +- LAN3_LED_MAPPING_MASK, +- LAN3_PHY1_LED_MAP ++ LAN2_LED_MAPPING_MASK, ++ LAN2_PHY_LED_MAP(0) + }, + .regmap_size = 2, + }, { +@@ -1521,8 +1502,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, +- LAN4_LED_MAPPING_MASK, +- LAN4_PHY1_LED_MAP ++ LAN3_LED_MAPPING_MASK, ++ LAN3_PHY_LED_MAP(0) + }, + .regmap_size = 2, + }, +@@ -1540,8 +1521,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, +- LAN1_LED_MAPPING_MASK, +- LAN1_PHY2_LED_MAP ++ LAN0_LED_MAPPING_MASK, ++ LAN0_PHY_LED_MAP(1) + }, + .regmap_size = 2, + }, { +@@ -1555,8 +1536,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, +- LAN2_LED_MAPPING_MASK, +- LAN2_PHY2_LED_MAP ++ LAN1_LED_MAPPING_MASK, ++ LAN1_PHY_LED_MAP(1) + }, + .regmap_size = 2, + }, { +@@ -1570,8 +1551,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, +- LAN3_LED_MAPPING_MASK, +- LAN3_PHY2_LED_MAP ++ LAN2_LED_MAPPING_MASK, ++ LAN2_PHY_LED_MAP(1) + }, + .regmap_size = 2, + }, { +@@ -1585,8 +1566,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, +- LAN4_LED_MAPPING_MASK, +- LAN4_PHY2_LED_MAP ++ LAN3_LED_MAPPING_MASK, ++ LAN3_PHY_LED_MAP(1) + }, + .regmap_size = 2, + }, +@@ -1604,8 +1585,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, +- LAN1_LED_MAPPING_MASK, +- LAN1_PHY3_LED_MAP ++ LAN0_LED_MAPPING_MASK, ++ LAN0_PHY_LED_MAP(2) + }, + .regmap_size = 2, + }, { +@@ -1619,8 +1600,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, +- LAN2_LED_MAPPING_MASK, +- LAN2_PHY3_LED_MAP ++ LAN1_LED_MAPPING_MASK, ++ LAN1_PHY_LED_MAP(2) + }, + .regmap_size = 2, + }, { +@@ -1634,8 +1615,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, +- LAN3_LED_MAPPING_MASK, +- LAN3_PHY3_LED_MAP ++ LAN2_LED_MAPPING_MASK, ++ LAN2_PHY_LED_MAP(2) + }, + .regmap_size = 2, + }, { +@@ -1649,8 +1630,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, +- LAN4_LED_MAPPING_MASK, +- LAN4_PHY3_LED_MAP ++ LAN3_LED_MAPPING_MASK, ++ LAN3_PHY_LED_MAP(2) + }, + .regmap_size = 2, + }, +@@ -1668,8 +1649,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, +- LAN1_LED_MAPPING_MASK, +- LAN1_PHY4_LED_MAP ++ LAN0_LED_MAPPING_MASK, ++ LAN0_PHY_LED_MAP(3) + }, + .regmap_size = 2, + }, { +@@ -1683,8 +1664,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, +- LAN2_LED_MAPPING_MASK, +- LAN2_PHY4_LED_MAP ++ LAN1_LED_MAPPING_MASK, ++ LAN1_PHY_LED_MAP(3) + }, + .regmap_size = 2, + }, { +@@ -1698,8 +1679,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, +- LAN3_LED_MAPPING_MASK, +- LAN3_PHY4_LED_MAP ++ LAN2_LED_MAPPING_MASK, ++ LAN2_PHY_LED_MAP(3) + }, + .regmap_size = 2, + }, { +@@ -1713,8 +1694,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED0_MAPPING, +- LAN4_LED_MAPPING_MASK, +- LAN4_PHY4_LED_MAP ++ LAN3_LED_MAPPING_MASK, ++ LAN3_PHY_LED_MAP(3) + }, + .regmap_size = 2, + }, +@@ -1732,8 +1713,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, +- LAN1_LED_MAPPING_MASK, +- LAN1_PHY1_LED_MAP ++ LAN0_LED_MAPPING_MASK, ++ LAN0_PHY_LED_MAP(0) + }, + .regmap_size = 2, + }, { +@@ -1747,8 +1728,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, +- LAN2_LED_MAPPING_MASK, +- LAN2_PHY1_LED_MAP ++ LAN1_LED_MAPPING_MASK, ++ LAN1_PHY_LED_MAP(0) + }, + .regmap_size = 2, + }, { +@@ -1762,8 +1743,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, +- LAN3_LED_MAPPING_MASK, +- LAN3_PHY1_LED_MAP ++ LAN2_LED_MAPPING_MASK, ++ LAN2_PHY_LED_MAP(0) + }, + .regmap_size = 2, + }, { +@@ -1777,8 +1758,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, +- LAN4_LED_MAPPING_MASK, +- LAN4_PHY1_LED_MAP ++ LAN3_LED_MAPPING_MASK, ++ LAN3_PHY_LED_MAP(0) + }, + .regmap_size = 2, + }, +@@ -1796,8 +1777,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, +- LAN1_LED_MAPPING_MASK, +- LAN1_PHY2_LED_MAP ++ LAN0_LED_MAPPING_MASK, ++ LAN0_PHY_LED_MAP(1) + }, + .regmap_size = 2, + }, { +@@ -1811,8 +1792,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, +- LAN2_LED_MAPPING_MASK, +- LAN2_PHY2_LED_MAP ++ LAN1_LED_MAPPING_MASK, ++ LAN1_PHY_LED_MAP(1) + }, + .regmap_size = 2, + }, { +@@ -1826,8 +1807,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, +- LAN3_LED_MAPPING_MASK, +- LAN3_PHY2_LED_MAP ++ LAN2_LED_MAPPING_MASK, ++ LAN2_PHY_LED_MAP(1) + }, + .regmap_size = 2, + }, { +@@ -1841,8 +1822,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, +- LAN4_LED_MAPPING_MASK, +- LAN4_PHY2_LED_MAP ++ LAN3_LED_MAPPING_MASK, ++ LAN3_PHY_LED_MAP(1) + }, + .regmap_size = 2, + }, +@@ -1860,8 +1841,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, +- LAN1_LED_MAPPING_MASK, +- LAN1_PHY3_LED_MAP ++ LAN0_LED_MAPPING_MASK, ++ LAN0_PHY_LED_MAP(2) + }, + .regmap_size = 2, + }, { +@@ -1875,8 +1856,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, +- LAN2_LED_MAPPING_MASK, +- LAN2_PHY3_LED_MAP ++ LAN1_LED_MAPPING_MASK, ++ LAN1_PHY_LED_MAP(2) + }, + .regmap_size = 2, + }, { +@@ -1890,8 +1871,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, +- LAN3_LED_MAPPING_MASK, +- LAN3_PHY3_LED_MAP ++ LAN2_LED_MAPPING_MASK, ++ LAN2_PHY_LED_MAP(2) + }, + .regmap_size = 2, + }, { +@@ -1905,8 +1886,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, +- LAN4_LED_MAPPING_MASK, +- LAN4_PHY3_LED_MAP ++ LAN3_LED_MAPPING_MASK, ++ LAN3_PHY_LED_MAP(2) + }, + .regmap_size = 2, + }, +@@ -1924,8 +1905,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, +- LAN1_LED_MAPPING_MASK, +- LAN1_PHY4_LED_MAP ++ LAN0_LED_MAPPING_MASK, ++ LAN0_PHY_LED_MAP(3) + }, + .regmap_size = 2, + }, { +@@ -1939,8 +1920,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, +- LAN2_LED_MAPPING_MASK, +- LAN2_PHY4_LED_MAP ++ LAN1_LED_MAPPING_MASK, ++ LAN1_PHY_LED_MAP(3) + }, + .regmap_size = 2, + }, { +@@ -1954,8 +1935,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, +- LAN3_LED_MAPPING_MASK, +- LAN3_PHY4_LED_MAP ++ LAN2_LED_MAPPING_MASK, ++ LAN2_PHY_LED_MAP(3) + }, + .regmap_size = 2, + }, { +@@ -1969,8 +1950,8 @@ static const struct airoha_pinctrl_func_ + .regmap[1] = { + AIROHA_FUNC_MUX, + REG_LAN_LED1_MAPPING, +- LAN4_LED_MAPPING_MASK, +- LAN4_PHY4_LED_MAP ++ LAN3_LED_MAPPING_MASK, ++ LAN3_PHY_LED_MAP(3) + }, + .regmap_size = 2, + }, diff --git a/lede/target/linux/airoha/patches-6.12/063-01-v6.15-net-airoha-Move-min-max-packet-len-configuration-in-.patch b/lede/target/linux/airoha/patches-6.12/063-01-v6.15-net-airoha-Move-min-max-packet-len-configuration-in-.patch new file mode 100644 index 0000000000..2b8903d667 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/063-01-v6.15-net-airoha-Move-min-max-packet-len-configuration-in-.patch @@ -0,0 +1,59 @@ +From 54d989d58d2ac87c8504c2306ba8b4957c60e8dc Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 4 Mar 2025 15:21:08 +0100 +Subject: [PATCH 1/6] net: airoha: Move min/max packet len configuration in + airoha_dev_open() + +In order to align max allowed packet size to the configured mtu, move +REG_GDM_LEN_CFG configuration in airoha_dev_open routine. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250304-airoha-eth-rx-sg-v1-1-283ebc61120e@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -138,15 +138,10 @@ static void airoha_fe_maccr_init(struct + { + int p; + +- for (p = 1; p <= ARRAY_SIZE(eth->ports); p++) { ++ for (p = 1; p <= ARRAY_SIZE(eth->ports); p++) + airoha_fe_set(eth, REG_GDM_FWD_CFG(p), + GDM_TCP_CKSUM | GDM_UDP_CKSUM | GDM_IP4_CKSUM | + GDM_DROP_CRC_ERR); +- airoha_fe_rmw(eth, REG_GDM_LEN_CFG(p), +- GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, +- FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | +- FIELD_PREP(GDM_LONG_LEN_MASK, 4004)); +- } + + airoha_fe_rmw(eth, REG_CDM1_VLAN_CTRL, CDM1_VLAN_MASK, + FIELD_PREP(CDM1_VLAN_MASK, 0x8100)); +@@ -1520,9 +1515,9 @@ static void airoha_update_hw_stats(struc + + static int airoha_dev_open(struct net_device *dev) + { ++ int err, len = ETH_HLEN + dev->mtu + ETH_FCS_LEN; + struct airoha_gdm_port *port = netdev_priv(dev); + struct airoha_qdma *qdma = port->qdma; +- int err; + + netif_tx_start_all_queues(dev); + err = airoha_set_vip_for_gdm_port(port, true); +@@ -1536,6 +1531,11 @@ static int airoha_dev_open(struct net_de + airoha_fe_clear(qdma->eth, REG_GDM_INGRESS_CFG(port->id), + GDM_STAG_EN_MASK); + ++ airoha_fe_rmw(qdma->eth, REG_GDM_LEN_CFG(port->id), ++ GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, ++ FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | ++ FIELD_PREP(GDM_LONG_LEN_MASK, len)); ++ + airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG, + GLOBAL_CFG_TX_DMA_EN_MASK | + GLOBAL_CFG_RX_DMA_EN_MASK); diff --git a/lede/target/linux/airoha/patches-6.12/063-02-v6.15-net-airoha-Enable-Rx-Scatter-Gather.patch b/lede/target/linux/airoha/patches-6.12/063-02-v6.15-net-airoha-Enable-Rx-Scatter-Gather.patch new file mode 100644 index 0000000000..073f8e89a4 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/063-02-v6.15-net-airoha-Enable-Rx-Scatter-Gather.patch @@ -0,0 +1,170 @@ +From e12182ddb6e712951d21a50e2c8ccd700e41a40c Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 4 Mar 2025 15:21:09 +0100 +Subject: [PATCH 2/6] net: airoha: Enable Rx Scatter-Gather + +EN7581 SoC can receive 9k frames. Enable the reception of Scatter-Gather +(SG) frames. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250304-airoha-eth-rx-sg-v1-2-283ebc61120e@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 68 ++++++++++++++--------- + drivers/net/ethernet/airoha/airoha_eth.h | 1 + + drivers/net/ethernet/airoha/airoha_regs.h | 5 ++ + 3 files changed, 48 insertions(+), 26 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -615,10 +615,10 @@ static int airoha_qdma_rx_process(struct + struct airoha_qdma_desc *desc = &q->desc[q->tail]; + u32 hash, reason, msg1 = le32_to_cpu(desc->msg1); + dma_addr_t dma_addr = le32_to_cpu(desc->addr); ++ struct page *page = virt_to_head_page(e->buf); + u32 desc_ctrl = le32_to_cpu(desc->ctrl); + struct airoha_gdm_port *port; +- struct sk_buff *skb; +- int len, p; ++ int data_len, len, p; + + if (!(desc_ctrl & QDMA_DESC_DONE_MASK)) + break; +@@ -636,30 +636,41 @@ static int airoha_qdma_rx_process(struct + dma_sync_single_for_cpu(eth->dev, dma_addr, + SKB_WITH_OVERHEAD(q->buf_size), dir); + ++ data_len = q->skb ? q->buf_size ++ : SKB_WITH_OVERHEAD(q->buf_size); ++ if (data_len < len) ++ goto free_frag; ++ + p = airoha_qdma_get_gdm_port(eth, desc); +- if (p < 0 || !eth->ports[p]) { +- page_pool_put_full_page(q->page_pool, +- virt_to_head_page(e->buf), +- true); +- continue; +- } ++ if (p < 0 || !eth->ports[p]) ++ goto free_frag; + + port = eth->ports[p]; +- skb = napi_build_skb(e->buf, q->buf_size); +- if (!skb) { +- page_pool_put_full_page(q->page_pool, +- virt_to_head_page(e->buf), +- true); +- break; ++ if (!q->skb) { /* first buffer */ ++ q->skb = napi_build_skb(e->buf, q->buf_size); ++ if (!q->skb) ++ goto free_frag; ++ ++ __skb_put(q->skb, len); ++ skb_mark_for_recycle(q->skb); ++ q->skb->dev = port->dev; ++ q->skb->protocol = eth_type_trans(q->skb, port->dev); ++ q->skb->ip_summed = CHECKSUM_UNNECESSARY; ++ skb_record_rx_queue(q->skb, qid); ++ } else { /* scattered frame */ ++ struct skb_shared_info *shinfo = skb_shinfo(q->skb); ++ int nr_frags = shinfo->nr_frags; ++ ++ if (nr_frags >= ARRAY_SIZE(shinfo->frags)) ++ goto free_frag; ++ ++ skb_add_rx_frag(q->skb, nr_frags, page, ++ e->buf - page_address(page), len, ++ q->buf_size); + } + +- skb_reserve(skb, 2); +- __skb_put(skb, len); +- skb_mark_for_recycle(skb); +- skb->dev = port->dev; +- skb->protocol = eth_type_trans(skb, skb->dev); +- skb->ip_summed = CHECKSUM_UNNECESSARY; +- skb_record_rx_queue(skb, qid); ++ if (FIELD_GET(QDMA_DESC_MORE_MASK, desc_ctrl)) ++ continue; + + if (netdev_uses_dsa(port->dev)) { + /* PPE module requires untagged packets to work +@@ -672,22 +683,27 @@ static int airoha_qdma_rx_process(struct + + if (sptag < ARRAY_SIZE(port->dsa_meta) && + port->dsa_meta[sptag]) +- skb_dst_set_noref(skb, ++ skb_dst_set_noref(q->skb, + &port->dsa_meta[sptag]->dst); + } + + hash = FIELD_GET(AIROHA_RXD4_FOE_ENTRY, msg1); + if (hash != AIROHA_RXD4_FOE_ENTRY) +- skb_set_hash(skb, jhash_1word(hash, 0), ++ skb_set_hash(q->skb, jhash_1word(hash, 0), + PKT_HASH_TYPE_L4); + + reason = FIELD_GET(AIROHA_RXD4_PPE_CPU_REASON, msg1); + if (reason == PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) + airoha_ppe_check_skb(eth->ppe, hash); + +- napi_gro_receive(&q->napi, skb); +- + done++; ++ napi_gro_receive(&q->napi, q->skb); ++ q->skb = NULL; ++ continue; ++free_frag: ++ page_pool_put_full_page(q->page_pool, page, true); ++ dev_kfree_skb(q->skb); ++ q->skb = NULL; + } + airoha_qdma_fill_rx_queue(q); + +@@ -762,6 +778,7 @@ static int airoha_qdma_init_rx_queue(str + FIELD_PREP(RX_RING_THR_MASK, thr)); + airoha_qdma_rmw(qdma, REG_RX_DMA_IDX(qid), RX_RING_DMA_IDX_MASK, + FIELD_PREP(RX_RING_DMA_IDX_MASK, q->head)); ++ airoha_qdma_set(qdma, REG_RX_SCATTER_CFG(qid), RX_RING_SG_EN_MASK); + + airoha_qdma_fill_rx_queue(q); + +@@ -1161,7 +1178,6 @@ static int airoha_qdma_hw_init(struct ai + } + + airoha_qdma_wr(qdma, REG_QDMA_GLOBAL_CFG, +- GLOBAL_CFG_RX_2B_OFFSET_MASK | + FIELD_PREP(GLOBAL_CFG_DMA_PREFERENCE_MASK, 3) | + GLOBAL_CFG_CPU_TXR_RR_MASK | + GLOBAL_CFG_PAYLOAD_BYTE_SWAP_MASK | +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -176,6 +176,7 @@ struct airoha_queue { + + struct napi_struct napi; + struct page_pool *page_pool; ++ struct sk_buff *skb; + }; + + struct airoha_tx_irq_queue { +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -626,10 +626,15 @@ + #define REG_RX_DELAY_INT_IDX(_n) \ + (((_n) < 16) ? 0x0210 + ((_n) << 5) : 0x0e10 + (((_n) - 16) << 5)) + ++#define REG_RX_SCATTER_CFG(_n) \ ++ (((_n) < 16) ? 0x0214 + ((_n) << 5) : 0x0e14 + (((_n) - 16) << 5)) ++ + #define RX_DELAY_INT_MASK GENMASK(15, 0) + + #define RX_RING_DMA_IDX_MASK GENMASK(15, 0) + ++#define RX_RING_SG_EN_MASK BIT(0) ++ + #define REG_INGRESS_TRTCM_CFG 0x0070 + #define INGRESS_TRTCM_EN_MASK BIT(31) + #define INGRESS_TRTCM_MODE_MASK BIT(30) diff --git a/lede/target/linux/airoha/patches-6.12/063-03-v6.15-net-airoha-Introduce-airoha_dev_change_mtu-callback.patch b/lede/target/linux/airoha/patches-6.12/063-03-v6.15-net-airoha-Introduce-airoha_dev_change_mtu-callback.patch new file mode 100644 index 0000000000..a203ac2692 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/063-03-v6.15-net-airoha-Introduce-airoha_dev_change_mtu-callback.patch @@ -0,0 +1,47 @@ +From 03b1b69f0662c46f258a45e4a7d7837351c11692 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 4 Mar 2025 15:21:10 +0100 +Subject: [PATCH 3/6] net: airoha: Introduce airoha_dev_change_mtu callback + +Add airoha_dev_change_mtu callback to update the MTU of a running +device. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250304-airoha-eth-rx-sg-v1-3-283ebc61120e@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1705,6 +1705,20 @@ static void airoha_dev_get_stats64(struc + } while (u64_stats_fetch_retry(&port->stats.syncp, start)); + } + ++static int airoha_dev_change_mtu(struct net_device *dev, int mtu) ++{ ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ struct airoha_eth *eth = port->qdma->eth; ++ u32 len = ETH_HLEN + mtu + ETH_FCS_LEN; ++ ++ airoha_fe_rmw(eth, REG_GDM_LEN_CFG(port->id), ++ GDM_LONG_LEN_MASK, ++ FIELD_PREP(GDM_LONG_LEN_MASK, len)); ++ WRITE_ONCE(dev->mtu, mtu); ++ ++ return 0; ++} ++ + static u16 airoha_dev_select_queue(struct net_device *dev, struct sk_buff *skb, + struct net_device *sb_dev) + { +@@ -2397,6 +2411,7 @@ static const struct net_device_ops airoh + .ndo_init = airoha_dev_init, + .ndo_open = airoha_dev_open, + .ndo_stop = airoha_dev_stop, ++ .ndo_change_mtu = airoha_dev_change_mtu, + .ndo_select_queue = airoha_dev_select_queue, + .ndo_start_xmit = airoha_dev_xmit, + .ndo_get_stats64 = airoha_dev_get_stats64, diff --git a/lede/target/linux/airoha/patches-6.12/063-04-v6.15-net-airoha-Increase-max-mtu-to-9k.patch b/lede/target/linux/airoha/patches-6.12/063-04-v6.15-net-airoha-Increase-max-mtu-to-9k.patch new file mode 100644 index 0000000000..8771ff22db --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/063-04-v6.15-net-airoha-Increase-max-mtu-to-9k.patch @@ -0,0 +1,26 @@ +From 168ef0c1dee83c401896a0bca680e9f97b1ebd64 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 4 Mar 2025 15:21:11 +0100 +Subject: [PATCH 4/6] net: airoha: Increase max mtu to 9k + +EN7581 SoC supports 9k maximum MTU. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250304-airoha-eth-rx-sg-v1-4-283ebc61120e@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -20,7 +20,7 @@ + #define AIROHA_MAX_DSA_PORTS 7 + #define AIROHA_MAX_NUM_RSTS 3 + #define AIROHA_MAX_NUM_XSI_RSTS 5 +-#define AIROHA_MAX_MTU 2000 ++#define AIROHA_MAX_MTU 9216 + #define AIROHA_MAX_PACKET_SIZE 2048 + #define AIROHA_NUM_QOS_CHANNELS 4 + #define AIROHA_NUM_QOS_QUEUES 8 diff --git a/lede/target/linux/airoha/patches-6.12/063-05-v6.15-net-airoha-Fix-lan4-support-in-airoha_qdma_get_gdm_p.patch b/lede/target/linux/airoha/patches-6.12/063-05-v6.15-net-airoha-Fix-lan4-support-in-airoha_qdma_get_gdm_p.patch new file mode 100644 index 0000000000..1c3030afd0 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/063-05-v6.15-net-airoha-Fix-lan4-support-in-airoha_qdma_get_gdm_p.patch @@ -0,0 +1,29 @@ +From 35ea4f06fd33fc32f556a0c26d1d8340497fa7f8 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 4 Mar 2025 15:38:05 +0100 +Subject: [PATCH 5/6] net: airoha: Fix lan4 support in + airoha_qdma_get_gdm_port() + +EN7581 SoC supports lan{1,4} ports on MT7530 DSA switch. Fix lan4 +reported value in airoha_qdma_get_gdm_port routine. + +Fixes: 23020f0493270 ("net: airoha: Introduce ethernet support for EN7581 SoC") +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250304-airoha-eth-fix-lan4-v1-1-832417da4bb5@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -589,7 +589,7 @@ static int airoha_qdma_get_gdm_port(stru + + sport = FIELD_GET(QDMA_ETH_RXMSG_SPORT_MASK, msg1); + switch (sport) { +- case 0x10 ... 0x13: ++ case 0x10 ... 0x14: + port = 0; + break; + case 0x2 ... 0x4: diff --git a/lede/target/linux/airoha/patches-6.12/063-06-v6.15-net-airoha-Enable-TSO-Scatter-Gather-for-LAN-port.patch b/lede/target/linux/airoha/patches-6.12/063-06-v6.15-net-airoha-Enable-TSO-Scatter-Gather-for-LAN-port.patch new file mode 100644 index 0000000000..76d82ee70e --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/063-06-v6.15-net-airoha-Enable-TSO-Scatter-Gather-for-LAN-port.patch @@ -0,0 +1,27 @@ +From a202dfe31cae2f2120297a7142385d80a5577d42 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 4 Mar 2025 16:46:40 +0100 +Subject: [PATCH 6/6] net: airoha: Enable TSO/Scatter Gather for LAN port + +Set net_device vlan_features in order to enable TSO and Scatter Gather +for DSA user ports. + +Reviewed-by: Mateusz Polchlopek +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250304-lan-enable-tso-v1-1-b398eb9976ba@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2502,6 +2502,7 @@ static int airoha_alloc_gdm_port(struct + NETIF_F_SG | NETIF_F_TSO | + NETIF_F_HW_TC; + dev->features |= dev->hw_features; ++ dev->vlan_features = dev->hw_features; + dev->dev.of_node = np; + dev->irq = qdma->irq; + SET_NETDEV_DEV(dev, eth->dev); diff --git a/lede/target/linux/airoha/patches-6.12/064-v6.15-net-airoha-Fix-dev-dsa_ptr-check-in-airoha_get_dsa_t.patch b/lede/target/linux/airoha/patches-6.12/064-v6.15-net-airoha-Fix-dev-dsa_ptr-check-in-airoha_get_dsa_t.patch new file mode 100644 index 0000000000..f2b930d4a8 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/064-v6.15-net-airoha-Fix-dev-dsa_ptr-check-in-airoha_get_dsa_t.patch @@ -0,0 +1,47 @@ +From e368d2a1e8b6f0926e4e76a56b484249905192f5 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Thu, 6 Mar 2025 11:52:20 +0100 +Subject: [PATCH] net: airoha: Fix dev->dsa_ptr check in airoha_get_dsa_tag() + +Fix the following warning reported by Smatch static checker in +airoha_get_dsa_tag routine: + +drivers/net/ethernet/airoha/airoha_eth.c:1722 airoha_get_dsa_tag() +warn: 'dp' isn't an ERR_PTR + +dev->dsa_ptr can't be set to an error pointer, it can just be NULL. +Remove this check since it is already performed in netdev_uses_dsa(). + +Reported-by: Dan Carpenter +Closes: https://lore.kernel.org/netdev/Z8l3E0lGOcrel07C@lore-desk/T/#m54adc113fcdd8c5e6c5f65ffd60d8e8b1d483d90 +Fixes: af3cf757d5c9 ("net: airoha: Move DSA tag in DMA descriptor") +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250306-airoha-flowtable-fixes-v1-1-68d3c1296cdd@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1741,18 +1741,13 @@ static u32 airoha_get_dsa_tag(struct sk_ + { + #if IS_ENABLED(CONFIG_NET_DSA) + struct ethhdr *ehdr; +- struct dsa_port *dp; + u8 xmit_tpid; + u16 tag; + + if (!netdev_uses_dsa(dev)) + return 0; + +- dp = dev->dsa_ptr; +- if (IS_ERR(dp)) +- return 0; +- +- if (dp->tag_ops->proto != DSA_TAG_PROTO_MTK) ++ if (dev->dsa_ptr->tag_ops->proto != DSA_TAG_PROTO_MTK) + return 0; + + if (skb_cow_head(skb, 0)) diff --git a/lede/target/linux/airoha/patches-6.12/065-v6.15-net-airoha-fix-CONFIG_DEBUG_FS-check.patch b/lede/target/linux/airoha/patches-6.12/065-v6.15-net-airoha-fix-CONFIG_DEBUG_FS-check.patch new file mode 100644 index 0000000000..a8467408ed --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/065-v6.15-net-airoha-fix-CONFIG_DEBUG_FS-check.patch @@ -0,0 +1,35 @@ +From 08d0185e36ad8bb5902a73711bf114765d282161 Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Fri, 14 Mar 2025 16:49:59 +0100 +Subject: [PATCH] net: airoha: fix CONFIG_DEBUG_FS check + +The #if check causes a build failure when CONFIG_DEBUG_FS is turned +off: + +In file included from drivers/net/ethernet/airoha/airoha_eth.c:17: +drivers/net/ethernet/airoha/airoha_eth.h:543:5: error: "CONFIG_DEBUG_FS" is not defined, evaluates to 0 [-Werror=undef] + 543 | #if CONFIG_DEBUG_FS + | ^~~~~~~~~~~~~~~ + +Replace it with the correct #ifdef. + +Fixes: 3fe15c640f38 ("net: airoha: Introduce PPE debugfs support") +Signed-off-by: Arnd Bergmann +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250314155009.4114308-1-arnd@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -540,7 +540,7 @@ void airoha_ppe_deinit(struct airoha_eth + struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe, + u32 hash); + +-#if CONFIG_DEBUG_FS ++#ifdef CONFIG_DEBUG_FS + int airoha_ppe_debugfs_init(struct airoha_ppe *ppe); + #else + static inline int airoha_ppe_debugfs_init(struct airoha_ppe *ppe) diff --git a/lede/target/linux/airoha/patches-6.12/066-01-v6.15-net-airoha-Fix-qid-report-in-airoha_tc_get_htb_get_l.patch b/lede/target/linux/airoha/patches-6.12/066-01-v6.15-net-airoha-Fix-qid-report-in-airoha_tc_get_htb_get_l.patch new file mode 100644 index 0000000000..b40e8222e1 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/066-01-v6.15-net-airoha-Fix-qid-report-in-airoha_tc_get_htb_get_l.patch @@ -0,0 +1,77 @@ +From 57b290d97c6150774bf929117ca737a26d8fc33d Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 31 Mar 2025 08:52:53 +0200 +Subject: [PATCH 1/2] net: airoha: Fix qid report in + airoha_tc_get_htb_get_leaf_queue() + +Fix the following kernel warning deleting HTB offloaded leafs and/or root +HTB qdisc in airoha_eth driver properly reporting qid in +airoha_tc_get_htb_get_leaf_queue routine. + +$tc qdisc replace dev eth1 root handle 10: htb offload +$tc class add dev eth1 arent 10: classid 10:4 htb rate 100mbit ceil 100mbit +$tc qdisc replace dev eth1 parent 10:4 handle 4: ets bands 8 \ + quanta 1514 3028 4542 6056 7570 9084 10598 12112 +$tc qdisc del dev eth1 root + +[ 55.827864] ------------[ cut here ]------------ +[ 55.832493] WARNING: CPU: 3 PID: 2678 at 0xffffffc0798695a4 +[ 55.956510] CPU: 3 PID: 2678 Comm: tc Tainted: G O 6.6.71 #0 +[ 55.963557] Hardware name: Airoha AN7581 Evaluation Board (DT) +[ 55.969383] pstate: 20400005 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) +[ 55.976344] pc : 0xffffffc0798695a4 +[ 55.979851] lr : 0xffffffc079869a20 +[ 55.983358] sp : ffffffc0850536a0 +[ 55.986665] x29: ffffffc0850536a0 x28: 0000000000000024 x27: 0000000000000001 +[ 55.993800] x26: 0000000000000000 x25: ffffff8008b19000 x24: ffffff800222e800 +[ 56.000935] x23: 0000000000000001 x22: 0000000000000000 x21: ffffff8008b19000 +[ 56.008071] x20: ffffff8002225800 x19: ffffff800379d000 x18: 0000000000000000 +[ 56.015206] x17: ffffffbf9ea59000 x16: ffffffc080018000 x15: 0000000000000000 +[ 56.022342] x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000001 +[ 56.029478] x11: ffffffc081471008 x10: ffffffc081575a98 x9 : 0000000000000000 +[ 56.036614] x8 : ffffffc08167fd40 x7 : ffffffc08069e104 x6 : ffffff8007f86000 +[ 56.043748] x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000001 +[ 56.050884] x2 : 0000000000000000 x1 : 0000000000000250 x0 : ffffff800222c000 +[ 56.058020] Call trace: +[ 56.060459] 0xffffffc0798695a4 +[ 56.063618] 0xffffffc079869a20 +[ 56.066777] __qdisc_destroy+0x40/0xa0 +[ 56.070528] qdisc_put+0x54/0x6c +[ 56.073748] qdisc_graft+0x41c/0x648 +[ 56.077324] tc_get_qdisc+0x168/0x2f8 +[ 56.080978] rtnetlink_rcv_msg+0x230/0x330 +[ 56.085076] netlink_rcv_skb+0x5c/0x128 +[ 56.088913] rtnetlink_rcv+0x14/0x1c +[ 56.092490] netlink_unicast+0x1e0/0x2c8 +[ 56.096413] netlink_sendmsg+0x198/0x3c8 +[ 56.100337] ____sys_sendmsg+0x1c4/0x274 +[ 56.104261] ___sys_sendmsg+0x7c/0xc0 +[ 56.107924] __sys_sendmsg+0x44/0x98 +[ 56.111492] __arm64_sys_sendmsg+0x20/0x28 +[ 56.115580] invoke_syscall.constprop.0+0x58/0xfc +[ 56.120285] do_el0_svc+0x3c/0xbc +[ 56.123592] el0_svc+0x18/0x4c +[ 56.126647] el0t_64_sync_handler+0x118/0x124 +[ 56.131005] el0t_64_sync+0x150/0x154 +[ 56.134660] ---[ end trace 0000000000000000 ]--- + +Fixes: ef1ca9271313b ("net: airoha: Add sched HTB offload support") +Signed-off-by: Lorenzo Bianconi +Acked-by: Paolo Abeni +Link: https://patch.msgid.link/20250331-airoha-htb-qdisc-offload-del-fix-v1-1-4ea429c2c968@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2355,7 +2355,7 @@ static int airoha_tc_get_htb_get_leaf_qu + return -EINVAL; + } + +- opt->qid = channel; ++ opt->qid = AIROHA_NUM_TX_RING + channel; + + return 0; + } diff --git a/lede/target/linux/airoha/patches-6.12/066-02-v6.15-net-airoha-Fix-ETS-priomap-validation.patch b/lede/target/linux/airoha/patches-6.12/066-02-v6.15-net-airoha-Fix-ETS-priomap-validation.patch new file mode 100644 index 0000000000..d7e4c66ba8 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/066-02-v6.15-net-airoha-Fix-ETS-priomap-validation.patch @@ -0,0 +1,58 @@ +From 367579274f60cb23c570ae5348966ab51e1509a4 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 31 Mar 2025 18:17:31 +0200 +Subject: [PATCH 2/2] net: airoha: Fix ETS priomap validation + +ETS Qdisc schedules SP bands in a priority order assigning band-0 the +highest priority (band-0 > band-1 > .. > band-n) while EN7581 arranges +SP bands in a priority order assigning band-7 the highest priority +(band-7 > band-6, .. > band-n). +Fix priomap check in airoha_qdma_set_tx_ets_sched routine in order to +align ETS Qdisc and airoha_eth driver SP priority ordering. + +Fixes: b56e4d660a96 ("net: airoha: Enforce ETS Qdisc priomap") +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Reviewed-by: Davide Caratti +Link: https://patch.msgid.link/20250331-airoha-ets-validate-priomap-v1-1-60a524488672@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2028,7 +2028,7 @@ static int airoha_qdma_set_tx_ets_sched( + struct tc_ets_qopt_offload_replace_params *p = &opt->replace_params; + enum tx_sched_mode mode = TC_SCH_SP; + u16 w[AIROHA_NUM_QOS_QUEUES] = {}; +- int i, nstrict = 0, nwrr, qidx; ++ int i, nstrict = 0; + + if (p->bands > AIROHA_NUM_QOS_QUEUES) + return -EINVAL; +@@ -2046,17 +2046,17 @@ static int airoha_qdma_set_tx_ets_sched( + * lowest priorities with respect to SP ones. + * e.g: WRR0, WRR1, .., WRRm, SP0, SP1, .., SPn + */ +- nwrr = p->bands - nstrict; +- qidx = nstrict && nwrr ? nstrict : 0; +- for (i = 1; i <= p->bands; i++) { +- if (p->priomap[i % AIROHA_NUM_QOS_QUEUES] != qidx) ++ for (i = 0; i < nstrict; i++) { ++ if (p->priomap[p->bands - i - 1] != i) + return -EINVAL; +- +- qidx = i == nwrr ? 0 : qidx + 1; + } + +- for (i = 0; i < nwrr; i++) ++ for (i = 0; i < p->bands - nstrict; i++) { ++ if (p->priomap[i] != nstrict + i) ++ return -EINVAL; ++ + w[i] = p->weights[nstrict + i]; ++ } + + if (!nstrict) + mode = TC_SCH_WRR8; diff --git a/lede/target/linux/airoha/patches-6.12/067-v6.15-net-airoha-Validate-egress-gdm-port-in-airoha_ppe_fo.patch b/lede/target/linux/airoha/patches-6.12/067-v6.15-net-airoha-Validate-egress-gdm-port-in-airoha_ppe_fo.patch new file mode 100644 index 0000000000..91f43f98b0 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/067-v6.15-net-airoha-Validate-egress-gdm-port-in-airoha_ppe_fo.patch @@ -0,0 +1,100 @@ +From 09bccf56db36501ccb1935d921dc24451e9f57dd Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 1 Apr 2025 11:42:30 +0200 +Subject: [PATCH] net: airoha: Validate egress gdm port in + airoha_ppe_foe_entry_prepare() + +Dev pointer in airoha_ppe_foe_entry_prepare routine is not strictly +a device allocated by airoha_eth driver since it is an egress device +and the flowtable can contain even wlan, pppoe or vlan devices. E.g: + +flowtable ft { + hook ingress priority filter + devices = { eth1, lan1, lan2, lan3, lan4, wlan0 } + flags offload ^ + | + "not allocated by airoha_eth" -- +} + +In this case airoha_get_dsa_port() will just return the original device +pointer and we can't assume netdev priv pointer points to an +airoha_gdm_port struct. +Fix the issue validating egress gdm port in airoha_ppe_foe_entry_prepare +routine before accessing net_device priv pointer. + +Fixes: 00a7678310fe ("net: airoha: Introduce flowtable offload support") +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250401-airoha-validate-egress-gdm-port-v4-1-c7315d33ce10@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 13 +++++++++++++ + drivers/net/ethernet/airoha/airoha_eth.h | 3 +++ + drivers/net/ethernet/airoha/airoha_ppe.c | 8 ++++++-- + 3 files changed, 22 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2451,6 +2451,19 @@ static void airoha_metadata_dst_free(str + } + } + ++bool airoha_is_valid_gdm_port(struct airoha_eth *eth, ++ struct airoha_gdm_port *port) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(eth->ports); i++) { ++ if (eth->ports[i] == port) ++ return true; ++ } ++ ++ return false; ++} ++ + static int airoha_alloc_gdm_port(struct airoha_eth *eth, + struct device_node *np, int index) + { +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -532,6 +532,9 @@ u32 airoha_rmw(void __iomem *base, u32 o + #define airoha_qdma_clear(qdma, offset, val) \ + airoha_rmw((qdma)->regs, (offset), (val), 0) + ++bool airoha_is_valid_gdm_port(struct airoha_eth *eth, ++ struct airoha_gdm_port *port); ++ + void airoha_ppe_check_skb(struct airoha_ppe *ppe, u16 hash); + int airoha_ppe_setup_tc_block_cb(enum tc_setup_type type, void *type_data, + void *cb_priv); +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -197,7 +197,8 @@ static int airoha_get_dsa_port(struct ne + #endif + } + +-static int airoha_ppe_foe_entry_prepare(struct airoha_foe_entry *hwe, ++static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth, ++ struct airoha_foe_entry *hwe, + struct net_device *dev, int type, + struct airoha_flow_data *data, + int l4proto) +@@ -225,6 +226,9 @@ static int airoha_ppe_foe_entry_prepare( + struct airoha_gdm_port *port = netdev_priv(dev); + u8 pse_port; + ++ if (!airoha_is_valid_gdm_port(eth, port)) ++ return -EINVAL; ++ + if (dsa_port >= 0) + pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id; + else +@@ -633,7 +637,7 @@ static int airoha_ppe_flow_offload_repla + !is_valid_ether_addr(data.eth.h_dest)) + return -EINVAL; + +- err = airoha_ppe_foe_entry_prepare(&hwe, odev, offload_type, ++ err = airoha_ppe_foe_entry_prepare(eth, &hwe, odev, offload_type, + &data, l4proto); + if (err) + return err; diff --git a/lede/target/linux/airoha/patches-6.12/068-01-v6.16-net-airoha-Add-l2_flows-rhashtable.patch b/lede/target/linux/airoha/patches-6.12/068-01-v6.16-net-airoha-Add-l2_flows-rhashtable.patch new file mode 100644 index 0000000000..95f83f53bd --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/068-01-v6.16-net-airoha-Add-l2_flows-rhashtable.patch @@ -0,0 +1,207 @@ +From b4916f67902e2ae1dc8e37dfa45e8894ad2f8921 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 9 Apr 2025 11:47:14 +0200 +Subject: [PATCH 1/2] net: airoha: Add l2_flows rhashtable + +Introduce l2_flows rhashtable in airoha_ppe struct in order to +store L2 flows committed by upper layers of the kernel. This is a +preliminary patch in order to offload L2 traffic rules. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Michal Kubiak +Link: https://patch.msgid.link/20250409-airoha-flowtable-l2b-v2-1-4a1e3935ea92@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.h | 15 +++- + drivers/net/ethernet/airoha/airoha_ppe.c | 103 ++++++++++++++++++----- + 2 files changed, 98 insertions(+), 20 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -422,12 +422,23 @@ struct airoha_flow_data { + } pppoe; + }; + ++enum airoha_flow_entry_type { ++ FLOW_TYPE_L4, ++ FLOW_TYPE_L2, ++ FLOW_TYPE_L2_SUBFLOW, ++}; ++ + struct airoha_flow_table_entry { +- struct hlist_node list; ++ union { ++ struct hlist_node list; /* PPE L3 flow entry */ ++ struct rhash_head l2_node; /* L2 flow entry */ ++ }; + + struct airoha_foe_entry data; + u32 hash; + ++ enum airoha_flow_entry_type type; ++ + struct rhash_head node; + unsigned long cookie; + }; +@@ -480,6 +491,8 @@ struct airoha_ppe { + void *foe; + dma_addr_t foe_dma; + ++ struct rhashtable l2_flows; ++ + struct hlist_head *foe_flow; + u16 foe_check_time[PPE_NUM_ENTRIES]; + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -24,6 +24,13 @@ static const struct rhashtable_params ai + .automatic_shrinking = true, + }; + ++static const struct rhashtable_params airoha_l2_flow_table_params = { ++ .head_offset = offsetof(struct airoha_flow_table_entry, l2_node), ++ .key_offset = offsetof(struct airoha_flow_table_entry, data.bridge), ++ .key_len = 2 * ETH_ALEN, ++ .automatic_shrinking = true, ++}; ++ + static bool airoha_ppe2_is_enabled(struct airoha_eth *eth) + { + return airoha_fe_rr(eth, REG_PPE_GLO_CFG(1)) & PPE_GLO_CFG_EN_MASK; +@@ -476,6 +483,43 @@ static int airoha_ppe_foe_commit_entry(s + return 0; + } + ++static void airoha_ppe_foe_remove_flow(struct airoha_ppe *ppe, ++ struct airoha_flow_table_entry *e) ++{ ++ lockdep_assert_held(&ppe_lock); ++ ++ hlist_del_init(&e->list); ++ if (e->hash != 0xffff) { ++ e->data.ib1 &= ~AIROHA_FOE_IB1_BIND_STATE; ++ e->data.ib1 |= FIELD_PREP(AIROHA_FOE_IB1_BIND_STATE, ++ AIROHA_FOE_STATE_INVALID); ++ airoha_ppe_foe_commit_entry(ppe, &e->data, e->hash); ++ e->hash = 0xffff; ++ } ++} ++ ++static void airoha_ppe_foe_remove_l2_flow(struct airoha_ppe *ppe, ++ struct airoha_flow_table_entry *e) ++{ ++ lockdep_assert_held(&ppe_lock); ++ ++ rhashtable_remove_fast(&ppe->l2_flows, &e->l2_node, ++ airoha_l2_flow_table_params); ++} ++ ++static void airoha_ppe_foe_flow_remove_entry(struct airoha_ppe *ppe, ++ struct airoha_flow_table_entry *e) ++{ ++ spin_lock_bh(&ppe_lock); ++ ++ if (e->type == FLOW_TYPE_L2) ++ airoha_ppe_foe_remove_l2_flow(ppe, e); ++ else ++ airoha_ppe_foe_remove_flow(ppe, e); ++ ++ spin_unlock_bh(&ppe_lock); ++} ++ + static void airoha_ppe_foe_insert_entry(struct airoha_ppe *ppe, u32 hash) + { + struct airoha_flow_table_entry *e; +@@ -505,11 +549,37 @@ unlock: + spin_unlock_bh(&ppe_lock); + } + ++static int ++airoha_ppe_foe_l2_flow_commit_entry(struct airoha_ppe *ppe, ++ struct airoha_flow_table_entry *e) ++{ ++ struct airoha_flow_table_entry *prev; ++ ++ e->type = FLOW_TYPE_L2; ++ prev = rhashtable_lookup_get_insert_fast(&ppe->l2_flows, &e->l2_node, ++ airoha_l2_flow_table_params); ++ if (!prev) ++ return 0; ++ ++ if (IS_ERR(prev)) ++ return PTR_ERR(prev); ++ ++ return rhashtable_replace_fast(&ppe->l2_flows, &prev->l2_node, ++ &e->l2_node, ++ airoha_l2_flow_table_params); ++} ++ + static int airoha_ppe_foe_flow_commit_entry(struct airoha_ppe *ppe, + struct airoha_flow_table_entry *e) + { +- u32 hash = airoha_ppe_foe_get_entry_hash(&e->data); ++ int type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, e->data.ib1); ++ u32 hash; + ++ if (type == PPE_PKT_TYPE_BRIDGE) ++ return airoha_ppe_foe_l2_flow_commit_entry(ppe, e); ++ ++ hash = airoha_ppe_foe_get_entry_hash(&e->data); ++ e->type = FLOW_TYPE_L4; + e->hash = 0xffff; + + spin_lock_bh(&ppe_lock); +@@ -519,23 +589,6 @@ static int airoha_ppe_foe_flow_commit_en + return 0; + } + +-static void airoha_ppe_foe_flow_remove_entry(struct airoha_ppe *ppe, +- struct airoha_flow_table_entry *e) +-{ +- spin_lock_bh(&ppe_lock); +- +- hlist_del_init(&e->list); +- if (e->hash != 0xffff) { +- e->data.ib1 &= ~AIROHA_FOE_IB1_BIND_STATE; +- e->data.ib1 |= FIELD_PREP(AIROHA_FOE_IB1_BIND_STATE, +- AIROHA_FOE_STATE_INVALID); +- airoha_ppe_foe_commit_entry(ppe, &e->data, e->hash); +- e->hash = 0xffff; +- } +- +- spin_unlock_bh(&ppe_lock); +-} +- + static int airoha_ppe_flow_offload_replace(struct airoha_gdm_port *port, + struct flow_cls_offload *f) + { +@@ -890,9 +943,20 @@ int airoha_ppe_init(struct airoha_eth *e + if (err) + return err; + ++ err = rhashtable_init(&ppe->l2_flows, &airoha_l2_flow_table_params); ++ if (err) ++ goto error_flow_table_destroy; ++ + err = airoha_ppe_debugfs_init(ppe); + if (err) +- rhashtable_destroy(ð->flow_table); ++ goto error_l2_flow_table_destroy; ++ ++ return 0; ++ ++error_l2_flow_table_destroy: ++ rhashtable_destroy(&ppe->l2_flows); ++error_flow_table_destroy: ++ rhashtable_destroy(ð->flow_table); + + return err; + } +@@ -909,6 +973,7 @@ void airoha_ppe_deinit(struct airoha_eth + } + rcu_read_unlock(); + ++ rhashtable_destroy(ð->ppe->l2_flows); + rhashtable_destroy(ð->flow_table); + debugfs_remove(eth->ppe->debugfs_dir); + } diff --git a/lede/target/linux/airoha/patches-6.12/068-02-v6.16-net-airoha-Add-L2-hw-acceleration-support.patch b/lede/target/linux/airoha/patches-6.12/068-02-v6.16-net-airoha-Add-L2-hw-acceleration-support.patch new file mode 100644 index 0000000000..2375962338 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/068-02-v6.16-net-airoha-Add-L2-hw-acceleration-support.patch @@ -0,0 +1,253 @@ +From cd53f622611f9a6dd83b858c85448dd3568b67ec Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 9 Apr 2025 11:47:15 +0200 +Subject: [PATCH 2/2] net: airoha: Add L2 hw acceleration support + +Similar to mtk driver, introduce the capability to offload L2 traffic +defining flower rules in the PSE/PPE engine available on EN7581 SoC. +Since the hw always reports L2/L3/L4 flower rules, link all L2 rules +sharing the same L2 info (with different L3/L4 info) in the L2 subflows +list of a given L2 PPE entry. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Michal Kubiak +Link: https://patch.msgid.link/20250409-airoha-flowtable-l2b-v2-2-4a1e3935ea92@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 2 +- + drivers/net/ethernet/airoha/airoha_eth.h | 9 +- + drivers/net/ethernet/airoha/airoha_ppe.c | 121 ++++++++++++++++++++--- + 3 files changed, 115 insertions(+), 17 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -694,7 +694,7 @@ static int airoha_qdma_rx_process(struct + + reason = FIELD_GET(AIROHA_RXD4_PPE_CPU_REASON, msg1); + if (reason == PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) +- airoha_ppe_check_skb(eth->ppe, hash); ++ airoha_ppe_check_skb(eth->ppe, q->skb, hash); + + done++; + napi_gro_receive(&q->napi, q->skb); +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -431,10 +431,14 @@ enum airoha_flow_entry_type { + struct airoha_flow_table_entry { + union { + struct hlist_node list; /* PPE L3 flow entry */ +- struct rhash_head l2_node; /* L2 flow entry */ ++ struct { ++ struct rhash_head l2_node; /* L2 flow entry */ ++ struct hlist_head l2_flows; /* PPE L2 subflows list */ ++ }; + }; + + struct airoha_foe_entry data; ++ struct hlist_node l2_subflow_node; /* PPE L2 subflow entry */ + u32 hash; + + enum airoha_flow_entry_type type; +@@ -548,7 +552,8 @@ u32 airoha_rmw(void __iomem *base, u32 o + bool airoha_is_valid_gdm_port(struct airoha_eth *eth, + struct airoha_gdm_port *port); + +-void airoha_ppe_check_skb(struct airoha_ppe *ppe, u16 hash); ++void airoha_ppe_check_skb(struct airoha_ppe *ppe, struct sk_buff *skb, ++ u16 hash); + int airoha_ppe_setup_tc_block_cb(enum tc_setup_type type, void *type_data, + void *cb_priv); + int airoha_ppe_init(struct airoha_eth *eth); +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -204,6 +204,15 @@ static int airoha_get_dsa_port(struct ne + #endif + } + ++static void airoha_ppe_foe_set_bridge_addrs(struct airoha_foe_bridge *br, ++ struct ethhdr *eh) ++{ ++ br->dest_mac_hi = get_unaligned_be32(eh->h_dest); ++ br->dest_mac_lo = get_unaligned_be16(eh->h_dest + 4); ++ br->src_mac_hi = get_unaligned_be16(eh->h_source); ++ br->src_mac_lo = get_unaligned_be32(eh->h_source + 2); ++} ++ + static int airoha_ppe_foe_entry_prepare(struct airoha_eth *eth, + struct airoha_foe_entry *hwe, + struct net_device *dev, int type, +@@ -254,13 +263,7 @@ static int airoha_ppe_foe_entry_prepare( + + qdata = FIELD_PREP(AIROHA_FOE_SHAPER_ID, 0x7f); + if (type == PPE_PKT_TYPE_BRIDGE) { +- hwe->bridge.dest_mac_hi = get_unaligned_be32(data->eth.h_dest); +- hwe->bridge.dest_mac_lo = +- get_unaligned_be16(data->eth.h_dest + 4); +- hwe->bridge.src_mac_hi = +- get_unaligned_be16(data->eth.h_source); +- hwe->bridge.src_mac_lo = +- get_unaligned_be32(data->eth.h_source + 2); ++ airoha_ppe_foe_set_bridge_addrs(&hwe->bridge, &data->eth); + hwe->bridge.data = qdata; + hwe->bridge.ib2 = val; + l2 = &hwe->bridge.l2.common; +@@ -385,6 +388,19 @@ static u32 airoha_ppe_foe_get_entry_hash + hv3 = hwe->ipv6.src_ip[1] ^ hwe->ipv6.dest_ip[1]; + hv3 ^= hwe->ipv6.src_ip[0]; + break; ++ case PPE_PKT_TYPE_BRIDGE: { ++ struct airoha_foe_mac_info *l2 = &hwe->bridge.l2; ++ ++ hv1 = l2->common.src_mac_hi & 0xffff; ++ hv1 = hv1 << 16 | l2->src_mac_lo; ++ ++ hv2 = l2->common.dest_mac_lo; ++ hv2 = hv2 << 16; ++ hv2 = hv2 | ((l2->common.src_mac_hi & 0xffff0000) >> 16); ++ ++ hv3 = l2->common.dest_mac_hi; ++ break; ++ } + case PPE_PKT_TYPE_IPV4_DSLITE: + case PPE_PKT_TYPE_IPV6_6RD: + default: +@@ -496,15 +512,24 @@ static void airoha_ppe_foe_remove_flow(s + airoha_ppe_foe_commit_entry(ppe, &e->data, e->hash); + e->hash = 0xffff; + } ++ if (e->type == FLOW_TYPE_L2_SUBFLOW) { ++ hlist_del_init(&e->l2_subflow_node); ++ kfree(e); ++ } + } + + static void airoha_ppe_foe_remove_l2_flow(struct airoha_ppe *ppe, + struct airoha_flow_table_entry *e) + { ++ struct hlist_head *head = &e->l2_flows; ++ struct hlist_node *n; ++ + lockdep_assert_held(&ppe_lock); + + rhashtable_remove_fast(&ppe->l2_flows, &e->l2_node, + airoha_l2_flow_table_params); ++ hlist_for_each_entry_safe(e, n, head, l2_subflow_node) ++ airoha_ppe_foe_remove_flow(ppe, e); + } + + static void airoha_ppe_foe_flow_remove_entry(struct airoha_ppe *ppe, +@@ -520,10 +545,56 @@ static void airoha_ppe_foe_flow_remove_e + spin_unlock_bh(&ppe_lock); + } + +-static void airoha_ppe_foe_insert_entry(struct airoha_ppe *ppe, u32 hash) ++static int ++airoha_ppe_foe_commit_subflow_entry(struct airoha_ppe *ppe, ++ struct airoha_flow_table_entry *e, ++ u32 hash) ++{ ++ u32 mask = AIROHA_FOE_IB1_BIND_PACKET_TYPE | AIROHA_FOE_IB1_BIND_UDP; ++ struct airoha_foe_entry *hwe_p, hwe; ++ struct airoha_flow_table_entry *f; ++ struct airoha_foe_mac_info *l2; ++ int type; ++ ++ hwe_p = airoha_ppe_foe_get_entry(ppe, hash); ++ if (!hwe_p) ++ return -EINVAL; ++ ++ f = kzalloc(sizeof(*f), GFP_ATOMIC); ++ if (!f) ++ return -ENOMEM; ++ ++ hlist_add_head(&f->l2_subflow_node, &e->l2_flows); ++ f->type = FLOW_TYPE_L2_SUBFLOW; ++ f->hash = hash; ++ ++ memcpy(&hwe, hwe_p, sizeof(*hwe_p)); ++ hwe.ib1 = (hwe.ib1 & mask) | (e->data.ib1 & ~mask); ++ l2 = &hwe.bridge.l2; ++ memcpy(l2, &e->data.bridge.l2, sizeof(*l2)); ++ ++ type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe.ib1); ++ if (type == PPE_PKT_TYPE_IPV4_HNAPT) ++ memcpy(&hwe.ipv4.new_tuple, &hwe.ipv4.orig_tuple, ++ sizeof(hwe.ipv4.new_tuple)); ++ else if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T && ++ l2->common.etype == ETH_P_IP) ++ l2->common.etype = ETH_P_IPV6; ++ ++ hwe.bridge.ib2 = e->data.bridge.ib2; ++ airoha_ppe_foe_commit_entry(ppe, &hwe, hash); ++ ++ return 0; ++} ++ ++static void airoha_ppe_foe_insert_entry(struct airoha_ppe *ppe, ++ struct sk_buff *skb, ++ u32 hash) + { + struct airoha_flow_table_entry *e; ++ struct airoha_foe_bridge br = {}; + struct airoha_foe_entry *hwe; ++ bool commit_done = false; + struct hlist_node *n; + u32 index, state; + +@@ -539,12 +610,33 @@ static void airoha_ppe_foe_insert_entry( + + index = airoha_ppe_foe_get_entry_hash(hwe); + hlist_for_each_entry_safe(e, n, &ppe->foe_flow[index], list) { +- if (airoha_ppe_foe_compare_entry(e, hwe)) { +- airoha_ppe_foe_commit_entry(ppe, &e->data, hash); +- e->hash = hash; +- break; ++ if (e->type == FLOW_TYPE_L2_SUBFLOW) { ++ state = FIELD_GET(AIROHA_FOE_IB1_BIND_STATE, hwe->ib1); ++ if (state != AIROHA_FOE_STATE_BIND) { ++ e->hash = 0xffff; ++ airoha_ppe_foe_remove_flow(ppe, e); ++ } ++ continue; ++ } ++ ++ if (commit_done || !airoha_ppe_foe_compare_entry(e, hwe)) { ++ e->hash = 0xffff; ++ continue; + } ++ ++ airoha_ppe_foe_commit_entry(ppe, &e->data, hash); ++ commit_done = true; ++ e->hash = hash; + } ++ ++ if (commit_done) ++ goto unlock; ++ ++ airoha_ppe_foe_set_bridge_addrs(&br, eth_hdr(skb)); ++ e = rhashtable_lookup_fast(&ppe->l2_flows, &br, ++ airoha_l2_flow_table_params); ++ if (e) ++ airoha_ppe_foe_commit_subflow_entry(ppe, e, hash); + unlock: + spin_unlock_bh(&ppe_lock); + } +@@ -899,7 +991,8 @@ int airoha_ppe_setup_tc_block_cb(enum tc + return err; + } + +-void airoha_ppe_check_skb(struct airoha_ppe *ppe, u16 hash) ++void airoha_ppe_check_skb(struct airoha_ppe *ppe, struct sk_buff *skb, ++ u16 hash) + { + u16 now, diff; + +@@ -912,7 +1005,7 @@ void airoha_ppe_check_skb(struct airoha_ + return; + + ppe->foe_check_time[hash] = now; +- airoha_ppe_foe_insert_entry(ppe, hash); ++ airoha_ppe_foe_insert_entry(ppe, skb, hash); + } + + int airoha_ppe_init(struct airoha_eth *eth) diff --git a/lede/target/linux/airoha/patches-6.12/069-v6.16-net-airoha-Add-matchall-filter-offload-support.patch b/lede/target/linux/airoha/patches-6.12/069-v6.16-net-airoha-Add-matchall-filter-offload-support.patch new file mode 100644 index 0000000000..4b8565aa6b --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/069-v6.16-net-airoha-Add-matchall-filter-offload-support.patch @@ -0,0 +1,405 @@ +From df8398fb7bb7a0e509200af56b79343aa133b7d6 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 15 Apr 2025 09:14:34 +0200 +Subject: [PATCH] net: airoha: Add matchall filter offload support + +Introduce tc matchall filter offload support in airoha_eth driver. +Matchall hw filter is used to implement hw rate policing via tc action +police: + +$tc qdisc add dev eth0 handle ffff: ingress +$tc filter add dev eth0 parent ffff: matchall action police \ + rate 100mbit burst 1000k drop + +The current implementation supports just drop/accept as exceed/notexceed +actions. Moreover, rate and burst are the only supported configuration +parameters. + +Reviewed-by: Davide Caratti +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250415-airoha-hw-rx-ratelimit-v4-1-03458784fbc3@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 273 +++++++++++++++++++++- + drivers/net/ethernet/airoha/airoha_eth.h | 8 +- + drivers/net/ethernet/airoha/airoha_ppe.c | 9 +- + drivers/net/ethernet/airoha/airoha_regs.h | 7 + + 4 files changed, 286 insertions(+), 11 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -527,6 +527,25 @@ static int airoha_fe_init(struct airoha_ + /* disable IFC by default */ + airoha_fe_clear(eth, REG_FE_CSR_IFC_CFG, FE_IFC_EN_MASK); + ++ airoha_fe_wr(eth, REG_PPE_DFT_CPORT0(0), ++ FIELD_PREP(DFT_CPORT_MASK(7), FE_PSE_PORT_CDM1) | ++ FIELD_PREP(DFT_CPORT_MASK(6), FE_PSE_PORT_CDM1) | ++ FIELD_PREP(DFT_CPORT_MASK(5), FE_PSE_PORT_CDM1) | ++ FIELD_PREP(DFT_CPORT_MASK(4), FE_PSE_PORT_CDM1) | ++ FIELD_PREP(DFT_CPORT_MASK(3), FE_PSE_PORT_CDM1) | ++ FIELD_PREP(DFT_CPORT_MASK(2), FE_PSE_PORT_CDM1) | ++ FIELD_PREP(DFT_CPORT_MASK(1), FE_PSE_PORT_CDM1) | ++ FIELD_PREP(DFT_CPORT_MASK(0), FE_PSE_PORT_CDM1)); ++ airoha_fe_wr(eth, REG_PPE_DFT_CPORT0(1), ++ FIELD_PREP(DFT_CPORT_MASK(7), FE_PSE_PORT_CDM2) | ++ FIELD_PREP(DFT_CPORT_MASK(6), FE_PSE_PORT_CDM2) | ++ FIELD_PREP(DFT_CPORT_MASK(5), FE_PSE_PORT_CDM2) | ++ FIELD_PREP(DFT_CPORT_MASK(4), FE_PSE_PORT_CDM2) | ++ FIELD_PREP(DFT_CPORT_MASK(3), FE_PSE_PORT_CDM2) | ++ FIELD_PREP(DFT_CPORT_MASK(2), FE_PSE_PORT_CDM2) | ++ FIELD_PREP(DFT_CPORT_MASK(1), FE_PSE_PORT_CDM2) | ++ FIELD_PREP(DFT_CPORT_MASK(0), FE_PSE_PORT_CDM2)); ++ + /* enable 1:N vlan action, init vlan table */ + airoha_fe_set(eth, REG_MC_VLAN_EN, MC_VLAN_EN_MASK); + +@@ -1631,7 +1650,6 @@ static void airhoha_set_gdm2_loopback(st + + if (port->id == 3) { + /* FIXME: handle XSI_PCE1_PORT */ +- airoha_fe_wr(eth, REG_PPE_DFT_CPORT0(0), 0x5500); + airoha_fe_rmw(eth, REG_FE_WAN_PORT, + WAN1_EN_MASK | WAN1_MASK | WAN0_MASK, + FIELD_PREP(WAN0_MASK, HSGMII_LAN_PCIE0_SRCPORT)); +@@ -2106,6 +2124,125 @@ static int airoha_tc_setup_qdisc_ets(str + } + } + ++static int airoha_qdma_get_rl_param(struct airoha_qdma *qdma, int queue_id, ++ u32 addr, enum trtcm_param_type param, ++ u32 *val_low, u32 *val_high) ++{ ++ u32 idx = QDMA_METER_IDX(queue_id), group = QDMA_METER_GROUP(queue_id); ++ u32 val, config = FIELD_PREP(RATE_LIMIT_PARAM_TYPE_MASK, param) | ++ FIELD_PREP(RATE_LIMIT_METER_GROUP_MASK, group) | ++ FIELD_PREP(RATE_LIMIT_PARAM_INDEX_MASK, idx); ++ ++ airoha_qdma_wr(qdma, REG_TRTCM_CFG_PARAM(addr), config); ++ if (read_poll_timeout(airoha_qdma_rr, val, ++ val & RATE_LIMIT_PARAM_RW_DONE_MASK, ++ USEC_PER_MSEC, 10 * USEC_PER_MSEC, true, qdma, ++ REG_TRTCM_CFG_PARAM(addr))) ++ return -ETIMEDOUT; ++ ++ *val_low = airoha_qdma_rr(qdma, REG_TRTCM_DATA_LOW(addr)); ++ if (val_high) ++ *val_high = airoha_qdma_rr(qdma, REG_TRTCM_DATA_HIGH(addr)); ++ ++ return 0; ++} ++ ++static int airoha_qdma_set_rl_param(struct airoha_qdma *qdma, int queue_id, ++ u32 addr, enum trtcm_param_type param, ++ u32 val) ++{ ++ u32 idx = QDMA_METER_IDX(queue_id), group = QDMA_METER_GROUP(queue_id); ++ u32 config = RATE_LIMIT_PARAM_RW_MASK | ++ FIELD_PREP(RATE_LIMIT_PARAM_TYPE_MASK, param) | ++ FIELD_PREP(RATE_LIMIT_METER_GROUP_MASK, group) | ++ FIELD_PREP(RATE_LIMIT_PARAM_INDEX_MASK, idx); ++ ++ airoha_qdma_wr(qdma, REG_TRTCM_DATA_LOW(addr), val); ++ airoha_qdma_wr(qdma, REG_TRTCM_CFG_PARAM(addr), config); ++ ++ return read_poll_timeout(airoha_qdma_rr, val, ++ val & RATE_LIMIT_PARAM_RW_DONE_MASK, ++ USEC_PER_MSEC, 10 * USEC_PER_MSEC, true, ++ qdma, REG_TRTCM_CFG_PARAM(addr)); ++} ++ ++static int airoha_qdma_set_rl_config(struct airoha_qdma *qdma, int queue_id, ++ u32 addr, bool enable, u32 enable_mask) ++{ ++ u32 val; ++ int err; ++ ++ err = airoha_qdma_get_rl_param(qdma, queue_id, addr, TRTCM_MISC_MODE, ++ &val, NULL); ++ if (err) ++ return err; ++ ++ val = enable ? val | enable_mask : val & ~enable_mask; ++ ++ return airoha_qdma_set_rl_param(qdma, queue_id, addr, TRTCM_MISC_MODE, ++ val); ++} ++ ++static int airoha_qdma_set_rl_token_bucket(struct airoha_qdma *qdma, ++ int queue_id, u32 rate_val, ++ u32 bucket_size) ++{ ++ u32 val, config, tick, unit, rate, rate_frac; ++ int err; ++ ++ err = airoha_qdma_get_rl_param(qdma, queue_id, REG_INGRESS_TRTCM_CFG, ++ TRTCM_MISC_MODE, &config, NULL); ++ if (err) ++ return err; ++ ++ val = airoha_qdma_rr(qdma, REG_INGRESS_TRTCM_CFG); ++ tick = FIELD_GET(INGRESS_FAST_TICK_MASK, val); ++ if (config & TRTCM_TICK_SEL) ++ tick *= FIELD_GET(INGRESS_SLOW_TICK_RATIO_MASK, val); ++ if (!tick) ++ return -EINVAL; ++ ++ unit = (config & TRTCM_PKT_MODE) ? 1000000 / tick : 8000 / tick; ++ if (!unit) ++ return -EINVAL; ++ ++ rate = rate_val / unit; ++ rate_frac = rate_val % unit; ++ rate_frac = FIELD_PREP(TRTCM_TOKEN_RATE_MASK, rate_frac) / unit; ++ rate = FIELD_PREP(TRTCM_TOKEN_RATE_MASK, rate) | ++ FIELD_PREP(TRTCM_TOKEN_RATE_FRACTION_MASK, rate_frac); ++ ++ err = airoha_qdma_set_rl_param(qdma, queue_id, REG_INGRESS_TRTCM_CFG, ++ TRTCM_TOKEN_RATE_MODE, rate); ++ if (err) ++ return err; ++ ++ val = bucket_size; ++ if (!(config & TRTCM_PKT_MODE)) ++ val = max_t(u32, val, MIN_TOKEN_SIZE); ++ val = min_t(u32, __fls(val), MAX_TOKEN_SIZE_OFFSET); ++ ++ return airoha_qdma_set_rl_param(qdma, queue_id, REG_INGRESS_TRTCM_CFG, ++ TRTCM_BUCKETSIZE_SHIFT_MODE, val); ++} ++ ++static int airoha_qdma_init_rl_config(struct airoha_qdma *qdma, int queue_id, ++ bool enable, enum trtcm_unit_type unit) ++{ ++ bool tick_sel = queue_id == 0 || queue_id == 2 || queue_id == 8; ++ enum trtcm_param mode = TRTCM_METER_MODE; ++ int err; ++ ++ mode |= unit == TRTCM_PACKET_UNIT ? TRTCM_PKT_MODE : 0; ++ err = airoha_qdma_set_rl_config(qdma, queue_id, REG_INGRESS_TRTCM_CFG, ++ enable, mode); ++ if (err) ++ return err; ++ ++ return airoha_qdma_set_rl_config(qdma, queue_id, REG_INGRESS_TRTCM_CFG, ++ tick_sel, TRTCM_TICK_SEL); ++} ++ + static int airoha_qdma_get_trtcm_param(struct airoha_qdma *qdma, int channel, + u32 addr, enum trtcm_param_type param, + enum trtcm_mode_type mode, +@@ -2270,10 +2407,142 @@ static int airoha_tc_htb_alloc_leaf_queu + return 0; + } + ++static int airoha_qdma_set_rx_meter(struct airoha_gdm_port *port, ++ u32 rate, u32 bucket_size, ++ enum trtcm_unit_type unit_type) ++{ ++ struct airoha_qdma *qdma = port->qdma; ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { ++ int err; ++ ++ if (!qdma->q_rx[i].ndesc) ++ continue; ++ ++ err = airoha_qdma_init_rl_config(qdma, i, !!rate, unit_type); ++ if (err) ++ return err; ++ ++ err = airoha_qdma_set_rl_token_bucket(qdma, i, rate, ++ bucket_size); ++ if (err) ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int airoha_tc_matchall_act_validate(struct tc_cls_matchall_offload *f) ++{ ++ const struct flow_action *actions = &f->rule->action; ++ const struct flow_action_entry *act; ++ ++ if (!flow_action_has_entries(actions)) { ++ NL_SET_ERR_MSG_MOD(f->common.extack, ++ "filter run with no actions"); ++ return -EINVAL; ++ } ++ ++ if (!flow_offload_has_one_action(actions)) { ++ NL_SET_ERR_MSG_MOD(f->common.extack, ++ "only once action per filter is supported"); ++ return -EOPNOTSUPP; ++ } ++ ++ act = &actions->entries[0]; ++ if (act->id != FLOW_ACTION_POLICE) { ++ NL_SET_ERR_MSG_MOD(f->common.extack, "unsupported action"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (act->police.exceed.act_id != FLOW_ACTION_DROP) { ++ NL_SET_ERR_MSG_MOD(f->common.extack, ++ "invalid exceed action id"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) { ++ NL_SET_ERR_MSG_MOD(f->common.extack, ++ "invalid notexceed action id"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT && ++ !flow_action_is_last_entry(actions, act)) { ++ NL_SET_ERR_MSG_MOD(f->common.extack, ++ "action accept must be last"); ++ return -EOPNOTSUPP; ++ } ++ ++ if (act->police.peakrate_bytes_ps || act->police.avrate || ++ act->police.overhead || act->police.mtu) { ++ NL_SET_ERR_MSG_MOD(f->common.extack, ++ "peakrate/avrate/overhead/mtu unsupported"); ++ return -EOPNOTSUPP; ++ } ++ ++ return 0; ++} ++ ++static int airoha_dev_tc_matchall(struct net_device *dev, ++ struct tc_cls_matchall_offload *f) ++{ ++ enum trtcm_unit_type unit_type = TRTCM_BYTE_UNIT; ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ u32 rate = 0, bucket_size = 0; ++ ++ switch (f->command) { ++ case TC_CLSMATCHALL_REPLACE: { ++ const struct flow_action_entry *act; ++ int err; ++ ++ err = airoha_tc_matchall_act_validate(f); ++ if (err) ++ return err; ++ ++ act = &f->rule->action.entries[0]; ++ if (act->police.rate_pkt_ps) { ++ rate = act->police.rate_pkt_ps; ++ bucket_size = act->police.burst_pkt; ++ unit_type = TRTCM_PACKET_UNIT; ++ } else { ++ rate = div_u64(act->police.rate_bytes_ps, 1000); ++ rate = rate << 3; /* Kbps */ ++ bucket_size = act->police.burst; ++ } ++ fallthrough; ++ } ++ case TC_CLSMATCHALL_DESTROY: ++ return airoha_qdma_set_rx_meter(port, rate, bucket_size, ++ unit_type); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static int airoha_dev_setup_tc_block_cb(enum tc_setup_type type, ++ void *type_data, void *cb_priv) ++{ ++ struct net_device *dev = cb_priv; ++ ++ if (!tc_can_offload(dev)) ++ return -EOPNOTSUPP; ++ ++ switch (type) { ++ case TC_SETUP_CLSFLOWER: ++ return airoha_ppe_setup_tc_block_cb(dev, type_data); ++ case TC_SETUP_CLSMATCHALL: ++ return airoha_dev_tc_matchall(dev, type_data); ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ + static int airoha_dev_setup_tc_block(struct airoha_gdm_port *port, + struct flow_block_offload *f) + { +- flow_setup_cb_t *cb = airoha_ppe_setup_tc_block_cb; ++ flow_setup_cb_t *cb = airoha_dev_setup_tc_block_cb; + static LIST_HEAD(block_cb_list); + struct flow_block_cb *block_cb; + +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -127,6 +127,11 @@ enum tx_sched_mode { + TC_SCH_WRR2, + }; + ++enum trtcm_unit_type { ++ TRTCM_BYTE_UNIT, ++ TRTCM_PACKET_UNIT, ++}; ++ + enum trtcm_param_type { + TRTCM_MISC_MODE, /* meter_en, pps_mode, tick_sel */ + TRTCM_TOKEN_RATE_MODE, +@@ -554,8 +559,7 @@ bool airoha_is_valid_gdm_port(struct air + + void airoha_ppe_check_skb(struct airoha_ppe *ppe, struct sk_buff *skb, + u16 hash); +-int airoha_ppe_setup_tc_block_cb(enum tc_setup_type type, void *type_data, +- void *cb_priv); ++int airoha_ppe_setup_tc_block_cb(struct net_device *dev, void *type_data); + int airoha_ppe_init(struct airoha_eth *eth); + void airoha_ppe_deinit(struct airoha_eth *eth); + struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe, +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -967,18 +967,13 @@ error_npu_put: + return err; + } + +-int airoha_ppe_setup_tc_block_cb(enum tc_setup_type type, void *type_data, +- void *cb_priv) ++int airoha_ppe_setup_tc_block_cb(struct net_device *dev, void *type_data) + { +- struct flow_cls_offload *cls = type_data; +- struct net_device *dev = cb_priv; + struct airoha_gdm_port *port = netdev_priv(dev); ++ struct flow_cls_offload *cls = type_data; + struct airoha_eth *eth = port->qdma->eth; + int err = 0; + +- if (!tc_can_offload(dev) || type != TC_SETUP_CLSFLOWER) +- return -EOPNOTSUPP; +- + mutex_lock(&flow_offload_mutex); + + if (!eth->npu) +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -283,6 +283,7 @@ + #define PPE_HASH_SEED 0x12345678 + + #define REG_PPE_DFT_CPORT0(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x248) ++#define DFT_CPORT_MASK(_n) GENMASK(3 + ((_n) << 2), ((_n) << 2)) + + #define REG_PPE_DFT_CPORT1(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x24c) + +@@ -691,6 +692,12 @@ + #define REG_TRTCM_DATA_LOW(_n) ((_n) + 0x8) + #define REG_TRTCM_DATA_HIGH(_n) ((_n) + 0xc) + ++#define RATE_LIMIT_PARAM_RW_MASK BIT(31) ++#define RATE_LIMIT_PARAM_RW_DONE_MASK BIT(30) ++#define RATE_LIMIT_PARAM_TYPE_MASK GENMASK(29, 28) ++#define RATE_LIMIT_METER_GROUP_MASK GENMASK(27, 26) ++#define RATE_LIMIT_PARAM_INDEX_MASK GENMASK(23, 16) ++ + #define REG_TXWRR_MODE_CFG 0x1020 + #define TWRR_WEIGHT_SCALE_MASK BIT(31) + #define TWRR_WEIGHT_BASE_MASK BIT(3) diff --git a/lede/target/linux/airoha/patches-6.12/070-01-v6.16-net-airoha-Introduce-airoha_irq_bank-struct.patch b/lede/target/linux/airoha/patches-6.12/070-01-v6.16-net-airoha-Introduce-airoha_irq_bank-struct.patch new file mode 100644 index 0000000000..79fc513542 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/070-01-v6.16-net-airoha-Introduce-airoha_irq_bank-struct.patch @@ -0,0 +1,292 @@ +From 9439db26d3ee4a897e5cd108864172531f31ce07 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 18 Apr 2025 12:40:49 +0200 +Subject: [PATCH 1/2] net: airoha: Introduce airoha_irq_bank struct + +EN7581 ethernet SoC supports 4 programmable IRQ lines each one composed +by 4 IRQ configuration registers. Add airoha_irq_bank struct as a +container for independent IRQ lines info (e.g. IRQ number, enabled source +interrupts, ecc). This is a preliminary patch to support multiple IRQ lines +in airoha_eth driver. + +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250418-airoha-eth-multi-irq-v1-1-1ab0083ca3c1@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 106 ++++++++++++++-------- + drivers/net/ethernet/airoha/airoha_eth.h | 13 ++- + drivers/net/ethernet/airoha/airoha_regs.h | 11 ++- + 3 files changed, 86 insertions(+), 44 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -34,37 +34,40 @@ u32 airoha_rmw(void __iomem *base, u32 o + return val; + } + +-static void airoha_qdma_set_irqmask(struct airoha_qdma *qdma, int index, +- u32 clear, u32 set) ++static void airoha_qdma_set_irqmask(struct airoha_irq_bank *irq_bank, ++ int index, u32 clear, u32 set) + { ++ struct airoha_qdma *qdma = irq_bank->qdma; ++ int bank = irq_bank - &qdma->irq_banks[0]; + unsigned long flags; + +- if (WARN_ON_ONCE(index >= ARRAY_SIZE(qdma->irqmask))) ++ if (WARN_ON_ONCE(index >= ARRAY_SIZE(irq_bank->irqmask))) + return; + +- spin_lock_irqsave(&qdma->irq_lock, flags); ++ spin_lock_irqsave(&irq_bank->irq_lock, flags); + +- qdma->irqmask[index] &= ~clear; +- qdma->irqmask[index] |= set; +- airoha_qdma_wr(qdma, REG_INT_ENABLE(index), qdma->irqmask[index]); ++ irq_bank->irqmask[index] &= ~clear; ++ irq_bank->irqmask[index] |= set; ++ airoha_qdma_wr(qdma, REG_INT_ENABLE(bank, index), ++ irq_bank->irqmask[index]); + /* Read irq_enable register in order to guarantee the update above + * completes in the spinlock critical section. + */ +- airoha_qdma_rr(qdma, REG_INT_ENABLE(index)); ++ airoha_qdma_rr(qdma, REG_INT_ENABLE(bank, index)); + +- spin_unlock_irqrestore(&qdma->irq_lock, flags); ++ spin_unlock_irqrestore(&irq_bank->irq_lock, flags); + } + +-static void airoha_qdma_irq_enable(struct airoha_qdma *qdma, int index, +- u32 mask) ++static void airoha_qdma_irq_enable(struct airoha_irq_bank *irq_bank, ++ int index, u32 mask) + { +- airoha_qdma_set_irqmask(qdma, index, 0, mask); ++ airoha_qdma_set_irqmask(irq_bank, index, 0, mask); + } + +-static void airoha_qdma_irq_disable(struct airoha_qdma *qdma, int index, +- u32 mask) ++static void airoha_qdma_irq_disable(struct airoha_irq_bank *irq_bank, ++ int index, u32 mask) + { +- airoha_qdma_set_irqmask(qdma, index, mask, 0); ++ airoha_qdma_set_irqmask(irq_bank, index, mask, 0); + } + + static bool airhoa_is_lan_gdm_port(struct airoha_gdm_port *port) +@@ -732,6 +735,7 @@ free_frag: + static int airoha_qdma_rx_napi_poll(struct napi_struct *napi, int budget) + { + struct airoha_queue *q = container_of(napi, struct airoha_queue, napi); ++ struct airoha_irq_bank *irq_bank = &q->qdma->irq_banks[0]; + int cur, done = 0; + + do { +@@ -740,7 +744,7 @@ static int airoha_qdma_rx_napi_poll(stru + } while (cur && done < budget); + + if (done < budget && napi_complete(napi)) +- airoha_qdma_irq_enable(q->qdma, QDMA_INT_REG_IDX1, ++ airoha_qdma_irq_enable(irq_bank, QDMA_INT_REG_IDX1, + RX_DONE_INT_MASK); + + return done; +@@ -944,7 +948,7 @@ unlock: + } + + if (done < budget && napi_complete(napi)) +- airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX0, ++ airoha_qdma_irq_enable(&qdma->irq_banks[0], QDMA_INT_REG_IDX0, + TX_DONE_INT_MASK(id)); + + return done; +@@ -1175,13 +1179,16 @@ static int airoha_qdma_hw_init(struct ai + int i; + + /* clear pending irqs */ +- for (i = 0; i < ARRAY_SIZE(qdma->irqmask); i++) ++ for (i = 0; i < ARRAY_SIZE(qdma->irq_banks[0].irqmask); i++) + airoha_qdma_wr(qdma, REG_INT_STATUS(i), 0xffffffff); + + /* setup irqs */ +- airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX0, INT_IDX0_MASK); +- airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX1, INT_IDX1_MASK); +- airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX4, INT_IDX4_MASK); ++ airoha_qdma_irq_enable(&qdma->irq_banks[0], QDMA_INT_REG_IDX0, ++ INT_IDX0_MASK); ++ airoha_qdma_irq_enable(&qdma->irq_banks[0], QDMA_INT_REG_IDX1, ++ INT_IDX1_MASK); ++ airoha_qdma_irq_enable(&qdma->irq_banks[0], QDMA_INT_REG_IDX4, ++ INT_IDX4_MASK); + + /* setup irq binding */ + for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { +@@ -1226,13 +1233,14 @@ static int airoha_qdma_hw_init(struct ai + + static irqreturn_t airoha_irq_handler(int irq, void *dev_instance) + { +- struct airoha_qdma *qdma = dev_instance; +- u32 intr[ARRAY_SIZE(qdma->irqmask)]; ++ struct airoha_irq_bank *irq_bank = dev_instance; ++ struct airoha_qdma *qdma = irq_bank->qdma; ++ u32 intr[ARRAY_SIZE(irq_bank->irqmask)]; + int i; + +- for (i = 0; i < ARRAY_SIZE(qdma->irqmask); i++) { ++ for (i = 0; i < ARRAY_SIZE(intr); i++) { + intr[i] = airoha_qdma_rr(qdma, REG_INT_STATUS(i)); +- intr[i] &= qdma->irqmask[i]; ++ intr[i] &= irq_bank->irqmask[i]; + airoha_qdma_wr(qdma, REG_INT_STATUS(i), intr[i]); + } + +@@ -1240,7 +1248,7 @@ static irqreturn_t airoha_irq_handler(in + return IRQ_NONE; + + if (intr[1] & RX_DONE_INT_MASK) { +- airoha_qdma_irq_disable(qdma, QDMA_INT_REG_IDX1, ++ airoha_qdma_irq_disable(irq_bank, QDMA_INT_REG_IDX1, + RX_DONE_INT_MASK); + + for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { +@@ -1257,7 +1265,7 @@ static irqreturn_t airoha_irq_handler(in + if (!(intr[0] & TX_DONE_INT_MASK(i))) + continue; + +- airoha_qdma_irq_disable(qdma, QDMA_INT_REG_IDX0, ++ airoha_qdma_irq_disable(irq_bank, QDMA_INT_REG_IDX0, + TX_DONE_INT_MASK(i)); + napi_schedule(&qdma->q_tx_irq[i].napi); + } +@@ -1266,6 +1274,39 @@ static irqreturn_t airoha_irq_handler(in + return IRQ_HANDLED; + } + ++static int airoha_qdma_init_irq_banks(struct platform_device *pdev, ++ struct airoha_qdma *qdma) ++{ ++ struct airoha_eth *eth = qdma->eth; ++ int i, id = qdma - ð->qdma[0]; ++ ++ for (i = 0; i < ARRAY_SIZE(qdma->irq_banks); i++) { ++ struct airoha_irq_bank *irq_bank = &qdma->irq_banks[i]; ++ int err, irq_index = 4 * id + i; ++ const char *name; ++ ++ spin_lock_init(&irq_bank->irq_lock); ++ irq_bank->qdma = qdma; ++ ++ irq_bank->irq = platform_get_irq(pdev, irq_index); ++ if (irq_bank->irq < 0) ++ return irq_bank->irq; ++ ++ name = devm_kasprintf(eth->dev, GFP_KERNEL, ++ KBUILD_MODNAME ".%d", irq_index); ++ if (!name) ++ return -ENOMEM; ++ ++ err = devm_request_irq(eth->dev, irq_bank->irq, ++ airoha_irq_handler, IRQF_SHARED, name, ++ irq_bank); ++ if (err) ++ return err; ++ } ++ ++ return 0; ++} ++ + static int airoha_qdma_init(struct platform_device *pdev, + struct airoha_eth *eth, + struct airoha_qdma *qdma) +@@ -1273,9 +1314,7 @@ static int airoha_qdma_init(struct platf + int err, id = qdma - ð->qdma[0]; + const char *res; + +- spin_lock_init(&qdma->irq_lock); + qdma->eth = eth; +- + res = devm_kasprintf(eth->dev, GFP_KERNEL, "qdma%d", id); + if (!res) + return -ENOMEM; +@@ -1285,12 +1324,7 @@ static int airoha_qdma_init(struct platf + return dev_err_probe(eth->dev, PTR_ERR(qdma->regs), + "failed to iomap qdma%d regs\n", id); + +- qdma->irq = platform_get_irq(pdev, 4 * id); +- if (qdma->irq < 0) +- return qdma->irq; +- +- err = devm_request_irq(eth->dev, qdma->irq, airoha_irq_handler, +- IRQF_SHARED, KBUILD_MODNAME, qdma); ++ err = airoha_qdma_init_irq_banks(pdev, qdma); + if (err) + return err; + +@@ -2781,7 +2815,7 @@ static int airoha_alloc_gdm_port(struct + dev->features |= dev->hw_features; + dev->vlan_features = dev->hw_features; + dev->dev.of_node = np; +- dev->irq = qdma->irq; ++ dev->irq = qdma->irq_banks[0].irq; + SET_NETDEV_DEV(dev, eth->dev); + + /* reserve hw queues for HTB offloading */ +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -17,6 +17,7 @@ + + #define AIROHA_MAX_NUM_GDM_PORTS 4 + #define AIROHA_MAX_NUM_QDMA 2 ++#define AIROHA_MAX_NUM_IRQ_BANKS 1 + #define AIROHA_MAX_DSA_PORTS 7 + #define AIROHA_MAX_NUM_RSTS 3 + #define AIROHA_MAX_NUM_XSI_RSTS 5 +@@ -452,17 +453,23 @@ struct airoha_flow_table_entry { + unsigned long cookie; + }; + +-struct airoha_qdma { +- struct airoha_eth *eth; +- void __iomem *regs; ++struct airoha_irq_bank { ++ struct airoha_qdma *qdma; + + /* protect concurrent irqmask accesses */ + spinlock_t irq_lock; + u32 irqmask[QDMA_INT_REG_MAX]; + int irq; ++}; ++ ++struct airoha_qdma { ++ struct airoha_eth *eth; ++ void __iomem *regs; + + atomic_t users; + ++ struct airoha_irq_bank irq_banks[AIROHA_MAX_NUM_IRQ_BANKS]; ++ + struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ]; + + struct airoha_queue q_tx[AIROHA_NUM_TX_RING]; +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -423,11 +423,12 @@ + ((_n) == 2) ? 0x0720 : \ + ((_n) == 1) ? 0x0024 : 0x0020) + +-#define REG_INT_ENABLE(_n) \ +- (((_n) == 4) ? 0x0750 : \ +- ((_n) == 3) ? 0x0744 : \ +- ((_n) == 2) ? 0x0740 : \ +- ((_n) == 1) ? 0x002c : 0x0028) ++#define REG_INT_ENABLE(_b, _n) \ ++ (((_n) == 4) ? 0x0750 + ((_b) << 5) : \ ++ ((_n) == 3) ? 0x0744 + ((_b) << 5) : \ ++ ((_n) == 2) ? 0x0740 + ((_b) << 5) : \ ++ ((_n) == 1) ? 0x002c + ((_b) << 3) : \ ++ 0x0028 + ((_b) << 3)) + + /* QDMA_CSR_INT_ENABLE1 */ + #define RX15_COHERENT_INT_MASK BIT(31) diff --git a/lede/target/linux/airoha/patches-6.12/070-02-v6.16-net-airoha-Enable-multiple-IRQ-lines-support-in-airo.patch b/lede/target/linux/airoha/patches-6.12/070-02-v6.16-net-airoha-Enable-multiple-IRQ-lines-support-in-airo.patch new file mode 100644 index 0000000000..0f7b0cb57c --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/070-02-v6.16-net-airoha-Enable-multiple-IRQ-lines-support-in-airo.patch @@ -0,0 +1,379 @@ +From f252493e1835366fc25ce631c3056f900977dd11 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 18 Apr 2025 12:40:50 +0200 +Subject: [PATCH 2/2] net: airoha: Enable multiple IRQ lines support in + airoha_eth driver. + +EN7581 ethernet SoC supports 4 programmable IRQ lines for Tx and Rx +interrupts. Enable multiple IRQ lines support. Map Rx/Tx queues to the +available IRQ lines using the default scheme used in the vendor SDK: + +- IRQ0: rx queues [0-4],[7-9],15 +- IRQ1: rx queues [21-30] +- IRQ2: rx queues 5 +- IRQ3: rx queues 6 + +Tx queues interrupts are managed by IRQ0. + +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250418-airoha-eth-multi-irq-v1-2-1ab0083ca3c1@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 67 +++++--- + drivers/net/ethernet/airoha/airoha_eth.h | 13 +- + drivers/net/ethernet/airoha/airoha_regs.h | 185 +++++++++++++++++----- + 3 files changed, 206 insertions(+), 59 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -735,7 +735,6 @@ free_frag: + static int airoha_qdma_rx_napi_poll(struct napi_struct *napi, int budget) + { + struct airoha_queue *q = container_of(napi, struct airoha_queue, napi); +- struct airoha_irq_bank *irq_bank = &q->qdma->irq_banks[0]; + int cur, done = 0; + + do { +@@ -743,9 +742,20 @@ static int airoha_qdma_rx_napi_poll(stru + done += cur; + } while (cur && done < budget); + +- if (done < budget && napi_complete(napi)) +- airoha_qdma_irq_enable(irq_bank, QDMA_INT_REG_IDX1, +- RX_DONE_INT_MASK); ++ if (done < budget && napi_complete(napi)) { ++ struct airoha_qdma *qdma = q->qdma; ++ int i, qid = q - &qdma->q_rx[0]; ++ int intr_reg = qid < RX_DONE_HIGH_OFFSET ? QDMA_INT_REG_IDX1 ++ : QDMA_INT_REG_IDX2; ++ ++ for (i = 0; i < ARRAY_SIZE(qdma->irq_banks); i++) { ++ if (!(BIT(qid) & RX_IRQ_BANK_PIN_MASK(i))) ++ continue; ++ ++ airoha_qdma_irq_enable(&qdma->irq_banks[i], intr_reg, ++ BIT(qid % RX_DONE_HIGH_OFFSET)); ++ } ++ } + + return done; + } +@@ -1178,17 +1188,24 @@ static int airoha_qdma_hw_init(struct ai + { + int i; + +- /* clear pending irqs */ +- for (i = 0; i < ARRAY_SIZE(qdma->irq_banks[0].irqmask); i++) ++ for (i = 0; i < ARRAY_SIZE(qdma->irq_banks); i++) { ++ /* clear pending irqs */ + airoha_qdma_wr(qdma, REG_INT_STATUS(i), 0xffffffff); +- +- /* setup irqs */ ++ /* setup rx irqs */ ++ airoha_qdma_irq_enable(&qdma->irq_banks[i], QDMA_INT_REG_IDX0, ++ INT_RX0_MASK(RX_IRQ_BANK_PIN_MASK(i))); ++ airoha_qdma_irq_enable(&qdma->irq_banks[i], QDMA_INT_REG_IDX1, ++ INT_RX1_MASK(RX_IRQ_BANK_PIN_MASK(i))); ++ airoha_qdma_irq_enable(&qdma->irq_banks[i], QDMA_INT_REG_IDX2, ++ INT_RX2_MASK(RX_IRQ_BANK_PIN_MASK(i))); ++ airoha_qdma_irq_enable(&qdma->irq_banks[i], QDMA_INT_REG_IDX3, ++ INT_RX3_MASK(RX_IRQ_BANK_PIN_MASK(i))); ++ } ++ /* setup tx irqs */ + airoha_qdma_irq_enable(&qdma->irq_banks[0], QDMA_INT_REG_IDX0, +- INT_IDX0_MASK); +- airoha_qdma_irq_enable(&qdma->irq_banks[0], QDMA_INT_REG_IDX1, +- INT_IDX1_MASK); ++ TX_COHERENT_LOW_INT_MASK | INT_TX_MASK); + airoha_qdma_irq_enable(&qdma->irq_banks[0], QDMA_INT_REG_IDX4, +- INT_IDX4_MASK); ++ TX_COHERENT_HIGH_INT_MASK); + + /* setup irq binding */ + for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) { +@@ -1235,6 +1252,7 @@ static irqreturn_t airoha_irq_handler(in + { + struct airoha_irq_bank *irq_bank = dev_instance; + struct airoha_qdma *qdma = irq_bank->qdma; ++ u32 rx_intr_mask = 0, rx_intr1, rx_intr2; + u32 intr[ARRAY_SIZE(irq_bank->irqmask)]; + int i; + +@@ -1247,17 +1265,24 @@ static irqreturn_t airoha_irq_handler(in + if (!test_bit(DEV_STATE_INITIALIZED, &qdma->eth->state)) + return IRQ_NONE; + +- if (intr[1] & RX_DONE_INT_MASK) { +- airoha_qdma_irq_disable(irq_bank, QDMA_INT_REG_IDX1, +- RX_DONE_INT_MASK); ++ rx_intr1 = intr[1] & RX_DONE_LOW_INT_MASK; ++ if (rx_intr1) { ++ airoha_qdma_irq_disable(irq_bank, QDMA_INT_REG_IDX1, rx_intr1); ++ rx_intr_mask |= rx_intr1; ++ } + +- for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) { +- if (!qdma->q_rx[i].ndesc) +- continue; ++ rx_intr2 = intr[2] & RX_DONE_HIGH_INT_MASK; ++ if (rx_intr2) { ++ airoha_qdma_irq_disable(irq_bank, QDMA_INT_REG_IDX2, rx_intr2); ++ rx_intr_mask |= (rx_intr2 << 16); ++ } + +- if (intr[1] & BIT(i)) +- napi_schedule(&qdma->q_rx[i].napi); +- } ++ for (i = 0; rx_intr_mask && i < ARRAY_SIZE(qdma->q_rx); i++) { ++ if (!qdma->q_rx[i].ndesc) ++ continue; ++ ++ if (rx_intr_mask & BIT(i)) ++ napi_schedule(&qdma->q_rx[i].napi); + } + + if (intr[0] & INT_TX_MASK) { +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -17,7 +17,7 @@ + + #define AIROHA_MAX_NUM_GDM_PORTS 4 + #define AIROHA_MAX_NUM_QDMA 2 +-#define AIROHA_MAX_NUM_IRQ_BANKS 1 ++#define AIROHA_MAX_NUM_IRQ_BANKS 4 + #define AIROHA_MAX_DSA_PORTS 7 + #define AIROHA_MAX_NUM_RSTS 3 + #define AIROHA_MAX_NUM_XSI_RSTS 5 +@@ -453,6 +453,17 @@ struct airoha_flow_table_entry { + unsigned long cookie; + }; + ++/* RX queue to IRQ mapping: BIT(q) in IRQ(n) */ ++#define RX_IRQ0_BANK_PIN_MASK 0x839f ++#define RX_IRQ1_BANK_PIN_MASK 0x7fe00000 ++#define RX_IRQ2_BANK_PIN_MASK 0x20 ++#define RX_IRQ3_BANK_PIN_MASK 0x40 ++#define RX_IRQ_BANK_PIN_MASK(_n) \ ++ (((_n) == 3) ? RX_IRQ3_BANK_PIN_MASK : \ ++ ((_n) == 2) ? RX_IRQ2_BANK_PIN_MASK : \ ++ ((_n) == 1) ? RX_IRQ1_BANK_PIN_MASK : \ ++ RX_IRQ0_BANK_PIN_MASK) ++ + struct airoha_irq_bank { + struct airoha_qdma *qdma; + +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -463,6 +463,26 @@ + #define IRQ0_FULL_INT_MASK BIT(1) + #define IRQ0_INT_MASK BIT(0) + ++#define RX_COHERENT_LOW_INT_MASK \ ++ (RX15_COHERENT_INT_MASK | RX14_COHERENT_INT_MASK | \ ++ RX13_COHERENT_INT_MASK | RX12_COHERENT_INT_MASK | \ ++ RX11_COHERENT_INT_MASK | RX10_COHERENT_INT_MASK | \ ++ RX9_COHERENT_INT_MASK | RX8_COHERENT_INT_MASK | \ ++ RX7_COHERENT_INT_MASK | RX6_COHERENT_INT_MASK | \ ++ RX5_COHERENT_INT_MASK | RX4_COHERENT_INT_MASK | \ ++ RX3_COHERENT_INT_MASK | RX2_COHERENT_INT_MASK | \ ++ RX1_COHERENT_INT_MASK | RX0_COHERENT_INT_MASK) ++ ++#define RX_COHERENT_LOW_OFFSET __ffs(RX_COHERENT_LOW_INT_MASK) ++#define INT_RX0_MASK(_n) \ ++ (((_n) << RX_COHERENT_LOW_OFFSET) & RX_COHERENT_LOW_INT_MASK) ++ ++#define TX_COHERENT_LOW_INT_MASK \ ++ (TX7_COHERENT_INT_MASK | TX6_COHERENT_INT_MASK | \ ++ TX5_COHERENT_INT_MASK | TX4_COHERENT_INT_MASK | \ ++ TX3_COHERENT_INT_MASK | TX2_COHERENT_INT_MASK | \ ++ TX1_COHERENT_INT_MASK | TX0_COHERENT_INT_MASK) ++ + #define TX_DONE_INT_MASK(_n) \ + ((_n) ? IRQ1_INT_MASK | IRQ1_FULL_INT_MASK \ + : IRQ0_INT_MASK | IRQ0_FULL_INT_MASK) +@@ -471,17 +491,6 @@ + (IRQ1_INT_MASK | IRQ1_FULL_INT_MASK | \ + IRQ0_INT_MASK | IRQ0_FULL_INT_MASK) + +-#define INT_IDX0_MASK \ +- (TX0_COHERENT_INT_MASK | TX1_COHERENT_INT_MASK | \ +- TX2_COHERENT_INT_MASK | TX3_COHERENT_INT_MASK | \ +- TX4_COHERENT_INT_MASK | TX5_COHERENT_INT_MASK | \ +- TX6_COHERENT_INT_MASK | TX7_COHERENT_INT_MASK | \ +- RX0_COHERENT_INT_MASK | RX1_COHERENT_INT_MASK | \ +- RX2_COHERENT_INT_MASK | RX3_COHERENT_INT_MASK | \ +- RX4_COHERENT_INT_MASK | RX7_COHERENT_INT_MASK | \ +- RX8_COHERENT_INT_MASK | RX9_COHERENT_INT_MASK | \ +- RX15_COHERENT_INT_MASK | INT_TX_MASK) +- + /* QDMA_CSR_INT_ENABLE2 */ + #define RX15_NO_CPU_DSCP_INT_MASK BIT(31) + #define RX14_NO_CPU_DSCP_INT_MASK BIT(30) +@@ -516,19 +525,121 @@ + #define RX1_DONE_INT_MASK BIT(1) + #define RX0_DONE_INT_MASK BIT(0) + +-#define RX_DONE_INT_MASK \ +- (RX0_DONE_INT_MASK | RX1_DONE_INT_MASK | \ +- RX2_DONE_INT_MASK | RX3_DONE_INT_MASK | \ +- RX4_DONE_INT_MASK | RX7_DONE_INT_MASK | \ +- RX8_DONE_INT_MASK | RX9_DONE_INT_MASK | \ +- RX15_DONE_INT_MASK) +-#define INT_IDX1_MASK \ +- (RX_DONE_INT_MASK | \ +- RX0_NO_CPU_DSCP_INT_MASK | RX1_NO_CPU_DSCP_INT_MASK | \ +- RX2_NO_CPU_DSCP_INT_MASK | RX3_NO_CPU_DSCP_INT_MASK | \ +- RX4_NO_CPU_DSCP_INT_MASK | RX7_NO_CPU_DSCP_INT_MASK | \ +- RX8_NO_CPU_DSCP_INT_MASK | RX9_NO_CPU_DSCP_INT_MASK | \ +- RX15_NO_CPU_DSCP_INT_MASK) ++#define RX_NO_CPU_DSCP_LOW_INT_MASK \ ++ (RX15_NO_CPU_DSCP_INT_MASK | RX14_NO_CPU_DSCP_INT_MASK | \ ++ RX13_NO_CPU_DSCP_INT_MASK | RX12_NO_CPU_DSCP_INT_MASK | \ ++ RX11_NO_CPU_DSCP_INT_MASK | RX10_NO_CPU_DSCP_INT_MASK | \ ++ RX9_NO_CPU_DSCP_INT_MASK | RX8_NO_CPU_DSCP_INT_MASK | \ ++ RX7_NO_CPU_DSCP_INT_MASK | RX6_NO_CPU_DSCP_INT_MASK | \ ++ RX5_NO_CPU_DSCP_INT_MASK | RX4_NO_CPU_DSCP_INT_MASK | \ ++ RX3_NO_CPU_DSCP_INT_MASK | RX2_NO_CPU_DSCP_INT_MASK | \ ++ RX1_NO_CPU_DSCP_INT_MASK | RX0_NO_CPU_DSCP_INT_MASK) ++ ++#define RX_DONE_LOW_INT_MASK \ ++ (RX15_DONE_INT_MASK | RX14_DONE_INT_MASK | \ ++ RX13_DONE_INT_MASK | RX12_DONE_INT_MASK | \ ++ RX11_DONE_INT_MASK | RX10_DONE_INT_MASK | \ ++ RX9_DONE_INT_MASK | RX8_DONE_INT_MASK | \ ++ RX7_DONE_INT_MASK | RX6_DONE_INT_MASK | \ ++ RX5_DONE_INT_MASK | RX4_DONE_INT_MASK | \ ++ RX3_DONE_INT_MASK | RX2_DONE_INT_MASK | \ ++ RX1_DONE_INT_MASK | RX0_DONE_INT_MASK) ++ ++#define RX_NO_CPU_DSCP_LOW_OFFSET __ffs(RX_NO_CPU_DSCP_LOW_INT_MASK) ++#define INT_RX1_MASK(_n) \ ++ ((((_n) << RX_NO_CPU_DSCP_LOW_OFFSET) & RX_NO_CPU_DSCP_LOW_INT_MASK) | \ ++ (RX_DONE_LOW_INT_MASK & (_n))) ++ ++/* QDMA_CSR_INT_ENABLE3 */ ++#define RX31_NO_CPU_DSCP_INT_MASK BIT(31) ++#define RX30_NO_CPU_DSCP_INT_MASK BIT(30) ++#define RX29_NO_CPU_DSCP_INT_MASK BIT(29) ++#define RX28_NO_CPU_DSCP_INT_MASK BIT(28) ++#define RX27_NO_CPU_DSCP_INT_MASK BIT(27) ++#define RX26_NO_CPU_DSCP_INT_MASK BIT(26) ++#define RX25_NO_CPU_DSCP_INT_MASK BIT(25) ++#define RX24_NO_CPU_DSCP_INT_MASK BIT(24) ++#define RX23_NO_CPU_DSCP_INT_MASK BIT(23) ++#define RX22_NO_CPU_DSCP_INT_MASK BIT(22) ++#define RX21_NO_CPU_DSCP_INT_MASK BIT(21) ++#define RX20_NO_CPU_DSCP_INT_MASK BIT(20) ++#define RX19_NO_CPU_DSCP_INT_MASK BIT(19) ++#define RX18_NO_CPU_DSCP_INT_MASK BIT(18) ++#define RX17_NO_CPU_DSCP_INT_MASK BIT(17) ++#define RX16_NO_CPU_DSCP_INT_MASK BIT(16) ++#define RX31_DONE_INT_MASK BIT(15) ++#define RX30_DONE_INT_MASK BIT(14) ++#define RX29_DONE_INT_MASK BIT(13) ++#define RX28_DONE_INT_MASK BIT(12) ++#define RX27_DONE_INT_MASK BIT(11) ++#define RX26_DONE_INT_MASK BIT(10) ++#define RX25_DONE_INT_MASK BIT(9) ++#define RX24_DONE_INT_MASK BIT(8) ++#define RX23_DONE_INT_MASK BIT(7) ++#define RX22_DONE_INT_MASK BIT(6) ++#define RX21_DONE_INT_MASK BIT(5) ++#define RX20_DONE_INT_MASK BIT(4) ++#define RX19_DONE_INT_MASK BIT(3) ++#define RX18_DONE_INT_MASK BIT(2) ++#define RX17_DONE_INT_MASK BIT(1) ++#define RX16_DONE_INT_MASK BIT(0) ++ ++#define RX_NO_CPU_DSCP_HIGH_INT_MASK \ ++ (RX31_NO_CPU_DSCP_INT_MASK | RX30_NO_CPU_DSCP_INT_MASK | \ ++ RX29_NO_CPU_DSCP_INT_MASK | RX28_NO_CPU_DSCP_INT_MASK | \ ++ RX27_NO_CPU_DSCP_INT_MASK | RX26_NO_CPU_DSCP_INT_MASK | \ ++ RX25_NO_CPU_DSCP_INT_MASK | RX24_NO_CPU_DSCP_INT_MASK | \ ++ RX23_NO_CPU_DSCP_INT_MASK | RX22_NO_CPU_DSCP_INT_MASK | \ ++ RX21_NO_CPU_DSCP_INT_MASK | RX20_NO_CPU_DSCP_INT_MASK | \ ++ RX19_NO_CPU_DSCP_INT_MASK | RX18_NO_CPU_DSCP_INT_MASK | \ ++ RX17_NO_CPU_DSCP_INT_MASK | RX16_NO_CPU_DSCP_INT_MASK) ++ ++#define RX_DONE_HIGH_INT_MASK \ ++ (RX31_DONE_INT_MASK | RX30_DONE_INT_MASK | \ ++ RX29_DONE_INT_MASK | RX28_DONE_INT_MASK | \ ++ RX27_DONE_INT_MASK | RX26_DONE_INT_MASK | \ ++ RX25_DONE_INT_MASK | RX24_DONE_INT_MASK | \ ++ RX23_DONE_INT_MASK | RX22_DONE_INT_MASK | \ ++ RX21_DONE_INT_MASK | RX20_DONE_INT_MASK | \ ++ RX19_DONE_INT_MASK | RX18_DONE_INT_MASK | \ ++ RX17_DONE_INT_MASK | RX16_DONE_INT_MASK) ++ ++#define RX_DONE_INT_MASK (RX_DONE_HIGH_INT_MASK | RX_DONE_LOW_INT_MASK) ++#define RX_DONE_HIGH_OFFSET fls(RX_DONE_HIGH_INT_MASK) ++ ++#define INT_RX2_MASK(_n) \ ++ ((RX_NO_CPU_DSCP_HIGH_INT_MASK & (_n)) | \ ++ (((_n) >> RX_DONE_HIGH_OFFSET) & RX_DONE_HIGH_INT_MASK)) ++ ++/* QDMA_CSR_INT_ENABLE4 */ ++#define RX31_COHERENT_INT_MASK BIT(31) ++#define RX30_COHERENT_INT_MASK BIT(30) ++#define RX29_COHERENT_INT_MASK BIT(29) ++#define RX28_COHERENT_INT_MASK BIT(28) ++#define RX27_COHERENT_INT_MASK BIT(27) ++#define RX26_COHERENT_INT_MASK BIT(26) ++#define RX25_COHERENT_INT_MASK BIT(25) ++#define RX24_COHERENT_INT_MASK BIT(24) ++#define RX23_COHERENT_INT_MASK BIT(23) ++#define RX22_COHERENT_INT_MASK BIT(22) ++#define RX21_COHERENT_INT_MASK BIT(21) ++#define RX20_COHERENT_INT_MASK BIT(20) ++#define RX19_COHERENT_INT_MASK BIT(19) ++#define RX18_COHERENT_INT_MASK BIT(18) ++#define RX17_COHERENT_INT_MASK BIT(17) ++#define RX16_COHERENT_INT_MASK BIT(16) ++ ++#define RX_COHERENT_HIGH_INT_MASK \ ++ (RX31_COHERENT_INT_MASK | RX30_COHERENT_INT_MASK | \ ++ RX29_COHERENT_INT_MASK | RX28_COHERENT_INT_MASK | \ ++ RX27_COHERENT_INT_MASK | RX26_COHERENT_INT_MASK | \ ++ RX25_COHERENT_INT_MASK | RX24_COHERENT_INT_MASK | \ ++ RX23_COHERENT_INT_MASK | RX22_COHERENT_INT_MASK | \ ++ RX21_COHERENT_INT_MASK | RX20_COHERENT_INT_MASK | \ ++ RX19_COHERENT_INT_MASK | RX18_COHERENT_INT_MASK | \ ++ RX17_COHERENT_INT_MASK | RX16_COHERENT_INT_MASK) ++ ++#define INT_RX3_MASK(_n) (RX_COHERENT_HIGH_INT_MASK & (_n)) + + /* QDMA_CSR_INT_ENABLE5 */ + #define TX31_COHERENT_INT_MASK BIT(31) +@@ -556,19 +667,19 @@ + #define TX9_COHERENT_INT_MASK BIT(9) + #define TX8_COHERENT_INT_MASK BIT(8) + +-#define INT_IDX4_MASK \ +- (TX8_COHERENT_INT_MASK | TX9_COHERENT_INT_MASK | \ +- TX10_COHERENT_INT_MASK | TX11_COHERENT_INT_MASK | \ +- TX12_COHERENT_INT_MASK | TX13_COHERENT_INT_MASK | \ +- TX14_COHERENT_INT_MASK | TX15_COHERENT_INT_MASK | \ +- TX16_COHERENT_INT_MASK | TX17_COHERENT_INT_MASK | \ +- TX18_COHERENT_INT_MASK | TX19_COHERENT_INT_MASK | \ +- TX20_COHERENT_INT_MASK | TX21_COHERENT_INT_MASK | \ +- TX22_COHERENT_INT_MASK | TX23_COHERENT_INT_MASK | \ +- TX24_COHERENT_INT_MASK | TX25_COHERENT_INT_MASK | \ +- TX26_COHERENT_INT_MASK | TX27_COHERENT_INT_MASK | \ +- TX28_COHERENT_INT_MASK | TX29_COHERENT_INT_MASK | \ +- TX30_COHERENT_INT_MASK | TX31_COHERENT_INT_MASK) ++#define TX_COHERENT_HIGH_INT_MASK \ ++ (TX31_COHERENT_INT_MASK | TX30_COHERENT_INT_MASK | \ ++ TX29_COHERENT_INT_MASK | TX28_COHERENT_INT_MASK | \ ++ TX27_COHERENT_INT_MASK | TX26_COHERENT_INT_MASK | \ ++ TX25_COHERENT_INT_MASK | TX24_COHERENT_INT_MASK | \ ++ TX23_COHERENT_INT_MASK | TX22_COHERENT_INT_MASK | \ ++ TX21_COHERENT_INT_MASK | TX20_COHERENT_INT_MASK | \ ++ TX19_COHERENT_INT_MASK | TX18_COHERENT_INT_MASK | \ ++ TX17_COHERENT_INT_MASK | TX16_COHERENT_INT_MASK | \ ++ TX15_COHERENT_INT_MASK | TX14_COHERENT_INT_MASK | \ ++ TX13_COHERENT_INT_MASK | TX12_COHERENT_INT_MASK | \ ++ TX11_COHERENT_INT_MASK | TX10_COHERENT_INT_MASK | \ ++ TX9_COHERENT_INT_MASK | TX8_COHERENT_INT_MASK) + + #define REG_TX_IRQ_BASE(_n) ((_n) ? 0x0048 : 0x0050) + diff --git a/lede/target/linux/airoha/patches-6.12/071-v6.15-net-airoha-Add-missing-field-to-ppe_mbox_data-struct.patch b/lede/target/linux/airoha/patches-6.12/071-v6.15-net-airoha-Add-missing-field-to-ppe_mbox_data-struct.patch new file mode 100644 index 0000000000..2fb90b6c3b --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/071-v6.15-net-airoha-Add-missing-field-to-ppe_mbox_data-struct.patch @@ -0,0 +1,48 @@ +From 4a7843cc8a41b9612becccc07715ed017770eb89 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 6 May 2025 18:56:47 +0200 +Subject: [PATCH] net: airoha: Add missing field to ppe_mbox_data struct + +The official Airoha EN7581 firmware requires adding max_packet field in +ppe_mbox_data struct while the unofficial one used to develop the Airoha +EN7581 flowtable support does not require this field. +This patch does not introduce any real backwards compatible issue since +EN7581 fw is not publicly available in linux-firmware or other +repositories (e.g. OpenWrt) yet and the official fw version will use this +new layout. For this reason this change needs to be backported. +Moreover, make explicit the padding added by the compiler introducing +the rsv array in init_info struct. +At the same time use u32 instead of int for init_info and set_info +struct definitions in ppe_mbox_data struct. + +Fixes: 23290c7bc190d ("net: airoha: Introduce Airoha NPU support") +Reviewed-by: Simon Horman +Reviewed-by: Jacob Keller +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250506-airoha-en7581-fix-ppe_mbox_data-v5-1-29cabed6864d@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_npu.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_npu.c ++++ b/drivers/net/ethernet/airoha/airoha_npu.c +@@ -104,12 +104,14 @@ struct ppe_mbox_data { + u8 xpon_hal_api; + u8 wan_xsi; + u8 ct_joyme4; +- int ppe_type; +- int wan_mode; +- int wan_sel; ++ u8 max_packet; ++ u8 rsv[3]; ++ u32 ppe_type; ++ u32 wan_mode; ++ u32 wan_sel; + } init_info; + struct { +- int func_id; ++ u32 func_id; + u32 size; + u32 data; + } set_info; diff --git a/lede/target/linux/airoha/patches-6.12/072-v6.15-net-airoha-Fix-page-recycling-in-airoha_qdma_rx_proc.patch b/lede/target/linux/airoha/patches-6.12/072-v6.15-net-airoha-Fix-page-recycling-in-airoha_qdma_rx_proc.patch new file mode 100644 index 0000000000..bcf60ce8dd --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/072-v6.15-net-airoha-Fix-page-recycling-in-airoha_qdma_rx_proc.patch @@ -0,0 +1,72 @@ +From d6d2b0e1538d5c381ec0ca95afaf772c096ea5dc Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Thu, 15 May 2025 08:33:06 +0200 +Subject: [PATCH] net: airoha: Fix page recycling in airoha_qdma_rx_process() + +Do not recycle the page twice in airoha_qdma_rx_process routine in case +of error. Just run dev_kfree_skb() if the skb has been allocated and marked +for recycling. Run page_pool_put_full_page() directly if the skb has not +been allocated yet. +Moreover, rely on DMA address from queue entry element instead of reading +it from the DMA descriptor for DMA syncing in airoha_qdma_rx_process(). + +Fixes: e12182ddb6e71 ("net: airoha: Enable Rx Scatter-Gather") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250515-airoha-fix-rx-process-error-condition-v2-1-657e92c894b9@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 22 +++++++++------------- + 1 file changed, 9 insertions(+), 13 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -636,7 +636,6 @@ static int airoha_qdma_rx_process(struct + struct airoha_queue_entry *e = &q->entry[q->tail]; + struct airoha_qdma_desc *desc = &q->desc[q->tail]; + u32 hash, reason, msg1 = le32_to_cpu(desc->msg1); +- dma_addr_t dma_addr = le32_to_cpu(desc->addr); + struct page *page = virt_to_head_page(e->buf); + u32 desc_ctrl = le32_to_cpu(desc->ctrl); + struct airoha_gdm_port *port; +@@ -645,22 +644,16 @@ static int airoha_qdma_rx_process(struct + if (!(desc_ctrl & QDMA_DESC_DONE_MASK)) + break; + +- if (!dma_addr) +- break; +- +- len = FIELD_GET(QDMA_DESC_LEN_MASK, desc_ctrl); +- if (!len) +- break; +- + q->tail = (q->tail + 1) % q->ndesc; + q->queued--; + +- dma_sync_single_for_cpu(eth->dev, dma_addr, ++ dma_sync_single_for_cpu(eth->dev, e->dma_addr, + SKB_WITH_OVERHEAD(q->buf_size), dir); + ++ len = FIELD_GET(QDMA_DESC_LEN_MASK, desc_ctrl); + data_len = q->skb ? q->buf_size + : SKB_WITH_OVERHEAD(q->buf_size); +- if (data_len < len) ++ if (!len || data_len < len) + goto free_frag; + + p = airoha_qdma_get_gdm_port(eth, desc); +@@ -723,9 +716,12 @@ static int airoha_qdma_rx_process(struct + q->skb = NULL; + continue; + free_frag: +- page_pool_put_full_page(q->page_pool, page, true); +- dev_kfree_skb(q->skb); +- q->skb = NULL; ++ if (q->skb) { ++ dev_kfree_skb(q->skb); ++ q->skb = NULL; ++ } else { ++ page_pool_put_full_page(q->page_pool, page, true); ++ } + } + airoha_qdma_fill_rx_queue(q); + diff --git a/lede/target/linux/airoha/patches-6.12/073-01-v6.16-net-airoha-npu-Move-memory-allocation-in-airoha_npu_.patch b/lede/target/linux/airoha/patches-6.12/073-01-v6.16-net-airoha-npu-Move-memory-allocation-in-airoha_npu_.patch new file mode 100644 index 0000000000..f0c41d5dc4 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/073-01-v6.16-net-airoha-npu-Move-memory-allocation-in-airoha_npu_.patch @@ -0,0 +1,196 @@ +From c52918744ee1e49cea86622a2633b9782446428f Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 16 May 2025 09:59:59 +0200 +Subject: [PATCH 1/3] net: airoha: npu: Move memory allocation in + airoha_npu_send_msg() caller + +Move ppe_mbox_data struct memory allocation from airoha_npu_send_msg +routine to the caller one. This is a preliminary patch to enable wlan NPU +offloading and flow counter stats support. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250516-airoha-en7581-flowstats-v2-1-06d5fbf28984@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_npu.c | 126 +++++++++++++---------- + 1 file changed, 72 insertions(+), 54 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_npu.c ++++ b/drivers/net/ethernet/airoha/airoha_npu.c +@@ -124,17 +124,12 @@ static int airoha_npu_send_msg(struct ai + u16 core = 0; /* FIXME */ + u32 val, offset = core << 4; + dma_addr_t dma_addr; +- void *addr; + int ret; + +- addr = kmemdup(p, size, GFP_ATOMIC); +- if (!addr) +- return -ENOMEM; +- +- dma_addr = dma_map_single(npu->dev, addr, size, DMA_TO_DEVICE); ++ dma_addr = dma_map_single(npu->dev, p, size, DMA_TO_DEVICE); + ret = dma_mapping_error(npu->dev, dma_addr); + if (ret) +- goto out; ++ return ret; + + spin_lock_bh(&npu->cores[core].lock); + +@@ -155,8 +150,6 @@ static int airoha_npu_send_msg(struct ai + spin_unlock_bh(&npu->cores[core].lock); + + dma_unmap_single(npu->dev, dma_addr, size, DMA_TO_DEVICE); +-out: +- kfree(addr); + + return ret; + } +@@ -261,76 +254,101 @@ static irqreturn_t airoha_npu_wdt_handle + + static int airoha_npu_ppe_init(struct airoha_npu *npu) + { +- struct ppe_mbox_data ppe_data = { +- .func_type = NPU_OP_SET, +- .func_id = PPE_FUNC_SET_WAIT_HWNAT_INIT, +- .init_info = { +- .ppe_type = PPE_TYPE_L2B_IPV4_IPV6, +- .wan_mode = QDMA_WAN_ETHER, +- }, +- }; ++ struct ppe_mbox_data *ppe_data; ++ int err; + +- return airoha_npu_send_msg(npu, NPU_FUNC_PPE, &ppe_data, +- sizeof(struct ppe_mbox_data)); ++ ppe_data = kzalloc(sizeof(*ppe_data), GFP_KERNEL); ++ if (!ppe_data) ++ return -ENOMEM; ++ ++ ppe_data->func_type = NPU_OP_SET; ++ ppe_data->func_id = PPE_FUNC_SET_WAIT_HWNAT_INIT; ++ ppe_data->init_info.ppe_type = PPE_TYPE_L2B_IPV4_IPV6; ++ ppe_data->init_info.wan_mode = QDMA_WAN_ETHER; ++ ++ err = airoha_npu_send_msg(npu, NPU_FUNC_PPE, ppe_data, ++ sizeof(*ppe_data)); ++ kfree(ppe_data); ++ ++ return err; + } + + static int airoha_npu_ppe_deinit(struct airoha_npu *npu) + { +- struct ppe_mbox_data ppe_data = { +- .func_type = NPU_OP_SET, +- .func_id = PPE_FUNC_SET_WAIT_HWNAT_DEINIT, +- }; ++ struct ppe_mbox_data *ppe_data; ++ int err; ++ ++ ppe_data = kzalloc(sizeof(*ppe_data), GFP_KERNEL); ++ if (!ppe_data) ++ return -ENOMEM; + +- return airoha_npu_send_msg(npu, NPU_FUNC_PPE, &ppe_data, +- sizeof(struct ppe_mbox_data)); ++ ppe_data->func_type = NPU_OP_SET; ++ ppe_data->func_id = PPE_FUNC_SET_WAIT_HWNAT_DEINIT; ++ ++ err = airoha_npu_send_msg(npu, NPU_FUNC_PPE, ppe_data, ++ sizeof(*ppe_data)); ++ kfree(ppe_data); ++ ++ return err; + } + + static int airoha_npu_ppe_flush_sram_entries(struct airoha_npu *npu, + dma_addr_t foe_addr, + int sram_num_entries) + { +- struct ppe_mbox_data ppe_data = { +- .func_type = NPU_OP_SET, +- .func_id = PPE_FUNC_SET_WAIT_API, +- .set_info = { +- .func_id = PPE_SRAM_RESET_VAL, +- .data = foe_addr, +- .size = sram_num_entries, +- }, +- }; ++ struct ppe_mbox_data *ppe_data; ++ int err; ++ ++ ppe_data = kzalloc(sizeof(*ppe_data), GFP_KERNEL); ++ if (!ppe_data) ++ return -ENOMEM; ++ ++ ppe_data->func_type = NPU_OP_SET; ++ ppe_data->func_id = PPE_FUNC_SET_WAIT_API; ++ ppe_data->set_info.func_id = PPE_SRAM_RESET_VAL; ++ ppe_data->set_info.data = foe_addr; ++ ppe_data->set_info.size = sram_num_entries; ++ ++ err = airoha_npu_send_msg(npu, NPU_FUNC_PPE, ppe_data, ++ sizeof(*ppe_data)); ++ kfree(ppe_data); + +- return airoha_npu_send_msg(npu, NPU_FUNC_PPE, &ppe_data, +- sizeof(struct ppe_mbox_data)); ++ return err; + } + + static int airoha_npu_foe_commit_entry(struct airoha_npu *npu, + dma_addr_t foe_addr, + u32 entry_size, u32 hash, bool ppe2) + { +- struct ppe_mbox_data ppe_data = { +- .func_type = NPU_OP_SET, +- .func_id = PPE_FUNC_SET_WAIT_API, +- .set_info = { +- .data = foe_addr, +- .size = entry_size, +- }, +- }; ++ struct ppe_mbox_data *ppe_data; + int err; + +- ppe_data.set_info.func_id = ppe2 ? PPE2_SRAM_SET_ENTRY +- : PPE_SRAM_SET_ENTRY; ++ ppe_data = kzalloc(sizeof(*ppe_data), GFP_ATOMIC); ++ if (!ppe_data) ++ return -ENOMEM; ++ ++ ppe_data->func_type = NPU_OP_SET; ++ ppe_data->func_id = PPE_FUNC_SET_WAIT_API; ++ ppe_data->set_info.data = foe_addr; ++ ppe_data->set_info.size = entry_size; ++ ppe_data->set_info.func_id = ppe2 ? PPE2_SRAM_SET_ENTRY ++ : PPE_SRAM_SET_ENTRY; + +- err = airoha_npu_send_msg(npu, NPU_FUNC_PPE, &ppe_data, +- sizeof(struct ppe_mbox_data)); ++ err = airoha_npu_send_msg(npu, NPU_FUNC_PPE, ppe_data, ++ sizeof(*ppe_data)); + if (err) +- return err; ++ goto out; + +- ppe_data.set_info.func_id = PPE_SRAM_SET_VAL; +- ppe_data.set_info.data = hash; +- ppe_data.set_info.size = sizeof(u32); ++ ppe_data->set_info.func_id = PPE_SRAM_SET_VAL; ++ ppe_data->set_info.data = hash; ++ ppe_data->set_info.size = sizeof(u32); ++ ++ err = airoha_npu_send_msg(npu, NPU_FUNC_PPE, ppe_data, ++ sizeof(*ppe_data)); ++out: ++ kfree(ppe_data); + +- return airoha_npu_send_msg(npu, NPU_FUNC_PPE, &ppe_data, +- sizeof(struct ppe_mbox_data)); ++ return err; + } + + struct airoha_npu *airoha_npu_get(struct device *dev) diff --git a/lede/target/linux/airoha/patches-6.12/073-02-v6.16-net-airoha-Add-FLOW_CLS_STATS-callback-support.patch b/lede/target/linux/airoha/patches-6.12/073-02-v6.16-net-airoha-Add-FLOW_CLS_STATS-callback-support.patch new file mode 100644 index 0000000000..584ddb1da8 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/073-02-v6.16-net-airoha-Add-FLOW_CLS_STATS-callback-support.patch @@ -0,0 +1,633 @@ +From b81e0f2b58be37628b2e12f8dffdd63c84573e75 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 16 May 2025 10:00:00 +0200 +Subject: [PATCH 2/3] net: airoha: Add FLOW_CLS_STATS callback support + +Introduce per-flow stats accounting to the flowtable hw offload in +the airoha_eth driver. Flow stats are split in the PPE and NPU modules: +- PPE: accounts for high 32bit of per-flow stats +- NPU: accounts for low 32bit of per-flow stats + +FLOW_CLS_STATS can be enabled or disabled at compile time. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250516-airoha-en7581-flowstats-v2-2-06d5fbf28984@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/Kconfig | 7 + + drivers/net/ethernet/airoha/airoha_eth.h | 33 +++ + drivers/net/ethernet/airoha/airoha_npu.c | 52 +++- + drivers/net/ethernet/airoha/airoha_npu.h | 4 +- + drivers/net/ethernet/airoha/airoha_ppe.c | 269 ++++++++++++++++-- + .../net/ethernet/airoha/airoha_ppe_debugfs.c | 9 +- + 6 files changed, 354 insertions(+), 20 deletions(-) + +--- a/drivers/net/ethernet/airoha/Kconfig ++++ b/drivers/net/ethernet/airoha/Kconfig +@@ -24,4 +24,11 @@ config NET_AIROHA + This driver supports the gigabit ethernet MACs in the + Airoha SoC family. + ++config NET_AIROHA_FLOW_STATS ++ default y ++ bool "Airoha flow stats" ++ depends on NET_AIROHA && NET_AIROHA_NPU ++ help ++ Enable Aiorha flowtable statistic counters. ++ + endif #NET_VENDOR_AIROHA +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -50,6 +50,14 @@ + #define PPE_NUM 2 + #define PPE1_SRAM_NUM_ENTRIES (8 * 1024) + #define PPE_SRAM_NUM_ENTRIES (2 * PPE1_SRAM_NUM_ENTRIES) ++#ifdef CONFIG_NET_AIROHA_FLOW_STATS ++#define PPE1_STATS_NUM_ENTRIES (4 * 1024) ++#else ++#define PPE1_STATS_NUM_ENTRIES 0 ++#endif /* CONFIG_NET_AIROHA_FLOW_STATS */ ++#define PPE_STATS_NUM_ENTRIES (2 * PPE1_STATS_NUM_ENTRIES) ++#define PPE1_SRAM_NUM_DATA_ENTRIES (PPE1_SRAM_NUM_ENTRIES - PPE1_STATS_NUM_ENTRIES) ++#define PPE_SRAM_NUM_DATA_ENTRIES (2 * PPE1_SRAM_NUM_DATA_ENTRIES) + #define PPE_DRAM_NUM_ENTRIES (16 * 1024) + #define PPE_NUM_ENTRIES (PPE_SRAM_NUM_ENTRIES + PPE_DRAM_NUM_ENTRIES) + #define PPE_HASH_MASK (PPE_NUM_ENTRIES - 1) +@@ -261,6 +269,8 @@ struct airoha_foe_mac_info { + + u16 pppoe_id; + u16 src_mac_lo; ++ ++ u32 meter; + }; + + #define AIROHA_FOE_IB1_UNBIND_PREBIND BIT(24) +@@ -296,6 +306,11 @@ struct airoha_foe_mac_info { + #define AIROHA_FOE_TUNNEL BIT(6) + #define AIROHA_FOE_TUNNEL_ID GENMASK(5, 0) + ++#define AIROHA_FOE_TUNNEL_MTU GENMASK(31, 16) ++#define AIROHA_FOE_ACNT_GRP3 GENMASK(15, 9) ++#define AIROHA_FOE_METER_GRP3 GENMASK(8, 5) ++#define AIROHA_FOE_METER_GRP2 GENMASK(4, 0) ++ + struct airoha_foe_bridge { + u32 dest_mac_hi; + +@@ -379,6 +394,8 @@ struct airoha_foe_ipv6 { + u32 ib2; + + struct airoha_foe_mac_info_common l2; ++ ++ u32 meter; + }; + + struct airoha_foe_entry { +@@ -397,6 +414,16 @@ struct airoha_foe_entry { + }; + }; + ++struct airoha_foe_stats { ++ u32 bytes; ++ u32 packets; ++}; ++ ++struct airoha_foe_stats64 { ++ u64 bytes; ++ u64 packets; ++}; ++ + struct airoha_flow_data { + struct ethhdr eth; + +@@ -447,6 +474,7 @@ struct airoha_flow_table_entry { + struct hlist_node l2_subflow_node; /* PPE L2 subflow entry */ + u32 hash; + ++ struct airoha_foe_stats64 stats; + enum airoha_flow_entry_type type; + + struct rhash_head node; +@@ -523,6 +551,9 @@ struct airoha_ppe { + struct hlist_head *foe_flow; + u16 foe_check_time[PPE_NUM_ENTRIES]; + ++ struct airoha_foe_stats *foe_stats; ++ dma_addr_t foe_stats_dma; ++ + struct dentry *debugfs_dir; + }; + +@@ -582,6 +613,8 @@ int airoha_ppe_init(struct airoha_eth *e + void airoha_ppe_deinit(struct airoha_eth *eth); + struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe, + u32 hash); ++void airoha_ppe_foe_entry_get_stats(struct airoha_ppe *ppe, u32 hash, ++ struct airoha_foe_stats64 *stats); + + #ifdef CONFIG_DEBUG_FS + int airoha_ppe_debugfs_init(struct airoha_ppe *ppe); +--- a/drivers/net/ethernet/airoha/airoha_npu.c ++++ b/drivers/net/ethernet/airoha/airoha_npu.c +@@ -12,6 +12,7 @@ + #include + #include + ++#include "airoha_eth.h" + #include "airoha_npu.h" + + #define NPU_EN7581_FIRMWARE_DATA "airoha/en7581_npu_data.bin" +@@ -72,6 +73,7 @@ enum { + PPE_FUNC_SET_WAIT_HWNAT_INIT, + PPE_FUNC_SET_WAIT_HWNAT_DEINIT, + PPE_FUNC_SET_WAIT_API, ++ PPE_FUNC_SET_WAIT_FLOW_STATS_SETUP, + }; + + enum { +@@ -115,6 +117,10 @@ struct ppe_mbox_data { + u32 size; + u32 data; + } set_info; ++ struct { ++ u32 npu_stats_addr; ++ u32 foe_stats_addr; ++ } stats_info; + }; + }; + +@@ -351,7 +357,40 @@ out: + return err; + } + +-struct airoha_npu *airoha_npu_get(struct device *dev) ++static int airoha_npu_stats_setup(struct airoha_npu *npu, ++ dma_addr_t foe_stats_addr) ++{ ++ int err, size = PPE_STATS_NUM_ENTRIES * sizeof(*npu->stats); ++ struct ppe_mbox_data *ppe_data; ++ ++ if (!size) /* flow stats are disabled */ ++ return 0; ++ ++ ppe_data = kzalloc(sizeof(*ppe_data), GFP_ATOMIC); ++ if (!ppe_data) ++ return -ENOMEM; ++ ++ ppe_data->func_type = NPU_OP_SET; ++ ppe_data->func_id = PPE_FUNC_SET_WAIT_FLOW_STATS_SETUP; ++ ppe_data->stats_info.foe_stats_addr = foe_stats_addr; ++ ++ err = airoha_npu_send_msg(npu, NPU_FUNC_PPE, ppe_data, ++ sizeof(*ppe_data)); ++ if (err) ++ goto out; ++ ++ npu->stats = devm_ioremap(npu->dev, ++ ppe_data->stats_info.npu_stats_addr, ++ size); ++ if (!npu->stats) ++ err = -ENOMEM; ++out: ++ kfree(ppe_data); ++ ++ return err; ++} ++ ++struct airoha_npu *airoha_npu_get(struct device *dev, dma_addr_t *stats_addr) + { + struct platform_device *pdev; + struct device_node *np; +@@ -389,6 +428,17 @@ struct airoha_npu *airoha_npu_get(struct + goto error_module_put; + } + ++ if (stats_addr) { ++ int err; ++ ++ err = airoha_npu_stats_setup(npu, *stats_addr); ++ if (err) { ++ dev_err(dev, "failed to allocate npu stats buffer\n"); ++ npu = ERR_PTR(err); ++ goto error_module_put; ++ } ++ } ++ + return npu; + + error_module_put: +--- a/drivers/net/ethernet/airoha/airoha_npu.h ++++ b/drivers/net/ethernet/airoha/airoha_npu.h +@@ -17,6 +17,8 @@ struct airoha_npu { + struct work_struct wdt_work; + } cores[NPU_NUM_CORES]; + ++ struct airoha_foe_stats __iomem *stats; ++ + struct { + int (*ppe_init)(struct airoha_npu *npu); + int (*ppe_deinit)(struct airoha_npu *npu); +@@ -30,5 +32,5 @@ struct airoha_npu { + } ops; + }; + +-struct airoha_npu *airoha_npu_get(struct device *dev); ++struct airoha_npu *airoha_npu_get(struct device *dev, dma_addr_t *stats_addr); + void airoha_npu_put(struct airoha_npu *npu); +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -102,7 +102,7 @@ static void airoha_ppe_hw_init(struct ai + + if (airoha_ppe2_is_enabled(eth)) { + sram_num_entries = +- PPE_RAM_NUM_ENTRIES_SHIFT(PPE1_SRAM_NUM_ENTRIES); ++ PPE_RAM_NUM_ENTRIES_SHIFT(PPE1_SRAM_NUM_DATA_ENTRIES); + airoha_fe_rmw(eth, REG_PPE_TB_CFG(0), + PPE_SRAM_TB_NUM_ENTRY_MASK | + PPE_DRAM_TB_NUM_ENTRY_MASK, +@@ -119,7 +119,7 @@ static void airoha_ppe_hw_init(struct ai + dram_num_entries)); + } else { + sram_num_entries = +- PPE_RAM_NUM_ENTRIES_SHIFT(PPE_SRAM_NUM_ENTRIES); ++ PPE_RAM_NUM_ENTRIES_SHIFT(PPE_SRAM_NUM_DATA_ENTRIES); + airoha_fe_rmw(eth, REG_PPE_TB_CFG(0), + PPE_SRAM_TB_NUM_ENTRY_MASK | + PPE_DRAM_TB_NUM_ENTRY_MASK, +@@ -417,6 +417,77 @@ static u32 airoha_ppe_foe_get_entry_hash + return hash; + } + ++static u32 airoha_ppe_foe_get_flow_stats_index(struct airoha_ppe *ppe, u32 hash) ++{ ++ if (!airoha_ppe2_is_enabled(ppe->eth)) ++ return hash; ++ ++ return hash >= PPE_STATS_NUM_ENTRIES ? hash - PPE1_STATS_NUM_ENTRIES ++ : hash; ++} ++ ++static void airoha_ppe_foe_flow_stat_entry_reset(struct airoha_ppe *ppe, ++ struct airoha_npu *npu, ++ int index) ++{ ++ memset_io(&npu->stats[index], 0, sizeof(*npu->stats)); ++ memset(&ppe->foe_stats[index], 0, sizeof(*ppe->foe_stats)); ++} ++ ++static void airoha_ppe_foe_flow_stats_reset(struct airoha_ppe *ppe, ++ struct airoha_npu *npu) ++{ ++ int i; ++ ++ for (i = 0; i < PPE_STATS_NUM_ENTRIES; i++) ++ airoha_ppe_foe_flow_stat_entry_reset(ppe, npu, i); ++} ++ ++static void airoha_ppe_foe_flow_stats_update(struct airoha_ppe *ppe, ++ struct airoha_npu *npu, ++ struct airoha_foe_entry *hwe, ++ u32 hash) ++{ ++ int type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe->ib1); ++ u32 index, pse_port, val, *data, *ib2, *meter; ++ u8 nbq; ++ ++ index = airoha_ppe_foe_get_flow_stats_index(ppe, hash); ++ if (index >= PPE_STATS_NUM_ENTRIES) ++ return; ++ ++ if (type == PPE_PKT_TYPE_BRIDGE) { ++ data = &hwe->bridge.data; ++ ib2 = &hwe->bridge.ib2; ++ meter = &hwe->bridge.l2.meter; ++ } else if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T) { ++ data = &hwe->ipv6.data; ++ ib2 = &hwe->ipv6.ib2; ++ meter = &hwe->ipv6.meter; ++ } else { ++ data = &hwe->ipv4.data; ++ ib2 = &hwe->ipv4.ib2; ++ meter = &hwe->ipv4.l2.meter; ++ } ++ ++ airoha_ppe_foe_flow_stat_entry_reset(ppe, npu, index); ++ ++ val = FIELD_GET(AIROHA_FOE_CHANNEL | AIROHA_FOE_QID, *data); ++ *data = (*data & ~AIROHA_FOE_ACTDP) | ++ FIELD_PREP(AIROHA_FOE_ACTDP, val); ++ ++ val = *ib2 & (AIROHA_FOE_IB2_NBQ | AIROHA_FOE_IB2_PSE_PORT | ++ AIROHA_FOE_IB2_PSE_QOS | AIROHA_FOE_IB2_FAST_PATH); ++ *meter |= FIELD_PREP(AIROHA_FOE_TUNNEL_MTU, val); ++ ++ pse_port = FIELD_GET(AIROHA_FOE_IB2_PSE_PORT, *ib2); ++ nbq = pse_port == 1 ? 6 : 5; ++ *ib2 &= ~(AIROHA_FOE_IB2_NBQ | AIROHA_FOE_IB2_PSE_PORT | ++ AIROHA_FOE_IB2_PSE_QOS); ++ *ib2 |= FIELD_PREP(AIROHA_FOE_IB2_PSE_PORT, 6) | ++ FIELD_PREP(AIROHA_FOE_IB2_NBQ, nbq); ++} ++ + struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe, + u32 hash) + { +@@ -470,6 +541,8 @@ static int airoha_ppe_foe_commit_entry(s + struct airoha_foe_entry *hwe = ppe->foe + hash * sizeof(*hwe); + u32 ts = airoha_ppe_get_timestamp(ppe); + struct airoha_eth *eth = ppe->eth; ++ struct airoha_npu *npu; ++ int err = 0; + + memcpy(&hwe->d, &e->d, sizeof(*hwe) - sizeof(hwe->ib1)); + wmb(); +@@ -478,25 +551,28 @@ static int airoha_ppe_foe_commit_entry(s + e->ib1 |= FIELD_PREP(AIROHA_FOE_IB1_BIND_TIMESTAMP, ts); + hwe->ib1 = e->ib1; + ++ rcu_read_lock(); ++ ++ npu = rcu_dereference(eth->npu); ++ if (!npu) { ++ err = -ENODEV; ++ goto unlock; ++ } ++ ++ airoha_ppe_foe_flow_stats_update(ppe, npu, hwe, hash); ++ + if (hash < PPE_SRAM_NUM_ENTRIES) { + dma_addr_t addr = ppe->foe_dma + hash * sizeof(*hwe); + bool ppe2 = airoha_ppe2_is_enabled(eth) && + hash >= PPE1_SRAM_NUM_ENTRIES; +- struct airoha_npu *npu; +- int err = -ENODEV; +- +- rcu_read_lock(); +- npu = rcu_dereference(eth->npu); +- if (npu) +- err = npu->ops.ppe_foe_commit_entry(npu, addr, +- sizeof(*hwe), hash, +- ppe2); +- rcu_read_unlock(); + +- return err; ++ err = npu->ops.ppe_foe_commit_entry(npu, addr, sizeof(*hwe), ++ hash, ppe2); + } ++unlock: ++ rcu_read_unlock(); + +- return 0; ++ return err; + } + + static void airoha_ppe_foe_remove_flow(struct airoha_ppe *ppe, +@@ -582,6 +658,7 @@ airoha_ppe_foe_commit_subflow_entry(stru + l2->common.etype = ETH_P_IPV6; + + hwe.bridge.ib2 = e->data.bridge.ib2; ++ hwe.bridge.data = e->data.bridge.data; + airoha_ppe_foe_commit_entry(ppe, &hwe, hash); + + return 0; +@@ -681,6 +758,98 @@ static int airoha_ppe_foe_flow_commit_en + return 0; + } + ++static int airoha_ppe_get_entry_idle_time(struct airoha_ppe *ppe, u32 ib1) ++{ ++ u32 state = FIELD_GET(AIROHA_FOE_IB1_BIND_STATE, ib1); ++ u32 ts, ts_mask, now = airoha_ppe_get_timestamp(ppe); ++ int idle; ++ ++ if (state == AIROHA_FOE_STATE_BIND) { ++ ts = FIELD_GET(AIROHA_FOE_IB1_BIND_TIMESTAMP, ib1); ++ ts_mask = AIROHA_FOE_IB1_BIND_TIMESTAMP; ++ } else { ++ ts = FIELD_GET(AIROHA_FOE_IB1_UNBIND_TIMESTAMP, ib1); ++ now = FIELD_GET(AIROHA_FOE_IB1_UNBIND_TIMESTAMP, now); ++ ts_mask = AIROHA_FOE_IB1_UNBIND_TIMESTAMP; ++ } ++ idle = now - ts; ++ ++ return idle < 0 ? idle + ts_mask + 1 : idle; ++} ++ ++static void ++airoha_ppe_foe_flow_l2_entry_update(struct airoha_ppe *ppe, ++ struct airoha_flow_table_entry *e) ++{ ++ int min_idle = airoha_ppe_get_entry_idle_time(ppe, e->data.ib1); ++ struct airoha_flow_table_entry *iter; ++ struct hlist_node *n; ++ ++ lockdep_assert_held(&ppe_lock); ++ ++ hlist_for_each_entry_safe(iter, n, &e->l2_flows, l2_subflow_node) { ++ struct airoha_foe_entry *hwe; ++ u32 ib1, state; ++ int idle; ++ ++ hwe = airoha_ppe_foe_get_entry(ppe, iter->hash); ++ ib1 = READ_ONCE(hwe->ib1); ++ ++ state = FIELD_GET(AIROHA_FOE_IB1_BIND_STATE, ib1); ++ if (state != AIROHA_FOE_STATE_BIND) { ++ iter->hash = 0xffff; ++ airoha_ppe_foe_remove_flow(ppe, iter); ++ continue; ++ } ++ ++ idle = airoha_ppe_get_entry_idle_time(ppe, ib1); ++ if (idle >= min_idle) ++ continue; ++ ++ min_idle = idle; ++ e->data.ib1 &= ~AIROHA_FOE_IB1_BIND_TIMESTAMP; ++ e->data.ib1 |= ib1 & AIROHA_FOE_IB1_BIND_TIMESTAMP; ++ } ++} ++ ++static void airoha_ppe_foe_flow_entry_update(struct airoha_ppe *ppe, ++ struct airoha_flow_table_entry *e) ++{ ++ struct airoha_foe_entry *hwe_p, hwe = {}; ++ ++ spin_lock_bh(&ppe_lock); ++ ++ if (e->type == FLOW_TYPE_L2) { ++ airoha_ppe_foe_flow_l2_entry_update(ppe, e); ++ goto unlock; ++ } ++ ++ if (e->hash == 0xffff) ++ goto unlock; ++ ++ hwe_p = airoha_ppe_foe_get_entry(ppe, e->hash); ++ if (!hwe_p) ++ goto unlock; ++ ++ memcpy(&hwe, hwe_p, sizeof(*hwe_p)); ++ if (!airoha_ppe_foe_compare_entry(e, &hwe)) { ++ e->hash = 0xffff; ++ goto unlock; ++ } ++ ++ e->data.ib1 = hwe.ib1; ++unlock: ++ spin_unlock_bh(&ppe_lock); ++} ++ ++static int airoha_ppe_entry_idle_time(struct airoha_ppe *ppe, ++ struct airoha_flow_table_entry *e) ++{ ++ airoha_ppe_foe_flow_entry_update(ppe, e); ++ ++ return airoha_ppe_get_entry_idle_time(ppe, e->data.ib1); ++} ++ + static int airoha_ppe_flow_offload_replace(struct airoha_gdm_port *port, + struct flow_cls_offload *f) + { +@@ -896,6 +1065,60 @@ static int airoha_ppe_flow_offload_destr + return 0; + } + ++void airoha_ppe_foe_entry_get_stats(struct airoha_ppe *ppe, u32 hash, ++ struct airoha_foe_stats64 *stats) ++{ ++ u32 index = airoha_ppe_foe_get_flow_stats_index(ppe, hash); ++ struct airoha_eth *eth = ppe->eth; ++ struct airoha_npu *npu; ++ ++ if (index >= PPE_STATS_NUM_ENTRIES) ++ return; ++ ++ rcu_read_lock(); ++ ++ npu = rcu_dereference(eth->npu); ++ if (npu) { ++ u64 packets = ppe->foe_stats[index].packets; ++ u64 bytes = ppe->foe_stats[index].bytes; ++ struct airoha_foe_stats npu_stats; ++ ++ memcpy_fromio(&npu_stats, &npu->stats[index], ++ sizeof(*npu->stats)); ++ stats->packets = packets << 32 | npu_stats.packets; ++ stats->bytes = bytes << 32 | npu_stats.bytes; ++ } ++ ++ rcu_read_unlock(); ++} ++ ++static int airoha_ppe_flow_offload_stats(struct airoha_gdm_port *port, ++ struct flow_cls_offload *f) ++{ ++ struct airoha_eth *eth = port->qdma->eth; ++ struct airoha_flow_table_entry *e; ++ u32 idle; ++ ++ e = rhashtable_lookup(ð->flow_table, &f->cookie, ++ airoha_flow_table_params); ++ if (!e) ++ return -ENOENT; ++ ++ idle = airoha_ppe_entry_idle_time(eth->ppe, e); ++ f->stats.lastused = jiffies - idle * HZ; ++ ++ if (e->hash != 0xffff) { ++ struct airoha_foe_stats64 stats = {}; ++ ++ airoha_ppe_foe_entry_get_stats(eth->ppe, e->hash, &stats); ++ f->stats.pkts += (stats.packets - e->stats.packets); ++ f->stats.bytes += (stats.bytes - e->stats.bytes); ++ e->stats = stats; ++ } ++ ++ return 0; ++} ++ + static int airoha_ppe_flow_offload_cmd(struct airoha_gdm_port *port, + struct flow_cls_offload *f) + { +@@ -904,6 +1127,8 @@ static int airoha_ppe_flow_offload_cmd(s + return airoha_ppe_flow_offload_replace(port, f); + case FLOW_CLS_DESTROY: + return airoha_ppe_flow_offload_destroy(port, f); ++ case FLOW_CLS_STATS: ++ return airoha_ppe_flow_offload_stats(port, f); + default: + break; + } +@@ -929,11 +1154,12 @@ static int airoha_ppe_flush_sram_entries + + static struct airoha_npu *airoha_ppe_npu_get(struct airoha_eth *eth) + { +- struct airoha_npu *npu = airoha_npu_get(eth->dev); ++ struct airoha_npu *npu = airoha_npu_get(eth->dev, ++ ð->ppe->foe_stats_dma); + + if (IS_ERR(npu)) { + request_module("airoha-npu"); +- npu = airoha_npu_get(eth->dev); ++ npu = airoha_npu_get(eth->dev, ð->ppe->foe_stats_dma); + } + + return npu; +@@ -956,6 +1182,8 @@ static int airoha_ppe_offload_setup(stru + if (err) + goto error_npu_put; + ++ airoha_ppe_foe_flow_stats_reset(eth->ppe, npu); ++ + rcu_assign_pointer(eth->npu, npu); + synchronize_rcu(); + +@@ -1027,6 +1255,15 @@ int airoha_ppe_init(struct airoha_eth *e + if (!ppe->foe_flow) + return -ENOMEM; + ++ foe_size = PPE_STATS_NUM_ENTRIES * sizeof(*ppe->foe_stats); ++ if (foe_size) { ++ ppe->foe_stats = dmam_alloc_coherent(eth->dev, foe_size, ++ &ppe->foe_stats_dma, ++ GFP_KERNEL); ++ if (!ppe->foe_stats) ++ return -ENOMEM; ++ } ++ + err = rhashtable_init(ð->flow_table, &airoha_flow_table_params); + if (err) + return err; +--- a/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c +@@ -61,6 +61,7 @@ static int airoha_ppe_debugfs_foe_show(s + u16 *src_port = NULL, *dest_port = NULL; + struct airoha_foe_mac_info_common *l2; + unsigned char h_source[ETH_ALEN] = {}; ++ struct airoha_foe_stats64 stats = {}; + unsigned char h_dest[ETH_ALEN]; + struct airoha_foe_entry *hwe; + u32 type, state, ib2, data; +@@ -144,14 +145,18 @@ static int airoha_ppe_debugfs_foe_show(s + cpu_to_be16(hwe->ipv4.l2.src_mac_lo); + } + ++ airoha_ppe_foe_entry_get_stats(ppe, i, &stats); ++ + *((__be32 *)h_dest) = cpu_to_be32(l2->dest_mac_hi); + *((__be16 *)&h_dest[4]) = cpu_to_be16(l2->dest_mac_lo); + *((__be32 *)h_source) = cpu_to_be32(l2->src_mac_hi); + + seq_printf(m, " eth=%pM->%pM etype=%04x data=%08x" +- " vlan=%d,%d ib1=%08x ib2=%08x\n", ++ " vlan=%d,%d ib1=%08x ib2=%08x" ++ " packets=%llu bytes=%llu\n", + h_source, h_dest, l2->etype, data, +- l2->vlan1, l2->vlan2, hwe->ib1, ib2); ++ l2->vlan1, l2->vlan2, hwe->ib1, ib2, ++ stats.packets, stats.bytes); + } + + return 0; diff --git a/lede/target/linux/airoha/patches-6.12/073-03-v6.16-net-airoha-ppe-Disable-packet-keepalive.patch b/lede/target/linux/airoha/patches-6.12/073-03-v6.16-net-airoha-ppe-Disable-packet-keepalive.patch new file mode 100644 index 0000000000..30c74ddec6 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/073-03-v6.16-net-airoha-ppe-Disable-packet-keepalive.patch @@ -0,0 +1,28 @@ +From a98326c151ea3d92e9496858cc2dacccd0870941 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 16 May 2025 10:00:01 +0200 +Subject: [PATCH 3/3] net: airoha: ppe: Disable packet keepalive + +Since netfilter flowtable entries are now refreshed by flow-stats +polling, we can disable hw packet keepalive used to periodically send +packets belonging to offloaded flows to the kernel in order to refresh +flowtable entries. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250516-airoha-en7581-flowstats-v2-3-06d5fbf28984@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -84,6 +84,7 @@ static void airoha_ppe_hw_init(struct ai + + airoha_fe_rmw(eth, REG_PPE_TB_CFG(i), + PPE_TB_CFG_SEARCH_MISS_MASK | ++ PPE_TB_CFG_KEEPALIVE_MASK | + PPE_TB_ENTRY_SIZE_MASK, + FIELD_PREP(PPE_TB_CFG_SEARCH_MISS_MASK, 3) | + FIELD_PREP(PPE_TB_ENTRY_SIZE_MASK, 0)); diff --git a/lede/target/linux/airoha/patches-6.12/074-01-v6.16-net-airoha-Do-not-store-hfwd-references-in-airoha_qd.patch b/lede/target/linux/airoha/patches-6.12/074-01-v6.16-net-airoha-Do-not-store-hfwd-references-in-airoha_qd.patch new file mode 100644 index 0000000000..1031964f7c --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/074-01-v6.16-net-airoha-Do-not-store-hfwd-references-in-airoha_qd.patch @@ -0,0 +1,57 @@ +From 09aa788f98da3e2f41ce158cc691d6d52e808bc9 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 21 May 2025 09:16:37 +0200 +Subject: [PATCH 1/3] net: airoha: Do not store hfwd references in airoha_qdma + struct + +Since hfwd descriptor and buffer queues are allocated via +dmam_alloc_coherent() we do not need to store their references +in airoha_qdma struct. This patch does not introduce any logical changes, +just code clean-up. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250521-airopha-desc-sram-v3-2-a6e9b085b4f0@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 8 ++------ + drivers/net/ethernet/airoha/airoha_eth.h | 6 ------ + 2 files changed, 2 insertions(+), 12 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1077,17 +1077,13 @@ static int airoha_qdma_init_hfwd_queues( + int size; + + size = HW_DSCP_NUM * sizeof(struct airoha_qdma_fwd_desc); +- qdma->hfwd.desc = dmam_alloc_coherent(eth->dev, size, &dma_addr, +- GFP_KERNEL); +- if (!qdma->hfwd.desc) ++ if (!dmam_alloc_coherent(eth->dev, size, &dma_addr, GFP_KERNEL)) + return -ENOMEM; + + airoha_qdma_wr(qdma, REG_FWD_DSCP_BASE, dma_addr); + + size = AIROHA_MAX_PACKET_SIZE * HW_DSCP_NUM; +- qdma->hfwd.q = dmam_alloc_coherent(eth->dev, size, &dma_addr, +- GFP_KERNEL); +- if (!qdma->hfwd.q) ++ if (!dmam_alloc_coherent(eth->dev, size, &dma_addr, GFP_KERNEL)) + return -ENOMEM; + + airoha_qdma_wr(qdma, REG_FWD_BUF_BASE, dma_addr); +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -513,12 +513,6 @@ struct airoha_qdma { + + struct airoha_queue q_tx[AIROHA_NUM_TX_RING]; + struct airoha_queue q_rx[AIROHA_NUM_RX_RING]; +- +- /* descriptor and packet buffers for qdma hw forward */ +- struct { +- void *desc; +- void *q; +- } hfwd; + }; + + struct airoha_gdm_port { diff --git a/lede/target/linux/airoha/patches-6.12/074-02-v6.16-net-airoha-Add-the-capability-to-allocate-hwfd-buffe.patch b/lede/target/linux/airoha/patches-6.12/074-02-v6.16-net-airoha-Add-the-capability-to-allocate-hwfd-buffe.patch new file mode 100644 index 0000000000..5aa8f318d4 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/074-02-v6.16-net-airoha-Add-the-capability-to-allocate-hwfd-buffe.patch @@ -0,0 +1,79 @@ +From 3a1ce9e3d01bbf3912c3e3f81cb554d558eb715b Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 21 May 2025 09:16:38 +0200 +Subject: [PATCH 2/3] net: airoha: Add the capability to allocate hwfd buffers + via reserved-memory + +In some configurations QDMA blocks require a contiguous block of +system memory for hwfd buffers queue. Introduce the capability to allocate +hw buffers forwarding queue via the reserved-memory DTS property instead of +running dmam_alloc_coherent(). + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250521-airopha-desc-sram-v3-3-a6e9b085b4f0@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 33 +++++++++++++++++++++--- + 1 file changed, 30 insertions(+), 3 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -5,6 +5,7 @@ + */ + #include + #include ++#include + #include + #include + #include +@@ -1072,9 +1073,11 @@ static void airoha_qdma_cleanup_tx_queue + static int airoha_qdma_init_hfwd_queues(struct airoha_qdma *qdma) + { + struct airoha_eth *eth = qdma->eth; ++ int id = qdma - ð->qdma[0]; + dma_addr_t dma_addr; ++ const char *name; ++ int size, index; + u32 status; +- int size; + + size = HW_DSCP_NUM * sizeof(struct airoha_qdma_fwd_desc); + if (!dmam_alloc_coherent(eth->dev, size, &dma_addr, GFP_KERNEL)) +@@ -1082,10 +1085,34 @@ static int airoha_qdma_init_hfwd_queues( + + airoha_qdma_wr(qdma, REG_FWD_DSCP_BASE, dma_addr); + +- size = AIROHA_MAX_PACKET_SIZE * HW_DSCP_NUM; +- if (!dmam_alloc_coherent(eth->dev, size, &dma_addr, GFP_KERNEL)) ++ name = devm_kasprintf(eth->dev, GFP_KERNEL, "qdma%d-buf", id); ++ if (!name) + return -ENOMEM; + ++ index = of_property_match_string(eth->dev->of_node, ++ "memory-region-names", name); ++ if (index >= 0) { ++ struct reserved_mem *rmem; ++ struct device_node *np; ++ ++ /* Consume reserved memory for hw forwarding buffers queue if ++ * available in the DTS ++ */ ++ np = of_parse_phandle(eth->dev->of_node, "memory-region", ++ index); ++ if (!np) ++ return -ENODEV; ++ ++ rmem = of_reserved_mem_lookup(np); ++ of_node_put(np); ++ dma_addr = rmem->base; ++ } else { ++ size = AIROHA_MAX_PACKET_SIZE * HW_DSCP_NUM; ++ if (!dmam_alloc_coherent(eth->dev, size, &dma_addr, ++ GFP_KERNEL)) ++ return -ENOMEM; ++ } ++ + airoha_qdma_wr(qdma, REG_FWD_BUF_BASE, dma_addr); + + airoha_qdma_rmw(qdma, REG_HW_FWD_DSCP_CFG, diff --git a/lede/target/linux/airoha/patches-6.12/074-03-v6.16-net-airoha-Add-the-capability-to-allocate-hfwd-descr.patch b/lede/target/linux/airoha/patches-6.12/074-03-v6.16-net-airoha-Add-the-capability-to-allocate-hfwd-descr.patch new file mode 100644 index 0000000000..ca1368270d --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/074-03-v6.16-net-airoha-Add-the-capability-to-allocate-hfwd-descr.patch @@ -0,0 +1,82 @@ +From c683e378c0907e66cee939145edf936c254ff1e3 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 21 May 2025 09:16:39 +0200 +Subject: [PATCH 3/3] net: airoha: Add the capability to allocate hfwd + descriptors in SRAM + +In order to improve packet processing and packet forwarding +performances, EN7581 SoC supports consuming SRAM instead of DRAM for +hw forwarding descriptors queue. +For downlink hw accelerated traffic request to consume SRAM memory +for hw forwarding descriptors queue. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250521-airopha-desc-sram-v3-4-a6e9b085b4f0@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 11 +---------- + drivers/net/ethernet/airoha/airoha_eth.h | 9 +++++++++ + drivers/net/ethernet/airoha/airoha_ppe.c | 6 ++++++ + 3 files changed, 16 insertions(+), 10 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -71,15 +71,6 @@ static void airoha_qdma_irq_disable(stru + airoha_qdma_set_irqmask(irq_bank, index, mask, 0); + } + +-static bool airhoa_is_lan_gdm_port(struct airoha_gdm_port *port) +-{ +- /* GDM1 port on EN7581 SoC is connected to the lan dsa switch. +- * GDM{2,3,4} can be used as wan port connected to an external +- * phy module. +- */ +- return port->id == 1; +-} +- + static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr) + { + struct airoha_eth *eth = port->qdma->eth; +@@ -1124,7 +1115,7 @@ static int airoha_qdma_init_hfwd_queues( + LMGR_INIT_START | LMGR_SRAM_MODE_MASK | + HW_FWD_DESC_NUM_MASK, + FIELD_PREP(HW_FWD_DESC_NUM_MASK, HW_DSCP_NUM) | +- LMGR_INIT_START); ++ LMGR_INIT_START | LMGR_SRAM_MODE_MASK); + + return read_poll_timeout(airoha_qdma_rr, status, + !(status & LMGR_INIT_START), USEC_PER_MSEC, +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -597,6 +597,15 @@ u32 airoha_rmw(void __iomem *base, u32 o + #define airoha_qdma_clear(qdma, offset, val) \ + airoha_rmw((qdma)->regs, (offset), (val), 0) + ++static inline bool airhoa_is_lan_gdm_port(struct airoha_gdm_port *port) ++{ ++ /* GDM1 port on EN7581 SoC is connected to the lan dsa switch. ++ * GDM{2,3,4} can be used as wan port connected to an external ++ * phy module. ++ */ ++ return port->id == 1; ++} ++ + bool airoha_is_valid_gdm_port(struct airoha_eth *eth, + struct airoha_gdm_port *port); + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -251,6 +251,12 @@ static int airoha_ppe_foe_entry_prepare( + else + pse_port = 2; /* uplink relies on GDM2 loopback */ + val |= FIELD_PREP(AIROHA_FOE_IB2_PSE_PORT, pse_port); ++ ++ /* For downlink traffic consume SRAM memory for hw forwarding ++ * descriptors queue. ++ */ ++ if (airhoa_is_lan_gdm_port(port)) ++ val |= AIROHA_FOE_IB2_FAST_PATH; + } + + if (is_multicast_ether_addr(data->eth.h_dest)) diff --git a/lede/target/linux/airoha/patches-6.12/075-v6.16-net-airoha-Fix-an-error-handling-path-in-airoha_allo.patch b/lede/target/linux/airoha/patches-6.12/075-v6.16-net-airoha-Fix-an-error-handling-path-in-airoha_allo.patch new file mode 100644 index 0000000000..3057e2f31f --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/075-v6.16-net-airoha-Fix-an-error-handling-path-in-airoha_allo.patch @@ -0,0 +1,42 @@ +From c59783780c8ad66f6076a9a7c74df3e006e29519 Mon Sep 17 00:00:00 2001 +From: Christophe JAILLET +Date: Sat, 24 May 2025 09:29:11 +0200 +Subject: [PATCH] net: airoha: Fix an error handling path in + airoha_alloc_gdm_port() + +If register_netdev() fails, the error handling path of the probe will not +free the memory allocated by the previous airoha_metadata_dst_alloc() call +because port->dev->reg_state will not be NETREG_REGISTERED. + +So, an explicit airoha_metadata_dst_free() call is needed in this case to +avoid a memory leak. + +Fixes: af3cf757d5c9 ("net: airoha: Move DSA tag in DMA descriptor") +Signed-off-by: Christophe JAILLET +Acked-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/1b94b91345017429ed653e2f05d25620dc2823f9.1746715755.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2880,7 +2880,15 @@ static int airoha_alloc_gdm_port(struct + if (err) + return err; + +- return register_netdev(dev); ++ err = register_netdev(dev); ++ if (err) ++ goto free_metadata_dst; ++ ++ return 0; ++ ++free_metadata_dst: ++ airoha_metadata_dst_free(port); ++ return err; + } + + static int airoha_probe(struct platform_device *pdev) diff --git a/lede/target/linux/airoha/patches-6.12/076-01-v6.16-net-airoha-Initialize-PPE-UPDMEM-source-mac-table.patch b/lede/target/linux/airoha/patches-6.12/076-01-v6.16-net-airoha-Initialize-PPE-UPDMEM-source-mac-table.patch new file mode 100644 index 0000000000..334661dd96 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/076-01-v6.16-net-airoha-Initialize-PPE-UPDMEM-source-mac-table.patch @@ -0,0 +1,122 @@ +From a869d3a5eb011a9cf9bd864f31f5cf27362de8c7 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 2 Jun 2025 12:55:37 +0200 +Subject: [PATCH 1/3] net: airoha: Initialize PPE UPDMEM source-mac table + +UPDMEM source-mac table is a key-value map used to store devices mac +addresses according to the port identifier. UPDMEM source mac table is +used during IPv6 traffic hw acceleration since PPE entries, for space +constraints, do not contain the full source mac address but just the +identifier in the UPDMEM source-mac table. +Configure UPDMEM source-mac table with device mac addresses and set +the source-mac ID field for PPE IPv6 entries in order to select the +proper device mac address as source mac for L3 IPv6 hw accelerated traffic. + +Fixes: 00a7678310fe ("net: airoha: Introduce flowtable offload support") +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250602-airoha-flowtable-ipv6-fix-v2-1-3287f8b55214@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 2 ++ + drivers/net/ethernet/airoha/airoha_eth.h | 1 + + drivers/net/ethernet/airoha/airoha_ppe.c | 26 ++++++++++++++++++++++- + drivers/net/ethernet/airoha/airoha_regs.h | 10 +++++++++ + 4 files changed, 38 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -84,6 +84,8 @@ static void airoha_set_macaddr(struct ai + val = (addr[3] << 16) | (addr[4] << 8) | addr[5]; + airoha_fe_wr(eth, REG_FE_MAC_LMIN(reg), val); + airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), val); ++ ++ airoha_ppe_init_upd_mem(port); + } + + static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr, +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -614,6 +614,7 @@ void airoha_ppe_check_skb(struct airoha_ + int airoha_ppe_setup_tc_block_cb(struct net_device *dev, void *type_data); + int airoha_ppe_init(struct airoha_eth *eth); + void airoha_ppe_deinit(struct airoha_eth *eth); ++void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port); + struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe, + u32 hash); + void airoha_ppe_foe_entry_get_stats(struct airoha_ppe *ppe, u32 hash, +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -223,6 +223,7 @@ static int airoha_ppe_foe_entry_prepare( + int dsa_port = airoha_get_dsa_port(&dev); + struct airoha_foe_mac_info_common *l2; + u32 qdata, ports_pad, val; ++ u8 smac_id = 0xf; + + memset(hwe, 0, sizeof(*hwe)); + +@@ -257,6 +258,8 @@ static int airoha_ppe_foe_entry_prepare( + */ + if (airhoa_is_lan_gdm_port(port)) + val |= AIROHA_FOE_IB2_FAST_PATH; ++ ++ smac_id = port->id; + } + + if (is_multicast_ether_addr(data->eth.h_dest)) +@@ -291,7 +294,7 @@ static int airoha_ppe_foe_entry_prepare( + hwe->ipv4.l2.src_mac_lo = + get_unaligned_be16(data->eth.h_source + 4); + } else { +- l2->src_mac_hi = FIELD_PREP(AIROHA_FOE_MAC_SMAC_ID, 0xf); ++ l2->src_mac_hi = FIELD_PREP(AIROHA_FOE_MAC_SMAC_ID, smac_id); + } + + if (data->vlan.num) { +@@ -1238,6 +1241,27 @@ void airoha_ppe_check_skb(struct airoha_ + airoha_ppe_foe_insert_entry(ppe, skb, hash); + } + ++void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port) ++{ ++ struct airoha_eth *eth = port->qdma->eth; ++ struct net_device *dev = port->dev; ++ const u8 *addr = dev->dev_addr; ++ u32 val; ++ ++ val = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | addr[5]; ++ airoha_fe_wr(eth, REG_UPDMEM_DATA(0), val); ++ airoha_fe_wr(eth, REG_UPDMEM_CTRL(0), ++ FIELD_PREP(PPE_UPDMEM_ADDR_MASK, port->id) | ++ PPE_UPDMEM_WR_MASK | PPE_UPDMEM_REQ_MASK); ++ ++ val = (addr[0] << 8) | addr[1]; ++ airoha_fe_wr(eth, REG_UPDMEM_DATA(0), val); ++ airoha_fe_wr(eth, REG_UPDMEM_CTRL(0), ++ FIELD_PREP(PPE_UPDMEM_ADDR_MASK, port->id) | ++ FIELD_PREP(PPE_UPDMEM_OFFSET_MASK, 1) | ++ PPE_UPDMEM_WR_MASK | PPE_UPDMEM_REQ_MASK); ++} ++ + int airoha_ppe_init(struct airoha_eth *eth) + { + struct airoha_ppe *ppe; +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -313,6 +313,16 @@ + #define REG_PPE_RAM_BASE(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x320) + #define REG_PPE_RAM_ENTRY(_m, _n) (REG_PPE_RAM_BASE(_m) + ((_n) << 2)) + ++#define REG_UPDMEM_CTRL(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x370) ++#define PPE_UPDMEM_ACK_MASK BIT(31) ++#define PPE_UPDMEM_ADDR_MASK GENMASK(11, 8) ++#define PPE_UPDMEM_OFFSET_MASK GENMASK(7, 4) ++#define PPE_UPDMEM_SEL_MASK GENMASK(3, 2) ++#define PPE_UPDMEM_WR_MASK BIT(1) ++#define PPE_UPDMEM_REQ_MASK BIT(0) ++ ++#define REG_UPDMEM_DATA(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x374) ++ + #define REG_FE_GDM_TX_OK_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x280) + #define REG_FE_GDM_TX_OK_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x284) + #define REG_FE_GDM_TX_ETH_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x288) diff --git a/lede/target/linux/airoha/patches-6.12/076-02-v6.16-net-airoha-Fix-IPv6-hw-acceleration-in-bridge-mode.patch b/lede/target/linux/airoha/patches-6.12/076-02-v6.16-net-airoha-Fix-IPv6-hw-acceleration-in-bridge-mode.patch new file mode 100644 index 0000000000..faa7669e0d --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/076-02-v6.16-net-airoha-Fix-IPv6-hw-acceleration-in-bridge-mode.patch @@ -0,0 +1,64 @@ +From 504a577c9b000f9e0e99e1b28616fb4eb369e1ef Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 2 Jun 2025 12:55:38 +0200 +Subject: [PATCH 2/3] net: airoha: Fix IPv6 hw acceleration in bridge mode + +ib2 and airoha_foe_mac_info_common have not the same offsets in +airoha_foe_bridge and airoha_foe_ipv6 structures. Current codebase does +not accelerate IPv6 traffic in bridge mode since ib2 and l2 info are not +set properly copying airoha_foe_bridge struct into airoha_foe_ipv6 one +in airoha_ppe_foe_commit_subflow_entry routine. +Fix IPv6 hw acceleration in bridge mode resolving ib2 and +airoha_foe_mac_info_common overwrite in +airoha_ppe_foe_commit_subflow_entry() and configuring them with proper +values. + +Fixes: cd53f622611f ("net: airoha: Add L2 hw acceleration support") +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250602-airoha-flowtable-ipv6-fix-v2-2-3287f8b55214@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 23 ++++++++++++----------- + 1 file changed, 12 insertions(+), 11 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -639,7 +639,6 @@ airoha_ppe_foe_commit_subflow_entry(stru + u32 mask = AIROHA_FOE_IB1_BIND_PACKET_TYPE | AIROHA_FOE_IB1_BIND_UDP; + struct airoha_foe_entry *hwe_p, hwe; + struct airoha_flow_table_entry *f; +- struct airoha_foe_mac_info *l2; + int type; + + hwe_p = airoha_ppe_foe_get_entry(ppe, hash); +@@ -656,18 +655,20 @@ airoha_ppe_foe_commit_subflow_entry(stru + + memcpy(&hwe, hwe_p, sizeof(*hwe_p)); + hwe.ib1 = (hwe.ib1 & mask) | (e->data.ib1 & ~mask); +- l2 = &hwe.bridge.l2; +- memcpy(l2, &e->data.bridge.l2, sizeof(*l2)); + + type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe.ib1); +- if (type == PPE_PKT_TYPE_IPV4_HNAPT) +- memcpy(&hwe.ipv4.new_tuple, &hwe.ipv4.orig_tuple, +- sizeof(hwe.ipv4.new_tuple)); +- else if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T && +- l2->common.etype == ETH_P_IP) +- l2->common.etype = ETH_P_IPV6; ++ if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T) { ++ memcpy(&hwe.ipv6.l2, &e->data.bridge.l2, sizeof(hwe.ipv6.l2)); ++ hwe.ipv6.ib2 = e->data.bridge.ib2; ++ } else { ++ memcpy(&hwe.bridge.l2, &e->data.bridge.l2, ++ sizeof(hwe.bridge.l2)); ++ hwe.bridge.ib2 = e->data.bridge.ib2; ++ if (type == PPE_PKT_TYPE_IPV4_HNAPT) ++ memcpy(&hwe.ipv4.new_tuple, &hwe.ipv4.orig_tuple, ++ sizeof(hwe.ipv4.new_tuple)); ++ } + +- hwe.bridge.ib2 = e->data.bridge.ib2; + hwe.bridge.data = e->data.bridge.data; + airoha_ppe_foe_commit_entry(ppe, &hwe, hash); + diff --git a/lede/target/linux/airoha/patches-6.12/076-03-v6.16-net-airoha-Fix-smac_id-configuration-in-bridge-mode.patch b/lede/target/linux/airoha/patches-6.12/076-03-v6.16-net-airoha-Fix-smac_id-configuration-in-bridge-mode.patch new file mode 100644 index 0000000000..f790d9d148 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/076-03-v6.16-net-airoha-Fix-smac_id-configuration-in-bridge-mode.patch @@ -0,0 +1,32 @@ +From c86fac5365d3a068422beeb508f2741f1a2d734d Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 2 Jun 2025 12:55:39 +0200 +Subject: [PATCH 3/3] net: airoha: Fix smac_id configuration in bridge mode + +Set PPE entry smac_id field to 0xf in airoha_ppe_foe_commit_subflow_entry +routine for IPv6 traffic in order to instruct the hw to keep original +source mac address for IPv6 hw accelerated traffic in bridge mode. + +Fixes: cd53f622611f ("net: airoha: Add L2 hw acceleration support") +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250602-airoha-flowtable-ipv6-fix-v2-3-3287f8b55214@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -660,6 +660,11 @@ airoha_ppe_foe_commit_subflow_entry(stru + if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T) { + memcpy(&hwe.ipv6.l2, &e->data.bridge.l2, sizeof(hwe.ipv6.l2)); + hwe.ipv6.ib2 = e->data.bridge.ib2; ++ /* setting smac_id to 0xf instruct the hw to keep original ++ * source mac address ++ */ ++ hwe.ipv6.l2.src_mac_hi = FIELD_PREP(AIROHA_FOE_MAC_SMAC_ID, ++ 0xf); + } else { + memcpy(&hwe.bridge.l2, &e->data.bridge.l2, + sizeof(hwe.bridge.l2)); diff --git a/lede/target/linux/airoha/patches-6.12/077-v6.17-net-airoha-Add-PPPoE-offload-support.patch b/lede/target/linux/airoha/patches-6.12/077-v6.17-net-airoha-Add-PPPoE-offload-support.patch new file mode 100644 index 0000000000..6245f0d218 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/077-v6.17-net-airoha-Add-PPPoE-offload-support.patch @@ -0,0 +1,87 @@ +From 0097c4195b1d0ca57d15979626c769c74747b5a0 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 9 Jun 2025 22:28:40 +0200 +Subject: [PATCH] net: airoha: Add PPPoE offload support + +Introduce flowtable hw acceleration for PPPoE traffic. + +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250609-b4-airoha-flowtable-pppoe-v1-1-1520fa7711b4@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 31 ++++++++++++++++++------ + 1 file changed, 23 insertions(+), 8 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -232,6 +232,7 @@ static int airoha_ppe_foe_entry_prepare( + FIELD_PREP(AIROHA_FOE_IB1_BIND_UDP, l4proto == IPPROTO_UDP) | + FIELD_PREP(AIROHA_FOE_IB1_BIND_VLAN_LAYER, data->vlan.num) | + FIELD_PREP(AIROHA_FOE_IB1_BIND_VPM, data->vlan.num) | ++ FIELD_PREP(AIROHA_FOE_IB1_BIND_PPPOE, data->pppoe.num) | + AIROHA_FOE_IB1_BIND_TTL; + hwe->ib1 = val; + +@@ -281,33 +282,42 @@ static int airoha_ppe_foe_entry_prepare( + hwe->ipv6.data = qdata; + hwe->ipv6.ib2 = val; + l2 = &hwe->ipv6.l2; ++ l2->etype = ETH_P_IPV6; + } else { + hwe->ipv4.data = qdata; + hwe->ipv4.ib2 = val; + l2 = &hwe->ipv4.l2.common; ++ l2->etype = ETH_P_IP; + } + + l2->dest_mac_hi = get_unaligned_be32(data->eth.h_dest); + l2->dest_mac_lo = get_unaligned_be16(data->eth.h_dest + 4); + if (type <= PPE_PKT_TYPE_IPV4_DSLITE) { ++ struct airoha_foe_mac_info *mac_info; ++ + l2->src_mac_hi = get_unaligned_be32(data->eth.h_source); + hwe->ipv4.l2.src_mac_lo = + get_unaligned_be16(data->eth.h_source + 4); ++ ++ mac_info = (struct airoha_foe_mac_info *)l2; ++ mac_info->pppoe_id = data->pppoe.sid; + } else { +- l2->src_mac_hi = FIELD_PREP(AIROHA_FOE_MAC_SMAC_ID, smac_id); ++ l2->src_mac_hi = FIELD_PREP(AIROHA_FOE_MAC_SMAC_ID, smac_id) | ++ FIELD_PREP(AIROHA_FOE_MAC_PPPOE_ID, ++ data->pppoe.sid); + } + + if (data->vlan.num) { +- l2->etype = dsa_port >= 0 ? BIT(dsa_port) : 0; + l2->vlan1 = data->vlan.hdr[0].id; + if (data->vlan.num == 2) + l2->vlan2 = data->vlan.hdr[1].id; +- } else if (dsa_port >= 0) { +- l2->etype = BIT(15) | BIT(dsa_port); +- } else if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T) { +- l2->etype = ETH_P_IPV6; +- } else { +- l2->etype = ETH_P_IP; ++ } ++ ++ if (dsa_port >= 0) { ++ l2->etype = BIT(dsa_port); ++ l2->etype |= !data->vlan.num ? BIT(15) : 0; ++ } else if (data->pppoe.num) { ++ l2->etype = ETH_P_PPP_SES; + } + + return 0; +@@ -957,6 +967,11 @@ static int airoha_ppe_flow_offload_repla + case FLOW_ACTION_VLAN_POP: + break; + case FLOW_ACTION_PPPOE_PUSH: ++ if (data.pppoe.num == 1 || data.vlan.num == 2) ++ return -EOPNOTSUPP; ++ ++ data.pppoe.sid = act->pppoe.sid; ++ data.pppoe.num++; + break; + default: + return -EOPNOTSUPP; diff --git a/lede/target/linux/airoha/patches-6.12/078-v6.16-net-airoha-Enable-RX-queues-16-31.patch b/lede/target/linux/airoha/patches-6.12/078-v6.16-net-airoha-Enable-RX-queues-16-31.patch new file mode 100644 index 0000000000..1550c59261 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/078-v6.16-net-airoha-Enable-RX-queues-16-31.patch @@ -0,0 +1,28 @@ +From f478d68b653323b691280b40fbd3b8ca1ac75aa2 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 9 Jun 2025 22:40:35 +0200 +Subject: [PATCH] net: airoha: Enable RX queues 16-31 + +Fix RX_DONE_INT_MASK definition in order to enable RX queues 16-31. + +Fixes: f252493e18353 ("net: airoha: Enable multiple IRQ lines support in airoha_eth driver.") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250609-aioha-fix-rx-queue-mask-v1-1-f33706a06fa2@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_regs.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -614,8 +614,9 @@ + RX19_DONE_INT_MASK | RX18_DONE_INT_MASK | \ + RX17_DONE_INT_MASK | RX16_DONE_INT_MASK) + +-#define RX_DONE_INT_MASK (RX_DONE_HIGH_INT_MASK | RX_DONE_LOW_INT_MASK) + #define RX_DONE_HIGH_OFFSET fls(RX_DONE_HIGH_INT_MASK) ++#define RX_DONE_INT_MASK \ ++ ((RX_DONE_HIGH_INT_MASK << RX_DONE_HIGH_OFFSET) | RX_DONE_LOW_INT_MASK) + + #define INT_RX2_MASK(_n) \ + ((RX_NO_CPU_DSCP_HIGH_INT_MASK & (_n)) | \ diff --git a/lede/target/linux/airoha/patches-6.12/079-v6.16-net-airoha-Always-check-return-value-from-airoha_ppe.patch b/lede/target/linux/airoha/patches-6.12/079-v6.16-net-airoha-Always-check-return-value-from-airoha_ppe.patch new file mode 100644 index 0000000000..551e8e3c9d --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/079-v6.16-net-airoha-Always-check-return-value-from-airoha_ppe.patch @@ -0,0 +1,32 @@ +From 78bd03ee1f20a267d2c218884b66041b3508ac9c Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 18 Jun 2025 09:37:40 +0200 +Subject: [PATCH] net: airoha: Always check return value from + airoha_ppe_foe_get_entry() + +airoha_ppe_foe_get_entry routine can return NULL, so check the returned +pointer is not NULL in airoha_ppe_foe_flow_l2_entry_update() + +Fixes: b81e0f2b58be3 ("net: airoha: Add FLOW_CLS_STATS callback support") +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250618-check-ret-from-airoha_ppe_foe_get_entry-v2-1-068dcea3cc66@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -819,8 +819,10 @@ airoha_ppe_foe_flow_l2_entry_update(stru + int idle; + + hwe = airoha_ppe_foe_get_entry(ppe, iter->hash); +- ib1 = READ_ONCE(hwe->ib1); ++ if (!hwe) ++ continue; + ++ ib1 = READ_ONCE(hwe->ib1); + state = FIELD_GET(AIROHA_FOE_IB1_BIND_STATE, ib1); + if (state != AIROHA_FOE_STATE_BIND) { + iter->hash = 0xffff; diff --git a/lede/target/linux/airoha/patches-6.12/080-01-v6.16-net-airoha-Compute-number-of-descriptors-according-t.patch b/lede/target/linux/airoha/patches-6.12/080-01-v6.16-net-airoha-Compute-number-of-descriptors-according-t.patch new file mode 100644 index 0000000000..042ca743eb --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/080-01-v6.16-net-airoha-Compute-number-of-descriptors-according-t.patch @@ -0,0 +1,77 @@ +From edf8afeecfbb0b8c1a2edb8c8892d2f759d35321 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Thu, 19 Jun 2025 09:07:24 +0200 +Subject: [PATCH 1/2] net: airoha: Compute number of descriptors according to + reserved memory size + +In order to not exceed the reserved memory size for hwfd buffers, +compute the number of hwfd buffers/descriptors according to the +reserved memory size and the size of each hwfd buffer (2KB). + +Fixes: 3a1ce9e3d01b ("net: airoha: Add the capability to allocate hwfd buffers via reserved-memory") +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250619-airoha-hw-num-desc-v4-1-49600a9b319a@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1065,19 +1065,13 @@ static void airoha_qdma_cleanup_tx_queue + + static int airoha_qdma_init_hfwd_queues(struct airoha_qdma *qdma) + { ++ int size, index, num_desc = HW_DSCP_NUM; + struct airoha_eth *eth = qdma->eth; + int id = qdma - ð->qdma[0]; + dma_addr_t dma_addr; + const char *name; +- int size, index; + u32 status; + +- size = HW_DSCP_NUM * sizeof(struct airoha_qdma_fwd_desc); +- if (!dmam_alloc_coherent(eth->dev, size, &dma_addr, GFP_KERNEL)) +- return -ENOMEM; +- +- airoha_qdma_wr(qdma, REG_FWD_DSCP_BASE, dma_addr); +- + name = devm_kasprintf(eth->dev, GFP_KERNEL, "qdma%d-buf", id); + if (!name) + return -ENOMEM; +@@ -1099,8 +1093,12 @@ static int airoha_qdma_init_hfwd_queues( + rmem = of_reserved_mem_lookup(np); + of_node_put(np); + dma_addr = rmem->base; ++ /* Compute the number of hw descriptors according to the ++ * reserved memory size and the payload buffer size ++ */ ++ num_desc = rmem->size / AIROHA_MAX_PACKET_SIZE; + } else { +- size = AIROHA_MAX_PACKET_SIZE * HW_DSCP_NUM; ++ size = AIROHA_MAX_PACKET_SIZE * num_desc; + if (!dmam_alloc_coherent(eth->dev, size, &dma_addr, + GFP_KERNEL)) + return -ENOMEM; +@@ -1108,6 +1106,11 @@ static int airoha_qdma_init_hfwd_queues( + + airoha_qdma_wr(qdma, REG_FWD_BUF_BASE, dma_addr); + ++ size = num_desc * sizeof(struct airoha_qdma_fwd_desc); ++ if (!dmam_alloc_coherent(eth->dev, size, &dma_addr, GFP_KERNEL)) ++ return -ENOMEM; ++ ++ airoha_qdma_wr(qdma, REG_FWD_DSCP_BASE, dma_addr); + airoha_qdma_rmw(qdma, REG_HW_FWD_DSCP_CFG, + HW_FWD_DSCP_PAYLOAD_SIZE_MASK, + FIELD_PREP(HW_FWD_DSCP_PAYLOAD_SIZE_MASK, 0)); +@@ -1116,7 +1119,7 @@ static int airoha_qdma_init_hfwd_queues( + airoha_qdma_rmw(qdma, REG_LMGR_INIT_CFG, + LMGR_INIT_START | LMGR_SRAM_MODE_MASK | + HW_FWD_DESC_NUM_MASK, +- FIELD_PREP(HW_FWD_DESC_NUM_MASK, HW_DSCP_NUM) | ++ FIELD_PREP(HW_FWD_DESC_NUM_MASK, num_desc) | + LMGR_INIT_START | LMGR_SRAM_MODE_MASK); + + return read_poll_timeout(airoha_qdma_rr, status, diff --git a/lede/target/linux/airoha/patches-6.12/080-02-v6.16-net-airoha-Differentiate-hwfd-buffer-size-for-QDMA0-.patch b/lede/target/linux/airoha/patches-6.12/080-02-v6.16-net-airoha-Differentiate-hwfd-buffer-size-for-QDMA0-.patch new file mode 100644 index 0000000000..e6a90a335c --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/080-02-v6.16-net-airoha-Differentiate-hwfd-buffer-size-for-QDMA0-.patch @@ -0,0 +1,64 @@ +From 7b46bdaec00a675f6fac9d0b01a2105b5746ebe9 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Thu, 19 Jun 2025 09:07:25 +0200 +Subject: [PATCH 2/2] net: airoha: Differentiate hwfd buffer size for QDMA0 and + QDMA1 + +EN7581 SoC allows configuring the size and the number of buffers in +hwfd payload queue for both QDMA0 and QDMA1. +In order to reduce the required DRAM used for hwfd buffers queues and +decrease the memory footprint, differentiate hwfd buffer size for QDMA0 +and QDMA1 and reduce hwfd buffer size to 1KB for QDMA1 (WAN) while +maintaining 2KB for QDMA0 (LAN). + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250619-airoha-hw-num-desc-v4-2-49600a9b319a@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1068,14 +1068,15 @@ static int airoha_qdma_init_hfwd_queues( + int size, index, num_desc = HW_DSCP_NUM; + struct airoha_eth *eth = qdma->eth; + int id = qdma - ð->qdma[0]; ++ u32 status, buf_size; + dma_addr_t dma_addr; + const char *name; +- u32 status; + + name = devm_kasprintf(eth->dev, GFP_KERNEL, "qdma%d-buf", id); + if (!name) + return -ENOMEM; + ++ buf_size = id ? AIROHA_MAX_PACKET_SIZE / 2 : AIROHA_MAX_PACKET_SIZE; + index = of_property_match_string(eth->dev->of_node, + "memory-region-names", name); + if (index >= 0) { +@@ -1096,9 +1097,9 @@ static int airoha_qdma_init_hfwd_queues( + /* Compute the number of hw descriptors according to the + * reserved memory size and the payload buffer size + */ +- num_desc = rmem->size / AIROHA_MAX_PACKET_SIZE; ++ num_desc = div_u64(rmem->size, buf_size); + } else { +- size = AIROHA_MAX_PACKET_SIZE * num_desc; ++ size = buf_size * num_desc; + if (!dmam_alloc_coherent(eth->dev, size, &dma_addr, + GFP_KERNEL)) + return -ENOMEM; +@@ -1111,9 +1112,10 @@ static int airoha_qdma_init_hfwd_queues( + return -ENOMEM; + + airoha_qdma_wr(qdma, REG_FWD_DSCP_BASE, dma_addr); ++ /* QDMA0: 2KB. QDMA1: 1KB */ + airoha_qdma_rmw(qdma, REG_HW_FWD_DSCP_CFG, + HW_FWD_DSCP_PAYLOAD_SIZE_MASK, +- FIELD_PREP(HW_FWD_DSCP_PAYLOAD_SIZE_MASK, 0)); ++ FIELD_PREP(HW_FWD_DSCP_PAYLOAD_SIZE_MASK, !!id)); + airoha_qdma_rmw(qdma, REG_FWD_DSCP_LOW_THR, FWD_DSCP_LOW_THR_MASK, + FIELD_PREP(FWD_DSCP_LOW_THR_MASK, 128)); + airoha_qdma_rmw(qdma, REG_LMGR_INIT_CFG, diff --git a/lede/target/linux/airoha/patches-6.12/081-v6.17-net-airoha-Fix-PPE-table-access-in-airoha_ppe_debugf.patch b/lede/target/linux/airoha/patches-6.12/081-v6.17-net-airoha-Fix-PPE-table-access-in-airoha_ppe_debugf.patch new file mode 100644 index 0000000000..919b6b44da --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/081-v6.17-net-airoha-Fix-PPE-table-access-in-airoha_ppe_debugf.patch @@ -0,0 +1,92 @@ +From 38358fa3cc8e16c6862a3e5c5c233f9f652e3a6d Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Thu, 31 Jul 2025 12:29:08 +0200 +Subject: [PATCH] net: airoha: Fix PPE table access in + airoha_ppe_debugfs_foe_show() + +In order to avoid any possible race we need to hold the ppe_lock +spinlock accessing the hw PPE table. airoha_ppe_foe_get_entry routine is +always executed holding ppe_lock except in airoha_ppe_debugfs_foe_show +routine. Fix the problem introducing airoha_ppe_foe_get_entry_locked +routine. + +Fixes: 3fe15c640f380 ("net: airoha: Introduce PPE debugfs support") +Reviewed-by: Dawid Osuchowski +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250731-airoha_ppe_foe_get_entry_locked-v2-1-50efbd8c0fd6@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 26 ++++++++++++++++++------ + 1 file changed, 20 insertions(+), 6 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -508,9 +508,11 @@ static void airoha_ppe_foe_flow_stats_up + FIELD_PREP(AIROHA_FOE_IB2_NBQ, nbq); + } + +-struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe, +- u32 hash) ++static struct airoha_foe_entry * ++airoha_ppe_foe_get_entry_locked(struct airoha_ppe *ppe, u32 hash) + { ++ lockdep_assert_held(&ppe_lock); ++ + if (hash < PPE_SRAM_NUM_ENTRIES) { + u32 *hwe = ppe->foe + hash * sizeof(struct airoha_foe_entry); + struct airoha_eth *eth = ppe->eth; +@@ -537,6 +539,18 @@ struct airoha_foe_entry *airoha_ppe_foe_ + return ppe->foe + hash * sizeof(struct airoha_foe_entry); + } + ++struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe, ++ u32 hash) ++{ ++ struct airoha_foe_entry *hwe; ++ ++ spin_lock_bh(&ppe_lock); ++ hwe = airoha_ppe_foe_get_entry_locked(ppe, hash); ++ spin_unlock_bh(&ppe_lock); ++ ++ return hwe; ++} ++ + static bool airoha_ppe_foe_compare_entry(struct airoha_flow_table_entry *e, + struct airoha_foe_entry *hwe) + { +@@ -651,7 +665,7 @@ airoha_ppe_foe_commit_subflow_entry(stru + struct airoha_flow_table_entry *f; + int type; + +- hwe_p = airoha_ppe_foe_get_entry(ppe, hash); ++ hwe_p = airoha_ppe_foe_get_entry_locked(ppe, hash); + if (!hwe_p) + return -EINVAL; + +@@ -703,7 +717,7 @@ static void airoha_ppe_foe_insert_entry( + + spin_lock_bh(&ppe_lock); + +- hwe = airoha_ppe_foe_get_entry(ppe, hash); ++ hwe = airoha_ppe_foe_get_entry_locked(ppe, hash); + if (!hwe) + goto unlock; + +@@ -818,7 +832,7 @@ airoha_ppe_foe_flow_l2_entry_update(stru + u32 ib1, state; + int idle; + +- hwe = airoha_ppe_foe_get_entry(ppe, iter->hash); ++ hwe = airoha_ppe_foe_get_entry_locked(ppe, iter->hash); + if (!hwe) + continue; + +@@ -855,7 +869,7 @@ static void airoha_ppe_foe_flow_entry_up + if (e->hash == 0xffff) + goto unlock; + +- hwe_p = airoha_ppe_foe_get_entry(ppe, e->hash); ++ hwe_p = airoha_ppe_foe_get_entry_locked(ppe, e->hash); + if (!hwe_p) + goto unlock; + diff --git a/lede/target/linux/airoha/patches-6.12/082-v6.17-net-airoha-ppe-Do-not-invalid-PPE-entries-in-case-of.patch b/lede/target/linux/airoha/patches-6.12/082-v6.17-net-airoha-ppe-Do-not-invalid-PPE-entries-in-case-of.patch new file mode 100644 index 0000000000..eda914aab7 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/082-v6.17-net-airoha-ppe-Do-not-invalid-PPE-entries-in-case-of.patch @@ -0,0 +1,42 @@ +From 9f6b606b6b37e61427412708411e8e04b1a858e8 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 18 Aug 2025 11:58:25 +0200 +Subject: [PATCH] net: airoha: ppe: Do not invalid PPE entries in case of SW + hash collision + +SW hash computed by airoha_ppe_foe_get_entry_hash routine (used for +foe_flow hlist) can theoretically produce collisions between two +different HW PPE entries. +In airoha_ppe_foe_insert_entry() if the collision occurs we will mark +the second PPE entry in the list as stale (setting the hw hash to 0xffff). +Stale entries are no more updated in airoha_ppe_foe_flow_entry_update +routine and so they are removed by Netfilter. +Fix the problem not marking the second entry as stale in +airoha_ppe_foe_insert_entry routine if we have already inserted the +brand new entry in the PPE table and let Netfilter remove real stale +entries according to their timestamp. +Please note this is just a theoretical issue spotted reviewing the code +and not faced running the system. + +Fixes: cd53f622611f9 ("net: airoha: Add L2 hw acceleration support") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250818-airoha-en7581-hash-collision-fix-v1-1-d190c4b53d1c@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -736,10 +736,8 @@ static void airoha_ppe_foe_insert_entry( + continue; + } + +- if (commit_done || !airoha_ppe_foe_compare_entry(e, hwe)) { +- e->hash = 0xffff; ++ if (!airoha_ppe_foe_compare_entry(e, hwe)) + continue; +- } + + airoha_ppe_foe_commit_entry(ppe, &e->data, hash); + commit_done = true; diff --git a/lede/target/linux/airoha/patches-6.12/083-01-v6.13-resource-Add-resource-set-range-and-size-helpers.patch b/lede/target/linux/airoha/patches-6.12/083-01-v6.13-resource-Add-resource-set-range-and-size-helpers.patch new file mode 100644 index 0000000000..0ea3e2ab5d --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/083-01-v6.13-resource-Add-resource-set-range-and-size-helpers.patch @@ -0,0 +1,73 @@ +From 9fb6fef0fb49124291837af1da5028f79d53f98e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= +Date: Fri, 14 Jun 2024 13:06:03 +0300 +Subject: [PATCH] resource: Add resource set range and size helpers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Setting the end address for a resource with a given size lacks a helper and +is therefore coded manually unlike the getter side which has a helper for +resource size calculation. Also, almost all callsites that calculate the +end address for a resource also set the start address right before it like +this: + + res->start = start_addr; + res->end = res->start + size - 1; + +Add resource_set_range(res, start_addr, size) that sets the start address +and calculates the end address to simplify this often repeated fragment. + +Also add resource_set_size() for the cases where setting the start address +of the resource is not necessary but mention in its kerneldoc that +resource_set_range() is preferred when setting both addresses. + +Link: https://lore.kernel.org/r/20240614100606.15830-2-ilpo.jarvinen@linux.intel.com +Signed-off-by: Ilpo Järvinen +Signed-off-by: Bjorn Helgaas +Reviewed-by: Jonathan Cameron +--- + include/linux/ioport.h | 32 ++++++++++++++++++++++++++++++++ + 1 file changed, 32 insertions(+) + +--- a/include/linux/ioport.h ++++ b/include/linux/ioport.h +@@ -249,6 +249,38 @@ struct resource *lookup_resource(struct + int adjust_resource(struct resource *res, resource_size_t start, + resource_size_t size); + resource_size_t resource_alignment(struct resource *res); ++ ++/** ++ * resource_set_size - Calculate resource end address from size and start ++ * @res: Resource descriptor ++ * @size: Size of the resource ++ * ++ * Calculate the end address for @res based on @size. ++ * ++ * Note: The start address of @res must be set when calling this function. ++ * Prefer resource_set_range() if setting both the start address and @size. ++ */ ++static inline void resource_set_size(struct resource *res, resource_size_t size) ++{ ++ res->end = res->start + size - 1; ++} ++ ++/** ++ * resource_set_range - Set resource start and end addresses ++ * @res: Resource descriptor ++ * @start: Start address for the resource ++ * @size: Size of the resource ++ * ++ * Set @res start address and calculate the end address based on @size. ++ */ ++static inline void resource_set_range(struct resource *res, ++ resource_size_t start, ++ resource_size_t size) ++{ ++ res->start = start; ++ resource_set_size(res, size); ++} ++ + static inline resource_size_t resource_size(const struct resource *res) + { + return res->end - res->start + 1; diff --git a/lede/target/linux/airoha/patches-6.12/083-02-v6.16-of-reserved_mem-Add-functions-to-parse-memory-region.patch b/lede/target/linux/airoha/patches-6.12/083-02-v6.16-of-reserved_mem-Add-functions-to-parse-memory-region.patch new file mode 100644 index 0000000000..b5bbb6e723 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/083-02-v6.16-of-reserved_mem-Add-functions-to-parse-memory-region.patch @@ -0,0 +1,163 @@ +From f4fcfdda2fd8834c62dcb9bfddcf1f89d190b70e Mon Sep 17 00:00:00 2001 +From: "Rob Herring (Arm)" +Date: Wed, 23 Apr 2025 14:42:13 -0500 +Subject: [PATCH] of: reserved_mem: Add functions to parse "memory-region" + +Drivers with "memory-region" properties currently have to do their own +parsing of "memory-region" properties. The result is all the drivers +have similar patterns of a call to parse "memory-region" and then get +the region's address and size. As this is a standard property, it should +have common functions for drivers to use. Add new functions to count the +number of regions and retrieve the region's address as a resource. + +Reviewed-by: Daniel Baluta +Acked-by: Arnaud Pouliquen +Link: https://lore.kernel.org/r/20250423-dt-memory-region-v2-v2-1-2fbd6ebd3c88@kernel.org +Signed-off-by: Rob Herring (Arm) +--- + drivers/of/of_reserved_mem.c | 80 +++++++++++++++++++++++++++++++++ + include/linux/of_reserved_mem.h | 26 +++++++++++ + 2 files changed, 106 insertions(+) + +--- a/drivers/of/of_reserved_mem.c ++++ b/drivers/of/of_reserved_mem.c +@@ -12,6 +12,7 @@ + #define pr_fmt(fmt) "OF: reserved mem: " fmt + + #include ++#include + #include + #include + #include +@@ -694,3 +695,82 @@ struct reserved_mem *of_reserved_mem_loo + return NULL; + } + EXPORT_SYMBOL_GPL(of_reserved_mem_lookup); ++ ++/** ++ * of_reserved_mem_region_to_resource() - Get a reserved memory region as a resource ++ * @np: node containing 'memory-region' property ++ * @idx: index of 'memory-region' property to lookup ++ * @res: Pointer to a struct resource to fill in with reserved region ++ * ++ * This function allows drivers to lookup a node's 'memory-region' property ++ * entries by index and return a struct resource for the entry. ++ * ++ * Returns 0 on success with @res filled in. Returns -ENODEV if 'memory-region' ++ * is missing or unavailable, -EINVAL for any other error. ++ */ ++int of_reserved_mem_region_to_resource(const struct device_node *np, ++ unsigned int idx, struct resource *res) ++{ ++ struct reserved_mem *rmem; ++ ++ if (!np) ++ return -EINVAL; ++ ++ struct device_node __free(device_node) *target = of_parse_phandle(np, "memory-region", idx); ++ if (!target || !of_device_is_available(target)) ++ return -ENODEV; ++ ++ rmem = of_reserved_mem_lookup(target); ++ if (!rmem) ++ return -EINVAL; ++ ++ resource_set_range(res, rmem->base, rmem->size); ++ res->name = rmem->name; ++ return 0; ++} ++EXPORT_SYMBOL_GPL(of_reserved_mem_region_to_resource); ++ ++/** ++ * of_reserved_mem_region_to_resource_byname() - Get a reserved memory region as a resource ++ * @np: node containing 'memory-region' property ++ * @name: name of 'memory-region' property entry to lookup ++ * @res: Pointer to a struct resource to fill in with reserved region ++ * ++ * This function allows drivers to lookup a node's 'memory-region' property ++ * entries by name and return a struct resource for the entry. ++ * ++ * Returns 0 on success with @res filled in, or a negative error-code on ++ * failure. ++ */ ++int of_reserved_mem_region_to_resource_byname(const struct device_node *np, ++ const char *name, ++ struct resource *res) ++{ ++ int idx; ++ ++ if (!name) ++ return -EINVAL; ++ ++ idx = of_property_match_string(np, "memory-region-names", name); ++ if (idx < 0) ++ return idx; ++ ++ return of_reserved_mem_region_to_resource(np, idx, res); ++} ++EXPORT_SYMBOL_GPL(of_reserved_mem_region_to_resource_byname); ++ ++/** ++ * of_reserved_mem_region_count() - Return the number of 'memory-region' entries ++ * @np: node containing 'memory-region' property ++ * ++ * This function allows drivers to retrieve the number of entries for a node's ++ * 'memory-region' property. ++ * ++ * Returns the number of entries on success, or negative error code on a ++ * malformed property. ++ */ ++int of_reserved_mem_region_count(const struct device_node *np) ++{ ++ return of_count_phandle_with_args(np, "memory-region", NULL); ++} ++EXPORT_SYMBOL_GPL(of_reserved_mem_region_count); +--- a/include/linux/of_reserved_mem.h ++++ b/include/linux/of_reserved_mem.h +@@ -7,6 +7,7 @@ + + struct of_phandle_args; + struct reserved_mem_ops; ++struct resource; + + struct reserved_mem { + const char *name; +@@ -39,6 +40,12 @@ int of_reserved_mem_device_init_by_name( + void of_reserved_mem_device_release(struct device *dev); + + struct reserved_mem *of_reserved_mem_lookup(struct device_node *np); ++int of_reserved_mem_region_to_resource(const struct device_node *np, ++ unsigned int idx, struct resource *res); ++int of_reserved_mem_region_to_resource_byname(const struct device_node *np, ++ const char *name, struct resource *res); ++int of_reserved_mem_region_count(const struct device_node *np); ++ + #else + + #define RESERVEDMEM_OF_DECLARE(name, compat, init) \ +@@ -63,6 +70,25 @@ static inline struct reserved_mem *of_re + { + return NULL; + } ++ ++static inline int of_reserved_mem_region_to_resource(const struct device_node *np, ++ unsigned int idx, ++ struct resource *res) ++{ ++ return -ENOSYS; ++} ++ ++static inline int of_reserved_mem_region_to_resource_byname(const struct device_node *np, ++ const char *name, ++ struct resource *res) ++{ ++ return -ENOSYS; ++} ++ ++static inline int of_reserved_mem_region_count(const struct device_node *np) ++{ ++ return 0; ++} + #endif + + /** diff --git a/lede/target/linux/airoha/patches-6.12/084-01-v6.18-net-airoha-npu-Add-NPU-wlan-memory-initialization-co.patch b/lede/target/linux/airoha/patches-6.12/084-01-v6.18-net-airoha-npu-Add-NPU-wlan-memory-initialization-co.patch new file mode 100644 index 0000000000..7e9e9423ec --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/084-01-v6.18-net-airoha-npu-Add-NPU-wlan-memory-initialization-co.patch @@ -0,0 +1,179 @@ +From 564923b02c1d2fe02ee789f9849ff79979b63b9f Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 11 Aug 2025 17:31:37 +0200 +Subject: [PATCH 1/6] net: airoha: npu: Add NPU wlan memory initialization + commands + +Introduce wlan_init_reserved_memory callback used by MT76 driver during +NPU wlan offloading setup. +This is a preliminary patch to enable wlan flowtable offload for EN7581 +SoC with MT76 driver. + +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250811-airoha-en7581-wlan-offlaod-v7-2-58823603bb4e@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_npu.c | 82 ++++++++++++++++++++++++ + drivers/net/ethernet/airoha/airoha_npu.h | 38 +++++++++++ + 2 files changed, 120 insertions(+) + +--- a/drivers/net/ethernet/airoha/airoha_npu.c ++++ b/drivers/net/ethernet/airoha/airoha_npu.c +@@ -124,6 +124,13 @@ struct ppe_mbox_data { + }; + }; + ++struct wlan_mbox_data { ++ u32 ifindex:4; ++ u32 func_type:4; ++ u32 func_id; ++ DECLARE_FLEX_ARRAY(u8, d); ++}; ++ + static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id, + void *p, int size) + { +@@ -390,6 +397,80 @@ out: + return err; + } + ++static int airoha_npu_wlan_msg_send(struct airoha_npu *npu, int ifindex, ++ enum airoha_npu_wlan_set_cmd func_id, ++ void *data, int data_len, gfp_t gfp) ++{ ++ struct wlan_mbox_data *wlan_data; ++ int err, len; ++ ++ len = sizeof(*wlan_data) + data_len; ++ wlan_data = kzalloc(len, gfp); ++ if (!wlan_data) ++ return -ENOMEM; ++ ++ wlan_data->ifindex = ifindex; ++ wlan_data->func_type = NPU_OP_SET; ++ wlan_data->func_id = func_id; ++ memcpy(wlan_data->d, data, data_len); ++ ++ err = airoha_npu_send_msg(npu, NPU_FUNC_WIFI, wlan_data, len); ++ kfree(wlan_data); ++ ++ return err; ++} ++ ++static int ++airoha_npu_wlan_set_reserved_memory(struct airoha_npu *npu, ++ int ifindex, const char *name, ++ enum airoha_npu_wlan_set_cmd func_id) ++{ ++ struct device *dev = npu->dev; ++ struct resource res; ++ int err; ++ u32 val; ++ ++ err = of_reserved_mem_region_to_resource_byname(dev->of_node, name, ++ &res); ++ if (err) ++ return err; ++ ++ val = res.start; ++ return airoha_npu_wlan_msg_send(npu, ifindex, func_id, &val, ++ sizeof(val), GFP_KERNEL); ++} ++ ++static int airoha_npu_wlan_init_memory(struct airoha_npu *npu) ++{ ++ enum airoha_npu_wlan_set_cmd cmd = WLAN_FUNC_SET_WAIT_NPU_BAND0_ONCPU; ++ u32 val = 0; ++ int err; ++ ++ err = airoha_npu_wlan_msg_send(npu, 1, cmd, &val, sizeof(val), ++ GFP_KERNEL); ++ if (err) ++ return err; ++ ++ cmd = WLAN_FUNC_SET_WAIT_TX_BUF_CHECK_ADDR; ++ err = airoha_npu_wlan_set_reserved_memory(npu, 0, "tx-bufid", cmd); ++ if (err) ++ return err; ++ ++ cmd = WLAN_FUNC_SET_WAIT_PKT_BUF_ADDR; ++ err = airoha_npu_wlan_set_reserved_memory(npu, 0, "pkt", cmd); ++ if (err) ++ return err; ++ ++ cmd = WLAN_FUNC_SET_WAIT_TX_PKT_BUF_ADDR; ++ err = airoha_npu_wlan_set_reserved_memory(npu, 0, "tx-pkt", cmd); ++ if (err) ++ return err; ++ ++ cmd = WLAN_FUNC_SET_WAIT_IS_FORCE_TO_CPU; ++ return airoha_npu_wlan_msg_send(npu, 0, cmd, &val, sizeof(val), ++ GFP_KERNEL); ++} ++ + struct airoha_npu *airoha_npu_get(struct device *dev, dma_addr_t *stats_addr) + { + struct platform_device *pdev; +@@ -493,6 +574,7 @@ static int airoha_npu_probe(struct platf + npu->ops.ppe_deinit = airoha_npu_ppe_deinit; + npu->ops.ppe_flush_sram_entries = airoha_npu_ppe_flush_sram_entries; + npu->ops.ppe_foe_commit_entry = airoha_npu_foe_commit_entry; ++ npu->ops.wlan_init_reserved_memory = airoha_npu_wlan_init_memory; + + npu->regmap = devm_regmap_init_mmio(dev, base, ®map_config); + if (IS_ERR(npu->regmap)) +--- a/drivers/net/ethernet/airoha/airoha_npu.h ++++ b/drivers/net/ethernet/airoha/airoha_npu.h +@@ -6,6 +6,43 @@ + + #define NPU_NUM_CORES 8 + ++enum airoha_npu_wlan_set_cmd { ++ WLAN_FUNC_SET_WAIT_PCIE_ADDR, ++ WLAN_FUNC_SET_WAIT_DESC, ++ WLAN_FUNC_SET_WAIT_NPU_INIT_DONE, ++ WLAN_FUNC_SET_WAIT_TRAN_TO_CPU, ++ WLAN_FUNC_SET_WAIT_BA_WIN_SIZE, ++ WLAN_FUNC_SET_WAIT_DRIVER_MODEL, ++ WLAN_FUNC_SET_WAIT_DEL_STA, ++ WLAN_FUNC_SET_WAIT_DRAM_BA_NODE_ADDR, ++ WLAN_FUNC_SET_WAIT_PKT_BUF_ADDR, ++ WLAN_FUNC_SET_WAIT_IS_TEST_NOBA, ++ WLAN_FUNC_SET_WAIT_FLUSHONE_TIMEOUT, ++ WLAN_FUNC_SET_WAIT_FLUSHALL_TIMEOUT, ++ WLAN_FUNC_SET_WAIT_IS_FORCE_TO_CPU, ++ WLAN_FUNC_SET_WAIT_PCIE_STATE, ++ WLAN_FUNC_SET_WAIT_PCIE_PORT_TYPE, ++ WLAN_FUNC_SET_WAIT_ERROR_RETRY_TIMES, ++ WLAN_FUNC_SET_WAIT_BAR_INFO, ++ WLAN_FUNC_SET_WAIT_FAST_FLAG, ++ WLAN_FUNC_SET_WAIT_NPU_BAND0_ONCPU, ++ WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR, ++ WLAN_FUNC_SET_WAIT_TX_DESC_HW_BASE, ++ WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE, ++ WLAN_FUNC_SET_WAIT_RX_RING_FOR_TXDONE_HW_BASE, ++ WLAN_FUNC_SET_WAIT_TX_PKT_BUF_ADDR, ++ WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR, ++ WLAN_FUNC_SET_WAIT_INODE_DEBUG_FLAG, ++ WLAN_FUNC_SET_WAIT_INODE_HW_CFG_INFO, ++ WLAN_FUNC_SET_WAIT_INODE_STOP_ACTION, ++ WLAN_FUNC_SET_WAIT_INODE_PCIE_SWAP, ++ WLAN_FUNC_SET_WAIT_RATELIMIT_CTRL, ++ WLAN_FUNC_SET_WAIT_HWNAT_INIT, ++ WLAN_FUNC_SET_WAIT_ARHT_CHIP_INFO, ++ WLAN_FUNC_SET_WAIT_TX_BUF_CHECK_ADDR, ++ WLAN_FUNC_SET_WAIT_TOKEN_ID_SIZE, ++}; ++ + struct airoha_npu { + struct device *dev; + struct regmap *regmap; +@@ -29,6 +66,7 @@ struct airoha_npu { + dma_addr_t foe_addr, + u32 entry_size, u32 hash, + bool ppe2); ++ int (*wlan_init_reserved_memory)(struct airoha_npu *npu); + } ops; + }; + diff --git a/lede/target/linux/airoha/patches-6.12/084-02-v6.18-net-airoha-npu-Add-wlan_-send-get-_msg-NPU-callbacks.patch b/lede/target/linux/airoha/patches-6.12/084-02-v6.18-net-airoha-npu-Add-wlan_-send-get-_msg-NPU-callbacks.patch new file mode 100644 index 0000000000..5ff820d0be --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/084-02-v6.18-net-airoha-npu-Add-wlan_-send-get-_msg-NPU-callbacks.patch @@ -0,0 +1,139 @@ +From f97fc66185b2004ad5f393f78b3e645009ddd1d0 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 11 Aug 2025 17:31:38 +0200 +Subject: [PATCH 2/6] net: airoha: npu: Add wlan_{send,get}_msg NPU callbacks + +Introduce wlan_send_msg() and wlan_get_msg() NPU wlan callbacks used +by the wlan driver (MT76) to initialize NPU module registers in order to +offload wireless-wired traffic. +This is a preliminary patch to enable wlan flowtable offload for EN7581 +SoC with MT76 driver. + +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250811-airoha-en7581-wlan-offlaod-v7-3-58823603bb4e@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_npu.c | 52 ++++++++++++++++++++++++ + drivers/net/ethernet/airoha/airoha_npu.h | 22 ++++++++++ + 2 files changed, 74 insertions(+) + +--- a/drivers/net/ethernet/airoha/airoha_npu.c ++++ b/drivers/net/ethernet/airoha/airoha_npu.c +@@ -42,6 +42,22 @@ + #define REG_CR_MBQ8_CTRL(_n) (NPU_MBOX_BASE_ADDR + 0x0b0 + ((_n) << 2)) + #define REG_CR_NPU_MIB(_n) (NPU_MBOX_BASE_ADDR + 0x140 + ((_n) << 2)) + ++#define NPU_WLAN_BASE_ADDR 0x30d000 ++ ++#define REG_IRQ_STATUS (NPU_WLAN_BASE_ADDR + 0x030) ++#define REG_IRQ_RXDONE(_n) (NPU_WLAN_BASE_ADDR + ((_n) << 2) + 0x034) ++#define NPU_IRQ_RX_MASK(_n) ((_n) == 1 ? BIT(17) : BIT(16)) ++ ++#define REG_TX_BASE(_n) (NPU_WLAN_BASE_ADDR + ((_n) << 4) + 0x080) ++#define REG_TX_DSCP_NUM(_n) (NPU_WLAN_BASE_ADDR + ((_n) << 4) + 0x084) ++#define REG_TX_CPU_IDX(_n) (NPU_WLAN_BASE_ADDR + ((_n) << 4) + 0x088) ++#define REG_TX_DMA_IDX(_n) (NPU_WLAN_BASE_ADDR + ((_n) << 4) + 0x08c) ++ ++#define REG_RX_BASE(_n) (NPU_WLAN_BASE_ADDR + ((_n) << 4) + 0x180) ++#define REG_RX_DSCP_NUM(_n) (NPU_WLAN_BASE_ADDR + ((_n) << 4) + 0x184) ++#define REG_RX_CPU_IDX(_n) (NPU_WLAN_BASE_ADDR + ((_n) << 4) + 0x188) ++#define REG_RX_DMA_IDX(_n) (NPU_WLAN_BASE_ADDR + ((_n) << 4) + 0x18c) ++ + #define NPU_TIMER_BASE_ADDR 0x310100 + #define REG_WDT_TIMER_CTRL(_n) (NPU_TIMER_BASE_ADDR + ((_n) * 0x100)) + #define WDT_EN_MASK BIT(25) +@@ -420,6 +436,30 @@ static int airoha_npu_wlan_msg_send(stru + return err; + } + ++static int airoha_npu_wlan_msg_get(struct airoha_npu *npu, int ifindex, ++ enum airoha_npu_wlan_get_cmd func_id, ++ void *data, int data_len, gfp_t gfp) ++{ ++ struct wlan_mbox_data *wlan_data; ++ int err, len; ++ ++ len = sizeof(*wlan_data) + data_len; ++ wlan_data = kzalloc(len, gfp); ++ if (!wlan_data) ++ return -ENOMEM; ++ ++ wlan_data->ifindex = ifindex; ++ wlan_data->func_type = NPU_OP_GET; ++ wlan_data->func_id = func_id; ++ ++ err = airoha_npu_send_msg(npu, NPU_FUNC_WIFI, wlan_data, len); ++ if (!err) ++ memcpy(data, wlan_data->d, data_len); ++ kfree(wlan_data); ++ ++ return err; ++} ++ + static int + airoha_npu_wlan_set_reserved_memory(struct airoha_npu *npu, + int ifindex, const char *name, +@@ -471,6 +511,15 @@ static int airoha_npu_wlan_init_memory(s + GFP_KERNEL); + } + ++static u32 airoha_npu_wlan_queue_addr_get(struct airoha_npu *npu, int qid, ++ bool xmit) ++{ ++ if (xmit) ++ return REG_TX_BASE(qid + 2); ++ ++ return REG_RX_BASE(qid); ++} ++ + struct airoha_npu *airoha_npu_get(struct device *dev, dma_addr_t *stats_addr) + { + struct platform_device *pdev; +@@ -575,6 +624,9 @@ static int airoha_npu_probe(struct platf + npu->ops.ppe_flush_sram_entries = airoha_npu_ppe_flush_sram_entries; + npu->ops.ppe_foe_commit_entry = airoha_npu_foe_commit_entry; + npu->ops.wlan_init_reserved_memory = airoha_npu_wlan_init_memory; ++ npu->ops.wlan_send_msg = airoha_npu_wlan_msg_send; ++ npu->ops.wlan_get_msg = airoha_npu_wlan_msg_get; ++ npu->ops.wlan_get_queue_addr = airoha_npu_wlan_queue_addr_get; + + npu->regmap = devm_regmap_init_mmio(dev, base, ®map_config); + if (IS_ERR(npu->regmap)) +--- a/drivers/net/ethernet/airoha/airoha_npu.h ++++ b/drivers/net/ethernet/airoha/airoha_npu.h +@@ -43,6 +43,20 @@ enum airoha_npu_wlan_set_cmd { + WLAN_FUNC_SET_WAIT_TOKEN_ID_SIZE, + }; + ++enum airoha_npu_wlan_get_cmd { ++ WLAN_FUNC_GET_WAIT_NPU_INFO, ++ WLAN_FUNC_GET_WAIT_LAST_RATE, ++ WLAN_FUNC_GET_WAIT_COUNTER, ++ WLAN_FUNC_GET_WAIT_DBG_COUNTER, ++ WLAN_FUNC_GET_WAIT_RXDESC_BASE, ++ WLAN_FUNC_GET_WAIT_WCID_DBG_COUNTER, ++ WLAN_FUNC_GET_WAIT_DMA_ADDR, ++ WLAN_FUNC_GET_WAIT_RING_SIZE, ++ WLAN_FUNC_GET_WAIT_NPU_SUPPORT_MAP, ++ WLAN_FUNC_GET_WAIT_MDC_LOCK_ADDRESS, ++ WLAN_FUNC_GET_WAIT_NPU_VERSION, ++}; ++ + struct airoha_npu { + struct device *dev; + struct regmap *regmap; +@@ -67,6 +81,14 @@ struct airoha_npu { + u32 entry_size, u32 hash, + bool ppe2); + int (*wlan_init_reserved_memory)(struct airoha_npu *npu); ++ int (*wlan_send_msg)(struct airoha_npu *npu, int ifindex, ++ enum airoha_npu_wlan_set_cmd func_id, ++ void *data, int data_len, gfp_t gfp); ++ int (*wlan_get_msg)(struct airoha_npu *npu, int ifindex, ++ enum airoha_npu_wlan_get_cmd func_id, ++ void *data, int data_len, gfp_t gfp); ++ u32 (*wlan_get_queue_addr)(struct airoha_npu *npu, int qid, ++ bool xmit); + } ops; + }; + diff --git a/lede/target/linux/airoha/patches-6.12/084-03-v6.18-net-airoha-npu-Add-wlan-irq-management-callbacks.patch b/lede/target/linux/airoha/patches-6.12/084-03-v6.18-net-airoha-npu-Add-wlan-irq-management-callbacks.patch new file mode 100644 index 0000000000..f05b947cec --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/084-03-v6.18-net-airoha-npu-Add-wlan-irq-management-callbacks.patch @@ -0,0 +1,74 @@ +From 03b7ca3ee5e1b700c462aed5b6cb88f616d6ba7f Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 11 Aug 2025 17:31:39 +0200 +Subject: [PATCH 3/6] net: airoha: npu: Add wlan irq management callbacks + +Introduce callbacks used by the MT76 driver to configure NPU SoC +interrupts. This is a preliminary patch to enable wlan flowtable +offload for EN7581 SoC with MT76 driver. + +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250811-airoha-en7581-wlan-offlaod-v7-4-58823603bb4e@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_npu.c | 27 ++++++++++++++++++++++++ + drivers/net/ethernet/airoha/airoha_npu.h | 4 ++++ + 2 files changed, 31 insertions(+) + +--- a/drivers/net/ethernet/airoha/airoha_npu.c ++++ b/drivers/net/ethernet/airoha/airoha_npu.c +@@ -520,6 +520,29 @@ static u32 airoha_npu_wlan_queue_addr_ge + return REG_RX_BASE(qid); + } + ++static void airoha_npu_wlan_irq_status_set(struct airoha_npu *npu, u32 val) ++{ ++ regmap_write(npu->regmap, REG_IRQ_STATUS, val); ++} ++ ++static u32 airoha_npu_wlan_irq_status_get(struct airoha_npu *npu, int q) ++{ ++ u32 val; ++ ++ regmap_read(npu->regmap, REG_IRQ_STATUS, &val); ++ return val; ++} ++ ++static void airoha_npu_wlan_irq_enable(struct airoha_npu *npu, int q) ++{ ++ regmap_set_bits(npu->regmap, REG_IRQ_RXDONE(q), NPU_IRQ_RX_MASK(q)); ++} ++ ++static void airoha_npu_wlan_irq_disable(struct airoha_npu *npu, int q) ++{ ++ regmap_clear_bits(npu->regmap, REG_IRQ_RXDONE(q), NPU_IRQ_RX_MASK(q)); ++} ++ + struct airoha_npu *airoha_npu_get(struct device *dev, dma_addr_t *stats_addr) + { + struct platform_device *pdev; +@@ -627,6 +650,10 @@ static int airoha_npu_probe(struct platf + npu->ops.wlan_send_msg = airoha_npu_wlan_msg_send; + npu->ops.wlan_get_msg = airoha_npu_wlan_msg_get; + npu->ops.wlan_get_queue_addr = airoha_npu_wlan_queue_addr_get; ++ npu->ops.wlan_set_irq_status = airoha_npu_wlan_irq_status_set; ++ npu->ops.wlan_get_irq_status = airoha_npu_wlan_irq_status_get; ++ npu->ops.wlan_enable_irq = airoha_npu_wlan_irq_enable; ++ npu->ops.wlan_disable_irq = airoha_npu_wlan_irq_disable; + + npu->regmap = devm_regmap_init_mmio(dev, base, ®map_config); + if (IS_ERR(npu->regmap)) +--- a/drivers/net/ethernet/airoha/airoha_npu.h ++++ b/drivers/net/ethernet/airoha/airoha_npu.h +@@ -89,6 +89,10 @@ struct airoha_npu { + void *data, int data_len, gfp_t gfp); + u32 (*wlan_get_queue_addr)(struct airoha_npu *npu, int qid, + bool xmit); ++ void (*wlan_set_irq_status)(struct airoha_npu *npu, u32 val); ++ u32 (*wlan_get_irq_status)(struct airoha_npu *npu, int q); ++ void (*wlan_enable_irq)(struct airoha_npu *npu, int q); ++ void (*wlan_disable_irq)(struct airoha_npu *npu, int q); + } ops; + }; + diff --git a/lede/target/linux/airoha/patches-6.12/084-04-v6.18-net-airoha-npu-Read-NPU-wlan-interrupt-lines-from-th.patch b/lede/target/linux/airoha/patches-6.12/084-04-v6.18-net-airoha-npu-Read-NPU-wlan-interrupt-lines-from-th.patch new file mode 100644 index 0000000000..234dc8b99a --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/084-04-v6.18-net-airoha-npu-Read-NPU-wlan-interrupt-lines-from-th.patch @@ -0,0 +1,58 @@ +From a1740b16c83729d908c760eaa821f27b51e58a13 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 11 Aug 2025 17:31:40 +0200 +Subject: [PATCH 4/6] net: airoha: npu: Read NPU wlan interrupt lines from the + DTS + +Read all NPU wlan IRQ lines from the NPU device-tree node. +NPU module fires wlan irq lines when the traffic to/from the WiFi NIC is +not hw accelerated (these interrupts will be consumed by the MT76 driver +in subsequent patches). +This is a preliminary patch to enable wlan flowtable offload for EN7581 +SoC. + +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250811-airoha-en7581-wlan-offlaod-v7-5-58823603bb4e@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_npu.c | 9 +++++++++ + drivers/net/ethernet/airoha/airoha_npu.h | 3 +++ + 2 files changed, 12 insertions(+) + +--- a/drivers/net/ethernet/airoha/airoha_npu.c ++++ b/drivers/net/ethernet/airoha/airoha_npu.c +@@ -696,6 +696,15 @@ static int airoha_npu_probe(struct platf + INIT_WORK(&core->wdt_work, airoha_npu_wdt_work); + } + ++ /* wlan IRQ lines */ ++ for (i = 0; i < ARRAY_SIZE(npu->irqs); i++) { ++ irq = platform_get_irq(pdev, i + ARRAY_SIZE(npu->cores) + 1); ++ if (irq < 0) ++ return irq; ++ ++ npu->irqs[i] = irq; ++ } ++ + err = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); + if (err) + return err; +--- a/drivers/net/ethernet/airoha/airoha_npu.h ++++ b/drivers/net/ethernet/airoha/airoha_npu.h +@@ -5,6 +5,7 @@ + */ + + #define NPU_NUM_CORES 8 ++#define NPU_NUM_IRQ 6 + + enum airoha_npu_wlan_set_cmd { + WLAN_FUNC_SET_WAIT_PCIE_ADDR, +@@ -68,6 +69,8 @@ struct airoha_npu { + struct work_struct wdt_work; + } cores[NPU_NUM_CORES]; + ++ int irqs[NPU_NUM_IRQ]; ++ + struct airoha_foe_stats __iomem *stats; + + struct { diff --git a/lede/target/linux/airoha/patches-6.12/084-05-v6.18-net-airoha-npu-Enable-core-3-for-WiFi-offloading.patch b/lede/target/linux/airoha/patches-6.12/084-05-v6.18-net-airoha-npu-Enable-core-3-for-WiFi-offloading.patch new file mode 100644 index 0000000000..c285af23c3 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/084-05-v6.18-net-airoha-npu-Enable-core-3-for-WiFi-offloading.patch @@ -0,0 +1,28 @@ +From 29c4a3ce508961a02d185ead2d52699b16d82c6d Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 11 Aug 2025 17:31:41 +0200 +Subject: [PATCH 5/6] net: airoha: npu: Enable core 3 for WiFi offloading + +NPU core 3 is responsible for WiFi offloading so enable it during NPU +probe. + +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250811-airoha-en7581-wlan-offlaod-v7-6-58823603bb4e@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_npu.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_npu.c ++++ b/drivers/net/ethernet/airoha/airoha_npu.c +@@ -726,8 +726,7 @@ static int airoha_npu_probe(struct platf + usleep_range(1000, 2000); + + /* enable NPU cores */ +- /* do not start core3 since it is used for WiFi offloading */ +- regmap_write(npu->regmap, REG_CR_BOOT_CONFIG, 0xf7); ++ regmap_write(npu->regmap, REG_CR_BOOT_CONFIG, 0xff); + regmap_write(npu->regmap, REG_CR_BOOT_TRIGGER, 0x1); + msleep(100); + diff --git a/lede/target/linux/airoha/patches-6.12/084-06-v6.18-net-airoha-Add-airoha_offload.h-header.patch b/lede/target/linux/airoha/patches-6.12/084-06-v6.18-net-airoha-Add-airoha_offload.h-header.patch new file mode 100644 index 0000000000..ef98c85c36 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/084-06-v6.18-net-airoha-Add-airoha_offload.h-header.patch @@ -0,0 +1,416 @@ +From b3ef7bdec66fb1813e865fd39d179a93cefd2015 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 11 Aug 2025 17:31:42 +0200 +Subject: [PATCH 6/6] net: airoha: Add airoha_offload.h header + +Move NPU definitions to airoha_offload.h in include/linux/soc/airoha/ in +order to allow the MT76 driver to access the callback definitions. + +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250811-airoha-en7581-wlan-offlaod-v7-7-58823603bb4e@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_npu.c | 2 +- + drivers/net/ethernet/airoha/airoha_npu.h | 103 --------- + drivers/net/ethernet/airoha/airoha_ppe.c | 2 +- + include/linux/soc/airoha/airoha_offload.h | 260 ++++++++++++++++++++++ + 4 files changed, 262 insertions(+), 105 deletions(-) + delete mode 100644 drivers/net/ethernet/airoha/airoha_npu.h + create mode 100644 include/linux/soc/airoha/airoha_offload.h + +--- a/drivers/net/ethernet/airoha/airoha_npu.c ++++ b/drivers/net/ethernet/airoha/airoha_npu.c +@@ -11,9 +11,9 @@ + #include + #include + #include ++#include + + #include "airoha_eth.h" +-#include "airoha_npu.h" + + #define NPU_EN7581_FIRMWARE_DATA "airoha/en7581_npu_data.bin" + #define NPU_EN7581_FIRMWARE_RV32 "airoha/en7581_npu_rv32.bin" +--- a/drivers/net/ethernet/airoha/airoha_npu.h ++++ /dev/null +@@ -1,103 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0-only */ +-/* +- * Copyright (c) 2025 AIROHA Inc +- * Author: Lorenzo Bianconi +- */ +- +-#define NPU_NUM_CORES 8 +-#define NPU_NUM_IRQ 6 +- +-enum airoha_npu_wlan_set_cmd { +- WLAN_FUNC_SET_WAIT_PCIE_ADDR, +- WLAN_FUNC_SET_WAIT_DESC, +- WLAN_FUNC_SET_WAIT_NPU_INIT_DONE, +- WLAN_FUNC_SET_WAIT_TRAN_TO_CPU, +- WLAN_FUNC_SET_WAIT_BA_WIN_SIZE, +- WLAN_FUNC_SET_WAIT_DRIVER_MODEL, +- WLAN_FUNC_SET_WAIT_DEL_STA, +- WLAN_FUNC_SET_WAIT_DRAM_BA_NODE_ADDR, +- WLAN_FUNC_SET_WAIT_PKT_BUF_ADDR, +- WLAN_FUNC_SET_WAIT_IS_TEST_NOBA, +- WLAN_FUNC_SET_WAIT_FLUSHONE_TIMEOUT, +- WLAN_FUNC_SET_WAIT_FLUSHALL_TIMEOUT, +- WLAN_FUNC_SET_WAIT_IS_FORCE_TO_CPU, +- WLAN_FUNC_SET_WAIT_PCIE_STATE, +- WLAN_FUNC_SET_WAIT_PCIE_PORT_TYPE, +- WLAN_FUNC_SET_WAIT_ERROR_RETRY_TIMES, +- WLAN_FUNC_SET_WAIT_BAR_INFO, +- WLAN_FUNC_SET_WAIT_FAST_FLAG, +- WLAN_FUNC_SET_WAIT_NPU_BAND0_ONCPU, +- WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR, +- WLAN_FUNC_SET_WAIT_TX_DESC_HW_BASE, +- WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE, +- WLAN_FUNC_SET_WAIT_RX_RING_FOR_TXDONE_HW_BASE, +- WLAN_FUNC_SET_WAIT_TX_PKT_BUF_ADDR, +- WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR, +- WLAN_FUNC_SET_WAIT_INODE_DEBUG_FLAG, +- WLAN_FUNC_SET_WAIT_INODE_HW_CFG_INFO, +- WLAN_FUNC_SET_WAIT_INODE_STOP_ACTION, +- WLAN_FUNC_SET_WAIT_INODE_PCIE_SWAP, +- WLAN_FUNC_SET_WAIT_RATELIMIT_CTRL, +- WLAN_FUNC_SET_WAIT_HWNAT_INIT, +- WLAN_FUNC_SET_WAIT_ARHT_CHIP_INFO, +- WLAN_FUNC_SET_WAIT_TX_BUF_CHECK_ADDR, +- WLAN_FUNC_SET_WAIT_TOKEN_ID_SIZE, +-}; +- +-enum airoha_npu_wlan_get_cmd { +- WLAN_FUNC_GET_WAIT_NPU_INFO, +- WLAN_FUNC_GET_WAIT_LAST_RATE, +- WLAN_FUNC_GET_WAIT_COUNTER, +- WLAN_FUNC_GET_WAIT_DBG_COUNTER, +- WLAN_FUNC_GET_WAIT_RXDESC_BASE, +- WLAN_FUNC_GET_WAIT_WCID_DBG_COUNTER, +- WLAN_FUNC_GET_WAIT_DMA_ADDR, +- WLAN_FUNC_GET_WAIT_RING_SIZE, +- WLAN_FUNC_GET_WAIT_NPU_SUPPORT_MAP, +- WLAN_FUNC_GET_WAIT_MDC_LOCK_ADDRESS, +- WLAN_FUNC_GET_WAIT_NPU_VERSION, +-}; +- +-struct airoha_npu { +- struct device *dev; +- struct regmap *regmap; +- +- struct airoha_npu_core { +- struct airoha_npu *npu; +- /* protect concurrent npu memory accesses */ +- spinlock_t lock; +- struct work_struct wdt_work; +- } cores[NPU_NUM_CORES]; +- +- int irqs[NPU_NUM_IRQ]; +- +- struct airoha_foe_stats __iomem *stats; +- +- struct { +- int (*ppe_init)(struct airoha_npu *npu); +- int (*ppe_deinit)(struct airoha_npu *npu); +- int (*ppe_flush_sram_entries)(struct airoha_npu *npu, +- dma_addr_t foe_addr, +- int sram_num_entries); +- int (*ppe_foe_commit_entry)(struct airoha_npu *npu, +- dma_addr_t foe_addr, +- u32 entry_size, u32 hash, +- bool ppe2); +- int (*wlan_init_reserved_memory)(struct airoha_npu *npu); +- int (*wlan_send_msg)(struct airoha_npu *npu, int ifindex, +- enum airoha_npu_wlan_set_cmd func_id, +- void *data, int data_len, gfp_t gfp); +- int (*wlan_get_msg)(struct airoha_npu *npu, int ifindex, +- enum airoha_npu_wlan_get_cmd func_id, +- void *data, int data_len, gfp_t gfp); +- u32 (*wlan_get_queue_addr)(struct airoha_npu *npu, int qid, +- bool xmit); +- void (*wlan_set_irq_status)(struct airoha_npu *npu, u32 val); +- u32 (*wlan_get_irq_status)(struct airoha_npu *npu, int q); +- void (*wlan_enable_irq)(struct airoha_npu *npu, int q); +- void (*wlan_disable_irq)(struct airoha_npu *npu, int q); +- } ops; +-}; +- +-struct airoha_npu *airoha_npu_get(struct device *dev, dma_addr_t *stats_addr); +-void airoha_npu_put(struct airoha_npu *npu); +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -7,10 +7,10 @@ + #include + #include + #include ++#include + #include + #include + +-#include "airoha_npu.h" + #include "airoha_regs.h" + #include "airoha_eth.h" + +--- /dev/null ++++ b/include/linux/soc/airoha/airoha_offload.h +@@ -0,0 +1,260 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (c) 2025 AIROHA Inc ++ * Author: Lorenzo Bianconi ++ */ ++#ifndef AIROHA_OFFLOAD_H ++#define AIROHA_OFFLOAD_H ++ ++#include ++#include ++ ++#define NPU_NUM_CORES 8 ++#define NPU_NUM_IRQ 6 ++#define NPU_RX0_DESC_NUM 512 ++#define NPU_RX1_DESC_NUM 512 ++ ++/* CTRL */ ++#define NPU_RX_DMA_DESC_LAST_MASK BIT(29) ++#define NPU_RX_DMA_DESC_LEN_MASK GENMASK(28, 15) ++#define NPU_RX_DMA_DESC_CUR_LEN_MASK GENMASK(14, 1) ++#define NPU_RX_DMA_DESC_DONE_MASK BIT(0) ++/* INFO */ ++#define NPU_RX_DMA_PKT_COUNT_MASK GENMASK(31, 28) ++#define NPU_RX_DMA_PKT_ID_MASK GENMASK(28, 26) ++#define NPU_RX_DMA_SRC_PORT_MASK GENMASK(25, 21) ++#define NPU_RX_DMA_CRSN_MASK GENMASK(20, 16) ++#define NPU_RX_DMA_FOE_ID_MASK GENMASK(15, 0) ++/* DATA */ ++#define NPU_RX_DMA_SID_MASK GENMASK(31, 16) ++#define NPU_RX_DMA_FRAG_TYPE_MASK GENMASK(15, 14) ++#define NPU_RX_DMA_PRIORITY_MASK GENMASK(13, 10) ++#define NPU_RX_DMA_RADIO_ID_MASK GENMASK(9, 6) ++#define NPU_RX_DMA_VAP_ID_MASK GENMASK(5, 2) ++#define NPU_RX_DMA_FRAME_TYPE_MASK GENMASK(1, 0) ++ ++struct airoha_npu_rx_dma_desc { ++ u32 ctrl; ++ u32 info; ++ u32 data; ++ u32 addr; ++ u64 rsv; ++} __packed; ++ ++/* CTRL */ ++#define NPU_TX_DMA_DESC_SCHED_MASK BIT(31) ++#define NPU_TX_DMA_DESC_LEN_MASK GENMASK(30, 18) ++#define NPU_TX_DMA_DESC_VEND_LEN_MASK GENMASK(17, 1) ++#define NPU_TX_DMA_DESC_DONE_MASK BIT(0) ++ ++#define NPU_TXWI_LEN 192 ++ ++struct airoha_npu_tx_dma_desc { ++ u32 ctrl; ++ u32 addr; ++ u64 rsv; ++ u8 txwi[NPU_TXWI_LEN]; ++} __packed; ++ ++enum airoha_npu_wlan_set_cmd { ++ WLAN_FUNC_SET_WAIT_PCIE_ADDR, ++ WLAN_FUNC_SET_WAIT_DESC, ++ WLAN_FUNC_SET_WAIT_NPU_INIT_DONE, ++ WLAN_FUNC_SET_WAIT_TRAN_TO_CPU, ++ WLAN_FUNC_SET_WAIT_BA_WIN_SIZE, ++ WLAN_FUNC_SET_WAIT_DRIVER_MODEL, ++ WLAN_FUNC_SET_WAIT_DEL_STA, ++ WLAN_FUNC_SET_WAIT_DRAM_BA_NODE_ADDR, ++ WLAN_FUNC_SET_WAIT_PKT_BUF_ADDR, ++ WLAN_FUNC_SET_WAIT_IS_TEST_NOBA, ++ WLAN_FUNC_SET_WAIT_FLUSHONE_TIMEOUT, ++ WLAN_FUNC_SET_WAIT_FLUSHALL_TIMEOUT, ++ WLAN_FUNC_SET_WAIT_IS_FORCE_TO_CPU, ++ WLAN_FUNC_SET_WAIT_PCIE_STATE, ++ WLAN_FUNC_SET_WAIT_PCIE_PORT_TYPE, ++ WLAN_FUNC_SET_WAIT_ERROR_RETRY_TIMES, ++ WLAN_FUNC_SET_WAIT_BAR_INFO, ++ WLAN_FUNC_SET_WAIT_FAST_FLAG, ++ WLAN_FUNC_SET_WAIT_NPU_BAND0_ONCPU, ++ WLAN_FUNC_SET_WAIT_TX_RING_PCIE_ADDR, ++ WLAN_FUNC_SET_WAIT_TX_DESC_HW_BASE, ++ WLAN_FUNC_SET_WAIT_TX_BUF_SPACE_HW_BASE, ++ WLAN_FUNC_SET_WAIT_RX_RING_FOR_TXDONE_HW_BASE, ++ WLAN_FUNC_SET_WAIT_TX_PKT_BUF_ADDR, ++ WLAN_FUNC_SET_WAIT_INODE_TXRX_REG_ADDR, ++ WLAN_FUNC_SET_WAIT_INODE_DEBUG_FLAG, ++ WLAN_FUNC_SET_WAIT_INODE_HW_CFG_INFO, ++ WLAN_FUNC_SET_WAIT_INODE_STOP_ACTION, ++ WLAN_FUNC_SET_WAIT_INODE_PCIE_SWAP, ++ WLAN_FUNC_SET_WAIT_RATELIMIT_CTRL, ++ WLAN_FUNC_SET_WAIT_HWNAT_INIT, ++ WLAN_FUNC_SET_WAIT_ARHT_CHIP_INFO, ++ WLAN_FUNC_SET_WAIT_TX_BUF_CHECK_ADDR, ++ WLAN_FUNC_SET_WAIT_TOKEN_ID_SIZE, ++}; ++ ++enum airoha_npu_wlan_get_cmd { ++ WLAN_FUNC_GET_WAIT_NPU_INFO, ++ WLAN_FUNC_GET_WAIT_LAST_RATE, ++ WLAN_FUNC_GET_WAIT_COUNTER, ++ WLAN_FUNC_GET_WAIT_DBG_COUNTER, ++ WLAN_FUNC_GET_WAIT_RXDESC_BASE, ++ WLAN_FUNC_GET_WAIT_WCID_DBG_COUNTER, ++ WLAN_FUNC_GET_WAIT_DMA_ADDR, ++ WLAN_FUNC_GET_WAIT_RING_SIZE, ++ WLAN_FUNC_GET_WAIT_NPU_SUPPORT_MAP, ++ WLAN_FUNC_GET_WAIT_MDC_LOCK_ADDRESS, ++ WLAN_FUNC_GET_WAIT_NPU_VERSION, ++}; ++ ++struct airoha_npu { ++#if (IS_BUILTIN(CONFIG_NET_AIROHA_NPU) || IS_MODULE(CONFIG_NET_AIROHA_NPU)) ++ struct device *dev; ++ struct regmap *regmap; ++ ++ struct airoha_npu_core { ++ struct airoha_npu *npu; ++ /* protect concurrent npu memory accesses */ ++ spinlock_t lock; ++ struct work_struct wdt_work; ++ } cores[NPU_NUM_CORES]; ++ ++ int irqs[NPU_NUM_IRQ]; ++ ++ struct airoha_foe_stats __iomem *stats; ++ ++ struct { ++ int (*ppe_init)(struct airoha_npu *npu); ++ int (*ppe_deinit)(struct airoha_npu *npu); ++ int (*ppe_flush_sram_entries)(struct airoha_npu *npu, ++ dma_addr_t foe_addr, ++ int sram_num_entries); ++ int (*ppe_foe_commit_entry)(struct airoha_npu *npu, ++ dma_addr_t foe_addr, ++ u32 entry_size, u32 hash, ++ bool ppe2); ++ int (*wlan_init_reserved_memory)(struct airoha_npu *npu); ++ int (*wlan_send_msg)(struct airoha_npu *npu, int ifindex, ++ enum airoha_npu_wlan_set_cmd func_id, ++ void *data, int data_len, gfp_t gfp); ++ int (*wlan_get_msg)(struct airoha_npu *npu, int ifindex, ++ enum airoha_npu_wlan_get_cmd func_id, ++ void *data, int data_len, gfp_t gfp); ++ u32 (*wlan_get_queue_addr)(struct airoha_npu *npu, int qid, ++ bool xmit); ++ void (*wlan_set_irq_status)(struct airoha_npu *npu, u32 val); ++ u32 (*wlan_get_irq_status)(struct airoha_npu *npu, int q); ++ void (*wlan_enable_irq)(struct airoha_npu *npu, int q); ++ void (*wlan_disable_irq)(struct airoha_npu *npu, int q); ++ } ops; ++#endif ++}; ++ ++#if (IS_BUILTIN(CONFIG_NET_AIROHA_NPU) || IS_MODULE(CONFIG_NET_AIROHA_NPU)) ++struct airoha_npu *airoha_npu_get(struct device *dev, dma_addr_t *stats_addr); ++void airoha_npu_put(struct airoha_npu *npu); ++ ++static inline int airoha_npu_wlan_init_reserved_memory(struct airoha_npu *npu) ++{ ++ return npu->ops.wlan_init_reserved_memory(npu); ++} ++ ++static inline int airoha_npu_wlan_send_msg(struct airoha_npu *npu, ++ int ifindex, ++ enum airoha_npu_wlan_set_cmd cmd, ++ void *data, int data_len, gfp_t gfp) ++{ ++ return npu->ops.wlan_send_msg(npu, ifindex, cmd, data, data_len, gfp); ++} ++ ++static inline int airoha_npu_wlan_get_msg(struct airoha_npu *npu, int ifindex, ++ enum airoha_npu_wlan_get_cmd cmd, ++ void *data, int data_len, gfp_t gfp) ++{ ++ return npu->ops.wlan_get_msg(npu, ifindex, cmd, data, data_len, gfp); ++} ++ ++static inline u32 airoha_npu_wlan_get_queue_addr(struct airoha_npu *npu, ++ int qid, bool xmit) ++{ ++ return npu->ops.wlan_get_queue_addr(npu, qid, xmit); ++} ++ ++static inline void airoha_npu_wlan_set_irq_status(struct airoha_npu *npu, ++ u32 val) ++{ ++ npu->ops.wlan_set_irq_status(npu, val); ++} ++ ++static inline u32 airoha_npu_wlan_get_irq_status(struct airoha_npu *npu, int q) ++{ ++ return npu->ops.wlan_get_irq_status(npu, q); ++} ++ ++static inline void airoha_npu_wlan_enable_irq(struct airoha_npu *npu, int q) ++{ ++ npu->ops.wlan_enable_irq(npu, q); ++} ++ ++static inline void airoha_npu_wlan_disable_irq(struct airoha_npu *npu, int q) ++{ ++ npu->ops.wlan_disable_irq(npu, q); ++} ++#else ++static inline struct airoha_npu *airoha_npu_get(struct device *dev, ++ dma_addr_t *foe_stats_addr) ++{ ++ return NULL; ++} ++ ++static inline void airoha_npu_put(struct airoha_npu *npu) ++{ ++} ++ ++static inline int airoha_npu_wlan_init_reserved_memory(struct airoha_npu *npu) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static inline int airoha_npu_wlan_send_msg(struct airoha_npu *npu, ++ int ifindex, ++ enum airoha_npu_wlan_set_cmd cmd, ++ void *data, int data_len, gfp_t gfp) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static inline int airoha_npu_wlan_get_msg(struct airoha_npu *npu, int ifindex, ++ enum airoha_npu_wlan_get_cmd cmd, ++ void *data, int data_len, gfp_t gfp) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static inline u32 airoha_npu_wlan_get_queue_addr(struct airoha_npu *npu, ++ int qid, bool xmit) ++{ ++ return 0; ++} ++ ++static inline void airoha_npu_wlan_set_irq_status(struct airoha_npu *npu, ++ u32 val) ++{ ++} ++ ++static inline u32 airoha_npu_wlan_get_irq_status(struct airoha_npu *npu, ++ int q) ++{ ++ return 0; ++} ++ ++static inline void airoha_npu_wlan_enable_irq(struct airoha_npu *npu, int q) ++{ ++} ++ ++static inline void airoha_npu_wlan_disable_irq(struct airoha_npu *npu, int q) ++{ ++} ++#endif ++ ++#endif /* AIROHA_OFFLOAD_H */ diff --git a/lede/target/linux/airoha/patches-6.12/085-v6.18-net-airoha-Add-wlan-flowtable-TX-offload.patch b/lede/target/linux/airoha/patches-6.12/085-v6.18-net-airoha-Add-wlan-flowtable-TX-offload.patch new file mode 100644 index 0000000000..ab9a3761a5 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/085-v6.18-net-airoha-Add-wlan-flowtable-TX-offload.patch @@ -0,0 +1,198 @@ +From a8bdd935d1ddb7186358fb60ffe84253e85340c8 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Thu, 14 Aug 2025 09:51:16 +0200 +Subject: [PATCH] net: airoha: Add wlan flowtable TX offload + +Introduce support to offload the traffic received on the ethernet NIC +and forwarded to the wireless one using HW Packet Processor Engine (PPE) +capabilities. + +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250814-airoha-en7581-wlan-tx-offload-v1-1-72e0a312003e@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.h | 11 +++ + drivers/net/ethernet/airoha/airoha_ppe.c | 103 ++++++++++++++++------- + 2 files changed, 85 insertions(+), 29 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -252,6 +252,10 @@ enum { + #define AIROHA_FOE_MAC_SMAC_ID GENMASK(20, 16) + #define AIROHA_FOE_MAC_PPPOE_ID GENMASK(15, 0) + ++#define AIROHA_FOE_MAC_WDMA_QOS GENMASK(15, 12) ++#define AIROHA_FOE_MAC_WDMA_BAND BIT(11) ++#define AIROHA_FOE_MAC_WDMA_WCID GENMASK(10, 0) ++ + struct airoha_foe_mac_info_common { + u16 vlan1; + u16 etype; +@@ -481,6 +485,13 @@ struct airoha_flow_table_entry { + unsigned long cookie; + }; + ++struct airoha_wdma_info { ++ u8 idx; ++ u8 queue; ++ u16 wcid; ++ u8 bss; ++}; ++ + /* RX queue to IRQ mapping: BIT(q) in IRQ(n) */ + #define RX_IRQ0_BANK_PIN_MASK 0x839f + #define RX_IRQ1_BANK_PIN_MASK 0x7fe00000 +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -190,6 +190,31 @@ static int airoha_ppe_flow_mangle_ipv4(c + return 0; + } + ++static int airoha_ppe_get_wdma_info(struct net_device *dev, const u8 *addr, ++ struct airoha_wdma_info *info) ++{ ++ struct net_device_path_stack stack; ++ struct net_device_path *path; ++ int err; ++ ++ if (!dev) ++ return -ENODEV; ++ ++ err = dev_fill_forward_path(dev, addr, &stack); ++ if (err) ++ return err; ++ ++ path = &stack.path[stack.num_paths - 1]; ++ if (path->type != DEV_PATH_MTK_WDMA) ++ return -1; ++ ++ info->idx = path->mtk_wdma.wdma_idx; ++ info->bss = path->mtk_wdma.bss; ++ info->wcid = path->mtk_wdma.wcid; ++ ++ return 0; ++} ++ + static int airoha_get_dsa_port(struct net_device **dev) + { + #if IS_ENABLED(CONFIG_NET_DSA) +@@ -220,9 +245,9 @@ static int airoha_ppe_foe_entry_prepare( + struct airoha_flow_data *data, + int l4proto) + { +- int dsa_port = airoha_get_dsa_port(&dev); ++ u32 qdata = FIELD_PREP(AIROHA_FOE_SHAPER_ID, 0x7f), ports_pad, val; ++ int wlan_etype = -EINVAL, dsa_port = airoha_get_dsa_port(&dev); + struct airoha_foe_mac_info_common *l2; +- u32 qdata, ports_pad, val; + u8 smac_id = 0xf; + + memset(hwe, 0, sizeof(*hwe)); +@@ -236,31 +261,47 @@ static int airoha_ppe_foe_entry_prepare( + AIROHA_FOE_IB1_BIND_TTL; + hwe->ib1 = val; + +- val = FIELD_PREP(AIROHA_FOE_IB2_PORT_AG, 0x1f) | +- AIROHA_FOE_IB2_PSE_QOS; +- if (dsa_port >= 0) +- val |= FIELD_PREP(AIROHA_FOE_IB2_NBQ, dsa_port); +- ++ val = FIELD_PREP(AIROHA_FOE_IB2_PORT_AG, 0x1f); + if (dev) { +- struct airoha_gdm_port *port = netdev_priv(dev); +- u8 pse_port; +- +- if (!airoha_is_valid_gdm_port(eth, port)) +- return -EINVAL; ++ struct airoha_wdma_info info = {}; + +- if (dsa_port >= 0) +- pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id; +- else +- pse_port = 2; /* uplink relies on GDM2 loopback */ +- val |= FIELD_PREP(AIROHA_FOE_IB2_PSE_PORT, pse_port); +- +- /* For downlink traffic consume SRAM memory for hw forwarding +- * descriptors queue. +- */ +- if (airhoa_is_lan_gdm_port(port)) +- val |= AIROHA_FOE_IB2_FAST_PATH; ++ if (!airoha_ppe_get_wdma_info(dev, data->eth.h_dest, &info)) { ++ val |= FIELD_PREP(AIROHA_FOE_IB2_NBQ, info.idx) | ++ FIELD_PREP(AIROHA_FOE_IB2_PSE_PORT, ++ FE_PSE_PORT_CDM4); ++ qdata |= FIELD_PREP(AIROHA_FOE_ACTDP, info.bss); ++ wlan_etype = FIELD_PREP(AIROHA_FOE_MAC_WDMA_BAND, ++ info.idx) | ++ FIELD_PREP(AIROHA_FOE_MAC_WDMA_WCID, ++ info.wcid); ++ } else { ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ u8 pse_port; ++ ++ if (!airoha_is_valid_gdm_port(eth, port)) ++ return -EINVAL; ++ ++ if (dsa_port >= 0) ++ pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 ++ : port->id; ++ else ++ pse_port = 2; /* uplink relies on GDM2 ++ * loopback ++ */ ++ ++ val |= FIELD_PREP(AIROHA_FOE_IB2_PSE_PORT, pse_port) | ++ AIROHA_FOE_IB2_PSE_QOS; ++ /* For downlink traffic consume SRAM memory for hw ++ * forwarding descriptors queue. ++ */ ++ if (airhoa_is_lan_gdm_port(port)) ++ val |= AIROHA_FOE_IB2_FAST_PATH; ++ if (dsa_port >= 0) ++ val |= FIELD_PREP(AIROHA_FOE_IB2_NBQ, ++ dsa_port); + +- smac_id = port->id; ++ smac_id = port->id; ++ } + } + + if (is_multicast_ether_addr(data->eth.h_dest)) +@@ -272,7 +313,6 @@ static int airoha_ppe_foe_entry_prepare( + if (type == PPE_PKT_TYPE_IPV6_ROUTE_3T) + hwe->ipv6.ports = ports_pad; + +- qdata = FIELD_PREP(AIROHA_FOE_SHAPER_ID, 0x7f); + if (type == PPE_PKT_TYPE_BRIDGE) { + airoha_ppe_foe_set_bridge_addrs(&hwe->bridge, &data->eth); + hwe->bridge.data = qdata; +@@ -313,7 +353,9 @@ static int airoha_ppe_foe_entry_prepare( + l2->vlan2 = data->vlan.hdr[1].id; + } + +- if (dsa_port >= 0) { ++ if (wlan_etype >= 0) { ++ l2->etype = wlan_etype; ++ } else if (dsa_port >= 0) { + l2->etype = BIT(dsa_port); + l2->etype |= !data->vlan.num ? BIT(15) : 0; + } else if (data->pppoe.num) { +@@ -490,6 +532,10 @@ static void airoha_ppe_foe_flow_stats_up + meter = &hwe->ipv4.l2.meter; + } + ++ pse_port = FIELD_GET(AIROHA_FOE_IB2_PSE_PORT, *ib2); ++ if (pse_port == FE_PSE_PORT_CDM4) ++ return; ++ + airoha_ppe_foe_flow_stat_entry_reset(ppe, npu, index); + + val = FIELD_GET(AIROHA_FOE_CHANNEL | AIROHA_FOE_QID, *data); +@@ -500,7 +546,6 @@ static void airoha_ppe_foe_flow_stats_up + AIROHA_FOE_IB2_PSE_QOS | AIROHA_FOE_IB2_FAST_PATH); + *meter |= FIELD_PREP(AIROHA_FOE_TUNNEL_MTU, val); + +- pse_port = FIELD_GET(AIROHA_FOE_IB2_PSE_PORT, *ib2); + nbq = pse_port == 1 ? 6 : 5; + *ib2 &= ~(AIROHA_FOE_IB2_NBQ | AIROHA_FOE_IB2_PSE_PORT | + AIROHA_FOE_IB2_PSE_QOS); diff --git a/lede/target/linux/airoha/patches-6.12/086-01-v6.18-net-airoha-Rely-on-airoha_eth-struct-in-airoha_ppe_f.patch b/lede/target/linux/airoha/patches-6.12/086-01-v6.18-net-airoha-Rely-on-airoha_eth-struct-in-airoha_ppe_f.patch new file mode 100644 index 0000000000..cef2922869 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/086-01-v6.18-net-airoha-Rely-on-airoha_eth-struct-in-airoha_ppe_f.patch @@ -0,0 +1,95 @@ +From 524a43c3a0c17fa0a1223eea36751dcba55e5530 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Sat, 23 Aug 2025 09:56:02 +0200 +Subject: [PATCH 1/3] net: airoha: Rely on airoha_eth struct in + airoha_ppe_flow_offload_cmd signature + +Rely on airoha_eth struct in airoha_ppe_flow_offload_cmd routine +signature and in all the called subroutines. +This is a preliminary patch to introduce flowtable offload for traffic +received by the wlan NIC and forwarded to the ethernet one. + +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250823-airoha-en7581-wlan-rx-offload-v3-1-f78600ec3ed8@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 20 ++++++++------------ + 1 file changed, 8 insertions(+), 12 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -935,11 +935,10 @@ static int airoha_ppe_entry_idle_time(st + return airoha_ppe_get_entry_idle_time(ppe, e->data.ib1); + } + +-static int airoha_ppe_flow_offload_replace(struct airoha_gdm_port *port, ++static int airoha_ppe_flow_offload_replace(struct airoha_eth *eth, + struct flow_cls_offload *f) + { + struct flow_rule *rule = flow_cls_offload_flow_rule(f); +- struct airoha_eth *eth = port->qdma->eth; + struct airoha_flow_table_entry *e; + struct airoha_flow_data data = {}; + struct net_device *odev = NULL; +@@ -1136,10 +1135,9 @@ free_entry: + return err; + } + +-static int airoha_ppe_flow_offload_destroy(struct airoha_gdm_port *port, ++static int airoha_ppe_flow_offload_destroy(struct airoha_eth *eth, + struct flow_cls_offload *f) + { +- struct airoha_eth *eth = port->qdma->eth; + struct airoha_flow_table_entry *e; + + e = rhashtable_lookup(ð->flow_table, &f->cookie, +@@ -1182,10 +1180,9 @@ void airoha_ppe_foe_entry_get_stats(stru + rcu_read_unlock(); + } + +-static int airoha_ppe_flow_offload_stats(struct airoha_gdm_port *port, ++static int airoha_ppe_flow_offload_stats(struct airoha_eth *eth, + struct flow_cls_offload *f) + { +- struct airoha_eth *eth = port->qdma->eth; + struct airoha_flow_table_entry *e; + u32 idle; + +@@ -1209,16 +1206,16 @@ static int airoha_ppe_flow_offload_stats + return 0; + } + +-static int airoha_ppe_flow_offload_cmd(struct airoha_gdm_port *port, ++static int airoha_ppe_flow_offload_cmd(struct airoha_eth *eth, + struct flow_cls_offload *f) + { + switch (f->command) { + case FLOW_CLS_REPLACE: +- return airoha_ppe_flow_offload_replace(port, f); ++ return airoha_ppe_flow_offload_replace(eth, f); + case FLOW_CLS_DESTROY: +- return airoha_ppe_flow_offload_destroy(port, f); ++ return airoha_ppe_flow_offload_destroy(eth, f); + case FLOW_CLS_STATS: +- return airoha_ppe_flow_offload_stats(port, f); ++ return airoha_ppe_flow_offload_stats(eth, f); + default: + break; + } +@@ -1288,7 +1285,6 @@ error_npu_put: + int airoha_ppe_setup_tc_block_cb(struct net_device *dev, void *type_data) + { + struct airoha_gdm_port *port = netdev_priv(dev); +- struct flow_cls_offload *cls = type_data; + struct airoha_eth *eth = port->qdma->eth; + int err = 0; + +@@ -1297,7 +1293,7 @@ int airoha_ppe_setup_tc_block_cb(struct + if (!eth->npu) + err = airoha_ppe_offload_setup(eth); + if (!err) +- err = airoha_ppe_flow_offload_cmd(port, cls); ++ err = airoha_ppe_flow_offload_cmd(eth, type_data); + + mutex_unlock(&flow_offload_mutex); + diff --git a/lede/target/linux/airoha/patches-6.12/086-02-v6.18-net-airoha-Add-airoha_ppe_dev-struct-definition.patch b/lede/target/linux/airoha/patches-6.12/086-02-v6.18-net-airoha-Add-airoha_ppe_dev-struct-definition.patch new file mode 100644 index 0000000000..fd76fc25f5 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/086-02-v6.18-net-airoha-Add-airoha_ppe_dev-struct-definition.patch @@ -0,0 +1,223 @@ +From f45fc18b6de04483643e8aa2ab97737abfe03d59 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Sat, 23 Aug 2025 09:56:03 +0200 +Subject: [PATCH 2/3] net: airoha: Add airoha_ppe_dev struct definition + +Introduce airoha_ppe_dev struct as container for PPE offload callbacks +consumed by the MT76 driver during flowtable offload for traffic +received by the wlan NIC and forwarded to the wired one. +Add airoha_ppe_setup_tc_block_cb routine to PPE offload ops for MT76 +driver. +Rely on airoha_ppe_dev pointer in airoha_ppe_setup_tc_block_cb +signature. + +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250823-airoha-en7581-wlan-rx-offload-v3-2-f78600ec3ed8@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 4 +- + drivers/net/ethernet/airoha/airoha_eth.h | 4 +- + drivers/net/ethernet/airoha/airoha_npu.c | 1 - + drivers/net/ethernet/airoha/airoha_ppe.c | 67 +++++++++++++++++++++-- + include/linux/soc/airoha/airoha_offload.h | 35 ++++++++++++ + 5 files changed, 104 insertions(+), 7 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2601,13 +2601,15 @@ static int airoha_dev_setup_tc_block_cb( + void *type_data, void *cb_priv) + { + struct net_device *dev = cb_priv; ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ struct airoha_eth *eth = port->qdma->eth; + + if (!tc_can_offload(dev)) + return -EOPNOTSUPP; + + switch (type) { + case TC_SETUP_CLSFLOWER: +- return airoha_ppe_setup_tc_block_cb(dev, type_data); ++ return airoha_ppe_setup_tc_block_cb(ð->ppe->dev, type_data); + case TC_SETUP_CLSMATCHALL: + return airoha_dev_tc_matchall(dev, type_data); + default: +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + + #define AIROHA_MAX_NUM_GDM_PORTS 4 +@@ -546,6 +547,7 @@ struct airoha_gdm_port { + #define AIROHA_RXD4_FOE_ENTRY GENMASK(15, 0) + + struct airoha_ppe { ++ struct airoha_ppe_dev dev; + struct airoha_eth *eth; + + void *foe; +@@ -622,7 +624,7 @@ bool airoha_is_valid_gdm_port(struct air + + void airoha_ppe_check_skb(struct airoha_ppe *ppe, struct sk_buff *skb, + u16 hash); +-int airoha_ppe_setup_tc_block_cb(struct net_device *dev, void *type_data); ++int airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev *dev, void *type_data); + int airoha_ppe_init(struct airoha_eth *eth); + void airoha_ppe_deinit(struct airoha_eth *eth); + void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port); +--- a/drivers/net/ethernet/airoha/airoha_npu.c ++++ b/drivers/net/ethernet/airoha/airoha_npu.c +@@ -11,7 +11,6 @@ + #include + #include + #include +-#include + + #include "airoha_eth.h" + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -6,8 +6,9 @@ + + #include + #include ++#include ++#include + #include +-#include + #include + #include + +@@ -1282,10 +1283,10 @@ error_npu_put: + return err; + } + +-int airoha_ppe_setup_tc_block_cb(struct net_device *dev, void *type_data) ++int airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev *dev, void *type_data) + { +- struct airoha_gdm_port *port = netdev_priv(dev); +- struct airoha_eth *eth = port->qdma->eth; ++ struct airoha_ppe *ppe = dev->priv; ++ struct airoha_eth *eth = ppe->eth; + int err = 0; + + mutex_lock(&flow_offload_mutex); +@@ -1338,6 +1339,61 @@ void airoha_ppe_init_upd_mem(struct airo + PPE_UPDMEM_WR_MASK | PPE_UPDMEM_REQ_MASK); + } + ++struct airoha_ppe_dev *airoha_ppe_get_dev(struct device *dev) ++{ ++ struct platform_device *pdev; ++ struct device_node *np; ++ struct airoha_eth *eth; ++ ++ np = of_parse_phandle(dev->of_node, "airoha,eth", 0); ++ if (!np) ++ return ERR_PTR(-ENODEV); ++ ++ pdev = of_find_device_by_node(np); ++ if (!pdev) { ++ dev_err(dev, "cannot find device node %s\n", np->name); ++ of_node_put(np); ++ return ERR_PTR(-ENODEV); ++ } ++ of_node_put(np); ++ ++ if (!try_module_get(THIS_MODULE)) { ++ dev_err(dev, "failed to get the device driver module\n"); ++ goto error_pdev_put; ++ } ++ ++ eth = platform_get_drvdata(pdev); ++ if (!eth) ++ goto error_module_put; ++ ++ if (!device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER)) { ++ dev_err(&pdev->dev, ++ "failed to create device link to consumer %s\n", ++ dev_name(dev)); ++ goto error_module_put; ++ } ++ ++ return ð->ppe->dev; ++ ++error_module_put: ++ module_put(THIS_MODULE); ++error_pdev_put: ++ platform_device_put(pdev); ++ ++ return ERR_PTR(-ENODEV); ++} ++EXPORT_SYMBOL_GPL(airoha_ppe_get_dev); ++ ++void airoha_ppe_put_dev(struct airoha_ppe_dev *dev) ++{ ++ struct airoha_ppe *ppe = dev->priv; ++ struct airoha_eth *eth = ppe->eth; ++ ++ module_put(THIS_MODULE); ++ put_device(eth->dev); ++} ++EXPORT_SYMBOL_GPL(airoha_ppe_put_dev); ++ + int airoha_ppe_init(struct airoha_eth *eth) + { + struct airoha_ppe *ppe; +@@ -1347,6 +1403,9 @@ int airoha_ppe_init(struct airoha_eth *e + if (!ppe) + return -ENOMEM; + ++ ppe->dev.ops.setup_tc_block_cb = airoha_ppe_setup_tc_block_cb; ++ ppe->dev.priv = ppe; ++ + foe_size = PPE_NUM_ENTRIES * sizeof(struct airoha_foe_entry); + ppe->foe = dmam_alloc_coherent(eth->dev, foe_size, &ppe->foe_dma, + GFP_KERNEL); +--- a/include/linux/soc/airoha/airoha_offload.h ++++ b/include/linux/soc/airoha/airoha_offload.h +@@ -9,6 +9,41 @@ + #include + #include + ++struct airoha_ppe_dev { ++ struct { ++ int (*setup_tc_block_cb)(struct airoha_ppe_dev *dev, ++ void *type_data); ++ } ops; ++ ++ void *priv; ++}; ++ ++#if (IS_BUILTIN(CONFIG_NET_AIROHA) || IS_MODULE(CONFIG_NET_AIROHA)) ++struct airoha_ppe_dev *airoha_ppe_get_dev(struct device *dev); ++void airoha_ppe_put_dev(struct airoha_ppe_dev *dev); ++ ++static inline int airoha_ppe_dev_setup_tc_block_cb(struct airoha_ppe_dev *dev, ++ void *type_data) ++{ ++ return dev->ops.setup_tc_block_cb(dev, type_data); ++} ++#else ++static inline struct airoha_ppe_dev *airoha_ppe_get_dev(struct device *dev) ++{ ++ return NULL; ++} ++ ++static inline void airoha_ppe_put_dev(struct airoha_ppe_dev *dev) ++{ ++} ++ ++static inline int airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev *dev, ++ void *type_data) ++{ ++ return -EOPNOTSUPP; ++} ++#endif ++ + #define NPU_NUM_CORES 8 + #define NPU_NUM_IRQ 6 + #define NPU_RX0_DESC_NUM 512 diff --git a/lede/target/linux/airoha/patches-6.12/086-03-v6.18-net-airoha-Introduce-check_skb-callback-in-ppe_dev-o.patch b/lede/target/linux/airoha/patches-6.12/086-03-v6.18-net-airoha-Introduce-check_skb-callback-in-ppe_dev-o.patch new file mode 100644 index 0000000000..1edc2aa54c --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/086-03-v6.18-net-airoha-Introduce-check_skb-callback-in-ppe_dev-o.patch @@ -0,0 +1,207 @@ +From a7cc1aa151e3a9c0314b995f06102f7763d3bd71 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Sat, 23 Aug 2025 09:56:04 +0200 +Subject: [PATCH 3/3] net: airoha: Introduce check_skb callback in ppe_dev ops + +Export airoha_ppe_check_skb routine in ppe_dev ops. check_skb callback +will be used by the MT76 driver in order to offload the traffic received +by the wlan NIC and forwarded to the ethernet one. +Add rx_wlan parameter to airoha_ppe_check_skb routine signature. + +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20250823-airoha-en7581-wlan-rx-offload-v3-3-f78600ec3ed8@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 3 ++- + drivers/net/ethernet/airoha/airoha_eth.h | 8 ++------ + drivers/net/ethernet/airoha/airoha_ppe.c | 25 +++++++++++++---------- + include/linux/soc/airoha/airoha_offload.h | 20 ++++++++++++++++++ + 4 files changed, 38 insertions(+), 18 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -703,7 +703,8 @@ static int airoha_qdma_rx_process(struct + + reason = FIELD_GET(AIROHA_RXD4_PPE_CPU_REASON, msg1); + if (reason == PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) +- airoha_ppe_check_skb(eth->ppe, q->skb, hash); ++ airoha_ppe_check_skb(ð->ppe->dev, q->skb, hash, ++ false); + + done++; + napi_gro_receive(&q->napi, q->skb); +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -230,10 +230,6 @@ struct airoha_hw_stats { + }; + + enum { +- PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED = 0x0f, +-}; +- +-enum { + AIROHA_FOE_STATE_INVALID, + AIROHA_FOE_STATE_UNBIND, + AIROHA_FOE_STATE_BIND, +@@ -622,8 +618,8 @@ static inline bool airhoa_is_lan_gdm_por + bool airoha_is_valid_gdm_port(struct airoha_eth *eth, + struct airoha_gdm_port *port); + +-void airoha_ppe_check_skb(struct airoha_ppe *ppe, struct sk_buff *skb, +- u16 hash); ++void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb, ++ u16 hash, bool rx_wlan); + int airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev *dev, void *type_data); + int airoha_ppe_init(struct airoha_eth *eth); + void airoha_ppe_deinit(struct airoha_eth *eth); +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -616,7 +616,7 @@ static bool airoha_ppe_foe_compare_entry + + static int airoha_ppe_foe_commit_entry(struct airoha_ppe *ppe, + struct airoha_foe_entry *e, +- u32 hash) ++ u32 hash, bool rx_wlan) + { + struct airoha_foe_entry *hwe = ppe->foe + hash * sizeof(*hwe); + u32 ts = airoha_ppe_get_timestamp(ppe); +@@ -639,7 +639,8 @@ static int airoha_ppe_foe_commit_entry(s + goto unlock; + } + +- airoha_ppe_foe_flow_stats_update(ppe, npu, hwe, hash); ++ if (!rx_wlan) ++ airoha_ppe_foe_flow_stats_update(ppe, npu, hwe, hash); + + if (hash < PPE_SRAM_NUM_ENTRIES) { + dma_addr_t addr = ppe->foe_dma + hash * sizeof(*hwe); +@@ -665,7 +666,7 @@ static void airoha_ppe_foe_remove_flow(s + e->data.ib1 &= ~AIROHA_FOE_IB1_BIND_STATE; + e->data.ib1 |= FIELD_PREP(AIROHA_FOE_IB1_BIND_STATE, + AIROHA_FOE_STATE_INVALID); +- airoha_ppe_foe_commit_entry(ppe, &e->data, e->hash); ++ airoha_ppe_foe_commit_entry(ppe, &e->data, e->hash, false); + e->hash = 0xffff; + } + if (e->type == FLOW_TYPE_L2_SUBFLOW) { +@@ -704,7 +705,7 @@ static void airoha_ppe_foe_flow_remove_e + static int + airoha_ppe_foe_commit_subflow_entry(struct airoha_ppe *ppe, + struct airoha_flow_table_entry *e, +- u32 hash) ++ u32 hash, bool rx_wlan) + { + u32 mask = AIROHA_FOE_IB1_BIND_PACKET_TYPE | AIROHA_FOE_IB1_BIND_UDP; + struct airoha_foe_entry *hwe_p, hwe; +@@ -745,14 +746,14 @@ airoha_ppe_foe_commit_subflow_entry(stru + } + + hwe.bridge.data = e->data.bridge.data; +- airoha_ppe_foe_commit_entry(ppe, &hwe, hash); ++ airoha_ppe_foe_commit_entry(ppe, &hwe, hash, rx_wlan); + + return 0; + } + + static void airoha_ppe_foe_insert_entry(struct airoha_ppe *ppe, + struct sk_buff *skb, +- u32 hash) ++ u32 hash, bool rx_wlan) + { + struct airoha_flow_table_entry *e; + struct airoha_foe_bridge br = {}; +@@ -785,7 +786,7 @@ static void airoha_ppe_foe_insert_entry( + if (!airoha_ppe_foe_compare_entry(e, hwe)) + continue; + +- airoha_ppe_foe_commit_entry(ppe, &e->data, hash); ++ airoha_ppe_foe_commit_entry(ppe, &e->data, hash, rx_wlan); + commit_done = true; + e->hash = hash; + } +@@ -797,7 +798,7 @@ static void airoha_ppe_foe_insert_entry( + e = rhashtable_lookup_fast(&ppe->l2_flows, &br, + airoha_l2_flow_table_params); + if (e) +- airoha_ppe_foe_commit_subflow_entry(ppe, e, hash); ++ airoha_ppe_foe_commit_subflow_entry(ppe, e, hash, rx_wlan); + unlock: + spin_unlock_bh(&ppe_lock); + } +@@ -1301,9 +1302,10 @@ int airoha_ppe_setup_tc_block_cb(struct + return err; + } + +-void airoha_ppe_check_skb(struct airoha_ppe *ppe, struct sk_buff *skb, +- u16 hash) ++void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb, ++ u16 hash, bool rx_wlan) + { ++ struct airoha_ppe *ppe = dev->priv; + u16 now, diff; + + if (hash > PPE_HASH_MASK) +@@ -1315,7 +1317,7 @@ void airoha_ppe_check_skb(struct airoha_ + return; + + ppe->foe_check_time[hash] = now; +- airoha_ppe_foe_insert_entry(ppe, skb, hash); ++ airoha_ppe_foe_insert_entry(ppe, skb, hash, rx_wlan); + } + + void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port) +@@ -1404,6 +1406,7 @@ int airoha_ppe_init(struct airoha_eth *e + return -ENOMEM; + + ppe->dev.ops.setup_tc_block_cb = airoha_ppe_setup_tc_block_cb; ++ ppe->dev.ops.check_skb = airoha_ppe_check_skb; + ppe->dev.priv = ppe; + + foe_size = PPE_NUM_ENTRIES * sizeof(struct airoha_foe_entry); +--- a/include/linux/soc/airoha/airoha_offload.h ++++ b/include/linux/soc/airoha/airoha_offload.h +@@ -9,10 +9,17 @@ + #include + #include + ++enum { ++ PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED = 0x0f, ++}; ++ + struct airoha_ppe_dev { + struct { + int (*setup_tc_block_cb)(struct airoha_ppe_dev *dev, + void *type_data); ++ void (*check_skb)(struct airoha_ppe_dev *dev, ++ struct sk_buff *skb, u16 hash, ++ bool rx_wlan); + } ops; + + void *priv; +@@ -27,6 +34,13 @@ static inline int airoha_ppe_dev_setup_t + { + return dev->ops.setup_tc_block_cb(dev, type_data); + } ++ ++static inline void airoha_ppe_dev_check_skb(struct airoha_ppe_dev *dev, ++ struct sk_buff *skb, ++ u16 hash, bool rx_wlan) ++{ ++ dev->ops.check_skb(dev, skb, hash, rx_wlan); ++} + #else + static inline struct airoha_ppe_dev *airoha_ppe_get_dev(struct device *dev) + { +@@ -42,6 +56,12 @@ static inline int airoha_ppe_setup_tc_bl + { + return -EOPNOTSUPP; + } ++ ++static inline void airoha_ppe_dev_check_skb(struct airoha_ppe_dev *dev, ++ struct sk_buff *skb, u16 hash, ++ bool rx_wlan) ++{ ++} + #endif + + #define NPU_NUM_CORES 8 diff --git a/lede/target/linux/airoha/patches-6.12/087-v6.17-pinctrl-airoha-Fix-return-value-in-pinconf-callbacks.patch b/lede/target/linux/airoha/patches-6.12/087-v6.17-pinctrl-airoha-Fix-return-value-in-pinconf-callbacks.patch new file mode 100644 index 0000000000..62390f8a6c --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/087-v6.17-pinctrl-airoha-Fix-return-value-in-pinconf-callbacks.patch @@ -0,0 +1,50 @@ +From 563fcd6475931c5c8c652a4dd548256314cc87ed Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 22 Aug 2025 14:14:18 +0200 +Subject: [PATCH] pinctrl: airoha: Fix return value in pinconf callbacks + +Pinctrl stack requires ENOTSUPP error code if the parameter is not +supported by the pinctrl driver. Fix the returned error code in pinconf +callbacks if the operation is not supported. + +Fixes: 1c8ace2d0725 ("pinctrl: airoha: Add support for EN7581 SoC") +Signed-off-by: Lorenzo Bianconi +Link: https://lore.kernel.org/20250822-airoha-pinconf-err-val-fix-v1-1-87b4f264ced2@kernel.org +Signed-off-by: Linus Walleij +--- + drivers/pinctrl/mediatek/pinctrl-airoha.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/pinctrl/mediatek/pinctrl-airoha.c ++++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c +@@ -2697,7 +2697,7 @@ static int airoha_pinconf_get(struct pin + arg = 1; + break; + default: +- return -EOPNOTSUPP; ++ return -ENOTSUPP; + } + + *config = pinconf_to_config_packed(param, arg); +@@ -2791,7 +2791,7 @@ static int airoha_pinconf_set(struct pin + break; + } + default: +- return -EOPNOTSUPP; ++ return -ENOTSUPP; + } + } + +@@ -2808,10 +2808,10 @@ static int airoha_pinconf_group_get(stru + if (airoha_pinconf_get(pctrl_dev, + airoha_pinctrl_groups[group].pins[i], + config)) +- return -EOPNOTSUPP; ++ return -ENOTSUPP; + + if (i && cur_config != *config) +- return -EOPNOTSUPP; ++ return -ENOTSUPP; + + cur_config = *config; + } diff --git a/lede/target/linux/airoha/patches-6.12/089-v6.14-net-airoha-Fix-channel-configuration-for-ETS-Qdisc.patch b/lede/target/linux/airoha/patches-6.12/089-v6.14-net-airoha-Fix-channel-configuration-for-ETS-Qdisc.patch new file mode 100644 index 0000000000..02ce75b308 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/089-v6.14-net-airoha-Fix-channel-configuration-for-ETS-Qdisc.patch @@ -0,0 +1,36 @@ +From 7d0da8f862340c5f42f0062b8560b8d0971a6ac4 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 7 Jan 2025 23:26:28 +0100 +Subject: [PATCH] net: airoha: Fix channel configuration for ETS Qdisc + +Limit ETS QoS channel to AIROHA_NUM_QOS_CHANNELS in +airoha_tc_setup_qdisc_ets() in order to align the configured channel to +the value set in airoha_dev_select_queue(). + +Fixes: 20bf7d07c956 ("net: airoha: Add sched ETS offload support") +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Michal Swiatkowski +Link: https://patch.msgid.link/20250107-airoha-ets-fix-chan-v1-1-97f66ed3a068@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2183,11 +2183,14 @@ static int airoha_qdma_get_tx_ets_stats( + static int airoha_tc_setup_qdisc_ets(struct airoha_gdm_port *port, + struct tc_ets_qopt_offload *opt) + { +- int channel = TC_H_MAJ(opt->handle) >> 16; ++ int channel; + + if (opt->parent == TC_H_ROOT) + return -EINVAL; + ++ channel = TC_H_MAJ(opt->handle) >> 16; ++ channel = channel % AIROHA_NUM_QOS_CHANNELS; ++ + switch (opt->command) { + case TC_ETS_REPLACE: + return airoha_qdma_set_tx_ets_sched(port, channel, opt); diff --git a/lede/target/linux/airoha/patches-6.12/090-v6.17-net-mdio-Add-MDIO-bus-controller-for-Airoha-AN7583.patch b/lede/target/linux/airoha/patches-6.12/090-v6.17-net-mdio-Add-MDIO-bus-controller-for-Airoha-AN7583.patch new file mode 100644 index 0000000000..37b0ed5c78 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/090-v6.17-net-mdio-Add-MDIO-bus-controller-for-Airoha-AN7583.patch @@ -0,0 +1,342 @@ +From 67e3ba978361cb262f8f8981ab88ccb97f1e2bda Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 17 Jun 2025 11:16:53 +0200 +Subject: [PATCH] net: mdio: Add MDIO bus controller for Airoha AN7583 + +Airoha AN7583 SoC have 2 dedicated MDIO bus controller in the SCU +register map. To driver register an MDIO controller based on the DT +reg property and access the register by accessing the parent syscon. + +The MDIO bus logic is similar to the MT7530 internal MDIO bus but +deviates of some setting and some HW bug. + +On Airoha AN7583 the MDIO clock is set to 25MHz by default and needs to +be correctly setup to 2.5MHz to correctly work (by setting the divisor +to 10x). + +There seems to be Hardware bug where AN7583_MII_RWDATA +is not wiped in the context of unconnected PHY and the +previous read value is returned. + +Example: (only one PHY on the BUS at 0x1f) + - read at 0x1f report at 0x2 0x7500 + - read at 0x0 report 0x7500 on every address + +To workaround this, we reset the Mdio BUS at every read +to have consistent values on read operation. + +Signed-off-by: Christian Marangi +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/mdio/Kconfig | 7 + + drivers/net/mdio/Makefile | 1 + + drivers/net/mdio/mdio-airoha.c | 276 +++++++++++++++++++++++++++++++++ + 3 files changed, 284 insertions(+) + create mode 100644 drivers/net/mdio/mdio-airoha.c + +--- a/drivers/net/mdio/Kconfig ++++ b/drivers/net/mdio/Kconfig +@@ -46,6 +46,13 @@ if MDIO_BUS + config MDIO_DEVRES + tristate + ++config MDIO_AIROHA ++ tristate "Airoha AN7583 MDIO bus controller" ++ depends on ARCH_AIROHA || COMPILE_TEST ++ help ++ This module provides a driver for the MDIO busses found in the ++ Airoha AN7583 SoC's. ++ + config MDIO_SUN4I + tristate "Allwinner sun4i MDIO interface support" + depends on ARCH_SUNXI || COMPILE_TEST +--- a/drivers/net/mdio/Makefile ++++ b/drivers/net/mdio/Makefile +@@ -5,6 +5,7 @@ obj-$(CONFIG_ACPI_MDIO) += acpi_mdio.o + obj-$(CONFIG_FWNODE_MDIO) += fwnode_mdio.o + obj-$(CONFIG_OF_MDIO) += of_mdio.o + ++obj-$(CONFIG_MDIO_AIROHA) += mdio-airoha.o + obj-$(CONFIG_MDIO_ASPEED) += mdio-aspeed.o + obj-$(CONFIG_MDIO_BCM_IPROC) += mdio-bcm-iproc.o + obj-$(CONFIG_MDIO_BCM_UNIMAC) += mdio-bcm-unimac.o +--- /dev/null ++++ b/drivers/net/mdio/mdio-airoha.c +@@ -0,0 +1,276 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* Airoha AN7583 MDIO interface driver ++ * ++ * Copyright (C) 2025 Christian Marangi ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* MII address register definitions */ ++#define AN7583_MII_BUSY BIT(31) ++#define AN7583_MII_RDY BIT(30) /* RO signal BUS is ready */ ++#define AN7583_MII_CL22_REG_ADDR GENMASK(29, 25) ++#define AN7583_MII_CL45_DEV_ADDR AN7583_MII_CL22_REG_ADDR ++#define AN7583_MII_PHY_ADDR GENMASK(24, 20) ++#define AN7583_MII_CMD GENMASK(19, 18) ++#define AN7583_MII_CMD_CL22_WRITE FIELD_PREP_CONST(AN7583_MII_CMD, 0x1) ++#define AN7583_MII_CMD_CL22_READ FIELD_PREP_CONST(AN7583_MII_CMD, 0x2) ++#define AN7583_MII_CMD_CL45_ADDR FIELD_PREP_CONST(AN7583_MII_CMD, 0x0) ++#define AN7583_MII_CMD_CL45_WRITE FIELD_PREP_CONST(AN7583_MII_CMD, 0x1) ++#define AN7583_MII_CMD_CL45_POSTREAD_INCADDR FIELD_PREP_CONST(AN7583_MII_CMD, 0x2) ++#define AN7583_MII_CMD_CL45_READ FIELD_PREP_CONST(AN7583_MII_CMD, 0x3) ++#define AN7583_MII_ST GENMASK(17, 16) ++#define AN7583_MII_ST_CL45 FIELD_PREP_CONST(AN7583_MII_ST, 0x0) ++#define AN7583_MII_ST_CL22 FIELD_PREP_CONST(AN7583_MII_ST, 0x1) ++#define AN7583_MII_RWDATA GENMASK(15, 0) ++#define AN7583_MII_CL45_REG_ADDR AN7583_MII_RWDATA ++ ++#define AN7583_MII_MDIO_DELAY_USEC 100 ++#define AN7583_MII_MDIO_RETRY_MSEC 100 ++ ++struct airoha_mdio_data { ++ u32 base_addr; ++ struct regmap *regmap; ++ struct clk *clk; ++ struct reset_control *reset; ++}; ++ ++static int airoha_mdio_wait_busy(struct airoha_mdio_data *priv) ++{ ++ u32 busy; ++ ++ return regmap_read_poll_timeout(priv->regmap, priv->base_addr, busy, ++ !(busy & AN7583_MII_BUSY), ++ AN7583_MII_MDIO_DELAY_USEC, ++ AN7583_MII_MDIO_RETRY_MSEC * USEC_PER_MSEC); ++} ++ ++static void airoha_mdio_reset(struct airoha_mdio_data *priv) ++{ ++ /* There seems to be Hardware bug where AN7583_MII_RWDATA ++ * is not wiped in the context of unconnected PHY and the ++ * previous read value is returned. ++ * ++ * Example: (only one PHY on the BUS at 0x1f) ++ * - read at 0x1f report at 0x2 0x7500 ++ * - read at 0x0 report 0x7500 on every address ++ * ++ * To workaround this, we reset the Mdio BUS at every read ++ * to have consistent values on read operation. ++ */ ++ reset_control_assert(priv->reset); ++ reset_control_deassert(priv->reset); ++} ++ ++static int airoha_mdio_read(struct mii_bus *bus, int addr, int regnum) ++{ ++ struct airoha_mdio_data *priv = bus->priv; ++ u32 val; ++ int ret; ++ ++ airoha_mdio_reset(priv); ++ ++ val = AN7583_MII_BUSY | AN7583_MII_ST_CL22 | ++ AN7583_MII_CMD_CL22_READ; ++ val |= FIELD_PREP(AN7583_MII_PHY_ADDR, addr); ++ val |= FIELD_PREP(AN7583_MII_CL22_REG_ADDR, regnum); ++ ++ ret = regmap_write(priv->regmap, priv->base_addr, val); ++ if (ret) ++ return ret; ++ ++ ret = airoha_mdio_wait_busy(priv); ++ if (ret) ++ return ret; ++ ++ ret = regmap_read(priv->regmap, priv->base_addr, &val); ++ if (ret) ++ return ret; ++ ++ return FIELD_GET(AN7583_MII_RWDATA, val); ++} ++ ++static int airoha_mdio_write(struct mii_bus *bus, int addr, int regnum, ++ u16 value) ++{ ++ struct airoha_mdio_data *priv = bus->priv; ++ u32 val; ++ int ret; ++ ++ val = AN7583_MII_BUSY | AN7583_MII_ST_CL22 | ++ AN7583_MII_CMD_CL22_WRITE; ++ val |= FIELD_PREP(AN7583_MII_PHY_ADDR, addr); ++ val |= FIELD_PREP(AN7583_MII_CL22_REG_ADDR, regnum); ++ val |= FIELD_PREP(AN7583_MII_RWDATA, value); ++ ++ ret = regmap_write(priv->regmap, priv->base_addr, val); ++ if (ret) ++ return ret; ++ ++ ret = airoha_mdio_wait_busy(priv); ++ ++ return ret; ++} ++ ++static int airoha_mdio_cl45_read(struct mii_bus *bus, int addr, int devnum, ++ int regnum) ++{ ++ struct airoha_mdio_data *priv = bus->priv; ++ u32 val; ++ int ret; ++ ++ airoha_mdio_reset(priv); ++ ++ val = AN7583_MII_BUSY | AN7583_MII_ST_CL45 | ++ AN7583_MII_CMD_CL45_ADDR; ++ val |= FIELD_PREP(AN7583_MII_PHY_ADDR, addr); ++ val |= FIELD_PREP(AN7583_MII_CL45_DEV_ADDR, devnum); ++ val |= FIELD_PREP(AN7583_MII_CL45_REG_ADDR, regnum); ++ ++ ret = regmap_write(priv->regmap, priv->base_addr, val); ++ if (ret) ++ return ret; ++ ++ ret = airoha_mdio_wait_busy(priv); ++ if (ret) ++ return ret; ++ ++ val = AN7583_MII_BUSY | AN7583_MII_ST_CL45 | ++ AN7583_MII_CMD_CL45_READ; ++ val |= FIELD_PREP(AN7583_MII_PHY_ADDR, addr); ++ val |= FIELD_PREP(AN7583_MII_CL45_DEV_ADDR, devnum); ++ ++ ret = regmap_write(priv->regmap, priv->base_addr, val); ++ if (ret) ++ return ret; ++ ++ ret = airoha_mdio_wait_busy(priv); ++ if (ret) ++ return ret; ++ ++ ret = regmap_read(priv->regmap, priv->base_addr, &val); ++ if (ret) ++ return ret; ++ ++ return FIELD_GET(AN7583_MII_RWDATA, val); ++} ++ ++static int airoha_mdio_cl45_write(struct mii_bus *bus, int addr, int devnum, ++ int regnum, u16 value) ++{ ++ struct airoha_mdio_data *priv = bus->priv; ++ u32 val; ++ int ret; ++ ++ val = AN7583_MII_BUSY | AN7583_MII_ST_CL45 | ++ AN7583_MII_CMD_CL45_ADDR; ++ val |= FIELD_PREP(AN7583_MII_PHY_ADDR, addr); ++ val |= FIELD_PREP(AN7583_MII_CL45_DEV_ADDR, devnum); ++ val |= FIELD_PREP(AN7583_MII_CL45_REG_ADDR, regnum); ++ ++ ret = regmap_write(priv->regmap, priv->base_addr, val); ++ if (ret) ++ return ret; ++ ++ ret = airoha_mdio_wait_busy(priv); ++ if (ret) ++ return ret; ++ ++ val = AN7583_MII_BUSY | AN7583_MII_ST_CL45 | ++ AN7583_MII_CMD_CL45_WRITE; ++ val |= FIELD_PREP(AN7583_MII_PHY_ADDR, addr); ++ val |= FIELD_PREP(AN7583_MII_CL45_DEV_ADDR, devnum); ++ val |= FIELD_PREP(AN7583_MII_RWDATA, value); ++ ++ ret = regmap_write(priv->regmap, priv->base_addr, val); ++ if (ret) ++ return ret; ++ ++ ret = airoha_mdio_wait_busy(priv); ++ ++ return ret; ++} ++ ++static int airoha_mdio_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct airoha_mdio_data *priv; ++ struct mii_bus *bus; ++ u32 addr, freq; ++ int ret; ++ ++ ret = of_property_read_u32(dev->of_node, "reg", &addr); ++ if (ret) ++ return ret; ++ ++ bus = devm_mdiobus_alloc_size(dev, sizeof(*priv)); ++ if (!bus) ++ return -ENOMEM; ++ ++ priv = bus->priv; ++ priv->base_addr = addr; ++ priv->regmap = device_node_to_regmap(dev->parent->of_node); ++ ++ priv->clk = devm_clk_get_enabled(dev, NULL); ++ if (IS_ERR(priv->clk)) ++ return PTR_ERR(priv->clk); ++ ++ priv->reset = devm_reset_control_get_exclusive(dev, NULL); ++ if (IS_ERR(priv->reset)) ++ return PTR_ERR(priv->reset); ++ ++ reset_control_deassert(priv->reset); ++ ++ bus->name = "airoha_mdio_bus"; ++ snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(dev)); ++ bus->parent = dev; ++ bus->read = airoha_mdio_read; ++ bus->write = airoha_mdio_write; ++ bus->read_c45 = airoha_mdio_cl45_read; ++ bus->write_c45 = airoha_mdio_cl45_write; ++ ++ /* Check if a custom frequency is defined in DT or default to 2.5 MHz */ ++ if (of_property_read_u32(dev->of_node, "clock-frequency", &freq)) ++ freq = 2500000; ++ ++ ret = clk_set_rate(priv->clk, freq); ++ if (ret) ++ return ret; ++ ++ ret = devm_of_mdiobus_register(dev, bus, dev->of_node); ++ if (ret) { ++ reset_control_assert(priv->reset); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id airoha_mdio_dt_ids[] = { ++ { .compatible = "airoha,an7583-mdio" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, airoha_mdio_dt_ids); ++ ++static struct platform_driver airoha_mdio_driver = { ++ .probe = airoha_mdio_probe, ++ .driver = { ++ .name = "airoha-mdio", ++ .of_match_table = airoha_mdio_dt_ids, ++ }, ++}; ++ ++module_platform_driver(airoha_mdio_driver); ++ ++MODULE_DESCRIPTION("Airoha AN7583 MDIO interface driver"); ++MODULE_AUTHOR("Christian Marangi "); ++MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/airoha/patches-6.12/091-01-v6.18-pinctrl-airoha-fix-wrong-PHY-LED-mux-value-for-LED1-.patch b/lede/target/linux/airoha/patches-6.12/091-01-v6.18-pinctrl-airoha-fix-wrong-PHY-LED-mux-value-for-LED1-.patch new file mode 100644 index 0000000000..e155375c3f --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/091-01-v6.18-pinctrl-airoha-fix-wrong-PHY-LED-mux-value-for-LED1-.patch @@ -0,0 +1,68 @@ +From af87d38c442c75a40c7d0a7d8c31557e2e6ccf98 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sun, 25 May 2025 20:22:40 +0200 +Subject: [PATCH 1/2] pinctrl: airoha: fix wrong PHY LED mux value for LED1 + GPIO46 + +In all the MUX value for LED1 GPIO46 there is a Copy-Paste error where +the MUX value is set to LED0_MODE_MASK instead of LED1_MODE_MASK. + +This wasn't notice as there were no board that made use of the +secondary PHY LED but looking at the internal Documentation the actual +value should be LED1_MODE_MASK similar to the other GPIO entry. + +Fix the wrong value to apply the correct MUX configuration. + +Cc: stable@vger.kernel.org +Fixes: 1c8ace2d0725 ("pinctrl: airoha: Add support for EN7581 SoC") +Signed-off-by: Christian Marangi +--- + drivers/pinctrl/mediatek/pinctrl-airoha.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/pinctrl/mediatek/pinctrl-airoha.c ++++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c +@@ -1752,8 +1752,8 @@ static const struct airoha_pinctrl_func_ + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN3_LED0_MODE_MASK, +- GPIO_LAN3_LED0_MODE_MASK ++ GPIO_LAN3_LED1_MODE_MASK, ++ GPIO_LAN3_LED1_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, +@@ -1816,8 +1816,8 @@ static const struct airoha_pinctrl_func_ + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN3_LED0_MODE_MASK, +- GPIO_LAN3_LED0_MODE_MASK ++ GPIO_LAN3_LED1_MODE_MASK, ++ GPIO_LAN3_LED1_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, +@@ -1880,8 +1880,8 @@ static const struct airoha_pinctrl_func_ + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN3_LED0_MODE_MASK, +- GPIO_LAN3_LED0_MODE_MASK ++ GPIO_LAN3_LED1_MODE_MASK, ++ GPIO_LAN3_LED1_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, +@@ -1944,8 +1944,8 @@ static const struct airoha_pinctrl_func_ + .regmap[0] = { + AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN3_LED0_MODE_MASK, +- GPIO_LAN3_LED0_MODE_MASK ++ GPIO_LAN3_LED1_MODE_MASK, ++ GPIO_LAN3_LED1_MODE_MASK + }, + .regmap[1] = { + AIROHA_FUNC_MUX, diff --git a/lede/target/linux/airoha/patches-6.12/091-02-v6.18-pinctrl-airoha-fix-wrong-MDIO-function-bitmaks.patch b/lede/target/linux/airoha/patches-6.12/091-02-v6.18-pinctrl-airoha-fix-wrong-MDIO-function-bitmaks.patch new file mode 100644 index 0000000000..abcedb5d51 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/091-02-v6.18-pinctrl-airoha-fix-wrong-MDIO-function-bitmaks.patch @@ -0,0 +1,58 @@ +From 110930eb12699b92f767fc599c7ab467dd42358a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 8 Jul 2025 14:49:56 +0200 +Subject: [PATCH 2/2] pinctrl: airoha: fix wrong MDIO function bitmaks + +With further testing with an attached Aeonsemi it was discovered that +the pinctrl MDIO function applied the wrong bitmask. The error was +probably caused by the confusing documentation related to these bits. + +Inspecting what the bootloader actually configure, the SGMII_MDIO_MODE +is never actually set but instead it's set force enable to the 2 GPIO +(gpio 1-2) for MDC and MDIO pin. + +Applying this configuration permits correct functionality of any +externally attached PHY. + +Cc: stable@vger.kernel.org +Fixes: 1c8ace2d0725 ("pinctrl: airoha: Add support for EN7581 SoC") +Signed-off-by: Christian Marangi +--- + drivers/pinctrl/mediatek/pinctrl-airoha.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +--- a/drivers/pinctrl/mediatek/pinctrl-airoha.c ++++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c +@@ -108,6 +108,9 @@ + #define JTAG_UDI_EN_MASK BIT(4) + #define JTAG_DFD_EN_MASK BIT(3) + ++#define REG_FORCE_GPIO_EN 0x0228 ++#define FORCE_GPIO_EN(n) BIT(n) ++ + /* LED MAP */ + #define REG_LAN_LED0_MAPPING 0x027c + #define REG_LAN_LED1_MAPPING 0x0280 +@@ -719,16 +722,16 @@ static const struct airoha_pinctrl_func_ + .name = "mdio", + .regmap[0] = { + AIROHA_FUNC_MUX, +- REG_GPIO_PON_MODE, +- GPIO_SGMII_MDIO_MODE_MASK, +- GPIO_SGMII_MDIO_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, + REG_GPIO_2ND_I2C_MODE, + GPIO_MDC_IO_MASTER_MODE_MODE, + GPIO_MDC_IO_MASTER_MODE_MODE + }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_FORCE_GPIO_EN, ++ FORCE_GPIO_EN(1) | FORCE_GPIO_EN(2), ++ FORCE_GPIO_EN(1) | FORCE_GPIO_EN(2) ++ }, + .regmap_size = 2, + }, + }; diff --git a/lede/target/linux/airoha/patches-6.12/092-v6.18-net-airoha-Avoid-Wflex-array-member-not-at-end-warni.patch b/lede/target/linux/airoha/patches-6.12/092-v6.18-net-airoha-Avoid-Wflex-array-member-not-at-end-warni.patch new file mode 100644 index 0000000000..5e52a3b429 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/092-v6.18-net-airoha-Avoid-Wflex-array-member-not-at-end-warni.patch @@ -0,0 +1,45 @@ +From 09630ab91d840416b0178f3660afa4eebce24286 Mon Sep 17 00:00:00 2001 +From: "Gustavo A. R. Silva" +Date: Mon, 22 Sep 2025 16:08:21 +0200 +Subject: [PATCH] net: airoha: Avoid -Wflex-array-member-not-at-end warning + +-Wflex-array-member-not-at-end was introduced in GCC-14, and we are +getting ready to enable it, globally. + +Move the conflicting declaration to the end of the corresponding +structure. Notice that `struct airoha_foe_entry` is a flexible +structure, this is a structure that contains a flexible-array +member. + +Fix the following warning: + +drivers/net/ethernet/airoha/airoha_eth.h:474:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end] + +Signed-off-by: Gustavo A. R. Silva +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/aNFYVYLXQDqm4yxb@kspp +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.h | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -471,7 +471,6 @@ struct airoha_flow_table_entry { + }; + }; + +- struct airoha_foe_entry data; + struct hlist_node l2_subflow_node; /* PPE L2 subflow entry */ + u32 hash; + +@@ -480,6 +479,9 @@ struct airoha_flow_table_entry { + + struct rhash_head node; + unsigned long cookie; ++ ++ /* Must be last --ends in a flexible-array member. */ ++ struct airoha_foe_entry data; + }; + + struct airoha_wdma_info { diff --git a/lede/target/linux/airoha/patches-6.12/093-v6.18-net-airoha-Fix-PPE_IP_PROTO_CHK-register-definitions.patch b/lede/target/linux/airoha/patches-6.12/093-v6.18-net-airoha-Fix-PPE_IP_PROTO_CHK-register-definitions.patch new file mode 100644 index 0000000000..31cd950437 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/093-v6.18-net-airoha-Fix-PPE_IP_PROTO_CHK-register-definitions.patch @@ -0,0 +1,29 @@ +From e156dd6b856fa462430d875b0d4cd281ecd66c23 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Thu, 18 Sep 2025 08:59:41 +0200 +Subject: [PATCH] net: airoha: Fix PPE_IP_PROTO_CHK register definitions + +Fix typo in PPE_IP_PROTO_CHK_IPV4_MASK and PPE_IP_PROTO_CHK_IPV6_MASK +register mask definitions. This is not a real problem since this +register is not actually used in the current codebase. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_regs.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -237,8 +237,8 @@ + #define PPE_FLOW_CFG_IP4_TCP_FRAG_MASK BIT(6) + + #define REG_PPE_IP_PROTO_CHK(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x208) +-#define PPE_IP_PROTO_CHK_IPV4_MASK GENMASK(15, 0) +-#define PPE_IP_PROTO_CHK_IPV6_MASK GENMASK(31, 16) ++#define PPE_IP_PROTO_CHK_IPV4_MASK GENMASK(31, 16) ++#define PPE_IP_PROTO_CHK_IPV6_MASK GENMASK(15, 0) + + #define REG_PPE_TB_CFG(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x21c) + #define PPE_SRAM_TB_NUM_ENTRY_MASK GENMASK(26, 24) diff --git a/lede/target/linux/airoha/patches-6.12/094-v6.18-net-airoha-npu-Add-a-NPU-callback-to-initialize-flow.patch b/lede/target/linux/airoha/patches-6.12/094-v6.18-net-airoha-npu-Add-a-NPU-callback-to-initialize-flow.patch new file mode 100644 index 0000000000..021ec0c8df --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/094-v6.18-net-airoha-npu-Add-a-NPU-callback-to-initialize-flow.patch @@ -0,0 +1,159 @@ +From 105ce7ad57e492b75ab40f2dc591db645fadbaa2 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 24 Sep 2025 23:14:53 +0200 +Subject: [PATCH] net: airoha: npu: Add a NPU callback to initialize flow stats + +Introduce a NPU callback to initialize flow stats and remove NPU stats +initialization from airoha_npu_get routine. Add num_stats_entries to +airoha_npu_ppe_stats_setup routine. +This patch makes the code more readable since NPU statistic are now +initialized on demand by the NPU consumer (at the moment NPU statistic +are configured just by the airoha_eth driver). +Moreover this patch allows the NPU consumer (PPE module) to explicitly +enable/disable NPU flow stats. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20250924-airoha-npu-init-stats-callback-v1-1-88bdf3c941b2@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_npu.c | 24 ++++++----------------- + drivers/net/ethernet/airoha/airoha_ppe.c | 19 ++++++++++++------ + include/linux/soc/airoha/airoha_offload.h | 7 ++++--- + 3 files changed, 23 insertions(+), 27 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_npu.c ++++ b/drivers/net/ethernet/airoha/airoha_npu.c +@@ -379,15 +379,13 @@ out: + return err; + } + +-static int airoha_npu_stats_setup(struct airoha_npu *npu, +- dma_addr_t foe_stats_addr) ++static int airoha_npu_ppe_stats_setup(struct airoha_npu *npu, ++ dma_addr_t foe_stats_addr, ++ u32 num_stats_entries) + { +- int err, size = PPE_STATS_NUM_ENTRIES * sizeof(*npu->stats); ++ int err, size = num_stats_entries * sizeof(*npu->stats); + struct ppe_mbox_data *ppe_data; + +- if (!size) /* flow stats are disabled */ +- return 0; +- + ppe_data = kzalloc(sizeof(*ppe_data), GFP_ATOMIC); + if (!ppe_data) + return -ENOMEM; +@@ -542,7 +540,7 @@ static void airoha_npu_wlan_irq_disable( + regmap_clear_bits(npu->regmap, REG_IRQ_RXDONE(q), NPU_IRQ_RX_MASK(q)); + } + +-struct airoha_npu *airoha_npu_get(struct device *dev, dma_addr_t *stats_addr) ++struct airoha_npu *airoha_npu_get(struct device *dev) + { + struct platform_device *pdev; + struct device_node *np; +@@ -580,17 +578,6 @@ struct airoha_npu *airoha_npu_get(struct + goto error_module_put; + } + +- if (stats_addr) { +- int err; +- +- err = airoha_npu_stats_setup(npu, *stats_addr); +- if (err) { +- dev_err(dev, "failed to allocate npu stats buffer\n"); +- npu = ERR_PTR(err); +- goto error_module_put; +- } +- } +- + return npu; + + error_module_put: +@@ -643,6 +630,7 @@ static int airoha_npu_probe(struct platf + npu->dev = dev; + npu->ops.ppe_init = airoha_npu_ppe_init; + npu->ops.ppe_deinit = airoha_npu_ppe_deinit; ++ npu->ops.ppe_init_stats = airoha_npu_ppe_stats_setup; + npu->ops.ppe_flush_sram_entries = airoha_npu_ppe_flush_sram_entries; + npu->ops.ppe_foe_commit_entry = airoha_npu_foe_commit_entry; + npu->ops.wlan_init_reserved_memory = airoha_npu_wlan_init_memory; +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -1243,12 +1243,11 @@ static int airoha_ppe_flush_sram_entries + + static struct airoha_npu *airoha_ppe_npu_get(struct airoha_eth *eth) + { +- struct airoha_npu *npu = airoha_npu_get(eth->dev, +- ð->ppe->foe_stats_dma); ++ struct airoha_npu *npu = airoha_npu_get(eth->dev); + + if (IS_ERR(npu)) { + request_module("airoha-npu"); +- npu = airoha_npu_get(eth->dev, ð->ppe->foe_stats_dma); ++ npu = airoha_npu_get(eth->dev); + } + + return npu; +@@ -1257,6 +1256,7 @@ static struct airoha_npu *airoha_ppe_npu + static int airoha_ppe_offload_setup(struct airoha_eth *eth) + { + struct airoha_npu *npu = airoha_ppe_npu_get(eth); ++ struct airoha_ppe *ppe = eth->ppe; + int err; + + if (IS_ERR(npu)) +@@ -1266,12 +1266,19 @@ static int airoha_ppe_offload_setup(stru + if (err) + goto error_npu_put; + +- airoha_ppe_hw_init(eth->ppe); +- err = airoha_ppe_flush_sram_entries(eth->ppe, npu); ++ if (PPE_STATS_NUM_ENTRIES) { ++ err = npu->ops.ppe_init_stats(npu, ppe->foe_stats_dma, ++ PPE_STATS_NUM_ENTRIES); ++ if (err) ++ goto error_npu_put; ++ } ++ ++ airoha_ppe_hw_init(ppe); ++ err = airoha_ppe_flush_sram_entries(ppe, npu); + if (err) + goto error_npu_put; + +- airoha_ppe_foe_flow_stats_reset(eth->ppe, npu); ++ airoha_ppe_foe_flow_stats_reset(ppe, npu); + + rcu_assign_pointer(eth->npu, npu); + synchronize_rcu(); +--- a/include/linux/soc/airoha/airoha_offload.h ++++ b/include/linux/soc/airoha/airoha_offload.h +@@ -181,6 +181,8 @@ struct airoha_npu { + struct { + int (*ppe_init)(struct airoha_npu *npu); + int (*ppe_deinit)(struct airoha_npu *npu); ++ int (*ppe_init_stats)(struct airoha_npu *npu, ++ dma_addr_t addr, u32 num_stats_entries); + int (*ppe_flush_sram_entries)(struct airoha_npu *npu, + dma_addr_t foe_addr, + int sram_num_entries); +@@ -206,7 +208,7 @@ struct airoha_npu { + }; + + #if (IS_BUILTIN(CONFIG_NET_AIROHA_NPU) || IS_MODULE(CONFIG_NET_AIROHA_NPU)) +-struct airoha_npu *airoha_npu_get(struct device *dev, dma_addr_t *stats_addr); ++struct airoha_npu *airoha_npu_get(struct device *dev); + void airoha_npu_put(struct airoha_npu *npu); + + static inline int airoha_npu_wlan_init_reserved_memory(struct airoha_npu *npu) +@@ -256,8 +258,7 @@ static inline void airoha_npu_wlan_disab + npu->ops.wlan_disable_irq(npu, q); + } + #else +-static inline struct airoha_npu *airoha_npu_get(struct device *dev, +- dma_addr_t *foe_stats_addr) ++static inline struct airoha_npu *airoha_npu_get(struct device *dev) + { + return NULL; + } diff --git a/lede/target/linux/airoha/patches-6.12/095-v6.19-net-airoha-Fix-loopback-mode-configuration-for-GDM2-.patch b/lede/target/linux/airoha/patches-6.12/095-v6.19-net-airoha-Fix-loopback-mode-configuration-for-GDM2-.patch new file mode 100644 index 0000000000..5c3fcc0c20 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/095-v6.19-net-airoha-Fix-loopback-mode-configuration-for-GDM2-.patch @@ -0,0 +1,43 @@ +From fea8cdf6738a8b25fccbb7b109b440795a0892cb Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 8 Oct 2025 11:27:43 +0200 +Subject: [PATCH] net: airoha: Fix loopback mode configuration for GDM2 port + +Add missing configuration for loopback mode in airhoha_set_gdm2_loopback +routine. + +Fixes: 9cd451d414f6e ("net: airoha: Add loopback support for GDM2") +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Jacob Keller +Link: https://patch.msgid.link/20251008-airoha-loopback-mode-fix-v2-1-045694fe7f60@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 4 +++- + drivers/net/ethernet/airoha/airoha_regs.h | 3 +++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1715,7 +1715,9 @@ static void airhoha_set_gdm2_loopback(st + airoha_fe_wr(eth, REG_GDM_RXCHN_EN(2), 0xffff); + airoha_fe_rmw(eth, REG_GDM_LPBK_CFG(2), + LPBK_CHAN_MASK | LPBK_MODE_MASK | LPBK_EN_MASK, +- FIELD_PREP(LPBK_CHAN_MASK, chan) | LPBK_EN_MASK); ++ FIELD_PREP(LPBK_CHAN_MASK, chan) | ++ LBK_GAP_MODE_MASK | LBK_LEN_MODE_MASK | ++ LBK_CHAN_MODE_MASK | LPBK_EN_MASK); + airoha_fe_rmw(eth, REG_GDM_LEN_CFG(2), + GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK, + FIELD_PREP(GDM_SHORT_LEN_MASK, 60) | +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -151,6 +151,9 @@ + #define LPBK_LEN_MASK GENMASK(23, 10) + #define LPBK_CHAN_MASK GENMASK(8, 4) + #define LPBK_MODE_MASK GENMASK(3, 1) ++#define LBK_GAP_MODE_MASK BIT(3) ++#define LBK_LEN_MODE_MASK BIT(2) ++#define LBK_CHAN_MODE_MASK BIT(1) + #define LPBK_EN_MASK BIT(0) + + #define REG_GDM_TXCHN_EN(_n) (GDM_BASE(_n) + 0x24) diff --git a/lede/target/linux/airoha/patches-6.12/096-v6.19-net-airoha-Add-missing-stats-to-ethtool_eth_mac_stat.patch b/lede/target/linux/airoha/patches-6.12/096-v6.19-net-airoha-Add-missing-stats-to-ethtool_eth_mac_stat.patch new file mode 100644 index 0000000000..66d72ded83 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/096-v6.19-net-airoha-Add-missing-stats-to-ethtool_eth_mac_stat.patch @@ -0,0 +1,34 @@ +From 331f8a8bea22aecf99437f3561453a85f40026de Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 13 Oct 2025 16:29:41 +0200 +Subject: [PATCH] net: airoha: Add missing stats to ethtool_eth_mac_stats + +Add the following stats to ethtool ethtool_eth_mac_stats stats: +- FramesTransmittedOK +- OctetsTransmittedOK +- FramesReceivedOK +- OctetsReceivedOK + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20251013-airoha-ethtool-improvements-v1-1-fdd1c6fc9be1@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2027,8 +2027,12 @@ static void airoha_ethtool_get_mac_stats + airoha_update_hw_stats(port); + do { + start = u64_stats_fetch_begin(&port->stats.syncp); ++ stats->FramesTransmittedOK = port->stats.tx_ok_pkts; ++ stats->OctetsTransmittedOK = port->stats.tx_ok_bytes; + stats->MulticastFramesXmittedOK = port->stats.tx_multicast; + stats->BroadcastFramesXmittedOK = port->stats.tx_broadcast; ++ stats->FramesReceivedOK = port->stats.rx_ok_pkts; ++ stats->OctetsReceivedOK = port->stats.rx_ok_bytes; + stats->BroadcastFramesReceivedOK = port->stats.rx_broadcast; + } while (u64_stats_fetch_retry(&port->stats.syncp, start)); + } diff --git a/lede/target/linux/airoha/patches-6.12/097-v6.19-net-airoha-Add-get_link-ethtool-callback.patch b/lede/target/linux/airoha/patches-6.12/097-v6.19-net-airoha-Add-get_link-ethtool-callback.patch new file mode 100644 index 0000000000..7d78bd6c03 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/097-v6.19-net-airoha-Add-get_link-ethtool-callback.patch @@ -0,0 +1,25 @@ +From fc4fed9054ef5b5269d4395dd9db36fe98fce9e3 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 13 Oct 2025 16:29:42 +0200 +Subject: [PATCH] net: airoha: Add get_link ethtool callback + +Set get_link ethtool callback to ethtool_op_get_link routine. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20251013-airoha-ethtool-improvements-v1-2-fdd1c6fc9be1@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2775,6 +2775,7 @@ static const struct ethtool_ops airoha_e + .get_drvinfo = airoha_ethtool_get_drvinfo, + .get_eth_mac_stats = airoha_ethtool_get_mac_stats, + .get_rmon_stats = airoha_ethtool_get_rmon_stats, ++ .get_link = ethtool_op_get_link, + }; + + static int airoha_metadata_dst_alloc(struct airoha_gdm_port *port) diff --git a/lede/target/linux/airoha/patches-6.12/098-v6.19-net-airoha-Take-into-account-out-of-order-tx-complet.patch b/lede/target/linux/airoha/patches-6.12/098-v6.19-net-airoha-Take-into-account-out-of-order-tx-complet.patch new file mode 100644 index 0000000000..46432b2480 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/098-v6.19-net-airoha-Take-into-account-out-of-order-tx-complet.patch @@ -0,0 +1,54 @@ +From bd5afca115f181c85f992d42a57cd497bc823ccb Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Sun, 12 Oct 2025 11:19:44 +0200 +Subject: [PATCH] net: airoha: Take into account out-of-order tx completions in + airoha_dev_xmit() + +Completion napi can free out-of-order tx descriptors if hw QoS is +enabled and packets with different priority are queued to same DMA ring. +Take into account possible out-of-order reports checking if the tx queue +is full using circular buffer head/tail pointer instead of the number of +queued packets. + +Fixes: 23020f0493270 ("net: airoha: Introduce ethernet support for EN7581 SoC") +Suggested-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251012-airoha-tx-busy-queue-v2-1-a600b08bab2d@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1878,6 +1878,20 @@ static u32 airoha_get_dsa_tag(struct sk_ + #endif + } + ++static bool airoha_dev_tx_queue_busy(struct airoha_queue *q, u32 nr_frags) ++{ ++ u32 tail = q->tail <= q->head ? q->tail + q->ndesc : q->tail; ++ u32 index = q->head + nr_frags; ++ ++ /* completion napi can free out-of-order tx descriptors if hw QoS is ++ * enabled and packets with different priorities are queued to the same ++ * DMA ring. Take into account possible out-of-order reports checking ++ * if the tx queue is full using circular buffer head/tail pointers ++ * instead of the number of queued packets. ++ */ ++ return index >= tail; ++} ++ + static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, + struct net_device *dev) + { +@@ -1931,7 +1945,7 @@ static netdev_tx_t airoha_dev_xmit(struc + txq = netdev_get_tx_queue(dev, qid); + nr_frags = 1 + skb_shinfo(skb)->nr_frags; + +- if (q->queued + nr_frags > q->ndesc) { ++ if (airoha_dev_tx_queue_busy(q, nr_frags)) { + /* not enough space in the queue */ + netif_tx_stop_queue(txq); + spin_unlock_bh(&q->lock); diff --git a/lede/target/linux/airoha/patches-6.12/099-01-v6.19-net-airoha-ppe-Dynamically-allocate-foe_check_time-a.patch b/lede/target/linux/airoha/patches-6.12/099-01-v6.19-net-airoha-ppe-Dynamically-allocate-foe_check_time-a.patch new file mode 100644 index 0000000000..3d4b0cfab0 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/099-01-v6.19-net-airoha-ppe-Dynamically-allocate-foe_check_time-a.patch @@ -0,0 +1,43 @@ +From 6d5b601d52a27aafff555b480e538507901c672c Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 17 Oct 2025 11:06:11 +0200 +Subject: [PATCH 01/12] net: airoha: ppe: Dynamically allocate foe_check_time + array in airoha_ppe struct + +This is a preliminary patch to properly enable PPE support for AN7583 +SoC. + +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-2-f28319666667@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.h | 2 +- + drivers/net/ethernet/airoha/airoha_ppe.c | 5 +++++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -554,7 +554,7 @@ struct airoha_ppe { + struct rhashtable l2_flows; + + struct hlist_head *foe_flow; +- u16 foe_check_time[PPE_NUM_ENTRIES]; ++ u16 *foe_check_time; + + struct airoha_foe_stats *foe_stats; + dma_addr_t foe_stats_dma; +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -1440,6 +1440,11 @@ int airoha_ppe_init(struct airoha_eth *e + return -ENOMEM; + } + ++ ppe->foe_check_time = devm_kzalloc(eth->dev, PPE_NUM_ENTRIES, ++ GFP_KERNEL); ++ if (!ppe->foe_check_time) ++ return -ENOMEM; ++ + err = rhashtable_init(ð->flow_table, &airoha_flow_table_params); + if (err) + return err; diff --git a/lede/target/linux/airoha/patches-6.12/099-02-v6.19-net-airoha-Add-airoha_ppe_get_num_stats_entries-and-.patch b/lede/target/linux/airoha/patches-6.12/099-02-v6.19-net-airoha-Add-airoha_ppe_get_num_stats_entries-and-.patch new file mode 100644 index 0000000000..6733331f1f --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/099-02-v6.19-net-airoha-Add-airoha_ppe_get_num_stats_entries-and-.patch @@ -0,0 +1,239 @@ +From 15f357cd4581ce6e02e5e97719320600783140ec Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 17 Oct 2025 11:06:12 +0200 +Subject: [PATCH 02/12] net: airoha: Add airoha_ppe_get_num_stats_entries() and + airoha_ppe_get_num_total_stats_entries() + +Introduce airoha_ppe_get_num_stats_entries and +airoha_ppe_get_num_total_stats_entries routines in order to make the +code more readable controlling if CONFIG_NET_AIROHA_FLOW_STATS is +enabled or disabled. +Modify airoha_ppe_foe_get_flow_stats_index routine signature relying on +airoha_ppe_get_num_total_stats_entries(). + +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-3-f28319666667@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.h | 10 +-- + drivers/net/ethernet/airoha/airoha_ppe.c | 101 ++++++++++++++++++----- + 2 files changed, 81 insertions(+), 30 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -50,15 +50,9 @@ + + #define PPE_NUM 2 + #define PPE1_SRAM_NUM_ENTRIES (8 * 1024) +-#define PPE_SRAM_NUM_ENTRIES (2 * PPE1_SRAM_NUM_ENTRIES) +-#ifdef CONFIG_NET_AIROHA_FLOW_STATS ++#define PPE_SRAM_NUM_ENTRIES (PPE_NUM * PPE1_SRAM_NUM_ENTRIES) + #define PPE1_STATS_NUM_ENTRIES (4 * 1024) +-#else +-#define PPE1_STATS_NUM_ENTRIES 0 +-#endif /* CONFIG_NET_AIROHA_FLOW_STATS */ +-#define PPE_STATS_NUM_ENTRIES (2 * PPE1_STATS_NUM_ENTRIES) +-#define PPE1_SRAM_NUM_DATA_ENTRIES (PPE1_SRAM_NUM_ENTRIES - PPE1_STATS_NUM_ENTRIES) +-#define PPE_SRAM_NUM_DATA_ENTRIES (2 * PPE1_SRAM_NUM_DATA_ENTRIES) ++#define PPE_STATS_NUM_ENTRIES (PPE_NUM * PPE1_STATS_NUM_ENTRIES) + #define PPE_DRAM_NUM_ENTRIES (16 * 1024) + #define PPE_NUM_ENTRIES (PPE_SRAM_NUM_ENTRIES + PPE_DRAM_NUM_ENTRIES) + #define PPE_HASH_MASK (PPE_NUM_ENTRIES - 1) +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -32,6 +32,24 @@ static const struct rhashtable_params ai + .automatic_shrinking = true, + }; + ++static int airoha_ppe_get_num_stats_entries(struct airoha_ppe *ppe) ++{ ++ if (!IS_ENABLED(CONFIG_NET_AIROHA_FLOW_STATS)) ++ return -EOPNOTSUPP; ++ ++ return PPE1_STATS_NUM_ENTRIES; ++} ++ ++static int airoha_ppe_get_total_num_stats_entries(struct airoha_ppe *ppe) ++{ ++ int num_stats = airoha_ppe_get_num_stats_entries(ppe); ++ ++ if (num_stats > 0) ++ num_stats = num_stats * PPE_NUM; ++ ++ return num_stats; ++} ++ + static bool airoha_ppe2_is_enabled(struct airoha_eth *eth) + { + return airoha_fe_rr(eth, REG_PPE_GLO_CFG(1)) & PPE_GLO_CFG_EN_MASK; +@@ -48,7 +66,7 @@ static void airoha_ppe_hw_init(struct ai + { + u32 sram_tb_size, sram_num_entries, dram_num_entries; + struct airoha_eth *eth = ppe->eth; +- int i; ++ int i, sram_num_stats_entries; + + sram_tb_size = PPE_SRAM_NUM_ENTRIES * sizeof(struct airoha_foe_entry); + dram_num_entries = PPE_RAM_NUM_ENTRIES_SHIFT(PPE_DRAM_NUM_ENTRIES); +@@ -103,8 +121,13 @@ static void airoha_ppe_hw_init(struct ai + } + + if (airoha_ppe2_is_enabled(eth)) { +- sram_num_entries = +- PPE_RAM_NUM_ENTRIES_SHIFT(PPE1_SRAM_NUM_DATA_ENTRIES); ++ sram_num_entries = PPE1_SRAM_NUM_ENTRIES; ++ sram_num_stats_entries = ++ airoha_ppe_get_num_stats_entries(ppe); ++ if (sram_num_stats_entries > 0) ++ sram_num_entries -= sram_num_stats_entries; ++ sram_num_entries = PPE_RAM_NUM_ENTRIES_SHIFT(sram_num_entries); ++ + airoha_fe_rmw(eth, REG_PPE_TB_CFG(0), + PPE_SRAM_TB_NUM_ENTRY_MASK | + PPE_DRAM_TB_NUM_ENTRY_MASK, +@@ -120,8 +143,13 @@ static void airoha_ppe_hw_init(struct ai + FIELD_PREP(PPE_DRAM_TB_NUM_ENTRY_MASK, + dram_num_entries)); + } else { +- sram_num_entries = +- PPE_RAM_NUM_ENTRIES_SHIFT(PPE_SRAM_NUM_DATA_ENTRIES); ++ sram_num_entries = PPE_SRAM_NUM_ENTRIES; ++ sram_num_stats_entries = ++ airoha_ppe_get_total_num_stats_entries(ppe); ++ if (sram_num_stats_entries > 0) ++ sram_num_entries -= sram_num_stats_entries; ++ sram_num_entries = PPE_RAM_NUM_ENTRIES_SHIFT(sram_num_entries); ++ + airoha_fe_rmw(eth, REG_PPE_TB_CFG(0), + PPE_SRAM_TB_NUM_ENTRY_MASK | + PPE_DRAM_TB_NUM_ENTRY_MASK, +@@ -480,13 +508,21 @@ static u32 airoha_ppe_foe_get_entry_hash + return hash; + } + +-static u32 airoha_ppe_foe_get_flow_stats_index(struct airoha_ppe *ppe, u32 hash) ++static int airoha_ppe_foe_get_flow_stats_index(struct airoha_ppe *ppe, ++ u32 hash, u32 *index) + { +- if (!airoha_ppe2_is_enabled(ppe->eth)) +- return hash; ++ int ppe_num_stats_entries; ++ ++ ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe); ++ if (ppe_num_stats_entries < 0) ++ return ppe_num_stats_entries; ++ ++ *index = hash; ++ if (airoha_ppe2_is_enabled(ppe->eth) && ++ hash >= ppe_num_stats_entries) ++ *index = *index - PPE_STATS_NUM_ENTRIES; + +- return hash >= PPE_STATS_NUM_ENTRIES ? hash - PPE1_STATS_NUM_ENTRIES +- : hash; ++ return 0; + } + + static void airoha_ppe_foe_flow_stat_entry_reset(struct airoha_ppe *ppe, +@@ -500,9 +536,13 @@ static void airoha_ppe_foe_flow_stat_ent + static void airoha_ppe_foe_flow_stats_reset(struct airoha_ppe *ppe, + struct airoha_npu *npu) + { +- int i; ++ int i, ppe_num_stats_entries; ++ ++ ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe); ++ if (ppe_num_stats_entries < 0) ++ return; + +- for (i = 0; i < PPE_STATS_NUM_ENTRIES; i++) ++ for (i = 0; i < ppe_num_stats_entries; i++) + airoha_ppe_foe_flow_stat_entry_reset(ppe, npu, i); + } + +@@ -513,10 +553,17 @@ static void airoha_ppe_foe_flow_stats_up + { + int type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe->ib1); + u32 index, pse_port, val, *data, *ib2, *meter; ++ int ppe_num_stats_entries; + u8 nbq; + +- index = airoha_ppe_foe_get_flow_stats_index(ppe, hash); +- if (index >= PPE_STATS_NUM_ENTRIES) ++ ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe); ++ if (ppe_num_stats_entries < 0) ++ return; ++ ++ if (airoha_ppe_foe_get_flow_stats_index(ppe, hash, &index)) ++ return; ++ ++ if (index >= ppe_num_stats_entries) + return; + + if (type == PPE_PKT_TYPE_BRIDGE) { +@@ -1158,11 +1205,19 @@ static int airoha_ppe_flow_offload_destr + void airoha_ppe_foe_entry_get_stats(struct airoha_ppe *ppe, u32 hash, + struct airoha_foe_stats64 *stats) + { +- u32 index = airoha_ppe_foe_get_flow_stats_index(ppe, hash); + struct airoha_eth *eth = ppe->eth; ++ int ppe_num_stats_entries; + struct airoha_npu *npu; ++ u32 index; ++ ++ ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe); ++ if (ppe_num_stats_entries < 0) ++ return; + +- if (index >= PPE_STATS_NUM_ENTRIES) ++ if (airoha_ppe_foe_get_flow_stats_index(ppe, hash, &index)) ++ return; ++ ++ if (index >= ppe_num_stats_entries) + return; + + rcu_read_lock(); +@@ -1257,7 +1312,7 @@ static int airoha_ppe_offload_setup(stru + { + struct airoha_npu *npu = airoha_ppe_npu_get(eth); + struct airoha_ppe *ppe = eth->ppe; +- int err; ++ int err, ppe_num_stats_entries; + + if (IS_ERR(npu)) + return PTR_ERR(npu); +@@ -1266,9 +1321,10 @@ static int airoha_ppe_offload_setup(stru + if (err) + goto error_npu_put; + +- if (PPE_STATS_NUM_ENTRIES) { ++ ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe); ++ if (ppe_num_stats_entries > 0) { + err = npu->ops.ppe_init_stats(npu, ppe->foe_stats_dma, +- PPE_STATS_NUM_ENTRIES); ++ ppe_num_stats_entries); + if (err) + goto error_npu_put; + } +@@ -1405,8 +1461,8 @@ EXPORT_SYMBOL_GPL(airoha_ppe_put_dev); + + int airoha_ppe_init(struct airoha_eth *eth) + { ++ int foe_size, err, ppe_num_stats_entries; + struct airoha_ppe *ppe; +- int foe_size, err; + + ppe = devm_kzalloc(eth->dev, sizeof(*ppe), GFP_KERNEL); + if (!ppe) +@@ -1431,8 +1487,9 @@ int airoha_ppe_init(struct airoha_eth *e + if (!ppe->foe_flow) + return -ENOMEM; + +- foe_size = PPE_STATS_NUM_ENTRIES * sizeof(*ppe->foe_stats); +- if (foe_size) { ++ ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe); ++ if (ppe_num_stats_entries > 0) { ++ foe_size = ppe_num_stats_entries * sizeof(*ppe->foe_stats); + ppe->foe_stats = dmam_alloc_coherent(eth->dev, foe_size, + &ppe->foe_stats_dma, + GFP_KERNEL); diff --git a/lede/target/linux/airoha/patches-6.12/099-03-v6.19-net-airoha-Add-airoha_eth_soc_data-struct.patch b/lede/target/linux/airoha/patches-6.12/099-03-v6.19-net-airoha-Add-airoha_eth_soc_data-struct.patch new file mode 100644 index 0000000000..9035e21447 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/099-03-v6.19-net-airoha-Add-airoha_eth_soc_data-struct.patch @@ -0,0 +1,152 @@ +From 5863b4e065e2253ef05684f728a04e4972046bcb Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 17 Oct 2025 11:06:13 +0200 +Subject: [PATCH 03/12] net: airoha: Add airoha_eth_soc_data struct + +Introduce airoha_eth_soc_data struct to contain differences between +various SoC. Move XSI reset names in airoha_eth_soc_data. This is a +preliminary patch to enable AN7583 ethernet controller support in +airoha-eth driver. + +Co-developed-by: Christian Marangi +Signed-off-by: Christian Marangi +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-4-f28319666667@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 42 +++++++++++++++++++----- + drivers/net/ethernet/airoha/airoha_eth.h | 17 ++++++++-- + 2 files changed, 48 insertions(+), 11 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1392,8 +1392,7 @@ static int airoha_hw_init(struct platfor + int err, i; + + /* disable xsi */ +- err = reset_control_bulk_assert(ARRAY_SIZE(eth->xsi_rsts), +- eth->xsi_rsts); ++ err = reset_control_bulk_assert(eth->soc->num_xsi_rsts, eth->xsi_rsts); + if (err) + return err; + +@@ -2927,6 +2926,7 @@ free_metadata_dst: + + static int airoha_probe(struct platform_device *pdev) + { ++ struct reset_control_bulk_data *xsi_rsts; + struct device_node *np; + struct airoha_eth *eth; + int i, err; +@@ -2935,6 +2935,10 @@ static int airoha_probe(struct platform_ + if (!eth) + return -ENOMEM; + ++ eth->soc = of_device_get_match_data(&pdev->dev); ++ if (!eth->soc) ++ return -EINVAL; ++ + eth->dev = &pdev->dev; + + err = dma_set_mask_and_coherent(eth->dev, DMA_BIT_MASK(32)); +@@ -2959,13 +2963,18 @@ static int airoha_probe(struct platform_ + return err; + } + +- eth->xsi_rsts[0].id = "xsi-mac"; +- eth->xsi_rsts[1].id = "hsi0-mac"; +- eth->xsi_rsts[2].id = "hsi1-mac"; +- eth->xsi_rsts[3].id = "hsi-mac"; +- eth->xsi_rsts[4].id = "xfp-mac"; ++ xsi_rsts = devm_kzalloc(eth->dev, ++ eth->soc->num_xsi_rsts * sizeof(*xsi_rsts), ++ GFP_KERNEL); ++ if (err) ++ return err; ++ ++ eth->xsi_rsts = xsi_rsts; ++ for (i = 0; i < eth->soc->num_xsi_rsts; i++) ++ eth->xsi_rsts[i].id = eth->soc->xsi_rsts_names[i]; ++ + err = devm_reset_control_bulk_get_exclusive(eth->dev, +- ARRAY_SIZE(eth->xsi_rsts), ++ eth->soc->num_xsi_rsts, + eth->xsi_rsts); + if (err) { + dev_err(eth->dev, "failed to get bulk xsi reset lines\n"); +@@ -3052,8 +3061,23 @@ static void airoha_remove(struct platfor + platform_set_drvdata(pdev, NULL); + } + ++static const char * const en7581_xsi_rsts_names[] = { ++ "xsi-mac", ++ "hsi0-mac", ++ "hsi1-mac", ++ "hsi-mac", ++ "xfp-mac", ++}; ++ ++static const struct airoha_eth_soc_data en7581_soc_data = { ++ .version = 0x7581, ++ .xsi_rsts_names = en7581_xsi_rsts_names, ++ .num_xsi_rsts = ARRAY_SIZE(en7581_xsi_rsts_names), ++ .num_ppe = 2, ++}; ++ + static const struct of_device_id of_airoha_match[] = { +- { .compatible = "airoha,en7581-eth" }, ++ { .compatible = "airoha,en7581-eth", .data = &en7581_soc_data }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, of_airoha_match); +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -21,7 +21,6 @@ + #define AIROHA_MAX_NUM_IRQ_BANKS 4 + #define AIROHA_MAX_DSA_PORTS 7 + #define AIROHA_MAX_NUM_RSTS 3 +-#define AIROHA_MAX_NUM_XSI_RSTS 5 + #define AIROHA_MAX_MTU 9216 + #define AIROHA_MAX_PACKET_SIZE 2048 + #define AIROHA_NUM_QOS_CHANNELS 4 +@@ -556,9 +555,18 @@ struct airoha_ppe { + struct dentry *debugfs_dir; + }; + ++struct airoha_eth_soc_data { ++ u16 version; ++ const char * const *xsi_rsts_names; ++ int num_xsi_rsts; ++ int num_ppe; ++}; ++ + struct airoha_eth { + struct device *dev; + ++ const struct airoha_eth_soc_data *soc; ++ + unsigned long state; + void __iomem *fe_regs; + +@@ -568,7 +576,7 @@ struct airoha_eth { + struct rhashtable flow_table; + + struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS]; +- struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS]; ++ struct reset_control_bulk_data *xsi_rsts; + + struct net_device *napi_dev; + +@@ -611,6 +619,11 @@ static inline bool airhoa_is_lan_gdm_por + return port->id == 1; + } + ++static inline bool airoha_is_7581(struct airoha_eth *eth) ++{ ++ return eth->soc->version == 0x7581; ++} ++ + bool airoha_is_valid_gdm_port(struct airoha_eth *eth, + struct airoha_gdm_port *port); + diff --git a/lede/target/linux/airoha/patches-6.12/099-04-v6.19-net-airoha-Generalize-airoha_ppe2_is_enabled-routine.patch b/lede/target/linux/airoha/patches-6.12/099-04-v6.19-net-airoha-Generalize-airoha_ppe2_is_enabled-routine.patch new file mode 100644 index 0000000000..e82ce24e4f --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/099-04-v6.19-net-airoha-Generalize-airoha_ppe2_is_enabled-routine.patch @@ -0,0 +1,147 @@ +From ef9449f080b61920cdc3d3106f8ffc2d9ba8b861 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 17 Oct 2025 11:06:14 +0200 +Subject: [PATCH 04/12] net: airoha: Generalize airoha_ppe2_is_enabled routine + +Rename airoha_ppe2_is_enabled() in airoha_ppe_is_enabled() and +generalize it in order to check if each PPE module is enabled. +Rely on airoha_ppe_is_enabled routine to properly initialize PPE for +AN7583 SoC since AN7583 does not support PPE2. + +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-5-f28319666667@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 32 ++++++++++++++++-------- + drivers/net/ethernet/airoha/airoha_eth.h | 1 + + drivers/net/ethernet/airoha/airoha_ppe.c | 17 +++++++------ + 3 files changed, 32 insertions(+), 18 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -297,8 +297,11 @@ static void airoha_fe_pse_ports_init(str + int q; + + all_rsv = airoha_fe_get_pse_all_rsv(eth); +- /* hw misses PPE2 oq rsv */ +- all_rsv += PSE_RSV_PAGES * pse_port_num_queues[FE_PSE_PORT_PPE2]; ++ if (airoha_ppe_is_enabled(eth, 1)) { ++ /* hw misses PPE2 oq rsv */ ++ all_rsv += PSE_RSV_PAGES * ++ pse_port_num_queues[FE_PSE_PORT_PPE2]; ++ } + airoha_fe_set(eth, REG_FE_PSE_BUF_SET, all_rsv); + + /* CMD1 */ +@@ -335,13 +338,17 @@ static void airoha_fe_pse_ports_init(str + for (q = 4; q < pse_port_num_queues[FE_PSE_PORT_CDM4]; q++) + airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_CDM4, q, + PSE_QUEUE_RSV_PAGES); +- /* PPE2 */ +- for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_PPE2]; q++) { +- if (q < pse_port_num_queues[FE_PSE_PORT_PPE2] / 2) +- airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE2, q, +- PSE_QUEUE_RSV_PAGES); +- else +- airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE2, q, 0); ++ if (airoha_ppe_is_enabled(eth, 1)) { ++ /* PPE2 */ ++ for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_PPE2]; q++) { ++ if (q < pse_port_num_queues[FE_PSE_PORT_PPE2] / 2) ++ airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE2, ++ q, ++ PSE_QUEUE_RSV_PAGES); ++ else ++ airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE2, ++ q, 0); ++ } + } + /* GMD4 */ + for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_GDM4]; q++) +@@ -1767,8 +1774,11 @@ static int airoha_dev_init(struct net_de + airhoha_set_gdm2_loopback(port); + fallthrough; + case 2: +- pse_port = FE_PSE_PORT_PPE2; +- break; ++ if (airoha_ppe_is_enabled(eth, 1)) { ++ pse_port = FE_PSE_PORT_PPE2; ++ break; ++ } ++ fallthrough; + default: + pse_port = FE_PSE_PORT_PPE1; + break; +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -627,6 +627,7 @@ static inline bool airoha_is_7581(struct + bool airoha_is_valid_gdm_port(struct airoha_eth *eth, + struct airoha_gdm_port *port); + ++bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index); + void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb, + u16 hash, bool rx_wlan); + int airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev *dev, void *type_data); +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -50,9 +50,12 @@ static int airoha_ppe_get_total_num_stat + return num_stats; + } + +-static bool airoha_ppe2_is_enabled(struct airoha_eth *eth) ++bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index) + { +- return airoha_fe_rr(eth, REG_PPE_GLO_CFG(1)) & PPE_GLO_CFG_EN_MASK; ++ if (index >= eth->soc->num_ppe) ++ return false; ++ ++ return airoha_fe_rr(eth, REG_PPE_GLO_CFG(index)) & PPE_GLO_CFG_EN_MASK; + } + + static u32 airoha_ppe_get_timestamp(struct airoha_ppe *ppe) +@@ -120,7 +123,7 @@ static void airoha_ppe_hw_init(struct ai + AIROHA_MAX_MTU)); + } + +- if (airoha_ppe2_is_enabled(eth)) { ++ if (airoha_ppe_is_enabled(eth, 1)) { + sram_num_entries = PPE1_SRAM_NUM_ENTRIES; + sram_num_stats_entries = + airoha_ppe_get_num_stats_entries(ppe); +@@ -518,7 +521,7 @@ static int airoha_ppe_foe_get_flow_stats + return ppe_num_stats_entries; + + *index = hash; +- if (airoha_ppe2_is_enabled(ppe->eth) && ++ if (airoha_ppe_is_enabled(ppe->eth, 1) && + hash >= ppe_num_stats_entries) + *index = *index - PPE_STATS_NUM_ENTRIES; + +@@ -613,7 +616,7 @@ airoha_ppe_foe_get_entry_locked(struct a + u32 val; + int i; + +- ppe2 = airoha_ppe2_is_enabled(ppe->eth) && ++ ppe2 = airoha_ppe_is_enabled(ppe->eth, 1) && + hash >= PPE1_SRAM_NUM_ENTRIES; + airoha_fe_wr(ppe->eth, REG_PPE_RAM_CTRL(ppe2), + FIELD_PREP(PPE_SRAM_CTRL_ENTRY_MASK, hash) | +@@ -691,7 +694,7 @@ static int airoha_ppe_foe_commit_entry(s + + if (hash < PPE_SRAM_NUM_ENTRIES) { + dma_addr_t addr = ppe->foe_dma + hash * sizeof(*hwe); +- bool ppe2 = airoha_ppe2_is_enabled(eth) && ++ bool ppe2 = airoha_ppe_is_enabled(eth, 1) && + hash >= PPE1_SRAM_NUM_ENTRIES; + + err = npu->ops.ppe_foe_commit_entry(npu, addr, sizeof(*hwe), +@@ -1286,7 +1289,7 @@ static int airoha_ppe_flush_sram_entries + int i, sram_num_entries = PPE_SRAM_NUM_ENTRIES; + struct airoha_foe_entry *hwe = ppe->foe; + +- if (airoha_ppe2_is_enabled(ppe->eth)) ++ if (airoha_ppe_is_enabled(ppe->eth, 1)) + sram_num_entries = sram_num_entries / 2; + + for (i = 0; i < sram_num_entries; i++) diff --git a/lede/target/linux/airoha/patches-6.12/099-05-v6.19-net-airoha-ppe-Move-PPE-memory-info-in-airoha_eth_so.patch b/lede/target/linux/airoha/patches-6.12/099-05-v6.19-net-airoha-ppe-Move-PPE-memory-info-in-airoha_eth_so.patch new file mode 100644 index 0000000000..2382a21168 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/099-05-v6.19-net-airoha-ppe-Move-PPE-memory-info-in-airoha_eth_so.patch @@ -0,0 +1,359 @@ +From 5bd1d1fd48ea9f8300b211540d946899c7f96480 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 17 Oct 2025 11:06:15 +0200 +Subject: [PATCH 05/12] net: airoha: ppe: Move PPE memory info in + airoha_eth_soc_data struct + +AN7583 SoC runs a single PPE device while EN7581 runs two of them. +Moreover PPE SRAM in AN7583 SoC is reduced to 8K (while SRAM is 16K on +EN7581). Take into account PPE memory layout during PPE configuration. + +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-6-f28319666667@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.h | 10 +- + drivers/net/ethernet/airoha/airoha_ppe.c | 133 +++++++++--------- + .../net/ethernet/airoha/airoha_ppe_debugfs.c | 3 +- + 3 files changed, 70 insertions(+), 76 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -47,14 +47,9 @@ + #define QDMA_METER_IDX(_n) ((_n) & 0xff) + #define QDMA_METER_GROUP(_n) (((_n) >> 8) & 0x3) + +-#define PPE_NUM 2 +-#define PPE1_SRAM_NUM_ENTRIES (8 * 1024) +-#define PPE_SRAM_NUM_ENTRIES (PPE_NUM * PPE1_SRAM_NUM_ENTRIES) +-#define PPE1_STATS_NUM_ENTRIES (4 * 1024) +-#define PPE_STATS_NUM_ENTRIES (PPE_NUM * PPE1_STATS_NUM_ENTRIES) ++#define PPE_SRAM_NUM_ENTRIES (8 * 1024) ++#define PPE_STATS_NUM_ENTRIES (4 * 1024) + #define PPE_DRAM_NUM_ENTRIES (16 * 1024) +-#define PPE_NUM_ENTRIES (PPE_SRAM_NUM_ENTRIES + PPE_DRAM_NUM_ENTRIES) +-#define PPE_HASH_MASK (PPE_NUM_ENTRIES - 1) + #define PPE_ENTRY_SIZE 80 + #define PPE_RAM_NUM_ENTRIES_SHIFT(_n) (__ffs((_n) >> 10)) + +@@ -634,6 +629,7 @@ int airoha_ppe_setup_tc_block_cb(struct + int airoha_ppe_init(struct airoha_eth *eth); + void airoha_ppe_deinit(struct airoha_eth *eth); + void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port); ++u32 airoha_ppe_get_total_num_entries(struct airoha_ppe *ppe); + struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe, + u32 hash); + void airoha_ppe_foe_entry_get_stats(struct airoha_ppe *ppe, u32 hash, +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -37,19 +37,36 @@ static int airoha_ppe_get_num_stats_entr + if (!IS_ENABLED(CONFIG_NET_AIROHA_FLOW_STATS)) + return -EOPNOTSUPP; + +- return PPE1_STATS_NUM_ENTRIES; ++ return PPE_STATS_NUM_ENTRIES; + } + + static int airoha_ppe_get_total_num_stats_entries(struct airoha_ppe *ppe) + { + int num_stats = airoha_ppe_get_num_stats_entries(ppe); + +- if (num_stats > 0) +- num_stats = num_stats * PPE_NUM; ++ if (num_stats > 0) { ++ struct airoha_eth *eth = ppe->eth; ++ ++ num_stats = num_stats * eth->soc->num_ppe; ++ } + + return num_stats; + } + ++static u32 airoha_ppe_get_total_sram_num_entries(struct airoha_ppe *ppe) ++{ ++ struct airoha_eth *eth = ppe->eth; ++ ++ return PPE_SRAM_NUM_ENTRIES * eth->soc->num_ppe; ++} ++ ++u32 airoha_ppe_get_total_num_entries(struct airoha_ppe *ppe) ++{ ++ u32 sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe); ++ ++ return sram_num_entries + PPE_DRAM_NUM_ENTRIES; ++} ++ + bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index) + { + if (index >= eth->soc->num_ppe) +@@ -67,14 +84,22 @@ static u32 airoha_ppe_get_timestamp(stru + + static void airoha_ppe_hw_init(struct airoha_ppe *ppe) + { +- u32 sram_tb_size, sram_num_entries, dram_num_entries; ++ u32 sram_ppe_num_data_entries = PPE_SRAM_NUM_ENTRIES, sram_num_entries; ++ u32 sram_tb_size, dram_num_entries; + struct airoha_eth *eth = ppe->eth; + int i, sram_num_stats_entries; + +- sram_tb_size = PPE_SRAM_NUM_ENTRIES * sizeof(struct airoha_foe_entry); ++ sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe); ++ sram_tb_size = sram_num_entries * sizeof(struct airoha_foe_entry); + dram_num_entries = PPE_RAM_NUM_ENTRIES_SHIFT(PPE_DRAM_NUM_ENTRIES); + +- for (i = 0; i < PPE_NUM; i++) { ++ sram_num_stats_entries = airoha_ppe_get_num_stats_entries(ppe); ++ if (sram_num_stats_entries > 0) ++ sram_ppe_num_data_entries -= sram_num_stats_entries; ++ sram_ppe_num_data_entries = ++ PPE_RAM_NUM_ENTRIES_SHIFT(sram_ppe_num_data_entries); ++ ++ for (i = 0; i < eth->soc->num_ppe; i++) { + int p; + + airoha_fe_wr(eth, REG_PPE_TB_BASE(i), +@@ -106,10 +131,16 @@ static void airoha_ppe_hw_init(struct ai + + airoha_fe_rmw(eth, REG_PPE_TB_CFG(i), + PPE_TB_CFG_SEARCH_MISS_MASK | ++ PPE_SRAM_TB_NUM_ENTRY_MASK | ++ PPE_DRAM_TB_NUM_ENTRY_MASK | + PPE_TB_CFG_KEEPALIVE_MASK | + PPE_TB_ENTRY_SIZE_MASK, + FIELD_PREP(PPE_TB_CFG_SEARCH_MISS_MASK, 3) | +- FIELD_PREP(PPE_TB_ENTRY_SIZE_MASK, 0)); ++ FIELD_PREP(PPE_TB_ENTRY_SIZE_MASK, 0) | ++ FIELD_PREP(PPE_SRAM_TB_NUM_ENTRY_MASK, ++ sram_ppe_num_data_entries) | ++ FIELD_PREP(PPE_DRAM_TB_NUM_ENTRY_MASK, ++ dram_num_entries)); + + airoha_fe_wr(eth, REG_PPE_HASH_SEED(i), PPE_HASH_SEED); + +@@ -122,45 +153,6 @@ static void airoha_ppe_hw_init(struct ai + FIELD_PREP(FP1_EGRESS_MTU_MASK, + AIROHA_MAX_MTU)); + } +- +- if (airoha_ppe_is_enabled(eth, 1)) { +- sram_num_entries = PPE1_SRAM_NUM_ENTRIES; +- sram_num_stats_entries = +- airoha_ppe_get_num_stats_entries(ppe); +- if (sram_num_stats_entries > 0) +- sram_num_entries -= sram_num_stats_entries; +- sram_num_entries = PPE_RAM_NUM_ENTRIES_SHIFT(sram_num_entries); +- +- airoha_fe_rmw(eth, REG_PPE_TB_CFG(0), +- PPE_SRAM_TB_NUM_ENTRY_MASK | +- PPE_DRAM_TB_NUM_ENTRY_MASK, +- FIELD_PREP(PPE_SRAM_TB_NUM_ENTRY_MASK, +- sram_num_entries) | +- FIELD_PREP(PPE_DRAM_TB_NUM_ENTRY_MASK, +- dram_num_entries)); +- airoha_fe_rmw(eth, REG_PPE_TB_CFG(1), +- PPE_SRAM_TB_NUM_ENTRY_MASK | +- PPE_DRAM_TB_NUM_ENTRY_MASK, +- FIELD_PREP(PPE_SRAM_TB_NUM_ENTRY_MASK, +- sram_num_entries) | +- FIELD_PREP(PPE_DRAM_TB_NUM_ENTRY_MASK, +- dram_num_entries)); +- } else { +- sram_num_entries = PPE_SRAM_NUM_ENTRIES; +- sram_num_stats_entries = +- airoha_ppe_get_total_num_stats_entries(ppe); +- if (sram_num_stats_entries > 0) +- sram_num_entries -= sram_num_stats_entries; +- sram_num_entries = PPE_RAM_NUM_ENTRIES_SHIFT(sram_num_entries); +- +- airoha_fe_rmw(eth, REG_PPE_TB_CFG(0), +- PPE_SRAM_TB_NUM_ENTRY_MASK | +- PPE_DRAM_TB_NUM_ENTRY_MASK, +- FIELD_PREP(PPE_SRAM_TB_NUM_ENTRY_MASK, +- sram_num_entries) | +- FIELD_PREP(PPE_DRAM_TB_NUM_ENTRY_MASK, +- dram_num_entries)); +- } + } + + static void airoha_ppe_flow_mangle_eth(const struct flow_action_entry *act, void *eth) +@@ -459,9 +451,11 @@ static int airoha_ppe_foe_entry_set_ipv6 + return 0; + } + +-static u32 airoha_ppe_foe_get_entry_hash(struct airoha_foe_entry *hwe) ++static u32 airoha_ppe_foe_get_entry_hash(struct airoha_ppe *ppe, ++ struct airoha_foe_entry *hwe) + { + int type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe->ib1); ++ u32 ppe_hash_mask = airoha_ppe_get_total_num_entries(ppe) - 1; + u32 hash, hv1, hv2, hv3; + + switch (type) { +@@ -499,14 +493,14 @@ static u32 airoha_ppe_foe_get_entry_hash + case PPE_PKT_TYPE_IPV6_6RD: + default: + WARN_ON_ONCE(1); +- return PPE_HASH_MASK; ++ return ppe_hash_mask; + } + + hash = (hv1 & hv2) | ((~hv1) & hv3); + hash = (hash >> 24) | ((hash & 0xffffff) << 8); + hash ^= hv1 ^ hv2 ^ hv3; + hash ^= hash >> 16; +- hash &= PPE_NUM_ENTRIES - 1; ++ hash &= ppe_hash_mask; + + return hash; + } +@@ -607,9 +601,11 @@ static void airoha_ppe_foe_flow_stats_up + static struct airoha_foe_entry * + airoha_ppe_foe_get_entry_locked(struct airoha_ppe *ppe, u32 hash) + { ++ u32 sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe); ++ + lockdep_assert_held(&ppe_lock); + +- if (hash < PPE_SRAM_NUM_ENTRIES) { ++ if (hash < sram_num_entries) { + u32 *hwe = ppe->foe + hash * sizeof(struct airoha_foe_entry); + struct airoha_eth *eth = ppe->eth; + bool ppe2; +@@ -617,7 +613,7 @@ airoha_ppe_foe_get_entry_locked(struct a + int i; + + ppe2 = airoha_ppe_is_enabled(ppe->eth, 1) && +- hash >= PPE1_SRAM_NUM_ENTRIES; ++ hash >= PPE_SRAM_NUM_ENTRIES; + airoha_fe_wr(ppe->eth, REG_PPE_RAM_CTRL(ppe2), + FIELD_PREP(PPE_SRAM_CTRL_ENTRY_MASK, hash) | + PPE_SRAM_CTRL_REQ_MASK); +@@ -668,6 +664,7 @@ static int airoha_ppe_foe_commit_entry(s + struct airoha_foe_entry *e, + u32 hash, bool rx_wlan) + { ++ u32 sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe); + struct airoha_foe_entry *hwe = ppe->foe + hash * sizeof(*hwe); + u32 ts = airoha_ppe_get_timestamp(ppe); + struct airoha_eth *eth = ppe->eth; +@@ -692,10 +689,10 @@ static int airoha_ppe_foe_commit_entry(s + if (!rx_wlan) + airoha_ppe_foe_flow_stats_update(ppe, npu, hwe, hash); + +- if (hash < PPE_SRAM_NUM_ENTRIES) { ++ if (hash < sram_num_entries) { + dma_addr_t addr = ppe->foe_dma + hash * sizeof(*hwe); + bool ppe2 = airoha_ppe_is_enabled(eth, 1) && +- hash >= PPE1_SRAM_NUM_ENTRIES; ++ hash >= PPE_SRAM_NUM_ENTRIES; + + err = npu->ops.ppe_foe_commit_entry(npu, addr, sizeof(*hwe), + hash, ppe2); +@@ -822,7 +819,7 @@ static void airoha_ppe_foe_insert_entry( + if (state == AIROHA_FOE_STATE_BIND) + goto unlock; + +- index = airoha_ppe_foe_get_entry_hash(hwe); ++ index = airoha_ppe_foe_get_entry_hash(ppe, hwe); + hlist_for_each_entry_safe(e, n, &ppe->foe_flow[index], list) { + if (e->type == FLOW_TYPE_L2_SUBFLOW) { + state = FIELD_GET(AIROHA_FOE_IB1_BIND_STATE, hwe->ib1); +@@ -882,7 +879,7 @@ static int airoha_ppe_foe_flow_commit_en + if (type == PPE_PKT_TYPE_BRIDGE) + return airoha_ppe_foe_l2_flow_commit_entry(ppe, e); + +- hash = airoha_ppe_foe_get_entry_hash(&e->data); ++ hash = airoha_ppe_foe_get_entry_hash(ppe, &e->data); + e->type = FLOW_TYPE_L4; + e->hash = 0xffff; + +@@ -1286,17 +1283,15 @@ static int airoha_ppe_flow_offload_cmd(s + static int airoha_ppe_flush_sram_entries(struct airoha_ppe *ppe, + struct airoha_npu *npu) + { +- int i, sram_num_entries = PPE_SRAM_NUM_ENTRIES; ++ u32 sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe); + struct airoha_foe_entry *hwe = ppe->foe; ++ int i; + +- if (airoha_ppe_is_enabled(ppe->eth, 1)) +- sram_num_entries = sram_num_entries / 2; +- +- for (i = 0; i < sram_num_entries; i++) ++ for (i = 0; i < PPE_SRAM_NUM_ENTRIES; i++) + memset(&hwe[i], 0, sizeof(*hwe)); + + return npu->ops.ppe_flush_sram_entries(npu, ppe->foe_dma, +- PPE_SRAM_NUM_ENTRIES); ++ sram_num_entries); + } + + static struct airoha_npu *airoha_ppe_npu_get(struct airoha_eth *eth) +@@ -1372,9 +1367,10 @@ void airoha_ppe_check_skb(struct airoha_ + u16 hash, bool rx_wlan) + { + struct airoha_ppe *ppe = dev->priv; ++ u32 ppe_hash_mask = airoha_ppe_get_total_num_entries(ppe) - 1; + u16 now, diff; + +- if (hash > PPE_HASH_MASK) ++ if (hash > ppe_hash_mask) + return; + + now = (u16)jiffies; +@@ -1465,6 +1461,7 @@ EXPORT_SYMBOL_GPL(airoha_ppe_put_dev); + int airoha_ppe_init(struct airoha_eth *eth) + { + int foe_size, err, ppe_num_stats_entries; ++ u32 ppe_num_entries; + struct airoha_ppe *ppe; + + ppe = devm_kzalloc(eth->dev, sizeof(*ppe), GFP_KERNEL); +@@ -1474,18 +1471,18 @@ int airoha_ppe_init(struct airoha_eth *e + ppe->dev.ops.setup_tc_block_cb = airoha_ppe_setup_tc_block_cb; + ppe->dev.ops.check_skb = airoha_ppe_check_skb; + ppe->dev.priv = ppe; ++ ppe->eth = eth; ++ eth->ppe = ppe; + +- foe_size = PPE_NUM_ENTRIES * sizeof(struct airoha_foe_entry); ++ ppe_num_entries = airoha_ppe_get_total_num_entries(ppe); ++ foe_size = ppe_num_entries * sizeof(struct airoha_foe_entry); + ppe->foe = dmam_alloc_coherent(eth->dev, foe_size, &ppe->foe_dma, + GFP_KERNEL); + if (!ppe->foe) + return -ENOMEM; + +- ppe->eth = eth; +- eth->ppe = ppe; +- + ppe->foe_flow = devm_kzalloc(eth->dev, +- PPE_NUM_ENTRIES * sizeof(*ppe->foe_flow), ++ ppe_num_entries * sizeof(*ppe->foe_flow), + GFP_KERNEL); + if (!ppe->foe_flow) + return -ENOMEM; +@@ -1500,7 +1497,7 @@ int airoha_ppe_init(struct airoha_eth *e + return -ENOMEM; + } + +- ppe->foe_check_time = devm_kzalloc(eth->dev, PPE_NUM_ENTRIES, ++ ppe->foe_check_time = devm_kzalloc(eth->dev, ppe_num_entries, + GFP_KERNEL); + if (!ppe->foe_check_time) + return -ENOMEM; +--- a/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c +@@ -53,9 +53,10 @@ static int airoha_ppe_debugfs_foe_show(s + [AIROHA_FOE_STATE_FIN] = "FIN", + }; + struct airoha_ppe *ppe = m->private; ++ u32 ppe_num_entries = airoha_ppe_get_total_num_entries(ppe); + int i; + +- for (i = 0; i < PPE_NUM_ENTRIES; i++) { ++ for (i = 0; i < ppe_num_entries; i++) { + const char *state_str, *type_str = "UNKNOWN"; + void *src_addr = NULL, *dest_addr = NULL; + u16 *src_port = NULL, *dest_port = NULL; diff --git a/lede/target/linux/airoha/patches-6.12/099-06-v6.19-net-airoha-ppe-Remove-airoha_ppe_is_enabled-where-no.patch b/lede/target/linux/airoha/patches-6.12/099-06-v6.19-net-airoha-ppe-Remove-airoha_ppe_is_enabled-where-no.patch new file mode 100644 index 0000000000..18b92fb50d --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/099-06-v6.19-net-airoha-ppe-Remove-airoha_ppe_is_enabled-where-no.patch @@ -0,0 +1,58 @@ +From 41139125f5c70e0f66f0cc4ac1b3a62f5801ab42 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 17 Oct 2025 11:06:16 +0200 +Subject: [PATCH 06/12] net: airoha: ppe: Remove airoha_ppe_is_enabled() where + not necessary + +Now each PPE has always PPE_STATS_NUM_ENTRIES entries so we do not need +to run airoha_ppe_is_enabled routine to check if the hash refers to +PPE1 or PPE2. + +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-7-f28319666667@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 13 ++++--------- + 1 file changed, 4 insertions(+), 9 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -514,10 +514,8 @@ static int airoha_ppe_foe_get_flow_stats + if (ppe_num_stats_entries < 0) + return ppe_num_stats_entries; + +- *index = hash; +- if (airoha_ppe_is_enabled(ppe->eth, 1) && +- hash >= ppe_num_stats_entries) +- *index = *index - PPE_STATS_NUM_ENTRIES; ++ *index = hash >= ppe_num_stats_entries ? hash - PPE_STATS_NUM_ENTRIES ++ : hash; + + return 0; + } +@@ -607,13 +605,11 @@ airoha_ppe_foe_get_entry_locked(struct a + + if (hash < sram_num_entries) { + u32 *hwe = ppe->foe + hash * sizeof(struct airoha_foe_entry); ++ bool ppe2 = hash >= PPE_SRAM_NUM_ENTRIES; + struct airoha_eth *eth = ppe->eth; +- bool ppe2; + u32 val; + int i; + +- ppe2 = airoha_ppe_is_enabled(ppe->eth, 1) && +- hash >= PPE_SRAM_NUM_ENTRIES; + airoha_fe_wr(ppe->eth, REG_PPE_RAM_CTRL(ppe2), + FIELD_PREP(PPE_SRAM_CTRL_ENTRY_MASK, hash) | + PPE_SRAM_CTRL_REQ_MASK); +@@ -691,8 +687,7 @@ static int airoha_ppe_foe_commit_entry(s + + if (hash < sram_num_entries) { + dma_addr_t addr = ppe->foe_dma + hash * sizeof(*hwe); +- bool ppe2 = airoha_ppe_is_enabled(eth, 1) && +- hash >= PPE_SRAM_NUM_ENTRIES; ++ bool ppe2 = hash >= PPE_SRAM_NUM_ENTRIES; + + err = npu->ops.ppe_foe_commit_entry(npu, addr, sizeof(*hwe), + hash, ppe2); diff --git a/lede/target/linux/airoha/patches-6.12/099-07-v6.19-net-airoha-ppe-Configure-SRAM-PPE-entries-via-the-cp.patch b/lede/target/linux/airoha/patches-6.12/099-07-v6.19-net-airoha-ppe-Configure-SRAM-PPE-entries-via-the-cp.patch new file mode 100644 index 0000000000..60b4ee1e44 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/099-07-v6.19-net-airoha-ppe-Configure-SRAM-PPE-entries-via-the-cp.patch @@ -0,0 +1,65 @@ +From 306b78f5035af4bd011753c5a6b12812515caa6c Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 17 Oct 2025 11:06:17 +0200 +Subject: [PATCH 07/12] net: airoha: ppe: Configure SRAM PPE entries via the + cpu + +Introduce airoha_ppe_foe_commit_sram_entry routine in order to configure +the SRAM PPE entries directly via the CPU instead of using the NPU APIs. +This is a preliminary patch to enable netfilter flowtable hw offload for +AN7583 SoC. + +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-8-f28319666667@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 30 ++++++++++++++++++------ + 1 file changed, 23 insertions(+), 7 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -656,6 +656,27 @@ static bool airoha_ppe_foe_compare_entry + return !memcmp(&e->data.d, &hwe->d, len - sizeof(hwe->ib1)); + } + ++static int airoha_ppe_foe_commit_sram_entry(struct airoha_ppe *ppe, u32 hash) ++{ ++ struct airoha_foe_entry *hwe = ppe->foe + hash * sizeof(*hwe); ++ bool ppe2 = hash >= PPE_SRAM_NUM_ENTRIES; ++ u32 *ptr = (u32 *)hwe, val; ++ int i; ++ ++ for (i = 0; i < sizeof(*hwe) / sizeof(*ptr); i++) ++ airoha_fe_wr(ppe->eth, REG_PPE_RAM_ENTRY(ppe2, i), ptr[i]); ++ ++ wmb(); ++ airoha_fe_wr(ppe->eth, REG_PPE_RAM_CTRL(ppe2), ++ FIELD_PREP(PPE_SRAM_CTRL_ENTRY_MASK, hash) | ++ PPE_SRAM_CTRL_WR_MASK | PPE_SRAM_CTRL_REQ_MASK); ++ ++ return read_poll_timeout_atomic(airoha_fe_rr, val, ++ val & PPE_SRAM_CTRL_ACK_MASK, ++ 10, 100, false, ppe->eth, ++ REG_PPE_RAM_CTRL(ppe2)); ++} ++ + static int airoha_ppe_foe_commit_entry(struct airoha_ppe *ppe, + struct airoha_foe_entry *e, + u32 hash, bool rx_wlan) +@@ -685,13 +706,8 @@ static int airoha_ppe_foe_commit_entry(s + if (!rx_wlan) + airoha_ppe_foe_flow_stats_update(ppe, npu, hwe, hash); + +- if (hash < sram_num_entries) { +- dma_addr_t addr = ppe->foe_dma + hash * sizeof(*hwe); +- bool ppe2 = hash >= PPE_SRAM_NUM_ENTRIES; +- +- err = npu->ops.ppe_foe_commit_entry(npu, addr, sizeof(*hwe), +- hash, ppe2); +- } ++ if (hash < sram_num_entries) ++ err = airoha_ppe_foe_commit_sram_entry(ppe, hash); + unlock: + rcu_read_unlock(); + diff --git a/lede/target/linux/airoha/patches-6.12/099-08-v6.19-net-airoha-ppe-Flush-PPE-SRAM-table-during-PPE-setup.patch b/lede/target/linux/airoha/patches-6.12/099-08-v6.19-net-airoha-ppe-Flush-PPE-SRAM-table-during-PPE-setup.patch new file mode 100644 index 0000000000..24ecccabc8 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/099-08-v6.19-net-airoha-ppe-Flush-PPE-SRAM-table-during-PPE-setup.patch @@ -0,0 +1,71 @@ +From 620d7b91aadbd4eb930895b07e34f0a155a9d3c1 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 17 Oct 2025 11:06:18 +0200 +Subject: [PATCH 08/12] net: airoha: ppe: Flush PPE SRAM table during PPE setup + +Rely on airoha_ppe_foe_commit_sram_entry routine to flush SRAM PPE table +entries. This patch allow moving PPE SRAM flush during PPE setup and +avoid dumping uninitialized values via the debugfs if no entries are +offloaded yet. + +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-9-f28319666667@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 24 ++++++++++++++---------- + 1 file changed, 14 insertions(+), 10 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -1291,18 +1291,22 @@ static int airoha_ppe_flow_offload_cmd(s + return -EOPNOTSUPP; + } + +-static int airoha_ppe_flush_sram_entries(struct airoha_ppe *ppe, +- struct airoha_npu *npu) ++static int airoha_ppe_flush_sram_entries(struct airoha_ppe *ppe) + { + u32 sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe); + struct airoha_foe_entry *hwe = ppe->foe; +- int i; ++ int i, err = 0; ++ ++ for (i = 0; i < sram_num_entries; i++) { ++ int err; + +- for (i = 0; i < PPE_SRAM_NUM_ENTRIES; i++) + memset(&hwe[i], 0, sizeof(*hwe)); ++ err = airoha_ppe_foe_commit_sram_entry(ppe, i); ++ if (err) ++ break; ++ } + +- return npu->ops.ppe_flush_sram_entries(npu, ppe->foe_dma, +- sram_num_entries); ++ return err; + } + + static struct airoha_npu *airoha_ppe_npu_get(struct airoha_eth *eth) +@@ -1339,10 +1343,6 @@ static int airoha_ppe_offload_setup(stru + } + + airoha_ppe_hw_init(ppe); +- err = airoha_ppe_flush_sram_entries(ppe, npu); +- if (err) +- goto error_npu_put; +- + airoha_ppe_foe_flow_stats_reset(ppe, npu); + + rcu_assign_pointer(eth->npu, npu); +@@ -1513,6 +1513,10 @@ int airoha_ppe_init(struct airoha_eth *e + if (!ppe->foe_check_time) + return -ENOMEM; + ++ err = airoha_ppe_flush_sram_entries(ppe); ++ if (err) ++ return err; ++ + err = rhashtable_init(ð->flow_table, &airoha_flow_table_params); + if (err) + return err; diff --git a/lede/target/linux/airoha/patches-6.12/099-09-v6.19-net-airoha-Select-default-ppe-cpu-port-in-airoha_dev.patch b/lede/target/linux/airoha/patches-6.12/099-09-v6.19-net-airoha-Select-default-ppe-cpu-port-in-airoha_dev.patch new file mode 100644 index 0000000000..c6ecbdb829 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/099-09-v6.19-net-airoha-Select-default-ppe-cpu-port-in-airoha_dev.patch @@ -0,0 +1,91 @@ +From c71a7a861ef02aa2bebb18c2f3385aa3f19094e0 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 17 Oct 2025 11:06:19 +0200 +Subject: [PATCH 09/12] net: airoha: Select default ppe cpu port in + airoha_dev_init() + +Select the PPE default cpu port in airoha_dev_init routine. +This patch allows to distribute the load between the two available cpu +ports (FE_PSE_PORT_CDM1 and FE_PSE_PORT_CDM2) if the device is running a +single PPE module (e.g. 7583) selecting the cpu port based on the use +QDMA device. For multi-PPE device (e.g. 7581) assign FE_PSE_PORT_CDM1 to +PPE1 and FE_PSE_PORT_CDM2 to PPE2. + +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-10-f28319666667@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 38 ++++++++++-------------- + 1 file changed, 16 insertions(+), 22 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -531,25 +531,6 @@ static int airoha_fe_init(struct airoha_ + /* disable IFC by default */ + airoha_fe_clear(eth, REG_FE_CSR_IFC_CFG, FE_IFC_EN_MASK); + +- airoha_fe_wr(eth, REG_PPE_DFT_CPORT0(0), +- FIELD_PREP(DFT_CPORT_MASK(7), FE_PSE_PORT_CDM1) | +- FIELD_PREP(DFT_CPORT_MASK(6), FE_PSE_PORT_CDM1) | +- FIELD_PREP(DFT_CPORT_MASK(5), FE_PSE_PORT_CDM1) | +- FIELD_PREP(DFT_CPORT_MASK(4), FE_PSE_PORT_CDM1) | +- FIELD_PREP(DFT_CPORT_MASK(3), FE_PSE_PORT_CDM1) | +- FIELD_PREP(DFT_CPORT_MASK(2), FE_PSE_PORT_CDM1) | +- FIELD_PREP(DFT_CPORT_MASK(1), FE_PSE_PORT_CDM1) | +- FIELD_PREP(DFT_CPORT_MASK(0), FE_PSE_PORT_CDM1)); +- airoha_fe_wr(eth, REG_PPE_DFT_CPORT0(1), +- FIELD_PREP(DFT_CPORT_MASK(7), FE_PSE_PORT_CDM2) | +- FIELD_PREP(DFT_CPORT_MASK(6), FE_PSE_PORT_CDM2) | +- FIELD_PREP(DFT_CPORT_MASK(5), FE_PSE_PORT_CDM2) | +- FIELD_PREP(DFT_CPORT_MASK(4), FE_PSE_PORT_CDM2) | +- FIELD_PREP(DFT_CPORT_MASK(3), FE_PSE_PORT_CDM2) | +- FIELD_PREP(DFT_CPORT_MASK(2), FE_PSE_PORT_CDM2) | +- FIELD_PREP(DFT_CPORT_MASK(1), FE_PSE_PORT_CDM2) | +- FIELD_PREP(DFT_CPORT_MASK(0), FE_PSE_PORT_CDM2)); +- + /* enable 1:N vlan action, init vlan table */ + airoha_fe_set(eth, REG_MC_VLAN_EN, MC_VLAN_EN_MASK); + +@@ -1761,8 +1742,10 @@ static void airhoha_set_gdm2_loopback(st + static int airoha_dev_init(struct net_device *dev) + { + struct airoha_gdm_port *port = netdev_priv(dev); +- struct airoha_eth *eth = port->qdma->eth; +- u32 pse_port; ++ struct airoha_qdma *qdma = port->qdma; ++ struct airoha_eth *eth = qdma->eth; ++ u32 pse_port, fe_cpu_port; ++ u8 ppe_id; + + airoha_set_macaddr(port, dev->dev_addr); + +@@ -1775,16 +1758,27 @@ static int airoha_dev_init(struct net_de + fallthrough; + case 2: + if (airoha_ppe_is_enabled(eth, 1)) { ++ /* For PPE2 always use secondary cpu port. */ ++ fe_cpu_port = FE_PSE_PORT_CDM2; + pse_port = FE_PSE_PORT_PPE2; + break; + } + fallthrough; +- default: ++ default: { ++ u8 qdma_id = qdma - ð->qdma[0]; ++ ++ /* For PPE1 select cpu port according to the running QDMA. */ ++ fe_cpu_port = qdma_id ? FE_PSE_PORT_CDM2 : FE_PSE_PORT_CDM1; + pse_port = FE_PSE_PORT_PPE1; + break; + } ++ } + + airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), pse_port); ++ ppe_id = pse_port == FE_PSE_PORT_PPE2 ? 1 : 0; ++ airoha_fe_rmw(eth, REG_PPE_DFT_CPORT0(ppe_id), ++ DFT_CPORT_MASK(port->id), ++ fe_cpu_port << __ffs(DFT_CPORT_MASK(port->id))); + + return 0; + } diff --git a/lede/target/linux/airoha/patches-6.12/099-10-v6.19-net-airoha-Refactor-src-port-configuration-in-airhoh.patch b/lede/target/linux/airoha/patches-6.12/099-10-v6.19-net-airoha-Refactor-src-port-configuration-in-airhoh.patch new file mode 100644 index 0000000000..cec079845c --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/099-10-v6.19-net-airoha-Refactor-src-port-configuration-in-airhoh.patch @@ -0,0 +1,202 @@ +From 9d5b5219f672c80bed4d4e15f0068e648cdca43b Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 17 Oct 2025 11:06:20 +0200 +Subject: [PATCH 10/12] net: airoha: Refactor src port configuration in + airhoha_set_gdm2_loopback + +AN7583 chipset relies on different definitions for source-port +identifier used for hw offloading. In order to support hw offloading +in AN7583 controller, refactor src port configuration in +airhoha_set_gdm2_loopback routine and introduce get_src_port_id +callback. + +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-11-f28319666667@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 82 ++++++++++++++++------- + drivers/net/ethernet/airoha/airoha_eth.h | 18 +++-- + drivers/net/ethernet/airoha/airoha_regs.h | 6 +- + 3 files changed, 73 insertions(+), 33 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1687,13 +1687,17 @@ static int airoha_dev_set_macaddr(struct + return 0; + } + +-static void airhoha_set_gdm2_loopback(struct airoha_gdm_port *port) ++static int airhoha_set_gdm2_loopback(struct airoha_gdm_port *port) + { +- u32 pse_port = port->id == 3 ? FE_PSE_PORT_GDM3 : FE_PSE_PORT_GDM4; ++ u32 val, pse_port, chan = port->id == AIROHA_GDM3_IDX ? 4 : 0; + struct airoha_eth *eth = port->qdma->eth; +- u32 chan = port->id == 3 ? 4 : 0; ++ /* XXX: handle XSI_USB_PORT and XSI_PCE1_PORT */ ++ u32 nbq = port->id == AIROHA_GDM3_IDX ? 4 : 0; ++ int src_port; + + /* Forward the traffic to the proper GDM port */ ++ pse_port = port->id == AIROHA_GDM3_IDX ? FE_PSE_PORT_GDM3 ++ : FE_PSE_PORT_GDM4; + airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(2), pse_port); + airoha_fe_clear(eth, REG_GDM_FWD_CFG(2), GDM_STRIP_CRC); + +@@ -1714,29 +1718,25 @@ static void airhoha_set_gdm2_loopback(st + airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(2)); + airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(2)); + +- if (port->id == 3) { +- /* FIXME: handle XSI_PCE1_PORT */ +- airoha_fe_rmw(eth, REG_FE_WAN_PORT, +- WAN1_EN_MASK | WAN1_MASK | WAN0_MASK, +- FIELD_PREP(WAN0_MASK, HSGMII_LAN_PCIE0_SRCPORT)); +- airoha_fe_rmw(eth, +- REG_SP_DFT_CPORT(HSGMII_LAN_PCIE0_SRCPORT >> 3), +- SP_CPORT_PCIE0_MASK, +- FIELD_PREP(SP_CPORT_PCIE0_MASK, +- FE_PSE_PORT_CDM2)); +- } else { +- /* FIXME: handle XSI_USB_PORT */ ++ src_port = eth->soc->ops.get_src_port_id(port, nbq); ++ if (src_port < 0) ++ return src_port; ++ ++ airoha_fe_rmw(eth, REG_FE_WAN_PORT, ++ WAN1_EN_MASK | WAN1_MASK | WAN0_MASK, ++ FIELD_PREP(WAN0_MASK, src_port)); ++ val = src_port & SP_CPORT_DFT_MASK; ++ airoha_fe_rmw(eth, ++ REG_SP_DFT_CPORT(src_port >> fls(SP_CPORT_DFT_MASK)), ++ SP_CPORT_MASK(val), ++ FE_PSE_PORT_CDM2 << __ffs(SP_CPORT_MASK(val))); ++ ++ if (port->id != AIROHA_GDM3_IDX) + airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6, + FC_ID_OF_SRC_PORT24_MASK, + FIELD_PREP(FC_ID_OF_SRC_PORT24_MASK, 2)); +- airoha_fe_rmw(eth, REG_FE_WAN_PORT, +- WAN1_EN_MASK | WAN1_MASK | WAN0_MASK, +- FIELD_PREP(WAN0_MASK, HSGMII_LAN_ETH_SRCPORT)); +- airoha_fe_rmw(eth, +- REG_SP_DFT_CPORT(HSGMII_LAN_ETH_SRCPORT >> 3), +- SP_CPORT_ETH_MASK, +- FIELD_PREP(SP_CPORT_ETH_MASK, FE_PSE_PORT_CDM2)); +- } ++ ++ return 0; + } + + static int airoha_dev_init(struct net_device *dev) +@@ -1753,8 +1753,13 @@ static int airoha_dev_init(struct net_de + case 3: + case 4: + /* If GDM2 is active we can't enable loopback */ +- if (!eth->ports[1]) +- airhoha_set_gdm2_loopback(port); ++ if (!eth->ports[1]) { ++ int err; ++ ++ err = airhoha_set_gdm2_loopback(port); ++ if (err) ++ return err; ++ } + fallthrough; + case 2: + if (airoha_ppe_is_enabled(eth, 1)) { +@@ -3073,11 +3078,38 @@ static const char * const en7581_xsi_rst + "xfp-mac", + }; + ++static int airoha_en7581_get_src_port_id(struct airoha_gdm_port *port, int nbq) ++{ ++ switch (port->id) { ++ case 3: ++ /* 7581 SoC supports PCIe serdes on GDM3 port */ ++ if (nbq == 4) ++ return HSGMII_LAN_7581_PCIE0_SRCPORT; ++ if (nbq == 5) ++ return HSGMII_LAN_7581_PCIE1_SRCPORT; ++ break; ++ case 4: ++ /* 7581 SoC supports eth and usb serdes on GDM4 port */ ++ if (!nbq) ++ return HSGMII_LAN_7581_ETH_SRCPORT; ++ if (nbq == 1) ++ return HSGMII_LAN_7581_USB_SRCPORT; ++ break; ++ default: ++ break; ++ } ++ ++ return -EINVAL; ++} ++ + static const struct airoha_eth_soc_data en7581_soc_data = { + .version = 0x7581, + .xsi_rsts_names = en7581_xsi_rsts_names, + .num_xsi_rsts = ARRAY_SIZE(en7581_xsi_rsts_names), + .num_ppe = 2, ++ .ops = { ++ .get_src_port_id = airoha_en7581_get_src_port_id, ++ }, + }; + + static const struct of_device_id of_airoha_match[] = { +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -67,10 +67,10 @@ enum { + }; + + enum { +- HSGMII_LAN_PCIE0_SRCPORT = 0x16, +- HSGMII_LAN_PCIE1_SRCPORT, +- HSGMII_LAN_ETH_SRCPORT, +- HSGMII_LAN_USB_SRCPORT, ++ HSGMII_LAN_7581_PCIE0_SRCPORT = 0x16, ++ HSGMII_LAN_7581_PCIE1_SRCPORT, ++ HSGMII_LAN_7581_ETH_SRCPORT, ++ HSGMII_LAN_7581_USB_SRCPORT, + }; + + enum { +@@ -99,6 +99,13 @@ enum { + CRSN_25 = 0x19, + }; + ++enum airoha_gdm_index { ++ AIROHA_GDM1_IDX = 1, ++ AIROHA_GDM2_IDX = 2, ++ AIROHA_GDM3_IDX = 3, ++ AIROHA_GDM4_IDX = 4, ++}; ++ + enum { + FE_PSE_PORT_CDM1, + FE_PSE_PORT_GDM1, +@@ -555,6 +562,9 @@ struct airoha_eth_soc_data { + const char * const *xsi_rsts_names; + int num_xsi_rsts; + int num_ppe; ++ struct { ++ int (*get_src_port_id)(struct airoha_gdm_port *port, int nbq); ++ } ops; + }; + + struct airoha_eth { +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -383,10 +383,8 @@ + #define REG_MC_VLAN_DATA 0x2108 + + #define REG_SP_DFT_CPORT(_n) (0x20e0 + ((_n) << 2)) +-#define SP_CPORT_PCIE1_MASK GENMASK(31, 28) +-#define SP_CPORT_PCIE0_MASK GENMASK(27, 24) +-#define SP_CPORT_USB_MASK GENMASK(7, 4) +-#define SP_CPORT_ETH_MASK GENMASK(7, 4) ++#define SP_CPORT_DFT_MASK GENMASK(2, 0) ++#define SP_CPORT_MASK(_n) GENMASK(3 + ((_n) << 2), ((_n) << 2)) + + #define REG_SRC_PORT_FC_MAP6 0x2298 + #define FC_ID_OF_SRC_PORT27_MASK GENMASK(28, 24) diff --git a/lede/target/linux/airoha/patches-6.12/099-11-v6.19-net-airoha-ppe-Do-not-use-magic-numbers-in-airoha_pp.patch b/lede/target/linux/airoha/patches-6.12/099-11-v6.19-net-airoha-ppe-Do-not-use-magic-numbers-in-airoha_pp.patch new file mode 100644 index 0000000000..93e7f5e592 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/099-11-v6.19-net-airoha-ppe-Do-not-use-magic-numbers-in-airoha_pp.patch @@ -0,0 +1,29 @@ +From 63f283d36b1fb06b55ae609a1f679544f5f66057 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 17 Oct 2025 11:06:21 +0200 +Subject: [PATCH 11/12] net: airoha: ppe: Do not use magic numbers in + airoha_ppe_foe_get_entry_locked() + +Explicit the size of entries pointed by hwe pointer in +airoha_ppe_foe_get_entry_locked routine + +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-12-f28319666667@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -619,7 +619,8 @@ airoha_ppe_foe_get_entry_locked(struct a + REG_PPE_RAM_CTRL(ppe2))) + return NULL; + +- for (i = 0; i < sizeof(struct airoha_foe_entry) / 4; i++) ++ for (i = 0; i < sizeof(struct airoha_foe_entry) / sizeof(*hwe); ++ i++) + hwe[i] = airoha_fe_rr(eth, + REG_PPE_RAM_ENTRY(ppe2, i)); + } diff --git a/lede/target/linux/airoha/patches-6.12/099-12-v6.19-net-airoha-Add-AN7583-SoC-support.patch b/lede/target/linux/airoha/patches-6.12/099-12-v6.19-net-airoha-Add-AN7583-SoC-support.patch new file mode 100644 index 0000000000..7f34a05ab5 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/099-12-v6.19-net-airoha-Add-AN7583-SoC-support.patch @@ -0,0 +1,185 @@ +From e4e5ce823bdd4601bd75ae7c206ae35e7c2fa60b Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 17 Oct 2025 11:06:22 +0200 +Subject: [PATCH 12/12] net: airoha: Add AN7583 SoC support + +Introduce support for AN7583 ethernet controller to airoha-eth dirver. + +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-13-f28319666667@kernel.org +Signed-off-by: Paolo Abeni +--- + drivers/net/ethernet/airoha/airoha_eth.c | 68 ++++++++++++++++++++++-- + drivers/net/ethernet/airoha/airoha_eth.h | 11 ++++ + drivers/net/ethernet/airoha/airoha_ppe.c | 3 ++ + 3 files changed, 77 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1689,10 +1689,8 @@ static int airoha_dev_set_macaddr(struct + + static int airhoha_set_gdm2_loopback(struct airoha_gdm_port *port) + { +- u32 val, pse_port, chan = port->id == AIROHA_GDM3_IDX ? 4 : 0; + struct airoha_eth *eth = port->qdma->eth; +- /* XXX: handle XSI_USB_PORT and XSI_PCE1_PORT */ +- u32 nbq = port->id == AIROHA_GDM3_IDX ? 4 : 0; ++ u32 val, pse_port, chan, nbq; + int src_port; + + /* Forward the traffic to the proper GDM port */ +@@ -1704,6 +1702,8 @@ static int airhoha_set_gdm2_loopback(str + /* Enable GDM2 loopback */ + airoha_fe_wr(eth, REG_GDM_TXCHN_EN(2), 0xffffffff); + airoha_fe_wr(eth, REG_GDM_RXCHN_EN(2), 0xffff); ++ ++ chan = port->id == AIROHA_GDM3_IDX ? airoha_is_7581(eth) ? 4 : 3 : 0; + airoha_fe_rmw(eth, REG_GDM_LPBK_CFG(2), + LPBK_CHAN_MASK | LPBK_MODE_MASK | LPBK_EN_MASK, + FIELD_PREP(LPBK_CHAN_MASK, chan) | +@@ -1718,6 +1718,8 @@ static int airhoha_set_gdm2_loopback(str + airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(2)); + airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(2)); + ++ /* XXX: handle XSI_USB_PORT and XSI_PCE1_PORT */ ++ nbq = port->id == AIROHA_GDM3_IDX && airoha_is_7581(eth) ? 4 : 0; + src_port = eth->soc->ops.get_src_port_id(port, nbq); + if (src_port < 0) + return src_port; +@@ -1731,7 +1733,7 @@ static int airhoha_set_gdm2_loopback(str + SP_CPORT_MASK(val), + FE_PSE_PORT_CDM2 << __ffs(SP_CPORT_MASK(val))); + +- if (port->id != AIROHA_GDM3_IDX) ++ if (port->id != AIROHA_GDM3_IDX && airoha_is_7581(eth)) + airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6, + FC_ID_OF_SRC_PORT24_MASK, + FIELD_PREP(FC_ID_OF_SRC_PORT24_MASK, 2)); +@@ -1900,6 +1902,22 @@ static bool airoha_dev_tx_queue_busy(str + return index >= tail; + } + ++static int airoha_get_fe_port(struct airoha_gdm_port *port) ++{ ++ struct airoha_qdma *qdma = port->qdma; ++ struct airoha_eth *eth = qdma->eth; ++ ++ switch (eth->soc->version) { ++ case 0x7583: ++ return port->id == AIROHA_GDM3_IDX ? FE_PSE_PORT_GDM3 ++ : port->id; ++ case 0x7581: ++ default: ++ return port->id == AIROHA_GDM4_IDX ? FE_PSE_PORT_GDM4 ++ : port->id; ++ } ++} ++ + static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, + struct net_device *dev) + { +@@ -1940,7 +1958,7 @@ static netdev_tx_t airoha_dev_xmit(struc + } + } + +- fport = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id; ++ fport = airoha_get_fe_port(port); + msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) | + FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f); + +@@ -3102,6 +3120,35 @@ static int airoha_en7581_get_src_port_id + return -EINVAL; + } + ++static const char * const an7583_xsi_rsts_names[] = { ++ "xsi-mac", ++ "hsi0-mac", ++ "hsi1-mac", ++ "xfp-mac", ++}; ++ ++static int airoha_an7583_get_src_port_id(struct airoha_gdm_port *port, int nbq) ++{ ++ switch (port->id) { ++ case 3: ++ /* 7583 SoC supports eth serdes on GDM3 port */ ++ if (!nbq) ++ return HSGMII_LAN_7583_ETH_SRCPORT; ++ break; ++ case 4: ++ /* 7583 SoC supports PCIe and USB serdes on GDM4 port */ ++ if (!nbq) ++ return HSGMII_LAN_7583_PCIE_SRCPORT; ++ if (nbq == 1) ++ return HSGMII_LAN_7583_USB_SRCPORT; ++ break; ++ default: ++ break; ++ } ++ ++ return -EINVAL; ++} ++ + static const struct airoha_eth_soc_data en7581_soc_data = { + .version = 0x7581, + .xsi_rsts_names = en7581_xsi_rsts_names, +@@ -3112,8 +3159,19 @@ static const struct airoha_eth_soc_data + }, + }; + ++static const struct airoha_eth_soc_data an7583_soc_data = { ++ .version = 0x7583, ++ .xsi_rsts_names = an7583_xsi_rsts_names, ++ .num_xsi_rsts = ARRAY_SIZE(an7583_xsi_rsts_names), ++ .num_ppe = 1, ++ .ops = { ++ .get_src_port_id = airoha_an7583_get_src_port_id, ++ }, ++}; ++ + static const struct of_device_id of_airoha_match[] = { + { .compatible = "airoha,en7581-eth", .data = &en7581_soc_data }, ++ { .compatible = "airoha,an7583-eth", .data = &an7583_soc_data }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, of_airoha_match); +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -74,6 +74,12 @@ enum { + }; + + enum { ++ HSGMII_LAN_7583_ETH_SRCPORT = 0x16, ++ HSGMII_LAN_7583_PCIE_SRCPORT = 0x18, ++ HSGMII_LAN_7583_USB_SRCPORT, ++}; ++ ++enum { + XSI_PCIE0_VIP_PORT_MASK = BIT(22), + XSI_PCIE1_VIP_PORT_MASK = BIT(23), + XSI_USB_VIP_PORT_MASK = BIT(25), +@@ -629,6 +635,11 @@ static inline bool airoha_is_7581(struct + return eth->soc->version == 0x7581; + } + ++static inline bool airoha_is_7583(struct airoha_eth *eth) ++{ ++ return eth->soc->version == 0x7583; ++} ++ + bool airoha_is_valid_gdm_port(struct airoha_eth *eth, + struct airoha_gdm_port *port); + +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -37,6 +37,9 @@ static int airoha_ppe_get_num_stats_entr + if (!IS_ENABLED(CONFIG_NET_AIROHA_FLOW_STATS)) + return -EOPNOTSUPP; + ++ if (airoha_is_7583(ppe->eth)) ++ return -EOPNOTSUPP; ++ + return PPE_STATS_NUM_ENTRIES; + } + diff --git a/lede/target/linux/airoha/patches-6.12/100-v6.17-net-airoha-npu-Add-missing-MODULE_FIRMWARE-macros.patch b/lede/target/linux/airoha/patches-6.12/100-v6.17-net-airoha-npu-Add-missing-MODULE_FIRMWARE-macros.patch new file mode 100644 index 0000000000..7e86417f9d --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/100-v6.17-net-airoha-npu-Add-missing-MODULE_FIRMWARE-macros.patch @@ -0,0 +1,27 @@ +From 4e7e471e2e3f9085fe1dbe821c4dd904a917c66a Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Fri, 1 Aug 2025 09:12:25 +0200 +Subject: [PATCH] net: airoha: npu: Add missing MODULE_FIRMWARE macros + +Introduce missing MODULE_FIRMWARE definitions for firmware autoload. + +Fixes: 23290c7bc190d ("net: airoha: Introduce Airoha NPU support") +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250801-airoha-npu-missing-module-firmware-v2-1-e860c824d515@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_npu.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/ethernet/airoha/airoha_npu.c ++++ b/drivers/net/ethernet/airoha/airoha_npu.c +@@ -741,6 +741,8 @@ static struct platform_driver airoha_npu + }; + module_platform_driver(airoha_npu_driver); + ++MODULE_FIRMWARE(NPU_EN7581_FIRMWARE_DATA); ++MODULE_FIRMWARE(NPU_EN7581_FIRMWARE_RV32); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Lorenzo Bianconi "); + MODULE_DESCRIPTION("Airoha Network Processor Unit driver"); diff --git a/lede/target/linux/airoha/patches-6.12/101-v6.17-net-airoha-Fix-a-NULL-vs-IS_ERR-bug-in-airoha_npu_ru.patch b/lede/target/linux/airoha/patches-6.12/101-v6.17-net-airoha-Fix-a-NULL-vs-IS_ERR-bug-in-airoha_npu_ru.patch new file mode 100644 index 0000000000..71453fd57f --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/101-v6.17-net-airoha-Fix-a-NULL-vs-IS_ERR-bug-in-airoha_npu_ru.patch @@ -0,0 +1,31 @@ +From 1e5e40f2558c07f6bc60a8983000309cc0a9d600 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Tue, 15 Jul 2025 18:01:10 -0500 +Subject: [PATCH] net: airoha: Fix a NULL vs IS_ERR() bug in + airoha_npu_run_firmware() + +The devm_ioremap_resource() function returns error pointers. It never +returns NULL. Update the check to match. + +Fixes: e27dba1951ce ("net: Use of_reserved_mem_region_to_resource{_byname}() for "memory-region"") +Signed-off-by: Dan Carpenter +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/fc6d194e-6bf5-49ca-bc77-3fdfda62c434@sabinyo.mountain +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_npu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_npu.c ++++ b/drivers/net/ethernet/airoha/airoha_npu.c +@@ -201,8 +201,8 @@ static int airoha_npu_run_firmware(struc + } + + addr = devm_ioremap(dev, rmem->base, rmem->size); +- if (!addr) { +- ret = -ENOMEM; ++ if (IS_ERR(addr)) { ++ ret = PTR_ERR(addr); + goto out; + } + diff --git a/lede/target/linux/airoha/patches-6.12/102-02-v6.19-net-airoha-npu-Add-airoha_npu_soc_data-struct.patch b/lede/target/linux/airoha/patches-6.12/102-02-v6.19-net-airoha-npu-Add-airoha_npu_soc_data-struct.patch new file mode 100644 index 0000000000..09972a9b62 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/102-02-v6.19-net-airoha-npu-Add-airoha_npu_soc_data-struct.patch @@ -0,0 +1,136 @@ +From 0850ae496d534847ec2c26744521c1bce04ec59d Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 13 Oct 2025 15:58:50 +0200 +Subject: [PATCH 2/3] net: airoha: npu: Add airoha_npu_soc_data struct + +Introduce airoha_npu_soc_data structure in order to generalize per-SoC +NPU firmware info. Introduce airoha_npu_load_firmware utility routine. +This is a preliminary patch in order to introduce AN7583 NPU support. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251013-airoha-npu-7583-v3-2-00f748b5a0c7@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_npu.c | 77 ++++++++++++++++-------- + 1 file changed, 51 insertions(+), 26 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_npu.c ++++ b/drivers/net/ethernet/airoha/airoha_npu.c +@@ -103,6 +103,16 @@ enum { + QDMA_WAN_PON_XDSL, + }; + ++struct airoha_npu_fw { ++ const char *name; ++ int max_size; ++}; ++ ++struct airoha_npu_soc_data { ++ struct airoha_npu_fw fw_rv32; ++ struct airoha_npu_fw fw_data; ++}; ++ + #define MBOX_MSG_FUNC_ID GENMASK(14, 11) + #define MBOX_MSG_STATIC_BUF BIT(5) + #define MBOX_MSG_STATUS GENMASK(4, 2) +@@ -182,49 +192,53 @@ static int airoha_npu_send_msg(struct ai + return ret; + } + +-static int airoha_npu_run_firmware(struct device *dev, void __iomem *base, +- struct reserved_mem *rmem) ++static int airoha_npu_load_firmware(struct device *dev, void __iomem *addr, ++ const struct airoha_npu_fw *fw_info) + { + const struct firmware *fw; +- void __iomem *addr; + int ret; + +- ret = request_firmware(&fw, NPU_EN7581_FIRMWARE_RV32, dev); ++ ret = request_firmware(&fw, fw_info->name, dev); + if (ret) + return ret == -ENOENT ? -EPROBE_DEFER : ret; + +- if (fw->size > NPU_EN7581_FIRMWARE_RV32_MAX_SIZE) { ++ if (fw->size > fw_info->max_size) { + dev_err(dev, "%s: fw size too overlimit (%zu)\n", +- NPU_EN7581_FIRMWARE_RV32, fw->size); ++ fw_info->name, fw->size); + ret = -E2BIG; + goto out; + } + +- addr = devm_ioremap(dev, rmem->base, rmem->size); +- if (IS_ERR(addr)) { +- ret = PTR_ERR(addr); +- goto out; +- } +- + memcpy_toio(addr, fw->data, fw->size); ++out: + release_firmware(fw); + +- ret = request_firmware(&fw, NPU_EN7581_FIRMWARE_DATA, dev); +- if (ret) +- return ret == -ENOENT ? -EPROBE_DEFER : ret; ++ return ret; ++} + +- if (fw->size > NPU_EN7581_FIRMWARE_DATA_MAX_SIZE) { +- dev_err(dev, "%s: fw size too overlimit (%zu)\n", +- NPU_EN7581_FIRMWARE_DATA, fw->size); +- ret = -E2BIG; +- goto out; +- } ++static int airoha_npu_run_firmware(struct device *dev, void __iomem *base, ++ struct reserved_mem *rmem) ++{ ++ const struct airoha_npu_soc_data *soc; ++ void __iomem *addr; ++ int ret; + +- memcpy_toio(base + REG_NPU_LOCAL_SRAM, fw->data, fw->size); +-out: +- release_firmware(fw); ++ soc = of_device_get_match_data(dev); ++ if (!soc) ++ return -EINVAL; + +- return ret; ++ addr = devm_ioremap(dev, rmem->base, rmem->size); ++ if (IS_ERR(addr)) ++ return PTR_ERR(addr); ++ ++ /* Load rv32 npu firmware */ ++ ret = airoha_npu_load_firmware(dev, addr, &soc->fw_rv32); ++ if (ret) ++ return ret; ++ ++ /* Load data npu firmware */ ++ return airoha_npu_load_firmware(dev, base + REG_NPU_LOCAL_SRAM, ++ &soc->fw_data); + } + + static irqreturn_t airoha_npu_mbox_handler(int irq, void *npu_instance) +@@ -596,8 +610,19 @@ void airoha_npu_put(struct airoha_npu *n + } + EXPORT_SYMBOL_GPL(airoha_npu_put); + ++static const struct airoha_npu_soc_data en7581_npu_soc_data = { ++ .fw_rv32 = { ++ .name = NPU_EN7581_FIRMWARE_RV32, ++ .max_size = NPU_EN7581_FIRMWARE_RV32_MAX_SIZE, ++ }, ++ .fw_data = { ++ .name = NPU_EN7581_FIRMWARE_DATA, ++ .max_size = NPU_EN7581_FIRMWARE_DATA_MAX_SIZE, ++ }, ++}; ++ + static const struct of_device_id of_airoha_npu_match[] = { +- { .compatible = "airoha,en7581-npu" }, ++ { .compatible = "airoha,en7581-npu", .data = &en7581_npu_soc_data }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, of_airoha_npu_match); diff --git a/lede/target/linux/airoha/patches-6.12/102-03-v6.19-net-airoha-npu-Add-7583-SoC-support.patch b/lede/target/linux/airoha/patches-6.12/102-03-v6.19-net-airoha-npu-Add-7583-SoC-support.patch new file mode 100644 index 0000000000..a628d09b77 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/102-03-v6.19-net-airoha-npu-Add-7583-SoC-support.patch @@ -0,0 +1,56 @@ +From 4478596f71d92060c9093bdf1d2d940881f41bcc Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Mon, 13 Oct 2025 15:58:51 +0200 +Subject: [PATCH 3/3] net: airoha: npu: Add 7583 SoC support + +Introduce support for Airoha 7583 SoC NPU selecting proper firmware images. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20251013-airoha-npu-7583-v3-3-00f748b5a0c7@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_npu.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/drivers/net/ethernet/airoha/airoha_npu.c ++++ b/drivers/net/ethernet/airoha/airoha_npu.c +@@ -16,6 +16,8 @@ + + #define NPU_EN7581_FIRMWARE_DATA "airoha/en7581_npu_data.bin" + #define NPU_EN7581_FIRMWARE_RV32 "airoha/en7581_npu_rv32.bin" ++#define NPU_AN7583_FIRMWARE_DATA "airoha/an7583_npu_data.bin" ++#define NPU_AN7583_FIRMWARE_RV32 "airoha/an7583_npu_rv32.bin" + #define NPU_EN7581_FIRMWARE_RV32_MAX_SIZE 0x200000 + #define NPU_EN7581_FIRMWARE_DATA_MAX_SIZE 0x10000 + #define NPU_DUMP_SIZE 512 +@@ -621,8 +623,20 @@ static const struct airoha_npu_soc_data + }, + }; + ++static const struct airoha_npu_soc_data an7583_npu_soc_data = { ++ .fw_rv32 = { ++ .name = NPU_AN7583_FIRMWARE_RV32, ++ .max_size = NPU_EN7581_FIRMWARE_RV32_MAX_SIZE, ++ }, ++ .fw_data = { ++ .name = NPU_AN7583_FIRMWARE_DATA, ++ .max_size = NPU_EN7581_FIRMWARE_DATA_MAX_SIZE, ++ }, ++}; ++ + static const struct of_device_id of_airoha_npu_match[] = { + { .compatible = "airoha,en7581-npu", .data = &en7581_npu_soc_data }, ++ { .compatible = "airoha,an7583-npu", .data = &an7583_npu_soc_data }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, of_airoha_npu_match); +@@ -768,6 +782,8 @@ module_platform_driver(airoha_npu_driver + + MODULE_FIRMWARE(NPU_EN7581_FIRMWARE_DATA); + MODULE_FIRMWARE(NPU_EN7581_FIRMWARE_RV32); ++MODULE_FIRMWARE(NPU_AN7583_FIRMWARE_DATA); ++MODULE_FIRMWARE(NPU_AN7583_FIRMWARE_RV32); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Lorenzo Bianconi "); + MODULE_DESCRIPTION("Airoha Network Processor Unit driver"); diff --git a/lede/target/linux/airoha/patches-6.12/103-v6.19-net-airoha-Remove-code-duplication-in-airoha_regs.h.patch b/lede/target/linux/airoha/patches-6.12/103-v6.19-net-airoha-Remove-code-duplication-in-airoha_regs.h.patch new file mode 100644 index 0000000000..654f287b14 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/103-v6.19-net-airoha-Remove-code-duplication-in-airoha_regs.h.patch @@ -0,0 +1,342 @@ +From 99ad2b6815f41acbec15ab051ccc79b11b05710a Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 22 Oct 2025 09:11:12 +0200 +Subject: [PATCH] net: airoha: Remove code duplication in airoha_regs.h + +This patch does not introduce any logical change, it just removes +duplicated code in airoha_regs.h. +Fix naming conventions in airoha_regs.h. + +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20251022-airoha-regs-cosmetics-v2-1-e0425b3f2c2c@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 102 ++++++++++---------- + drivers/net/ethernet/airoha/airoha_regs.h | 109 ++++++++++------------ + 2 files changed, 100 insertions(+), 111 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -137,11 +137,11 @@ static void airoha_fe_maccr_init(struct + + for (p = 1; p <= ARRAY_SIZE(eth->ports); p++) + airoha_fe_set(eth, REG_GDM_FWD_CFG(p), +- GDM_TCP_CKSUM | GDM_UDP_CKSUM | GDM_IP4_CKSUM | +- GDM_DROP_CRC_ERR); ++ GDM_TCP_CKSUM_MASK | GDM_UDP_CKSUM_MASK | ++ GDM_IP4_CKSUM_MASK | GDM_DROP_CRC_ERR_MASK); + +- airoha_fe_rmw(eth, REG_CDM1_VLAN_CTRL, CDM1_VLAN_MASK, +- FIELD_PREP(CDM1_VLAN_MASK, 0x8100)); ++ airoha_fe_rmw(eth, REG_CDM_VLAN_CTRL(1), CDM_VLAN_MASK, ++ FIELD_PREP(CDM_VLAN_MASK, 0x8100)); + + airoha_fe_set(eth, REG_FE_CPORT_CFG, FE_CPORT_PAD); + } +@@ -403,46 +403,46 @@ static int airoha_fe_mc_vlan_clear(struc + static void airoha_fe_crsn_qsel_init(struct airoha_eth *eth) + { + /* CDM1_CRSN_QSEL */ +- airoha_fe_rmw(eth, REG_CDM1_CRSN_QSEL(CRSN_22 >> 2), +- CDM1_CRSN_QSEL_REASON_MASK(CRSN_22), +- FIELD_PREP(CDM1_CRSN_QSEL_REASON_MASK(CRSN_22), ++ airoha_fe_rmw(eth, REG_CDM_CRSN_QSEL(1, CRSN_22 >> 2), ++ CDM_CRSN_QSEL_REASON_MASK(CRSN_22), ++ FIELD_PREP(CDM_CRSN_QSEL_REASON_MASK(CRSN_22), + CDM_CRSN_QSEL_Q1)); +- airoha_fe_rmw(eth, REG_CDM1_CRSN_QSEL(CRSN_08 >> 2), +- CDM1_CRSN_QSEL_REASON_MASK(CRSN_08), +- FIELD_PREP(CDM1_CRSN_QSEL_REASON_MASK(CRSN_08), ++ airoha_fe_rmw(eth, REG_CDM_CRSN_QSEL(1, CRSN_08 >> 2), ++ CDM_CRSN_QSEL_REASON_MASK(CRSN_08), ++ FIELD_PREP(CDM_CRSN_QSEL_REASON_MASK(CRSN_08), + CDM_CRSN_QSEL_Q1)); +- airoha_fe_rmw(eth, REG_CDM1_CRSN_QSEL(CRSN_21 >> 2), +- CDM1_CRSN_QSEL_REASON_MASK(CRSN_21), +- FIELD_PREP(CDM1_CRSN_QSEL_REASON_MASK(CRSN_21), ++ airoha_fe_rmw(eth, REG_CDM_CRSN_QSEL(1, CRSN_21 >> 2), ++ CDM_CRSN_QSEL_REASON_MASK(CRSN_21), ++ FIELD_PREP(CDM_CRSN_QSEL_REASON_MASK(CRSN_21), + CDM_CRSN_QSEL_Q1)); +- airoha_fe_rmw(eth, REG_CDM1_CRSN_QSEL(CRSN_24 >> 2), +- CDM1_CRSN_QSEL_REASON_MASK(CRSN_24), +- FIELD_PREP(CDM1_CRSN_QSEL_REASON_MASK(CRSN_24), ++ airoha_fe_rmw(eth, REG_CDM_CRSN_QSEL(1, CRSN_24 >> 2), ++ CDM_CRSN_QSEL_REASON_MASK(CRSN_24), ++ FIELD_PREP(CDM_CRSN_QSEL_REASON_MASK(CRSN_24), + CDM_CRSN_QSEL_Q6)); +- airoha_fe_rmw(eth, REG_CDM1_CRSN_QSEL(CRSN_25 >> 2), +- CDM1_CRSN_QSEL_REASON_MASK(CRSN_25), +- FIELD_PREP(CDM1_CRSN_QSEL_REASON_MASK(CRSN_25), ++ airoha_fe_rmw(eth, REG_CDM_CRSN_QSEL(1, CRSN_25 >> 2), ++ CDM_CRSN_QSEL_REASON_MASK(CRSN_25), ++ FIELD_PREP(CDM_CRSN_QSEL_REASON_MASK(CRSN_25), + CDM_CRSN_QSEL_Q1)); + /* CDM2_CRSN_QSEL */ +- airoha_fe_rmw(eth, REG_CDM2_CRSN_QSEL(CRSN_08 >> 2), +- CDM2_CRSN_QSEL_REASON_MASK(CRSN_08), +- FIELD_PREP(CDM2_CRSN_QSEL_REASON_MASK(CRSN_08), ++ airoha_fe_rmw(eth, REG_CDM_CRSN_QSEL(2, CRSN_08 >> 2), ++ CDM_CRSN_QSEL_REASON_MASK(CRSN_08), ++ FIELD_PREP(CDM_CRSN_QSEL_REASON_MASK(CRSN_08), + CDM_CRSN_QSEL_Q1)); +- airoha_fe_rmw(eth, REG_CDM2_CRSN_QSEL(CRSN_21 >> 2), +- CDM2_CRSN_QSEL_REASON_MASK(CRSN_21), +- FIELD_PREP(CDM2_CRSN_QSEL_REASON_MASK(CRSN_21), ++ airoha_fe_rmw(eth, REG_CDM_CRSN_QSEL(2, CRSN_21 >> 2), ++ CDM_CRSN_QSEL_REASON_MASK(CRSN_21), ++ FIELD_PREP(CDM_CRSN_QSEL_REASON_MASK(CRSN_21), + CDM_CRSN_QSEL_Q1)); +- airoha_fe_rmw(eth, REG_CDM2_CRSN_QSEL(CRSN_22 >> 2), +- CDM2_CRSN_QSEL_REASON_MASK(CRSN_22), +- FIELD_PREP(CDM2_CRSN_QSEL_REASON_MASK(CRSN_22), ++ airoha_fe_rmw(eth, REG_CDM_CRSN_QSEL(2, CRSN_22 >> 2), ++ CDM_CRSN_QSEL_REASON_MASK(CRSN_22), ++ FIELD_PREP(CDM_CRSN_QSEL_REASON_MASK(CRSN_22), + CDM_CRSN_QSEL_Q1)); +- airoha_fe_rmw(eth, REG_CDM2_CRSN_QSEL(CRSN_24 >> 2), +- CDM2_CRSN_QSEL_REASON_MASK(CRSN_24), +- FIELD_PREP(CDM2_CRSN_QSEL_REASON_MASK(CRSN_24), ++ airoha_fe_rmw(eth, REG_CDM_CRSN_QSEL(2, CRSN_24 >> 2), ++ CDM_CRSN_QSEL_REASON_MASK(CRSN_24), ++ FIELD_PREP(CDM_CRSN_QSEL_REASON_MASK(CRSN_24), + CDM_CRSN_QSEL_Q6)); +- airoha_fe_rmw(eth, REG_CDM2_CRSN_QSEL(CRSN_25 >> 2), +- CDM2_CRSN_QSEL_REASON_MASK(CRSN_25), +- FIELD_PREP(CDM2_CRSN_QSEL_REASON_MASK(CRSN_25), ++ airoha_fe_rmw(eth, REG_CDM_CRSN_QSEL(2, CRSN_25 >> 2), ++ CDM_CRSN_QSEL_REASON_MASK(CRSN_25), ++ FIELD_PREP(CDM_CRSN_QSEL_REASON_MASK(CRSN_25), + CDM_CRSN_QSEL_Q1)); + } + +@@ -462,18 +462,18 @@ static int airoha_fe_init(struct airoha_ + airoha_fe_wr(eth, REG_FE_PCE_CFG, + PCE_DPI_EN_MASK | PCE_KA_EN_MASK | PCE_MC_EN_MASK); + /* set vip queue selection to ring 1 */ +- airoha_fe_rmw(eth, REG_CDM1_FWD_CFG, CDM1_VIP_QSEL_MASK, +- FIELD_PREP(CDM1_VIP_QSEL_MASK, 0x4)); +- airoha_fe_rmw(eth, REG_CDM2_FWD_CFG, CDM2_VIP_QSEL_MASK, +- FIELD_PREP(CDM2_VIP_QSEL_MASK, 0x4)); ++ airoha_fe_rmw(eth, REG_CDM_FWD_CFG(1), CDM_VIP_QSEL_MASK, ++ FIELD_PREP(CDM_VIP_QSEL_MASK, 0x4)); ++ airoha_fe_rmw(eth, REG_CDM_FWD_CFG(2), CDM_VIP_QSEL_MASK, ++ FIELD_PREP(CDM_VIP_QSEL_MASK, 0x4)); + /* set GDM4 source interface offset to 8 */ +- airoha_fe_rmw(eth, REG_GDM4_SRC_PORT_SET, +- GDM4_SPORT_OFF2_MASK | +- GDM4_SPORT_OFF1_MASK | +- GDM4_SPORT_OFF0_MASK, +- FIELD_PREP(GDM4_SPORT_OFF2_MASK, 8) | +- FIELD_PREP(GDM4_SPORT_OFF1_MASK, 8) | +- FIELD_PREP(GDM4_SPORT_OFF0_MASK, 8)); ++ airoha_fe_rmw(eth, REG_GDM_SRC_PORT_SET(4), ++ GDM_SPORT_OFF2_MASK | ++ GDM_SPORT_OFF1_MASK | ++ GDM_SPORT_OFF0_MASK, ++ FIELD_PREP(GDM_SPORT_OFF2_MASK, 8) | ++ FIELD_PREP(GDM_SPORT_OFF1_MASK, 8) | ++ FIELD_PREP(GDM_SPORT_OFF0_MASK, 8)); + + /* set PSE Page as 128B */ + airoha_fe_rmw(eth, REG_FE_DMA_GLO_CFG, +@@ -499,8 +499,8 @@ static int airoha_fe_init(struct airoha_ + airoha_fe_set(eth, REG_GDM_MISC_CFG, + GDM2_RDM_ACK_WAIT_PREF_MASK | + GDM2_CHN_VLD_MODE_MASK); +- airoha_fe_rmw(eth, REG_CDM2_FWD_CFG, CDM2_OAM_QSEL_MASK, +- FIELD_PREP(CDM2_OAM_QSEL_MASK, 15)); ++ airoha_fe_rmw(eth, REG_CDM_FWD_CFG(2), CDM_OAM_QSEL_MASK, ++ FIELD_PREP(CDM_OAM_QSEL_MASK, 15)); + + /* init fragment and assemble Force Port */ + /* NPU Core-3, NPU Bridge Channel-3 */ +@@ -514,8 +514,8 @@ static int airoha_fe_init(struct airoha_ + FIELD_PREP(IP_ASSEMBLE_PORT_MASK, 0) | + FIELD_PREP(IP_ASSEMBLE_NBQ_MASK, 22)); + +- airoha_fe_set(eth, REG_GDM3_FWD_CFG, GDM3_PAD_EN_MASK); +- airoha_fe_set(eth, REG_GDM4_FWD_CFG, GDM4_PAD_EN_MASK); ++ airoha_fe_set(eth, REG_GDM_FWD_CFG(3), GDM_PAD_EN_MASK); ++ airoha_fe_set(eth, REG_GDM_FWD_CFG(4), GDM_PAD_EN_MASK); + + airoha_fe_crsn_qsel_init(eth); + +@@ -523,7 +523,7 @@ static int airoha_fe_init(struct airoha_ + airoha_fe_set(eth, REG_FE_CPORT_CFG, FE_CPORT_PORT_XFC_MASK); + + /* default aging mode for mbi unlock issue */ +- airoha_fe_rmw(eth, REG_GDM2_CHN_RLS, ++ airoha_fe_rmw(eth, REG_GDM_CHN_RLS(2), + MBI_RX_AGE_SEL_MASK | MBI_TX_AGE_SEL_MASK, + FIELD_PREP(MBI_RX_AGE_SEL_MASK, 3) | + FIELD_PREP(MBI_TX_AGE_SEL_MASK, 3)); +@@ -1697,7 +1697,7 @@ static int airhoha_set_gdm2_loopback(str + pse_port = port->id == AIROHA_GDM3_IDX ? FE_PSE_PORT_GDM3 + : FE_PSE_PORT_GDM4; + airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(2), pse_port); +- airoha_fe_clear(eth, REG_GDM_FWD_CFG(2), GDM_STRIP_CRC); ++ airoha_fe_clear(eth, REG_GDM_FWD_CFG(2), GDM_STRIP_CRC_MASK); + + /* Enable GDM2 loopback */ + airoha_fe_wr(eth, REG_GDM_TXCHN_EN(2), 0xffffffff); +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -23,6 +23,8 @@ + #define GDM3_BASE 0x1100 + #define GDM4_BASE 0x2500 + ++#define CDM_BASE(_n) \ ++ ((_n) == 2 ? CDM2_BASE : CDM1_BASE) + #define GDM_BASE(_n) \ + ((_n) == 4 ? GDM4_BASE : \ + (_n) == 3 ? GDM3_BASE : \ +@@ -109,30 +111,24 @@ + #define PATN_DP_MASK GENMASK(31, 16) + #define PATN_SP_MASK GENMASK(15, 0) + +-#define REG_CDM1_VLAN_CTRL CDM1_BASE +-#define CDM1_VLAN_MASK GENMASK(31, 16) ++#define REG_CDM_VLAN_CTRL(_n) CDM_BASE(_n) ++#define CDM_VLAN_MASK GENMASK(31, 16) + +-#define REG_CDM1_FWD_CFG (CDM1_BASE + 0x08) +-#define CDM1_VIP_QSEL_MASK GENMASK(24, 20) ++#define REG_CDM_FWD_CFG(_n) (CDM_BASE(_n) + 0x08) ++#define CDM_OAM_QSEL_MASK GENMASK(31, 27) ++#define CDM_VIP_QSEL_MASK GENMASK(24, 20) + +-#define REG_CDM1_CRSN_QSEL(_n) (CDM1_BASE + 0x10 + ((_n) << 2)) +-#define CDM1_CRSN_QSEL_REASON_MASK(_n) \ +- GENMASK(4 + (((_n) % 4) << 3), (((_n) % 4) << 3)) +- +-#define REG_CDM2_FWD_CFG (CDM2_BASE + 0x08) +-#define CDM2_OAM_QSEL_MASK GENMASK(31, 27) +-#define CDM2_VIP_QSEL_MASK GENMASK(24, 20) +- +-#define REG_CDM2_CRSN_QSEL(_n) (CDM2_BASE + 0x10 + ((_n) << 2)) +-#define CDM2_CRSN_QSEL_REASON_MASK(_n) \ ++#define REG_CDM_CRSN_QSEL(_n, _m) (CDM_BASE(_n) + 0x10 + ((_m) << 2)) ++#define CDM_CRSN_QSEL_REASON_MASK(_n) \ + GENMASK(4 + (((_n) % 4) << 3), (((_n) % 4) << 3)) + + #define REG_GDM_FWD_CFG(_n) GDM_BASE(_n) +-#define GDM_DROP_CRC_ERR BIT(23) +-#define GDM_IP4_CKSUM BIT(22) +-#define GDM_TCP_CKSUM BIT(21) +-#define GDM_UDP_CKSUM BIT(20) +-#define GDM_STRIP_CRC BIT(16) ++#define GDM_PAD_EN_MASK BIT(28) ++#define GDM_DROP_CRC_ERR_MASK BIT(23) ++#define GDM_IP4_CKSUM_MASK BIT(22) ++#define GDM_TCP_CKSUM_MASK BIT(21) ++#define GDM_UDP_CKSUM_MASK BIT(20) ++#define GDM_STRIP_CRC_MASK BIT(16) + #define GDM_UCFQ_MASK GENMASK(15, 12) + #define GDM_BCFQ_MASK GENMASK(11, 8) + #define GDM_MCFQ_MASK GENMASK(7, 4) +@@ -156,6 +152,10 @@ + #define LBK_CHAN_MODE_MASK BIT(1) + #define LPBK_EN_MASK BIT(0) + ++#define REG_GDM_CHN_RLS(_n) (GDM_BASE(_n) + 0x20) ++#define MBI_RX_AGE_SEL_MASK GENMASK(26, 25) ++#define MBI_TX_AGE_SEL_MASK GENMASK(18, 17) ++ + #define REG_GDM_TXCHN_EN(_n) (GDM_BASE(_n) + 0x24) + #define REG_GDM_RXCHN_EN(_n) (GDM_BASE(_n) + 0x28) + +@@ -168,10 +168,10 @@ + #define FE_GDM_MIB_RX_CLEAR_MASK BIT(1) + #define FE_GDM_MIB_TX_CLEAR_MASK BIT(0) + +-#define REG_FE_GDM1_MIB_CFG (GDM1_BASE + 0xf4) ++#define REG_FE_GDM_MIB_CFG(_n) (GDM_BASE(_n) + 0xf4) + #define FE_STRICT_RFC2819_MODE_MASK BIT(31) +-#define FE_GDM1_TX_MIB_SPLIT_EN_MASK BIT(17) +-#define FE_GDM1_RX_MIB_SPLIT_EN_MASK BIT(16) ++#define FE_GDM_TX_MIB_SPLIT_EN_MASK BIT(17) ++#define FE_GDM_RX_MIB_SPLIT_EN_MASK BIT(16) + #define FE_TX_MIB_ID_MASK GENMASK(15, 8) + #define FE_RX_MIB_ID_MASK GENMASK(7, 0) + +@@ -214,6 +214,33 @@ + #define REG_FE_GDM_RX_ETH_L511_CNT_L(_n) (GDM_BASE(_n) + 0x198) + #define REG_FE_GDM_RX_ETH_L1023_CNT_L(_n) (GDM_BASE(_n) + 0x19c) + ++#define REG_GDM_SRC_PORT_SET(_n) (GDM_BASE(_n) + 0x23c) ++#define GDM_SPORT_OFF2_MASK GENMASK(19, 16) ++#define GDM_SPORT_OFF1_MASK GENMASK(15, 12) ++#define GDM_SPORT_OFF0_MASK GENMASK(11, 8) ++ ++#define REG_FE_GDM_TX_OK_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x280) ++#define REG_FE_GDM_TX_OK_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x284) ++#define REG_FE_GDM_TX_ETH_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x288) ++#define REG_FE_GDM_TX_ETH_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x28c) ++ ++#define REG_FE_GDM_RX_OK_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x290) ++#define REG_FE_GDM_RX_OK_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x294) ++#define REG_FE_GDM_RX_ETH_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x298) ++#define REG_FE_GDM_RX_ETH_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x29c) ++#define REG_FE_GDM_TX_ETH_E64_CNT_H(_n) (GDM_BASE(_n) + 0x2b8) ++#define REG_FE_GDM_TX_ETH_L64_CNT_H(_n) (GDM_BASE(_n) + 0x2bc) ++#define REG_FE_GDM_TX_ETH_L127_CNT_H(_n) (GDM_BASE(_n) + 0x2c0) ++#define REG_FE_GDM_TX_ETH_L255_CNT_H(_n) (GDM_BASE(_n) + 0x2c4) ++#define REG_FE_GDM_TX_ETH_L511_CNT_H(_n) (GDM_BASE(_n) + 0x2c8) ++#define REG_FE_GDM_TX_ETH_L1023_CNT_H(_n) (GDM_BASE(_n) + 0x2cc) ++#define REG_FE_GDM_RX_ETH_E64_CNT_H(_n) (GDM_BASE(_n) + 0x2e8) ++#define REG_FE_GDM_RX_ETH_L64_CNT_H(_n) (GDM_BASE(_n) + 0x2ec) ++#define REG_FE_GDM_RX_ETH_L127_CNT_H(_n) (GDM_BASE(_n) + 0x2f0) ++#define REG_FE_GDM_RX_ETH_L255_CNT_H(_n) (GDM_BASE(_n) + 0x2f4) ++#define REG_FE_GDM_RX_ETH_L511_CNT_H(_n) (GDM_BASE(_n) + 0x2f8) ++#define REG_FE_GDM_RX_ETH_L1023_CNT_H(_n) (GDM_BASE(_n) + 0x2fc) ++ + #define REG_PPE_GLO_CFG(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x200) + #define PPE_GLO_CFG_BUSY_MASK BIT(31) + #define PPE_GLO_CFG_FLOW_DROP_UPDATE_MASK BIT(9) +@@ -326,44 +353,6 @@ + + #define REG_UPDMEM_DATA(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x374) + +-#define REG_FE_GDM_TX_OK_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x280) +-#define REG_FE_GDM_TX_OK_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x284) +-#define REG_FE_GDM_TX_ETH_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x288) +-#define REG_FE_GDM_TX_ETH_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x28c) +- +-#define REG_FE_GDM_RX_OK_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x290) +-#define REG_FE_GDM_RX_OK_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x294) +-#define REG_FE_GDM_RX_ETH_PKT_CNT_H(_n) (GDM_BASE(_n) + 0x298) +-#define REG_FE_GDM_RX_ETH_BYTE_CNT_H(_n) (GDM_BASE(_n) + 0x29c) +-#define REG_FE_GDM_TX_ETH_E64_CNT_H(_n) (GDM_BASE(_n) + 0x2b8) +-#define REG_FE_GDM_TX_ETH_L64_CNT_H(_n) (GDM_BASE(_n) + 0x2bc) +-#define REG_FE_GDM_TX_ETH_L127_CNT_H(_n) (GDM_BASE(_n) + 0x2c0) +-#define REG_FE_GDM_TX_ETH_L255_CNT_H(_n) (GDM_BASE(_n) + 0x2c4) +-#define REG_FE_GDM_TX_ETH_L511_CNT_H(_n) (GDM_BASE(_n) + 0x2c8) +-#define REG_FE_GDM_TX_ETH_L1023_CNT_H(_n) (GDM_BASE(_n) + 0x2cc) +-#define REG_FE_GDM_RX_ETH_E64_CNT_H(_n) (GDM_BASE(_n) + 0x2e8) +-#define REG_FE_GDM_RX_ETH_L64_CNT_H(_n) (GDM_BASE(_n) + 0x2ec) +-#define REG_FE_GDM_RX_ETH_L127_CNT_H(_n) (GDM_BASE(_n) + 0x2f0) +-#define REG_FE_GDM_RX_ETH_L255_CNT_H(_n) (GDM_BASE(_n) + 0x2f4) +-#define REG_FE_GDM_RX_ETH_L511_CNT_H(_n) (GDM_BASE(_n) + 0x2f8) +-#define REG_FE_GDM_RX_ETH_L1023_CNT_H(_n) (GDM_BASE(_n) + 0x2fc) +- +-#define REG_GDM2_CHN_RLS (GDM2_BASE + 0x20) +-#define MBI_RX_AGE_SEL_MASK GENMASK(26, 25) +-#define MBI_TX_AGE_SEL_MASK GENMASK(18, 17) +- +-#define REG_GDM3_FWD_CFG GDM3_BASE +-#define GDM3_PAD_EN_MASK BIT(28) +- +-#define REG_GDM4_FWD_CFG GDM4_BASE +-#define GDM4_PAD_EN_MASK BIT(28) +-#define GDM4_SPORT_OFFSET0_MASK GENMASK(11, 8) +- +-#define REG_GDM4_SRC_PORT_SET (GDM4_BASE + 0x23c) +-#define GDM4_SPORT_OFF2_MASK GENMASK(19, 16) +-#define GDM4_SPORT_OFF1_MASK GENMASK(15, 12) +-#define GDM4_SPORT_OFF0_MASK GENMASK(11, 8) +- + #define REG_IP_FRAG_FP 0x2010 + #define IP_ASSEMBLE_PORT_MASK GENMASK(24, 21) + #define IP_ASSEMBLE_NBQ_MASK GENMASK(20, 16) diff --git a/lede/target/linux/airoha/patches-6.12/104-6.19-net-airoha-Fix-a-copy-and-paste-bug-in-probe.patch b/lede/target/linux/airoha/patches-6.12/104-6.19-net-airoha-Fix-a-copy-and-paste-bug-in-probe.patch new file mode 100644 index 0000000000..e87035ec54 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/104-6.19-net-airoha-Fix-a-copy-and-paste-bug-in-probe.patch @@ -0,0 +1,37 @@ +From 05e090620bacf317020f9591cfff8926093380bd Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Fri, 24 Oct 2025 14:23:35 +0300 +Subject: [PATCH] net: airoha: Fix a copy and paste bug in probe() + +This code has a copy and paste bug where it accidentally checks "if (err)" +instead of checking if "xsi_rsts" is NULL. Also, as a free bonus, I +changed the allocation from kzalloc() to kcalloc() which is a kernel +hardening measure to protect against integer overflows. + +Fixes: 5863b4e065e2 ("net: airoha: Add airoha_eth_soc_data struct") +Signed-off-by: Dan Carpenter +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/aPtht6y5DRokn9zv@stanley.mountain +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2990,11 +2990,11 @@ static int airoha_probe(struct platform_ + return err; + } + +- xsi_rsts = devm_kzalloc(eth->dev, +- eth->soc->num_xsi_rsts * sizeof(*xsi_rsts), ++ xsi_rsts = devm_kcalloc(eth->dev, ++ eth->soc->num_xsi_rsts, sizeof(*xsi_rsts), + GFP_KERNEL); +- if (err) +- return err; ++ if (!xsi_rsts) ++ return -ENOMEM; + + eth->xsi_rsts = xsi_rsts; + for (i = 0; i < eth->soc->num_xsi_rsts; i++) diff --git a/lede/target/linux/airoha/patches-6.12/104-i2c-mt7621-optional-reset.patch b/lede/target/linux/airoha/patches-6.12/104-i2c-mt7621-optional-reset.patch new file mode 100644 index 0000000000..1fad1bdd01 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/104-i2c-mt7621-optional-reset.patch @@ -0,0 +1,11 @@ +--- a/drivers/i2c/busses/i2c-mt7621.c ++++ b/drivers/i2c/busses/i2c-mt7621.c +@@ -85,7 +85,7 @@ static void mtk_i2c_reset(struct mtk_i2c + { + int ret; + +- ret = device_reset(i2c->adap.dev.parent); ++ ret = device_reset_optional(i2c->adap.dev.parent); + if (ret) + dev_err(i2c->dev, "I2C reset failed!\n"); + diff --git a/lede/target/linux/airoha/patches-6.12/104-v6.16-net-airoha-Fix-an-error-handling-path-in-airoha_prob.patch b/lede/target/linux/airoha/patches-6.12/104-v6.16-net-airoha-Fix-an-error-handling-path-in-airoha_prob.patch new file mode 100644 index 0000000000..58e48cb8d0 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/104-v6.16-net-airoha-Fix-an-error-handling-path-in-airoha_prob.patch @@ -0,0 +1,29 @@ +From 3ef07434c7dbfba302df477bb6c70e082965f232 Mon Sep 17 00:00:00 2001 +From: Christophe JAILLET +Date: Sat, 5 Jul 2025 10:34:32 +0200 +Subject: [PATCH] net: airoha: Fix an error handling path in airoha_probe() + +If an error occurs after a successful airoha_hw_init() call, +airoha_ppe_deinit() needs to be called as already done in the remove +function. + +Fixes: 00a7678310fe ("net: airoha: Introduce flowtable offload support") +Signed-off-by: Christophe JAILLET +Reviewed-by: Simon Horman +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/1c940851b4fa3c3ed2a142910c821493a136f121.1746715755.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -3044,6 +3044,7 @@ static int airoha_probe(struct platform_ + error_napi_stop: + for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) + airoha_qdma_stop_napi(ð->qdma[i]); ++ airoha_ppe_deinit(eth); + error_hw_cleanup: + for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) + airoha_hw_cleanup(ð->qdma[i]); diff --git a/lede/target/linux/airoha/patches-6.12/105-6.17-net-airoha-Get-rid-of-dma_sync_single_for_device-in-.patch b/lede/target/linux/airoha/patches-6.12/105-6.17-net-airoha-Get-rid-of-dma_sync_single_for_device-in-.patch new file mode 100644 index 0000000000..0c690b0d65 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/105-6.17-net-airoha-Get-rid-of-dma_sync_single_for_device-in-.patch @@ -0,0 +1,40 @@ +From 4cd9d227ab838b3590c4b27e3707b8c3ef14d7e9 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Wed, 25 Jun 2025 16:43:15 +0200 +Subject: [PATCH] net: airoha: Get rid of dma_sync_single_for_device() in + airoha_qdma_fill_rx_queue() + +Since the page_pool for airoha_eth driver is created with +PP_FLAG_DMA_SYNC_DEV flag, we do not need to sync_for_device each page +received from the pool since it is already done by the page_pool codebase. + +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Alexander Lobakin +Link: https://patch.msgid.link/20250625-airoha-sync-for-device-v1-1-923741deaabf@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 5 ----- + 1 file changed, 5 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -539,9 +539,7 @@ static int airoha_fe_init(struct airoha_ + + static int airoha_qdma_fill_rx_queue(struct airoha_queue *q) + { +- enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool); + struct airoha_qdma *qdma = q->qdma; +- struct airoha_eth *eth = qdma->eth; + int qid = q - &qdma->q_rx[0]; + int nframes = 0; + +@@ -565,9 +563,6 @@ static int airoha_qdma_fill_rx_queue(str + e->dma_addr = page_pool_get_dma_addr(page) + offset; + e->dma_len = SKB_WITH_OVERHEAD(q->buf_size); + +- dma_sync_single_for_device(eth->dev, e->dma_addr, e->dma_len, +- dir); +- + val = FIELD_PREP(QDMA_DESC_LEN_MASK, e->dma_len); + WRITE_ONCE(desc->ctrl, cpu_to_le32(val)); + WRITE_ONCE(desc->addr, cpu_to_le32(e->dma_addr)); diff --git a/lede/target/linux/airoha/patches-6.12/105-uart-add-en7523-support.patch b/lede/target/linux/airoha/patches-6.12/105-uart-add-en7523-support.patch new file mode 100644 index 0000000000..cad2a715d9 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/105-uart-add-en7523-support.patch @@ -0,0 +1,206 @@ +--- /dev/null ++++ b/drivers/tty/serial/8250/8250_en7523.c +@@ -0,0 +1,94 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Airoha EN7523 driver. ++ * ++ * Copyright (c) 2022 Genexis Sweden AB ++ * Author: Benjamin Larsson ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "8250.h" ++ ++ ++/* The Airoha UART is 16550-compatible except for the baud rate calculation. ++ * ++ * crystal_clock = 20 MHz ++ * xindiv_clock = crystal_clock / clock_div ++ * (x/y) = XYD, 32 bit register with 16 bits of x and and then 16 bits of y ++ * clock_div = XINCLK_DIVCNT (default set to 10 (0x4)), ++ * - 3 bit register [ 1, 2, 4, 8, 10, 12, 16, 20 ] ++ * ++ * baud_rate = ((xindiv_clock) * (x/y)) / ([BRDH,BRDL] * 16) ++ * ++ * XYD_y seems to need to be larger then XYD_x for things to work. ++ * Setting [BRDH,BRDL] to [0,1] and XYD_y to 65000 give even values ++ * for usual baud rates. ++ * ++ * Selecting divider needs to fulfill ++ * 1.8432 MHz <= xindiv_clk <= APB clock / 2 ++ * The clocks are unknown but a divider of value 1 did not work. ++ * ++ * Optimally the XYD, BRD and XINCLK_DIVCNT registers could be searched to ++ * find values that gives the least error for every baud rate. But searching ++ * the space takes time and in practise only a few rates are of interest. ++ * With some value combinations not working a tested subset is used giving ++ * a usable range from 110 to 460800 baud. ++ */ ++ ++#define CLOCK_DIV_TAB_ELEMS 3 ++#define XYD_Y 65000 ++#define XINDIV_CLOCK 20000000 ++#define UART_BRDL_20M 0x01 ++#define UART_BRDH_20M 0x00 ++ ++static int clock_div_tab[] = { 10, 4, 2}; ++static int clock_div_reg[] = { 4, 2, 1}; ++ ++ ++int en7523_set_uart_baud_rate (struct uart_port *port, unsigned int baud) ++{ ++ struct uart_8250_port *up = up_to_u8250p(port); ++ unsigned int xyd_x, nom, denom; ++ int i; ++ ++ /* set DLAB to access the baud rate divider registers (BRDH, BRDL) */ ++ serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB); ++ ++ /* set baud rate calculation defaults */ ++ ++ /* set BRDIV ([BRDH,BRDL]) to 1 */ ++ serial_port_out(port, UART_BRDL, UART_BRDL_20M); ++ serial_port_out(port, UART_BRDH, UART_BRDH_20M); ++ ++ /* calculate XYD_x and XINCLKDR register */ ++ ++ for (i = 0 ; i < CLOCK_DIV_TAB_ELEMS ; i++) { ++ denom = (XINDIV_CLOCK/40) / clock_div_tab[i]; ++ nom = (baud * (XYD_Y/40)); ++ xyd_x = ((nom/denom) << 4); ++ if (xyd_x < XYD_Y) break; ++ } ++ ++ serial_port_out(port, UART_XINCLKDR, clock_div_reg[i]); ++ serial_port_out(port, UART_XYD, (xyd_x<<16) | XYD_Y); ++ ++ /* unset DLAB */ ++ serial_port_out(port, UART_LCR, up->lcr); ++ ++ return 0; ++} ++ ++EXPORT_SYMBOL_GPL(en7523_set_uart_baud_rate); +--- a/drivers/tty/serial/8250/8250_of.c ++++ b/drivers/tty/serial/8250/8250_of.c +@@ -341,6 +341,7 @@ static const struct of_device_id of_plat + { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, }, + { .compatible = "nuvoton,wpcm450-uart", .data = (void *)PORT_NPCM, }, + { .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, }, ++ { .compatible = "airoha,en7523-uart", .data = (void *)PORT_AIROHA, }, + { /* end of list */ }, + }; + MODULE_DEVICE_TABLE(of, of_platform_serial_table); +--- a/drivers/tty/serial/8250/8250_port.c ++++ b/drivers/tty/serial/8250/8250_port.c +@@ -319,6 +319,14 @@ static const struct serial8250_config ua + .rxtrig_bytes = {1, 8, 16, 30}, + .flags = UART_CAP_FIFO | UART_CAP_AFE, + }, ++ [PORT_AIROHA] = { ++ .name = "Airoha 16550", ++ .fifo_size = 8, ++ .tx_loadsz = 1, ++ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01, ++ .rxtrig_bytes = {1, 4}, ++ .flags = UART_CAP_FIFO, ++ }, + }; + + /* Uart divisor latch read */ +@@ -2835,6 +2843,12 @@ serial8250_do_set_termios(struct uart_po + + serial8250_set_divisor(port, baud, quot, frac); + ++#ifdef CONFIG_SERIAL_8250_AIROHA ++ /* Airoha SoCs have custom registers for baud rate settings */ ++ if (port->type == PORT_AIROHA) ++ en7523_set_uart_baud_rate(port, baud); ++#endif ++ + /* + * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR + * is written without DLAB set, this mode will be disabled. +--- a/drivers/tty/serial/8250/Kconfig ++++ b/drivers/tty/serial/8250/Kconfig +@@ -355,6 +355,16 @@ config SERIAL_8250_ACORN + system, say Y to this option. The driver can handle 1, 2, or 3 port + cards. If unsure, say N. + ++config SERIAL_8250_AIROHA ++ tristate "Airoha UART support" ++ depends on (ARCH_AIROHA || COMPILE_TEST) && OF && SERIAL_8250 ++ help ++ Selecting this option enables an Airoha SoC specific baud rate ++ calculation routine on an otherwise 16550 compatible UART hardware. ++ ++ If you have an Airoha based board and want to use the serial port, ++ say Y to this option. If unsure, say N. ++ + config SERIAL_8250_BCM2835AUX + tristate "BCM2835 auxiliar mini UART support" + depends on ARCH_BCM2835 || COMPILE_TEST +--- a/drivers/tty/serial/8250/Makefile ++++ b/drivers/tty/serial/8250/Makefile +@@ -20,6 +20,7 @@ obj-$(CONFIG_SERIAL_8250_CONSOLE) += 825 + + obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o + obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o ++obj-$(CONFIG_SERIAL_8250_AIROHA) += 8250_en7523.o + obj-$(CONFIG_SERIAL_8250_ASPEED_VUART) += 8250_aspeed_vuart.o + obj-$(CONFIG_SERIAL_8250_BCM2835AUX) += 8250_bcm2835aux.o + obj-$(CONFIG_SERIAL_8250_BCM7271) += 8250_bcm7271.o +--- a/include/uapi/linux/serial_reg.h ++++ b/include/uapi/linux/serial_reg.h +@@ -383,5 +383,17 @@ + #define UART_ALTR_EN_TXFIFO_LW 0x01 /* Enable the TX FIFO Low Watermark */ + #define UART_ALTR_TX_LOW 0x41 /* Tx FIFO Low Watermark */ + ++/* ++ * These are definitions for the Airoha EN75XX uart registers ++ * Normalized because of 32 bits registers. ++ */ ++#define UART_BRDL 0 ++#define UART_BRDH 1 ++#define UART_XINCLKDR 10 ++#define UART_XYD 11 ++#define UART_TXLVLCNT 12 ++#define UART_RXLVLCNT 13 ++#define UART_FINTLVL 14 ++ + #endif /* _LINUX_SERIAL_REG_H */ + +--- a/include/uapi/linux/serial_core.h ++++ b/include/uapi/linux/serial_core.h +@@ -31,6 +31,7 @@ + #define PORT_ALTR_16550_F128 28 /* Altera 16550 UART with 128 FIFOs */ + #define PORT_RT2880 29 /* Ralink RT2880 internal UART */ + #define PORT_16550A_FSL64 30 /* Freescale 16550 UART with 64 FIFOs */ ++#define PORT_AIROHA 31 /* Airoha 16550 UART */ + + /* + * ARM specific type numbers. These are not currently guaranteed +--- a/include/linux/serial_8250.h ++++ b/include/linux/serial_8250.h +@@ -195,6 +195,7 @@ void serial8250_do_set_mctrl(struct uart + void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud, + unsigned int quot); + int fsl8250_handle_irq(struct uart_port *port); ++int en7523_set_uart_baud_rate(struct uart_port *port, unsigned int baud); + int serial8250_handle_irq(struct uart_port *port, unsigned int iir); + u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr); + void serial8250_read_char(struct uart_8250_port *up, u16 lsr); diff --git a/lede/target/linux/airoha/patches-6.12/106-6.16-net-airoha-fix-potential-use-after-free-in-airoha_np.patch b/lede/target/linux/airoha/patches-6.12/106-6.16-net-airoha-fix-potential-use-after-free-in-airoha_np.patch new file mode 100644 index 0000000000..251395c751 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/106-6.16-net-airoha-fix-potential-use-after-free-in-airoha_np.patch @@ -0,0 +1,41 @@ +From 3cd582e7d0787506990ef0180405eb6224fa90a6 Mon Sep 17 00:00:00 2001 +From: Alok Tiwari +Date: Tue, 15 Jul 2025 07:30:58 -0700 +Subject: [PATCH] net: airoha: fix potential use-after-free in airoha_npu_get() + +np->name was being used after calling of_node_put(np), which +releases the node and can lead to a use-after-free bug. +Previously, of_node_put(np) was called unconditionally after +of_find_device_by_node(np), which could result in a use-after-free if +pdev is NULL. + +This patch moves of_node_put(np) after the error check to ensure +the node is only released after both the error and success cases +are handled appropriately, preventing potential resource issues. + +Fixes: 23290c7bc190 ("net: airoha: Introduce Airoha NPU support") +Signed-off-by: Alok Tiwari +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250715143102.3458286-1-alok.a.tiwari@oracle.com +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_npu.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_npu.c ++++ b/drivers/net/ethernet/airoha/airoha_npu.c +@@ -567,12 +567,13 @@ struct airoha_npu *airoha_npu_get(struct + return ERR_PTR(-ENODEV); + + pdev = of_find_device_by_node(np); +- of_node_put(np); + + if (!pdev) { + dev_err(dev, "cannot find device node %s\n", np->name); ++ of_node_put(np); + return ERR_PTR(-ENODEV); + } ++ of_node_put(np); + + if (!try_module_get(THIS_MODULE)) { + dev_err(dev, "failed to get the device driver module\n"); diff --git a/lede/target/linux/airoha/patches-6.12/107-v6.19-pwm-airoha-Add-support-for-EN7581-SoC.patch b/lede/target/linux/airoha/patches-6.12/107-v6.19-pwm-airoha-Add-support-for-EN7581-SoC.patch new file mode 100644 index 0000000000..0848cb410e --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/107-v6.19-pwm-airoha-Add-support-for-EN7581-SoC.patch @@ -0,0 +1,689 @@ +From 61d7c2f94d391594de08d8a52a7c2630d2f3d263 Mon Sep 17 00:00:00 2001 +From: Benjamin Larsson +Date: Mon, 13 Oct 2025 12:34:03 +0200 +Subject: [PATCH] pwm: airoha: Add support for EN7581 SoC +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Introduce driver for PWM module available on EN7581 SoC. + +Limitations: +- Only 8 concurrent waveform generators are available for 8 combinations of + duty_cycle and period. Waveform generators are shared between 16 GPIO + pins and 17 SIPO GPIO pins. +- Supports only normal polarity. +- On configuration the currently running period is completed. +- Minimum supported period is 4 ms +- Maximum supported period is 1s + +Signed-off-by: Benjamin Larsson +Reviewed-by: AngeloGioacchino Del Regno +Co-developed-by: Lorenzo Bianconi +Signed-off-by: Lorenzo Bianconi +Reviewed-by: Andy Shevchenko +Co-developed-by: Christian Marangi +Signed-off-by: Christian Marangi +Link: https://patch.msgid.link/20251013103408.14724-1-ansuelsmth@gmail.com +Signed-off-by: Uwe Kleine-König +--- + drivers/pwm/Kconfig | 10 + + drivers/pwm/Makefile | 1 + + drivers/pwm/pwm-airoha.c | 622 +++++++++++++++++++++++++++++++++++++++ + 3 files changed, 633 insertions(+) + create mode 100644 drivers/pwm/pwm-airoha.c + +--- a/drivers/pwm/Kconfig ++++ b/drivers/pwm/Kconfig +@@ -54,6 +54,16 @@ config PWM_ADP5585 + This option enables support for the PWM function found in the Analog + Devices ADP5585. + ++config PWM_AIROHA ++ tristate "Airoha PWM support" ++ depends on ARCH_AIROHA || COMPILE_TEST ++ select REGMAP_MMIO ++ help ++ Generic PWM framework driver for Airoha SoC. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called pwm-airoha. ++ + config PWM_APPLE + tristate "Apple SoC PWM support" + depends on ARCH_APPLE || COMPILE_TEST +--- a/drivers/pwm/Makefile ++++ b/drivers/pwm/Makefile +@@ -2,6 +2,7 @@ + obj-$(CONFIG_PWM) += core.o + obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o + obj-$(CONFIG_PWM_ADP5585) += pwm-adp5585.o ++obj-$(CONFIG_PWM_AIROHA) += pwm-airoha.o + obj-$(CONFIG_PWM_APPLE) += pwm-apple.o + obj-$(CONFIG_PWM_ATMEL) += pwm-atmel.o + obj-$(CONFIG_PWM_ATMEL_HLCDC_PWM) += pwm-atmel-hlcdc.o +--- /dev/null ++++ b/drivers/pwm/pwm-airoha.c +@@ -0,0 +1,622 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright 2022 Markus Gothe ++ * Copyright 2025 Christian Marangi ++ * ++ * Limitations: ++ * - Only 8 concurrent waveform generators are available for 8 combinations of ++ * duty_cycle and period. Waveform generators are shared between 16 GPIO ++ * pins and 17 SIPO GPIO pins. ++ * - Supports only normal polarity. ++ * - On configuration the currently running period is completed. ++ * - Minimum supported period is 4 ms ++ * - Maximum supported period is 1s ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define AIROHA_PWM_REG_SGPIO_LED_DATA 0x0024 ++#define AIROHA_PWM_SGPIO_LED_DATA_SHIFT_FLAG BIT(31) ++#define AIROHA_PWM_SGPIO_LED_DATA_DATA GENMASK(16, 0) ++ ++#define AIROHA_PWM_REG_SGPIO_CLK_DIVR 0x0028 ++#define AIROHA_PWM_SGPIO_CLK_DIVR GENMASK(1, 0) ++#define AIROHA_PWM_SGPIO_CLK_DIVR_32 FIELD_PREP_CONST(AIROHA_PWM_SGPIO_CLK_DIVR, 3) ++#define AIROHA_PWM_SGPIO_CLK_DIVR_16 FIELD_PREP_CONST(AIROHA_PWM_SGPIO_CLK_DIVR, 2) ++#define AIROHA_PWM_SGPIO_CLK_DIVR_8 FIELD_PREP_CONST(AIROHA_PWM_SGPIO_CLK_DIVR, 1) ++#define AIROHA_PWM_SGPIO_CLK_DIVR_4 FIELD_PREP_CONST(AIROHA_PWM_SGPIO_CLK_DIVR, 0) ++ ++#define AIROHA_PWM_REG_SGPIO_CLK_DLY 0x002c ++ ++#define AIROHA_PWM_REG_SIPO_FLASH_MODE_CFG 0x0030 ++#define AIROHA_PWM_SERIAL_GPIO_FLASH_MODE BIT(1) ++#define AIROHA_PWM_SERIAL_GPIO_MODE_74HC164 BIT(0) ++ ++#define AIROHA_PWM_REG_GPIO_FLASH_PRD_SET(_n) (0x003c + (4 * (_n))) ++#define AIROHA_PWM_REG_GPIO_FLASH_PRD_SHIFT(_n) (16 * (_n)) ++#define AIROHA_PWM_GPIO_FLASH_PRD_LOW GENMASK(15, 8) ++#define AIROHA_PWM_GPIO_FLASH_PRD_HIGH GENMASK(7, 0) ++ ++#define AIROHA_PWM_REG_GPIO_FLASH_MAP(_n) (0x004c + (4 * (_n))) ++#define AIROHA_PWM_REG_GPIO_FLASH_MAP_SHIFT(_n) (4 * (_n)) ++#define AIROHA_PWM_GPIO_FLASH_EN BIT(3) ++#define AIROHA_PWM_GPIO_FLASH_SET_ID GENMASK(2, 0) ++ ++/* Register map is equal to GPIO flash map */ ++#define AIROHA_PWM_REG_SIPO_FLASH_MAP(_n) (0x0054 + (4 * (_n))) ++ ++#define AIROHA_PWM_REG_CYCLE_CFG_VALUE(_n) (0x0098 + (4 * (_n))) ++#define AIROHA_PWM_REG_CYCLE_CFG_SHIFT(_n) (8 * (_n)) ++#define AIROHA_PWM_WAVE_GEN_CYCLE GENMASK(7, 0) ++ ++/* GPIO/SIPO flash map handles 8 pins in one register */ ++#define AIROHA_PWM_PINS_PER_FLASH_MAP 8 ++/* Cycle(Period) registers handles 4 generators in one 32-bit register */ ++#define AIROHA_PWM_BUCKET_PER_CYCLE_CFG 4 ++/* Flash(Duty) producer handles 2 generators in one 32-bit register */ ++#define AIROHA_PWM_BUCKET_PER_FLASH_PROD 2 ++ ++#define AIROHA_PWM_NUM_BUCKETS 8 ++/* ++ * The first 16 GPIO pins, GPIO0-GPIO15, are mapped into 16 PWM channels, 0-15. ++ * The SIPO GPIO pins are 17 pins which are mapped into 17 PWM channels, 16-32. ++ * However, we've only got 8 concurrent waveform generators and can therefore ++ * only use up to 8 different combinations of duty cycle and period at a time. ++ */ ++#define AIROHA_PWM_NUM_GPIO 16 ++#define AIROHA_PWM_NUM_SIPO 17 ++#define AIROHA_PWM_MAX_CHANNELS (AIROHA_PWM_NUM_GPIO + AIROHA_PWM_NUM_SIPO) ++ ++struct airoha_pwm_bucket { ++ /* Concurrent access protected by PWM core */ ++ int used; ++ u32 period_ticks; ++ u32 duty_ticks; ++}; ++ ++struct airoha_pwm { ++ struct regmap *regmap; ++ ++ DECLARE_BITMAP(initialized, AIROHA_PWM_MAX_CHANNELS); ++ ++ struct airoha_pwm_bucket buckets[AIROHA_PWM_NUM_BUCKETS]; ++ ++ /* Cache bucket used by each pwm channel */ ++ u8 channel_bucket[AIROHA_PWM_MAX_CHANNELS]; ++}; ++ ++/* The PWM hardware supports periods between 4 ms and 1 s */ ++#define AIROHA_PWM_PERIOD_TICK_NS (4 * NSEC_PER_MSEC) ++#define AIROHA_PWM_PERIOD_MAX_NS (1 * NSEC_PER_SEC) ++/* It is represented internally as 1/250 s between 1 and 250. Unit is ticks. */ ++#define AIROHA_PWM_PERIOD_MIN 1 ++#define AIROHA_PWM_PERIOD_MAX 250 ++/* Duty cycle is relative with 255 corresponding to 100% */ ++#define AIROHA_PWM_DUTY_FULL 255 ++ ++static void airoha_pwm_get_flash_map_addr_and_shift(unsigned int hwpwm, ++ u32 *addr, u32 *shift) ++{ ++ unsigned int offset, hwpwm_bit; ++ ++ if (hwpwm >= AIROHA_PWM_NUM_GPIO) { ++ unsigned int sipohwpwm = hwpwm - AIROHA_PWM_NUM_GPIO; ++ ++ offset = sipohwpwm / AIROHA_PWM_PINS_PER_FLASH_MAP; ++ hwpwm_bit = sipohwpwm % AIROHA_PWM_PINS_PER_FLASH_MAP; ++ ++ /* One FLASH_MAP register handles 8 pins */ ++ *shift = AIROHA_PWM_REG_GPIO_FLASH_MAP_SHIFT(hwpwm_bit); ++ *addr = AIROHA_PWM_REG_SIPO_FLASH_MAP(offset); ++ } else { ++ offset = hwpwm / AIROHA_PWM_PINS_PER_FLASH_MAP; ++ hwpwm_bit = hwpwm % AIROHA_PWM_PINS_PER_FLASH_MAP; ++ ++ /* One FLASH_MAP register handles 8 pins */ ++ *shift = AIROHA_PWM_REG_GPIO_FLASH_MAP_SHIFT(hwpwm_bit); ++ *addr = AIROHA_PWM_REG_GPIO_FLASH_MAP(offset); ++ } ++} ++ ++static u32 airoha_pwm_get_period_ticks_from_ns(u32 period_ns) ++{ ++ return period_ns / AIROHA_PWM_PERIOD_TICK_NS; ++} ++ ++static u32 airoha_pwm_get_duty_ticks_from_ns(u32 period_ns, u32 duty_ns) ++{ ++ return mul_u64_u32_div(duty_ns, AIROHA_PWM_DUTY_FULL, period_ns); ++} ++ ++static u32 airoha_pwm_get_period_ns_from_ticks(u32 period_tick) ++{ ++ return period_tick * AIROHA_PWM_PERIOD_TICK_NS; ++} ++ ++static u32 airoha_pwm_get_duty_ns_from_ticks(u32 period_tick, u32 duty_tick) ++{ ++ u32 period_ns = period_tick * AIROHA_PWM_PERIOD_TICK_NS; ++ ++ /* ++ * Overflow can't occur in multiplication as duty_tick is just 8 bit ++ * and period_ns is clamped to AIROHA_PWM_PERIOD_MAX_NS and fit in a ++ * u64. ++ */ ++ return DIV_U64_ROUND_UP(duty_tick * period_ns, AIROHA_PWM_DUTY_FULL); ++} ++ ++static int airoha_pwm_get_bucket(struct airoha_pwm *pc, int bucket, ++ u64 *period_ns, u64 *duty_ns) ++{ ++ struct regmap *map = pc->regmap; ++ u32 period_tick, duty_tick; ++ unsigned int offset; ++ u32 shift, val; ++ int ret; ++ ++ offset = bucket / AIROHA_PWM_BUCKET_PER_CYCLE_CFG; ++ shift = bucket % AIROHA_PWM_BUCKET_PER_CYCLE_CFG; ++ shift = AIROHA_PWM_REG_CYCLE_CFG_SHIFT(shift); ++ ++ ret = regmap_read(map, AIROHA_PWM_REG_CYCLE_CFG_VALUE(offset), &val); ++ if (ret) ++ return ret; ++ ++ period_tick = FIELD_GET(AIROHA_PWM_WAVE_GEN_CYCLE, val >> shift); ++ *period_ns = airoha_pwm_get_period_ns_from_ticks(period_tick); ++ ++ offset = bucket / AIROHA_PWM_BUCKET_PER_FLASH_PROD; ++ shift = bucket % AIROHA_PWM_BUCKET_PER_FLASH_PROD; ++ shift = AIROHA_PWM_REG_GPIO_FLASH_PRD_SHIFT(shift); ++ ++ ret = regmap_read(map, AIROHA_PWM_REG_GPIO_FLASH_PRD_SET(offset), ++ &val); ++ if (ret) ++ return ret; ++ ++ duty_tick = FIELD_GET(AIROHA_PWM_GPIO_FLASH_PRD_HIGH, val >> shift); ++ *duty_ns = airoha_pwm_get_duty_ns_from_ticks(period_tick, duty_tick); ++ ++ return 0; ++} ++ ++static int airoha_pwm_get_generator(struct airoha_pwm *pc, u32 duty_ticks, ++ u32 period_ticks) ++{ ++ int best = -ENOENT, unused = -ENOENT; ++ u32 duty_ns, best_duty_ns = 0; ++ u32 best_period_ticks = 0; ++ unsigned int i; ++ ++ duty_ns = airoha_pwm_get_duty_ns_from_ticks(period_ticks, duty_ticks); ++ ++ for (i = 0; i < ARRAY_SIZE(pc->buckets); i++) { ++ struct airoha_pwm_bucket *bucket = &pc->buckets[i]; ++ u32 bucket_period_ticks = bucket->period_ticks; ++ u32 bucket_duty_ticks = bucket->duty_ticks; ++ ++ /* If found, save an unused bucket to return it later */ ++ if (!bucket->used) { ++ unused = i; ++ continue; ++ } ++ ++ /* We found a matching bucket, exit early */ ++ if (duty_ticks == bucket_duty_ticks && ++ period_ticks == bucket_period_ticks) ++ return i; ++ ++ /* ++ * Unlike duty cycle zero, which can be handled by ++ * disabling PWM, a generator is needed for full duty ++ * cycle but it can be reused regardless of period ++ */ ++ if (duty_ticks == AIROHA_PWM_DUTY_FULL && ++ bucket_duty_ticks == AIROHA_PWM_DUTY_FULL) ++ return i; ++ ++ /* ++ * With an unused bucket available, skip searching for ++ * a bucket to recycle (closer to the requested period/duty) ++ */ ++ if (unused >= 0) ++ continue; ++ ++ /* Ignore bucket with invalid period */ ++ if (bucket_period_ticks > period_ticks) ++ continue; ++ ++ /* ++ * Search for a bucket closer to the requested period ++ * that has the maximal possible period that isn't bigger ++ * than the requested period. For that period pick the maximal ++ * duty cycle that isn't bigger than the requested duty_cycle. ++ */ ++ if (bucket_period_ticks >= best_period_ticks) { ++ u32 bucket_duty_ns = airoha_pwm_get_duty_ns_from_ticks(bucket_period_ticks, ++ bucket_duty_ticks); ++ ++ /* Skip bucket that goes over the requested duty */ ++ if (bucket_duty_ns > duty_ns) ++ continue; ++ ++ if (bucket_duty_ns > best_duty_ns) { ++ best_period_ticks = bucket_period_ticks; ++ best_duty_ns = bucket_duty_ns; ++ best = i; ++ } ++ } ++ } ++ ++ /* Return an unused bucket or the best one found (if ever) */ ++ return unused >= 0 ? unused : best; ++} ++ ++static void airoha_pwm_release_bucket_config(struct airoha_pwm *pc, ++ unsigned int hwpwm) ++{ ++ int bucket; ++ ++ /* Nothing to clear, PWM channel never used */ ++ if (!test_bit(hwpwm, pc->initialized)) ++ return; ++ ++ bucket = pc->channel_bucket[hwpwm]; ++ pc->buckets[bucket].used--; ++} ++ ++static int airoha_pwm_apply_bucket_config(struct airoha_pwm *pc, unsigned int bucket, ++ u32 duty_ticks, u32 period_ticks) ++{ ++ u32 mask, shift, val; ++ u32 offset; ++ int ret; ++ ++ offset = bucket / AIROHA_PWM_BUCKET_PER_CYCLE_CFG; ++ shift = bucket % AIROHA_PWM_BUCKET_PER_CYCLE_CFG; ++ shift = AIROHA_PWM_REG_CYCLE_CFG_SHIFT(shift); ++ ++ /* Configure frequency divisor */ ++ mask = AIROHA_PWM_WAVE_GEN_CYCLE << shift; ++ val = FIELD_PREP(AIROHA_PWM_WAVE_GEN_CYCLE, period_ticks) << shift; ++ ret = regmap_update_bits(pc->regmap, AIROHA_PWM_REG_CYCLE_CFG_VALUE(offset), ++ mask, val); ++ if (ret) ++ return ret; ++ ++ offset = bucket / AIROHA_PWM_BUCKET_PER_FLASH_PROD; ++ shift = bucket % AIROHA_PWM_BUCKET_PER_FLASH_PROD; ++ shift = AIROHA_PWM_REG_GPIO_FLASH_PRD_SHIFT(shift); ++ ++ /* Configure duty cycle */ ++ mask = AIROHA_PWM_GPIO_FLASH_PRD_HIGH << shift; ++ val = FIELD_PREP(AIROHA_PWM_GPIO_FLASH_PRD_HIGH, duty_ticks) << shift; ++ ret = regmap_update_bits(pc->regmap, AIROHA_PWM_REG_GPIO_FLASH_PRD_SET(offset), ++ mask, val); ++ if (ret) ++ return ret; ++ ++ mask = AIROHA_PWM_GPIO_FLASH_PRD_LOW << shift; ++ val = FIELD_PREP(AIROHA_PWM_GPIO_FLASH_PRD_LOW, ++ AIROHA_PWM_DUTY_FULL - duty_ticks) << shift; ++ return regmap_update_bits(pc->regmap, AIROHA_PWM_REG_GPIO_FLASH_PRD_SET(offset), ++ mask, val); ++} ++ ++static int airoha_pwm_consume_generator(struct airoha_pwm *pc, ++ u32 duty_ticks, u32 period_ticks, ++ unsigned int hwpwm) ++{ ++ bool config_bucket = false; ++ int bucket, ret; ++ ++ /* ++ * Search for a bucket that already satisfies duty and period ++ * or an unused one. ++ * If not found, -ENOENT is returned. ++ */ ++ bucket = airoha_pwm_get_generator(pc, duty_ticks, period_ticks); ++ if (bucket < 0) ++ return bucket; ++ ++ /* Release previous used bucket (if any) */ ++ airoha_pwm_release_bucket_config(pc, hwpwm); ++ ++ if (!pc->buckets[bucket].used) ++ config_bucket = true; ++ pc->buckets[bucket].used++; ++ ++ if (config_bucket) { ++ pc->buckets[bucket].period_ticks = period_ticks; ++ pc->buckets[bucket].duty_ticks = duty_ticks; ++ ret = airoha_pwm_apply_bucket_config(pc, bucket, ++ duty_ticks, ++ period_ticks); ++ if (ret) { ++ pc->buckets[bucket].used--; ++ return ret; ++ } ++ } ++ ++ return bucket; ++} ++ ++static int airoha_pwm_sipo_init(struct airoha_pwm *pc) ++{ ++ u32 val; ++ int ret; ++ ++ ret = regmap_clear_bits(pc->regmap, AIROHA_PWM_REG_SIPO_FLASH_MODE_CFG, ++ AIROHA_PWM_SERIAL_GPIO_MODE_74HC164); ++ if (ret) ++ return ret; ++ ++ /* Configure shift register chip clock timings, use 32x divisor */ ++ ret = regmap_write(pc->regmap, AIROHA_PWM_REG_SGPIO_CLK_DIVR, ++ AIROHA_PWM_SGPIO_CLK_DIVR_32); ++ if (ret) ++ return ret; ++ ++ /* ++ * Configure the shift register chip clock delay. This needs ++ * to be configured based on the chip characteristics when the SoC ++ * apply the shift register configuration. ++ * This doesn't affect actual PWM operation and is only specific to ++ * the shift register chip. ++ * ++ * For 74HC164 we set it to 0. ++ * ++ * For reference, the actual delay applied is the internal clock ++ * feed to the SGPIO chip + 1. ++ * ++ * From documentation is specified that clock delay should not be ++ * greater than (AIROHA_PWM_REG_SGPIO_CLK_DIVR / 2) - 1. ++ */ ++ ret = regmap_write(pc->regmap, AIROHA_PWM_REG_SGPIO_CLK_DLY, 0); ++ if (ret) ++ return ret; ++ ++ /* ++ * It is necessary to explicitly shift out all zeros after muxing ++ * to initialize the shift register before enabling PWM ++ * mode because in PWM mode SIPO will not start shifting until ++ * it needs to output a non-zero value (bit 31 of led_data ++ * indicates shifting in progress and it must return to zero ++ * before led_data can be written or PWM mode can be set). ++ */ ++ ret = regmap_read_poll_timeout(pc->regmap, AIROHA_PWM_REG_SGPIO_LED_DATA, val, ++ !(val & AIROHA_PWM_SGPIO_LED_DATA_SHIFT_FLAG), ++ 10, 200 * USEC_PER_MSEC); ++ if (ret) ++ return ret; ++ ++ ret = regmap_clear_bits(pc->regmap, AIROHA_PWM_REG_SGPIO_LED_DATA, ++ AIROHA_PWM_SGPIO_LED_DATA_DATA); ++ if (ret) ++ return ret; ++ ret = regmap_read_poll_timeout(pc->regmap, AIROHA_PWM_REG_SGPIO_LED_DATA, val, ++ !(val & AIROHA_PWM_SGPIO_LED_DATA_SHIFT_FLAG), ++ 10, 200 * USEC_PER_MSEC); ++ if (ret) ++ return ret; ++ ++ /* Set SIPO in PWM mode */ ++ return regmap_set_bits(pc->regmap, AIROHA_PWM_REG_SIPO_FLASH_MODE_CFG, ++ AIROHA_PWM_SERIAL_GPIO_FLASH_MODE); ++} ++ ++static int airoha_pwm_config_flash_map(struct airoha_pwm *pc, ++ unsigned int hwpwm, int index) ++{ ++ unsigned int addr; ++ u32 shift; ++ int ret; ++ ++ airoha_pwm_get_flash_map_addr_and_shift(hwpwm, &addr, &shift); ++ ++ /* negative index means disable PWM channel */ ++ if (index < 0) { ++ /* ++ * If we need to disable the PWM, we just put low the ++ * GPIO. No need to setup buckets. ++ */ ++ return regmap_clear_bits(pc->regmap, addr, ++ AIROHA_PWM_GPIO_FLASH_EN << shift); ++ } ++ ++ ret = regmap_update_bits(pc->regmap, addr, ++ AIROHA_PWM_GPIO_FLASH_SET_ID << shift, ++ FIELD_PREP(AIROHA_PWM_GPIO_FLASH_SET_ID, index) << shift); ++ if (ret) ++ return ret; ++ ++ return regmap_set_bits(pc->regmap, addr, AIROHA_PWM_GPIO_FLASH_EN << shift); ++} ++ ++static int airoha_pwm_config(struct airoha_pwm *pc, struct pwm_device *pwm, ++ u32 period_ticks, u32 duty_ticks) ++{ ++ unsigned int hwpwm = pwm->hwpwm; ++ int bucket, ret; ++ ++ bucket = airoha_pwm_consume_generator(pc, duty_ticks, period_ticks, ++ hwpwm); ++ if (bucket < 0) ++ return bucket; ++ ++ ret = airoha_pwm_config_flash_map(pc, hwpwm, bucket); ++ if (ret) { ++ pc->buckets[bucket].used--; ++ return ret; ++ } ++ ++ __set_bit(hwpwm, pc->initialized); ++ pc->channel_bucket[hwpwm] = bucket; ++ ++ /* ++ * SIPO are special GPIO attached to a shift register chip. The handling ++ * of this chip is internal to the SoC that takes care of applying the ++ * values based on the flash map. To apply a new flash map, it's needed ++ * to trigger a refresh on the shift register chip. ++ * If a SIPO is getting configuring , always reinit the shift register ++ * chip to make sure the correct flash map is applied. ++ * Skip reconfiguring the shift register if the related hwpwm ++ * is disabled (as it doesn't need to be mapped). ++ */ ++ if (hwpwm >= AIROHA_PWM_NUM_GPIO) { ++ ret = airoha_pwm_sipo_init(pc); ++ if (ret) { ++ airoha_pwm_release_bucket_config(pc, hwpwm); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static void airoha_pwm_disable(struct airoha_pwm *pc, struct pwm_device *pwm) ++{ ++ /* Disable PWM and release the bucket */ ++ airoha_pwm_config_flash_map(pc, pwm->hwpwm, -1); ++ airoha_pwm_release_bucket_config(pc, pwm->hwpwm); ++ ++ __clear_bit(pwm->hwpwm, pc->initialized); ++ ++ /* If no SIPO is used, disable the shift register chip */ ++ if (!bitmap_read(pc->initialized, ++ AIROHA_PWM_NUM_GPIO, AIROHA_PWM_NUM_SIPO)) ++ regmap_clear_bits(pc->regmap, AIROHA_PWM_REG_SIPO_FLASH_MODE_CFG, ++ AIROHA_PWM_SERIAL_GPIO_FLASH_MODE); ++} ++ ++static int airoha_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, ++ const struct pwm_state *state) ++{ ++ struct airoha_pwm *pc = pwmchip_get_drvdata(chip); ++ u32 period_ticks, duty_ticks; ++ u32 period_ns, duty_ns; ++ ++ if (!state->enabled) { ++ airoha_pwm_disable(pc, pwm); ++ return 0; ++ } ++ ++ /* Only normal polarity is supported */ ++ if (state->polarity == PWM_POLARITY_INVERSED) ++ return -EINVAL; ++ ++ /* Exit early if period is less than minimum supported */ ++ if (state->period < AIROHA_PWM_PERIOD_TICK_NS) ++ return -EINVAL; ++ ++ /* Clamp period to MAX supported value */ ++ if (state->period > AIROHA_PWM_PERIOD_MAX_NS) ++ period_ns = AIROHA_PWM_PERIOD_MAX_NS; ++ else ++ period_ns = state->period; ++ ++ /* Validate duty to configured period */ ++ if (state->duty_cycle > period_ns) ++ duty_ns = period_ns; ++ else ++ duty_ns = state->duty_cycle; ++ ++ /* Convert period ns to ticks */ ++ period_ticks = airoha_pwm_get_period_ticks_from_ns(period_ns); ++ /* Convert period ticks to ns again for cosistent duty tick calculation */ ++ period_ns = airoha_pwm_get_period_ns_from_ticks(period_ticks); ++ duty_ticks = airoha_pwm_get_duty_ticks_from_ns(period_ns, duty_ns); ++ ++ return airoha_pwm_config(pc, pwm, period_ticks, duty_ticks); ++} ++ ++static int airoha_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, ++ struct pwm_state *state) ++{ ++ struct airoha_pwm *pc = pwmchip_get_drvdata(chip); ++ int ret, hwpwm = pwm->hwpwm; ++ u32 addr, shift, val; ++ u8 bucket; ++ ++ airoha_pwm_get_flash_map_addr_and_shift(hwpwm, &addr, &shift); ++ ++ ret = regmap_read(pc->regmap, addr, &val); ++ if (ret) ++ return ret; ++ ++ state->enabled = FIELD_GET(AIROHA_PWM_GPIO_FLASH_EN, val >> shift); ++ if (!state->enabled) ++ return 0; ++ ++ state->polarity = PWM_POLARITY_NORMAL; ++ ++ bucket = FIELD_GET(AIROHA_PWM_GPIO_FLASH_SET_ID, val >> shift); ++ return airoha_pwm_get_bucket(pc, bucket, &state->period, ++ &state->duty_cycle); ++} ++ ++static const struct pwm_ops airoha_pwm_ops = { ++ .apply = airoha_pwm_apply, ++ .get_state = airoha_pwm_get_state, ++}; ++ ++static int airoha_pwm_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct airoha_pwm *pc; ++ struct pwm_chip *chip; ++ int ret; ++ ++ chip = devm_pwmchip_alloc(dev, AIROHA_PWM_MAX_CHANNELS, sizeof(*pc)); ++ if (IS_ERR(chip)) ++ return PTR_ERR(chip); ++ ++ chip->ops = &airoha_pwm_ops; ++ pc = pwmchip_get_drvdata(chip); ++ ++ pc->regmap = device_node_to_regmap(dev_of_node(dev->parent)); ++ if (IS_ERR(pc->regmap)) ++ return dev_err_probe(dev, PTR_ERR(pc->regmap), "Failed to get PWM regmap\n"); ++ ++ ret = devm_pwmchip_add(dev, chip); ++ if (ret) ++ return dev_err_probe(dev, ret, "Failed to add PWM chip\n"); ++ ++ return 0; ++} ++ ++static const struct of_device_id airoha_pwm_of_match[] = { ++ { .compatible = "airoha,en7581-pwm" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, airoha_pwm_of_match); ++ ++static struct platform_driver airoha_pwm_driver = { ++ .driver = { ++ .name = "pwm-airoha", ++ .probe_type = PROBE_PREFER_ASYNCHRONOUS, ++ .of_match_table = airoha_pwm_of_match, ++ }, ++ .probe = airoha_pwm_probe, ++}; ++module_platform_driver(airoha_pwm_driver); ++ ++MODULE_AUTHOR("Lorenzo Bianconi "); ++MODULE_AUTHOR("Markus Gothe "); ++MODULE_AUTHOR("Benjamin Larsson "); ++MODULE_AUTHOR("Christian Marangi "); ++MODULE_DESCRIPTION("Airoha EN7581 PWM driver"); ++MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/airoha/patches-6.12/108-v6.19-net-airoha-Add-the-capability-to-consume-out-of-orde.patch b/lede/target/linux/airoha/patches-6.12/108-v6.19-net-airoha-Add-the-capability-to-consume-out-of-orde.patch new file mode 100644 index 0000000000..b09ebd57b4 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/108-v6.19-net-airoha-Add-the-capability-to-consume-out-of-orde.patch @@ -0,0 +1,245 @@ +From 3f47e67dff1f7266e112c50313d63824f6f17102 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Thu, 6 Nov 2025 13:53:23 +0100 +Subject: [PATCH] net: airoha: Add the capability to consume out-of-order DMA + tx descriptors + +EN7581 and AN7583 SoCs are capable of DMA mapping non-linear tx skbs on +non-consecutive DMA descriptors. This feature is useful when multiple +flows are queued on the same hw tx queue since it allows to fully utilize +the available tx DMA descriptors and to avoid the starvation of +high-priority flow we have in the current codebase due to head-of-line +blocking introduced by low-priority flows. + +Tested-by: Xuegang Lu +Reviewed-by: Jacob Keller +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20251106-airoha-tx-linked-list-v2-1-0706d4a322bd@kernel.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/ethernet/airoha/airoha_eth.c | 85 +++++++++++------------- + drivers/net/ethernet/airoha/airoha_eth.h | 7 +- + 2 files changed, 45 insertions(+), 47 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -892,19 +892,13 @@ static int airoha_qdma_tx_napi_poll(stru + + dma_unmap_single(eth->dev, e->dma_addr, e->dma_len, + DMA_TO_DEVICE); +- memset(e, 0, sizeof(*e)); ++ e->dma_addr = 0; ++ list_add_tail(&e->list, &q->tx_list); ++ + WRITE_ONCE(desc->msg0, 0); + WRITE_ONCE(desc->msg1, 0); + q->queued--; + +- /* completion ring can report out-of-order indexes if hw QoS +- * is enabled and packets with different priority are queued +- * to same DMA ring. Take into account possible out-of-order +- * reports incrementing DMA ring tail pointer +- */ +- while (q->tail != q->head && !q->entry[q->tail].dma_addr) +- q->tail = (q->tail + 1) % q->ndesc; +- + if (skb) { + u16 queue = skb_get_queue_mapping(skb); + struct netdev_queue *txq; +@@ -949,6 +943,7 @@ static int airoha_qdma_init_tx_queue(str + q->ndesc = size; + q->qdma = qdma; + q->free_thr = 1 + MAX_SKB_FRAGS; ++ INIT_LIST_HEAD(&q->tx_list); + + q->entry = devm_kzalloc(eth->dev, q->ndesc * sizeof(*q->entry), + GFP_KERNEL); +@@ -961,9 +956,9 @@ static int airoha_qdma_init_tx_queue(str + return -ENOMEM; + + for (i = 0; i < q->ndesc; i++) { +- u32 val; ++ u32 val = FIELD_PREP(QDMA_DESC_DONE_MASK, 1); + +- val = FIELD_PREP(QDMA_DESC_DONE_MASK, 1); ++ list_add_tail(&q->entry[i].list, &q->tx_list); + WRITE_ONCE(q->desc[i].ctrl, cpu_to_le32(val)); + } + +@@ -973,9 +968,9 @@ static int airoha_qdma_init_tx_queue(str + + airoha_qdma_wr(qdma, REG_TX_RING_BASE(qid), dma_addr); + airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK, +- FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head)); ++ FIELD_PREP(TX_RING_CPU_IDX_MASK, 0)); + airoha_qdma_rmw(qdma, REG_TX_DMA_IDX(qid), TX_RING_DMA_IDX_MASK, +- FIELD_PREP(TX_RING_DMA_IDX_MASK, q->head)); ++ FIELD_PREP(TX_RING_DMA_IDX_MASK, 0)); + + return 0; + } +@@ -1031,17 +1026,21 @@ static int airoha_qdma_init_tx(struct ai + static void airoha_qdma_cleanup_tx_queue(struct airoha_queue *q) + { + struct airoha_eth *eth = q->qdma->eth; ++ int i; + + spin_lock_bh(&q->lock); +- while (q->queued) { +- struct airoha_queue_entry *e = &q->entry[q->tail]; ++ for (i = 0; i < q->ndesc; i++) { ++ struct airoha_queue_entry *e = &q->entry[i]; ++ ++ if (!e->dma_addr) ++ continue; + + dma_unmap_single(eth->dev, e->dma_addr, e->dma_len, + DMA_TO_DEVICE); + dev_kfree_skb_any(e->skb); ++ e->dma_addr = 0; + e->skb = NULL; +- +- q->tail = (q->tail + 1) % q->ndesc; ++ list_add_tail(&e->list, &q->tx_list); + q->queued--; + } + spin_unlock_bh(&q->lock); +@@ -1883,20 +1882,6 @@ static u32 airoha_get_dsa_tag(struct sk_ + #endif + } + +-static bool airoha_dev_tx_queue_busy(struct airoha_queue *q, u32 nr_frags) +-{ +- u32 tail = q->tail <= q->head ? q->tail + q->ndesc : q->tail; +- u32 index = q->head + nr_frags; +- +- /* completion napi can free out-of-order tx descriptors if hw QoS is +- * enabled and packets with different priorities are queued to the same +- * DMA ring. Take into account possible out-of-order reports checking +- * if the tx queue is full using circular buffer head/tail pointers +- * instead of the number of queued packets. +- */ +- return index >= tail; +-} +- + static int airoha_get_fe_port(struct airoha_gdm_port *port) + { + struct airoha_qdma *qdma = port->qdma; +@@ -1919,8 +1904,10 @@ static netdev_tx_t airoha_dev_xmit(struc + struct airoha_gdm_port *port = netdev_priv(dev); + struct airoha_qdma *qdma = port->qdma; + u32 nr_frags, tag, msg0, msg1, len; ++ struct airoha_queue_entry *e; + struct netdev_queue *txq; + struct airoha_queue *q; ++ LIST_HEAD(tx_list); + void *data; + int i, qid; + u16 index; +@@ -1966,7 +1953,7 @@ static netdev_tx_t airoha_dev_xmit(struc + txq = netdev_get_tx_queue(dev, qid); + nr_frags = 1 + skb_shinfo(skb)->nr_frags; + +- if (airoha_dev_tx_queue_busy(q, nr_frags)) { ++ if (q->queued + nr_frags >= q->ndesc) { + /* not enough space in the queue */ + netif_tx_stop_queue(txq); + spin_unlock_bh(&q->lock); +@@ -1975,11 +1962,13 @@ static netdev_tx_t airoha_dev_xmit(struc + + len = skb_headlen(skb); + data = skb->data; +- index = q->head; ++ ++ e = list_first_entry(&q->tx_list, struct airoha_queue_entry, ++ list); ++ index = e - q->entry; + + for (i = 0; i < nr_frags; i++) { + struct airoha_qdma_desc *desc = &q->desc[index]; +- struct airoha_queue_entry *e = &q->entry[index]; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + dma_addr_t addr; + u32 val; +@@ -1989,7 +1978,14 @@ static netdev_tx_t airoha_dev_xmit(struc + if (unlikely(dma_mapping_error(dev->dev.parent, addr))) + goto error_unmap; + +- index = (index + 1) % q->ndesc; ++ list_move_tail(&e->list, &tx_list); ++ e->skb = i ? NULL : skb; ++ e->dma_addr = addr; ++ e->dma_len = len; ++ ++ e = list_first_entry(&q->tx_list, struct airoha_queue_entry, ++ list); ++ index = e - q->entry; + + val = FIELD_PREP(QDMA_DESC_LEN_MASK, len); + if (i < nr_frags - 1) +@@ -2002,15 +1998,9 @@ static netdev_tx_t airoha_dev_xmit(struc + WRITE_ONCE(desc->msg1, cpu_to_le32(msg1)); + WRITE_ONCE(desc->msg2, cpu_to_le32(0xffff)); + +- e->skb = i ? NULL : skb; +- e->dma_addr = addr; +- e->dma_len = len; +- + data = skb_frag_address(frag); + len = skb_frag_size(frag); + } +- +- q->head = index; + q->queued += i; + + skb_tx_timestamp(skb); +@@ -2019,7 +2009,7 @@ static netdev_tx_t airoha_dev_xmit(struc + if (netif_xmit_stopped(txq) || !netdev_xmit_more()) + airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid), + TX_RING_CPU_IDX_MASK, +- FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head)); ++ FIELD_PREP(TX_RING_CPU_IDX_MASK, index)); + + if (q->ndesc - q->queued < q->free_thr) + netif_tx_stop_queue(txq); +@@ -2029,10 +2019,13 @@ static netdev_tx_t airoha_dev_xmit(struc + return NETDEV_TX_OK; + + error_unmap: +- for (i--; i >= 0; i--) { +- index = (q->head + i) % q->ndesc; +- dma_unmap_single(dev->dev.parent, q->entry[index].dma_addr, +- q->entry[index].dma_len, DMA_TO_DEVICE); ++ while (!list_empty(&tx_list)) { ++ e = list_first_entry(&tx_list, struct airoha_queue_entry, ++ list); ++ dma_unmap_single(dev->dev.parent, e->dma_addr, e->dma_len, ++ DMA_TO_DEVICE); ++ e->dma_addr = 0; ++ list_move_tail(&e->list, &q->tx_list); + } + + spin_unlock_bh(&q->lock); +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -169,7 +169,10 @@ enum trtcm_param { + struct airoha_queue_entry { + union { + void *buf; +- struct sk_buff *skb; ++ struct { ++ struct list_head list; ++ struct sk_buff *skb; ++ }; + }; + dma_addr_t dma_addr; + u16 dma_len; +@@ -193,6 +196,8 @@ struct airoha_queue { + struct napi_struct napi; + struct page_pool *page_pool; + struct sk_buff *skb; ++ ++ struct list_head tx_list; + }; + + struct airoha_tx_irq_queue { diff --git a/lede/target/linux/airoha/patches-6.12/109-01-v6.19-pinctrl-airoha-generalize-pins-group-function-confs-.patch b/lede/target/linux/airoha/patches-6.12/109-01-v6.19-pinctrl-airoha-generalize-pins-group-function-confs-.patch new file mode 100644 index 0000000000..c824f02e07 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/109-01-v6.19-pinctrl-airoha-generalize-pins-group-function-confs-.patch @@ -0,0 +1,781 @@ +From 4043b0c45f8555a079bdac69a19ed08695a47a7b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 7 Nov 2025 00:57:04 +0100 +Subject: [PATCH 1/5] pinctrl: airoha: generalize pins/group/function/confs + handling + +In preparation for support of Airoha AN7583, generalize +pins/group/function/confs handling and move them in match_data. +Inner function will base the values on the pinctrl priv struct instead of +relying on hardcoded struct. + +This permits to use different PIN data while keeping the same logic. + +Signed-off-by: Christian Marangi +Signed-off-by: Linus Walleij +--- + drivers/pinctrl/mediatek/pinctrl-airoha.c | 567 ++++++++++++---------- + 1 file changed, 318 insertions(+), 249 deletions(-) + +--- a/drivers/pinctrl/mediatek/pinctrl-airoha.c ++++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c +@@ -30,20 +30,20 @@ + #include "../pinconf.h" + #include "../pinmux.h" + +-#define PINCTRL_PIN_GROUP(id) \ +- PINCTRL_PINGROUP(#id, id##_pins, ARRAY_SIZE(id##_pins)) ++#define PINCTRL_PIN_GROUP(id, table) \ ++ PINCTRL_PINGROUP(id, table##_pins, ARRAY_SIZE(table##_pins)) + +-#define PINCTRL_FUNC_DESC(id) \ ++#define PINCTRL_FUNC_DESC(id, table) \ + { \ + .desc = { \ + .func = { \ +- .name = #id, \ +- .groups = id##_groups, \ +- .ngroups = ARRAY_SIZE(id##_groups), \ ++ .name = id, \ ++ .groups = table##_groups, \ ++ .ngroups = ARRAY_SIZE(table##_groups), \ + } \ + }, \ +- .groups = id##_func_group, \ +- .group_size = ARRAY_SIZE(id##_func_group), \ ++ .groups = table##_func_group, \ ++ .group_size = ARRAY_SIZE(table##_func_group), \ + } + + #define PINCTRL_CONF_DESC(p, offset, mask) \ +@@ -362,16 +362,46 @@ struct airoha_pinctrl_gpiochip { + u32 irq_type[AIROHA_NUM_PINS]; + }; + ++struct airoha_pinctrl_confs_info { ++ const struct airoha_pinctrl_conf *confs; ++ unsigned int num_confs; ++}; ++ ++enum airoha_pinctrl_confs_type { ++ AIROHA_PINCTRL_CONFS_PULLUP, ++ AIROHA_PINCTRL_CONFS_PULLDOWN, ++ AIROHA_PINCTRL_CONFS_DRIVE_E2, ++ AIROHA_PINCTRL_CONFS_DRIVE_E4, ++ AIROHA_PINCTRL_CONFS_PCIE_RST_OD, ++ ++ AIROHA_PINCTRL_CONFS_MAX, ++}; ++ + struct airoha_pinctrl { + struct pinctrl_dev *ctrl; + ++ struct pinctrl_desc desc; ++ const struct pingroup *grps; ++ const struct airoha_pinctrl_func *funcs; ++ const struct airoha_pinctrl_confs_info *confs_info; ++ + struct regmap *chip_scu; + struct regmap *regmap; + + struct airoha_pinctrl_gpiochip gpiochip; + }; + +-static struct pinctrl_pin_desc airoha_pinctrl_pins[] = { ++struct airoha_pinctrl_match_data { ++ const struct pinctrl_pin_desc *pins; ++ const unsigned int num_pins; ++ const struct pingroup *grps; ++ const unsigned int num_grps; ++ const struct airoha_pinctrl_func *funcs; ++ const unsigned int num_funcs; ++ const struct airoha_pinctrl_confs_info confs_info[AIROHA_PINCTRL_CONFS_MAX]; ++}; ++ ++static struct pinctrl_pin_desc en7581_pinctrl_pins[] = { + PINCTRL_PIN(0, "uart1_txd"), + PINCTRL_PIN(1, "uart1_rxd"), + PINCTRL_PIN(2, "i2c_scl"), +@@ -432,172 +462,172 @@ static struct pinctrl_pin_desc airoha_pi + PINCTRL_PIN(63, "pcie_reset2"), + }; + +-static const int pon_pins[] = { 49, 50, 51, 52, 53, 54 }; +-static const int pon_tod_1pps_pins[] = { 46 }; +-static const int gsw_tod_1pps_pins[] = { 46 }; +-static const int sipo_pins[] = { 16, 17 }; +-static const int sipo_rclk_pins[] = { 16, 17, 43 }; +-static const int mdio_pins[] = { 14, 15 }; +-static const int uart2_pins[] = { 48, 55 }; +-static const int uart2_cts_rts_pins[] = { 46, 47 }; +-static const int hsuart_pins[] = { 28, 29 }; +-static const int hsuart_cts_rts_pins[] = { 26, 27 }; +-static const int uart4_pins[] = { 38, 39 }; +-static const int uart5_pins[] = { 18, 19 }; +-static const int i2c0_pins[] = { 2, 3 }; +-static const int i2c1_pins[] = { 14, 15 }; +-static const int jtag_udi_pins[] = { 16, 17, 18, 19, 20 }; +-static const int jtag_dfd_pins[] = { 16, 17, 18, 19, 20 }; +-static const int i2s_pins[] = { 26, 27, 28, 29 }; +-static const int pcm1_pins[] = { 22, 23, 24, 25 }; +-static const int pcm2_pins[] = { 18, 19, 20, 21 }; +-static const int spi_quad_pins[] = { 32, 33 }; +-static const int spi_pins[] = { 4, 5, 6, 7 }; +-static const int spi_cs1_pins[] = { 34 }; +-static const int pcm_spi_pins[] = { 18, 19, 20, 21, 22, 23, 24, 25 }; +-static const int pcm_spi_int_pins[] = { 14 }; +-static const int pcm_spi_rst_pins[] = { 15 }; +-static const int pcm_spi_cs1_pins[] = { 43 }; +-static const int pcm_spi_cs2_pins[] = { 40 }; +-static const int pcm_spi_cs2_p128_pins[] = { 40 }; +-static const int pcm_spi_cs2_p156_pins[] = { 40 }; +-static const int pcm_spi_cs3_pins[] = { 41 }; +-static const int pcm_spi_cs4_pins[] = { 42 }; +-static const int emmc_pins[] = { 4, 5, 6, 30, 31, 32, 33, 34, 35, 36, 37 }; +-static const int pnand_pins[] = { 4, 5, 6, 7, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42 }; +-static const int gpio0_pins[] = { 13 }; +-static const int gpio1_pins[] = { 14 }; +-static const int gpio2_pins[] = { 15 }; +-static const int gpio3_pins[] = { 16 }; +-static const int gpio4_pins[] = { 17 }; +-static const int gpio5_pins[] = { 18 }; +-static const int gpio6_pins[] = { 19 }; +-static const int gpio7_pins[] = { 20 }; +-static const int gpio8_pins[] = { 21 }; +-static const int gpio9_pins[] = { 22 }; +-static const int gpio10_pins[] = { 23 }; +-static const int gpio11_pins[] = { 24 }; +-static const int gpio12_pins[] = { 25 }; +-static const int gpio13_pins[] = { 26 }; +-static const int gpio14_pins[] = { 27 }; +-static const int gpio15_pins[] = { 28 }; +-static const int gpio16_pins[] = { 29 }; +-static const int gpio17_pins[] = { 30 }; +-static const int gpio18_pins[] = { 31 }; +-static const int gpio19_pins[] = { 32 }; +-static const int gpio20_pins[] = { 33 }; +-static const int gpio21_pins[] = { 34 }; +-static const int gpio22_pins[] = { 35 }; +-static const int gpio23_pins[] = { 36 }; +-static const int gpio24_pins[] = { 37 }; +-static const int gpio25_pins[] = { 38 }; +-static const int gpio26_pins[] = { 39 }; +-static const int gpio27_pins[] = { 40 }; +-static const int gpio28_pins[] = { 41 }; +-static const int gpio29_pins[] = { 42 }; +-static const int gpio30_pins[] = { 43 }; +-static const int gpio31_pins[] = { 44 }; +-static const int gpio33_pins[] = { 46 }; +-static const int gpio34_pins[] = { 47 }; +-static const int gpio35_pins[] = { 48 }; +-static const int gpio36_pins[] = { 49 }; +-static const int gpio37_pins[] = { 50 }; +-static const int gpio38_pins[] = { 51 }; +-static const int gpio39_pins[] = { 52 }; +-static const int gpio40_pins[] = { 53 }; +-static const int gpio41_pins[] = { 54 }; +-static const int gpio42_pins[] = { 55 }; +-static const int gpio43_pins[] = { 56 }; +-static const int gpio44_pins[] = { 57 }; +-static const int gpio45_pins[] = { 58 }; +-static const int gpio46_pins[] = { 59 }; +-static const int pcie_reset0_pins[] = { 61 }; +-static const int pcie_reset1_pins[] = { 62 }; +-static const int pcie_reset2_pins[] = { 63 }; +- +-static const struct pingroup airoha_pinctrl_groups[] = { +- PINCTRL_PIN_GROUP(pon), +- PINCTRL_PIN_GROUP(pon_tod_1pps), +- PINCTRL_PIN_GROUP(gsw_tod_1pps), +- PINCTRL_PIN_GROUP(sipo), +- PINCTRL_PIN_GROUP(sipo_rclk), +- PINCTRL_PIN_GROUP(mdio), +- PINCTRL_PIN_GROUP(uart2), +- PINCTRL_PIN_GROUP(uart2_cts_rts), +- PINCTRL_PIN_GROUP(hsuart), +- PINCTRL_PIN_GROUP(hsuart_cts_rts), +- PINCTRL_PIN_GROUP(uart4), +- PINCTRL_PIN_GROUP(uart5), +- PINCTRL_PIN_GROUP(i2c0), +- PINCTRL_PIN_GROUP(i2c1), +- PINCTRL_PIN_GROUP(jtag_udi), +- PINCTRL_PIN_GROUP(jtag_dfd), +- PINCTRL_PIN_GROUP(i2s), +- PINCTRL_PIN_GROUP(pcm1), +- PINCTRL_PIN_GROUP(pcm2), +- PINCTRL_PIN_GROUP(spi), +- PINCTRL_PIN_GROUP(spi_quad), +- PINCTRL_PIN_GROUP(spi_cs1), +- PINCTRL_PIN_GROUP(pcm_spi), +- PINCTRL_PIN_GROUP(pcm_spi_int), +- PINCTRL_PIN_GROUP(pcm_spi_rst), +- PINCTRL_PIN_GROUP(pcm_spi_cs1), +- PINCTRL_PIN_GROUP(pcm_spi_cs2_p128), +- PINCTRL_PIN_GROUP(pcm_spi_cs2_p156), +- PINCTRL_PIN_GROUP(pcm_spi_cs2), +- PINCTRL_PIN_GROUP(pcm_spi_cs3), +- PINCTRL_PIN_GROUP(pcm_spi_cs4), +- PINCTRL_PIN_GROUP(emmc), +- PINCTRL_PIN_GROUP(pnand), +- PINCTRL_PIN_GROUP(gpio0), +- PINCTRL_PIN_GROUP(gpio1), +- PINCTRL_PIN_GROUP(gpio2), +- PINCTRL_PIN_GROUP(gpio3), +- PINCTRL_PIN_GROUP(gpio4), +- PINCTRL_PIN_GROUP(gpio5), +- PINCTRL_PIN_GROUP(gpio6), +- PINCTRL_PIN_GROUP(gpio7), +- PINCTRL_PIN_GROUP(gpio8), +- PINCTRL_PIN_GROUP(gpio9), +- PINCTRL_PIN_GROUP(gpio10), +- PINCTRL_PIN_GROUP(gpio11), +- PINCTRL_PIN_GROUP(gpio12), +- PINCTRL_PIN_GROUP(gpio13), +- PINCTRL_PIN_GROUP(gpio14), +- PINCTRL_PIN_GROUP(gpio15), +- PINCTRL_PIN_GROUP(gpio16), +- PINCTRL_PIN_GROUP(gpio17), +- PINCTRL_PIN_GROUP(gpio18), +- PINCTRL_PIN_GROUP(gpio19), +- PINCTRL_PIN_GROUP(gpio20), +- PINCTRL_PIN_GROUP(gpio21), +- PINCTRL_PIN_GROUP(gpio22), +- PINCTRL_PIN_GROUP(gpio23), +- PINCTRL_PIN_GROUP(gpio24), +- PINCTRL_PIN_GROUP(gpio25), +- PINCTRL_PIN_GROUP(gpio26), +- PINCTRL_PIN_GROUP(gpio27), +- PINCTRL_PIN_GROUP(gpio28), +- PINCTRL_PIN_GROUP(gpio29), +- PINCTRL_PIN_GROUP(gpio30), +- PINCTRL_PIN_GROUP(gpio31), +- PINCTRL_PIN_GROUP(gpio33), +- PINCTRL_PIN_GROUP(gpio34), +- PINCTRL_PIN_GROUP(gpio35), +- PINCTRL_PIN_GROUP(gpio36), +- PINCTRL_PIN_GROUP(gpio37), +- PINCTRL_PIN_GROUP(gpio38), +- PINCTRL_PIN_GROUP(gpio39), +- PINCTRL_PIN_GROUP(gpio40), +- PINCTRL_PIN_GROUP(gpio41), +- PINCTRL_PIN_GROUP(gpio42), +- PINCTRL_PIN_GROUP(gpio43), +- PINCTRL_PIN_GROUP(gpio44), +- PINCTRL_PIN_GROUP(gpio45), +- PINCTRL_PIN_GROUP(gpio46), +- PINCTRL_PIN_GROUP(pcie_reset0), +- PINCTRL_PIN_GROUP(pcie_reset1), +- PINCTRL_PIN_GROUP(pcie_reset2), ++static const int en7581_pon_pins[] = { 49, 50, 51, 52, 53, 54 }; ++static const int en7581_pon_tod_1pps_pins[] = { 46 }; ++static const int en7581_gsw_tod_1pps_pins[] = { 46 }; ++static const int en7581_sipo_pins[] = { 16, 17 }; ++static const int en7581_sipo_rclk_pins[] = { 16, 17, 43 }; ++static const int en7581_mdio_pins[] = { 14, 15 }; ++static const int en7581_uart2_pins[] = { 48, 55 }; ++static const int en7581_uart2_cts_rts_pins[] = { 46, 47 }; ++static const int en7581_hsuart_pins[] = { 28, 29 }; ++static const int en7581_hsuart_cts_rts_pins[] = { 26, 27 }; ++static const int en7581_uart4_pins[] = { 38, 39 }; ++static const int en7581_uart5_pins[] = { 18, 19 }; ++static const int en7581_i2c0_pins[] = { 2, 3 }; ++static const int en7581_i2c1_pins[] = { 14, 15 }; ++static const int en7581_jtag_udi_pins[] = { 16, 17, 18, 19, 20 }; ++static const int en7581_jtag_dfd_pins[] = { 16, 17, 18, 19, 20 }; ++static const int en7581_i2s_pins[] = { 26, 27, 28, 29 }; ++static const int en7581_pcm1_pins[] = { 22, 23, 24, 25 }; ++static const int en7581_pcm2_pins[] = { 18, 19, 20, 21 }; ++static const int en7581_spi_quad_pins[] = { 32, 33 }; ++static const int en7581_spi_pins[] = { 4, 5, 6, 7 }; ++static const int en7581_spi_cs1_pins[] = { 34 }; ++static const int en7581_pcm_spi_pins[] = { 18, 19, 20, 21, 22, 23, 24, 25 }; ++static const int en7581_pcm_spi_int_pins[] = { 14 }; ++static const int en7581_pcm_spi_rst_pins[] = { 15 }; ++static const int en7581_pcm_spi_cs1_pins[] = { 43 }; ++static const int en7581_pcm_spi_cs2_pins[] = { 40 }; ++static const int en7581_pcm_spi_cs2_p128_pins[] = { 40 }; ++static const int en7581_pcm_spi_cs2_p156_pins[] = { 40 }; ++static const int en7581_pcm_spi_cs3_pins[] = { 41 }; ++static const int en7581_pcm_spi_cs4_pins[] = { 42 }; ++static const int en7581_emmc_pins[] = { 4, 5, 6, 30, 31, 32, 33, 34, 35, 36, 37 }; ++static const int en7581_pnand_pins[] = { 4, 5, 6, 7, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42 }; ++static const int en7581_gpio0_pins[] = { 13 }; ++static const int en7581_gpio1_pins[] = { 14 }; ++static const int en7581_gpio2_pins[] = { 15 }; ++static const int en7581_gpio3_pins[] = { 16 }; ++static const int en7581_gpio4_pins[] = { 17 }; ++static const int en7581_gpio5_pins[] = { 18 }; ++static const int en7581_gpio6_pins[] = { 19 }; ++static const int en7581_gpio7_pins[] = { 20 }; ++static const int en7581_gpio8_pins[] = { 21 }; ++static const int en7581_gpio9_pins[] = { 22 }; ++static const int en7581_gpio10_pins[] = { 23 }; ++static const int en7581_gpio11_pins[] = { 24 }; ++static const int en7581_gpio12_pins[] = { 25 }; ++static const int en7581_gpio13_pins[] = { 26 }; ++static const int en7581_gpio14_pins[] = { 27 }; ++static const int en7581_gpio15_pins[] = { 28 }; ++static const int en7581_gpio16_pins[] = { 29 }; ++static const int en7581_gpio17_pins[] = { 30 }; ++static const int en7581_gpio18_pins[] = { 31 }; ++static const int en7581_gpio19_pins[] = { 32 }; ++static const int en7581_gpio20_pins[] = { 33 }; ++static const int en7581_gpio21_pins[] = { 34 }; ++static const int en7581_gpio22_pins[] = { 35 }; ++static const int en7581_gpio23_pins[] = { 36 }; ++static const int en7581_gpio24_pins[] = { 37 }; ++static const int en7581_gpio25_pins[] = { 38 }; ++static const int en7581_gpio26_pins[] = { 39 }; ++static const int en7581_gpio27_pins[] = { 40 }; ++static const int en7581_gpio28_pins[] = { 41 }; ++static const int en7581_gpio29_pins[] = { 42 }; ++static const int en7581_gpio30_pins[] = { 43 }; ++static const int en7581_gpio31_pins[] = { 44 }; ++static const int en7581_gpio33_pins[] = { 46 }; ++static const int en7581_gpio34_pins[] = { 47 }; ++static const int en7581_gpio35_pins[] = { 48 }; ++static const int en7581_gpio36_pins[] = { 49 }; ++static const int en7581_gpio37_pins[] = { 50 }; ++static const int en7581_gpio38_pins[] = { 51 }; ++static const int en7581_gpio39_pins[] = { 52 }; ++static const int en7581_gpio40_pins[] = { 53 }; ++static const int en7581_gpio41_pins[] = { 54 }; ++static const int en7581_gpio42_pins[] = { 55 }; ++static const int en7581_gpio43_pins[] = { 56 }; ++static const int en7581_gpio44_pins[] = { 57 }; ++static const int en7581_gpio45_pins[] = { 58 }; ++static const int en7581_gpio46_pins[] = { 59 }; ++static const int en7581_pcie_reset0_pins[] = { 61 }; ++static const int en7581_pcie_reset1_pins[] = { 62 }; ++static const int en7581_pcie_reset2_pins[] = { 63 }; ++ ++static const struct pingroup en7581_pinctrl_groups[] = { ++ PINCTRL_PIN_GROUP("pon", en7581_pon), ++ PINCTRL_PIN_GROUP("pon_tod_1pps", en7581_pon_tod_1pps), ++ PINCTRL_PIN_GROUP("gsw_tod_1pps", en7581_gsw_tod_1pps), ++ PINCTRL_PIN_GROUP("sipo", en7581_sipo), ++ PINCTRL_PIN_GROUP("sipo_rclk", en7581_sipo_rclk), ++ PINCTRL_PIN_GROUP("mdio", en7581_mdio), ++ PINCTRL_PIN_GROUP("uart2", en7581_uart2), ++ PINCTRL_PIN_GROUP("uart2_cts_rts", en7581_uart2_cts_rts), ++ PINCTRL_PIN_GROUP("hsuart", en7581_hsuart), ++ PINCTRL_PIN_GROUP("hsuart_cts_rts", en7581_hsuart_cts_rts), ++ PINCTRL_PIN_GROUP("uart4", en7581_uart4), ++ PINCTRL_PIN_GROUP("uart5", en7581_uart5), ++ PINCTRL_PIN_GROUP("i2c0", en7581_i2c0), ++ PINCTRL_PIN_GROUP("i2c1", en7581_i2c1), ++ PINCTRL_PIN_GROUP("jtag_udi", en7581_jtag_udi), ++ PINCTRL_PIN_GROUP("jtag_dfd", en7581_jtag_dfd), ++ PINCTRL_PIN_GROUP("i2s", en7581_i2s), ++ PINCTRL_PIN_GROUP("pcm1", en7581_pcm1), ++ PINCTRL_PIN_GROUP("pcm2", en7581_pcm2), ++ PINCTRL_PIN_GROUP("spi", en7581_spi), ++ PINCTRL_PIN_GROUP("spi_quad", en7581_spi_quad), ++ PINCTRL_PIN_GROUP("spi_cs1", en7581_spi_cs1), ++ PINCTRL_PIN_GROUP("pcm_spi", en7581_pcm_spi), ++ PINCTRL_PIN_GROUP("pcm_spi_int", en7581_pcm_spi_int), ++ PINCTRL_PIN_GROUP("pcm_spi_rst", en7581_pcm_spi_rst), ++ PINCTRL_PIN_GROUP("pcm_spi_cs1", en7581_pcm_spi_cs1), ++ PINCTRL_PIN_GROUP("pcm_spi_cs2_p128", en7581_pcm_spi_cs2_p128), ++ PINCTRL_PIN_GROUP("pcm_spi_cs2_p156", en7581_pcm_spi_cs2_p156), ++ PINCTRL_PIN_GROUP("pcm_spi_cs2", en7581_pcm_spi_cs2), ++ PINCTRL_PIN_GROUP("pcm_spi_cs3", en7581_pcm_spi_cs3), ++ PINCTRL_PIN_GROUP("pcm_spi_cs4", en7581_pcm_spi_cs4), ++ PINCTRL_PIN_GROUP("emmc", en7581_emmc), ++ PINCTRL_PIN_GROUP("pnand", en7581_pnand), ++ PINCTRL_PIN_GROUP("gpio0", en7581_gpio0), ++ PINCTRL_PIN_GROUP("gpio1", en7581_gpio1), ++ PINCTRL_PIN_GROUP("gpio2", en7581_gpio2), ++ PINCTRL_PIN_GROUP("gpio3", en7581_gpio3), ++ PINCTRL_PIN_GROUP("gpio4", en7581_gpio4), ++ PINCTRL_PIN_GROUP("gpio5", en7581_gpio5), ++ PINCTRL_PIN_GROUP("gpio6", en7581_gpio6), ++ PINCTRL_PIN_GROUP("gpio7", en7581_gpio7), ++ PINCTRL_PIN_GROUP("gpio8", en7581_gpio8), ++ PINCTRL_PIN_GROUP("gpio9", en7581_gpio9), ++ PINCTRL_PIN_GROUP("gpio10", en7581_gpio10), ++ PINCTRL_PIN_GROUP("gpio11", en7581_gpio11), ++ PINCTRL_PIN_GROUP("gpio12", en7581_gpio12), ++ PINCTRL_PIN_GROUP("gpio13", en7581_gpio13), ++ PINCTRL_PIN_GROUP("gpio14", en7581_gpio14), ++ PINCTRL_PIN_GROUP("gpio15", en7581_gpio15), ++ PINCTRL_PIN_GROUP("gpio16", en7581_gpio16), ++ PINCTRL_PIN_GROUP("gpio17", en7581_gpio17), ++ PINCTRL_PIN_GROUP("gpio18", en7581_gpio18), ++ PINCTRL_PIN_GROUP("gpio19", en7581_gpio19), ++ PINCTRL_PIN_GROUP("gpio20", en7581_gpio20), ++ PINCTRL_PIN_GROUP("gpio21", en7581_gpio21), ++ PINCTRL_PIN_GROUP("gpio22", en7581_gpio22), ++ PINCTRL_PIN_GROUP("gpio23", en7581_gpio23), ++ PINCTRL_PIN_GROUP("gpio24", en7581_gpio24), ++ PINCTRL_PIN_GROUP("gpio25", en7581_gpio25), ++ PINCTRL_PIN_GROUP("gpio26", en7581_gpio26), ++ PINCTRL_PIN_GROUP("gpio27", en7581_gpio27), ++ PINCTRL_PIN_GROUP("gpio28", en7581_gpio28), ++ PINCTRL_PIN_GROUP("gpio29", en7581_gpio29), ++ PINCTRL_PIN_GROUP("gpio30", en7581_gpio30), ++ PINCTRL_PIN_GROUP("gpio31", en7581_gpio31), ++ PINCTRL_PIN_GROUP("gpio33", en7581_gpio33), ++ PINCTRL_PIN_GROUP("gpio34", en7581_gpio34), ++ PINCTRL_PIN_GROUP("gpio35", en7581_gpio35), ++ PINCTRL_PIN_GROUP("gpio36", en7581_gpio36), ++ PINCTRL_PIN_GROUP("gpio37", en7581_gpio37), ++ PINCTRL_PIN_GROUP("gpio38", en7581_gpio38), ++ PINCTRL_PIN_GROUP("gpio39", en7581_gpio39), ++ PINCTRL_PIN_GROUP("gpio40", en7581_gpio40), ++ PINCTRL_PIN_GROUP("gpio41", en7581_gpio41), ++ PINCTRL_PIN_GROUP("gpio42", en7581_gpio42), ++ PINCTRL_PIN_GROUP("gpio43", en7581_gpio43), ++ PINCTRL_PIN_GROUP("gpio44", en7581_gpio44), ++ PINCTRL_PIN_GROUP("gpio45", en7581_gpio45), ++ PINCTRL_PIN_GROUP("gpio46", en7581_gpio46), ++ PINCTRL_PIN_GROUP("pcie_reset0", en7581_pcie_reset0), ++ PINCTRL_PIN_GROUP("pcie_reset1", en7581_pcie_reset1), ++ PINCTRL_PIN_GROUP("pcie_reset2", en7581_pcie_reset2), + }; + + static const char *const pon_groups[] = { "pon" }; +@@ -1960,33 +1990,33 @@ static const struct airoha_pinctrl_func_ + }, + }; + +-static const struct airoha_pinctrl_func airoha_pinctrl_funcs[] = { +- PINCTRL_FUNC_DESC(pon), +- PINCTRL_FUNC_DESC(tod_1pps), +- PINCTRL_FUNC_DESC(sipo), +- PINCTRL_FUNC_DESC(mdio), +- PINCTRL_FUNC_DESC(uart), +- PINCTRL_FUNC_DESC(i2c), +- PINCTRL_FUNC_DESC(jtag), +- PINCTRL_FUNC_DESC(pcm), +- PINCTRL_FUNC_DESC(spi), +- PINCTRL_FUNC_DESC(pcm_spi), +- PINCTRL_FUNC_DESC(i2s), +- PINCTRL_FUNC_DESC(emmc), +- PINCTRL_FUNC_DESC(pnand), +- PINCTRL_FUNC_DESC(pcie_reset), +- PINCTRL_FUNC_DESC(pwm), +- PINCTRL_FUNC_DESC(phy1_led0), +- PINCTRL_FUNC_DESC(phy2_led0), +- PINCTRL_FUNC_DESC(phy3_led0), +- PINCTRL_FUNC_DESC(phy4_led0), +- PINCTRL_FUNC_DESC(phy1_led1), +- PINCTRL_FUNC_DESC(phy2_led1), +- PINCTRL_FUNC_DESC(phy3_led1), +- PINCTRL_FUNC_DESC(phy4_led1), ++static const struct airoha_pinctrl_func en7581_pinctrl_funcs[] = { ++ PINCTRL_FUNC_DESC("pon", pon), ++ PINCTRL_FUNC_DESC("tod_1pps", tod_1pps), ++ PINCTRL_FUNC_DESC("sipo", sipo), ++ PINCTRL_FUNC_DESC("mdio", mdio), ++ PINCTRL_FUNC_DESC("uart", uart), ++ PINCTRL_FUNC_DESC("i2c", i2c), ++ PINCTRL_FUNC_DESC("jtag", jtag), ++ PINCTRL_FUNC_DESC("pcm", pcm), ++ PINCTRL_FUNC_DESC("spi", spi), ++ PINCTRL_FUNC_DESC("pcm_spi", pcm_spi), ++ PINCTRL_FUNC_DESC("i2s", i2s), ++ PINCTRL_FUNC_DESC("emmc", emmc), ++ PINCTRL_FUNC_DESC("pnand", pnand), ++ PINCTRL_FUNC_DESC("pcie_reset", pcie_reset), ++ PINCTRL_FUNC_DESC("pwm", pwm), ++ PINCTRL_FUNC_DESC("phy1_led0", phy1_led0), ++ PINCTRL_FUNC_DESC("phy2_led0", phy2_led0), ++ PINCTRL_FUNC_DESC("phy3_led0", phy3_led0), ++ PINCTRL_FUNC_DESC("phy4_led0", phy4_led0), ++ PINCTRL_FUNC_DESC("phy1_led1", phy1_led1), ++ PINCTRL_FUNC_DESC("phy2_led1", phy2_led1), ++ PINCTRL_FUNC_DESC("phy3_led1", phy3_led1), ++ PINCTRL_FUNC_DESC("phy4_led1", phy4_led1), + }; + +-static const struct airoha_pinctrl_conf airoha_pinctrl_pullup_conf[] = { ++static const struct airoha_pinctrl_conf en7581_pinctrl_pullup_conf[] = { + PINCTRL_CONF_DESC(0, REG_I2C_SDA_PU, UART1_TXD_PU_MASK), + PINCTRL_CONF_DESC(1, REG_I2C_SDA_PU, UART1_RXD_PU_MASK), + PINCTRL_CONF_DESC(2, REG_I2C_SDA_PU, I2C_SDA_PU_MASK), +@@ -2047,7 +2077,7 @@ static const struct airoha_pinctrl_conf + PINCTRL_CONF_DESC(63, REG_I2C_SDA_PU, PCIE2_RESET_PU_MASK), + }; + +-static const struct airoha_pinctrl_conf airoha_pinctrl_pulldown_conf[] = { ++static const struct airoha_pinctrl_conf en7581_pinctrl_pulldown_conf[] = { + PINCTRL_CONF_DESC(0, REG_I2C_SDA_PD, UART1_TXD_PD_MASK), + PINCTRL_CONF_DESC(1, REG_I2C_SDA_PD, UART1_RXD_PD_MASK), + PINCTRL_CONF_DESC(2, REG_I2C_SDA_PD, I2C_SDA_PD_MASK), +@@ -2108,7 +2138,7 @@ static const struct airoha_pinctrl_conf + PINCTRL_CONF_DESC(63, REG_I2C_SDA_PD, PCIE2_RESET_PD_MASK), + }; + +-static const struct airoha_pinctrl_conf airoha_pinctrl_drive_e2_conf[] = { ++static const struct airoha_pinctrl_conf en7581_pinctrl_drive_e2_conf[] = { + PINCTRL_CONF_DESC(0, REG_I2C_SDA_E2, UART1_TXD_E2_MASK), + PINCTRL_CONF_DESC(1, REG_I2C_SDA_E2, UART1_RXD_E2_MASK), + PINCTRL_CONF_DESC(2, REG_I2C_SDA_E2, I2C_SDA_E2_MASK), +@@ -2169,7 +2199,7 @@ static const struct airoha_pinctrl_conf + PINCTRL_CONF_DESC(63, REG_I2C_SDA_E2, PCIE2_RESET_E2_MASK), + }; + +-static const struct airoha_pinctrl_conf airoha_pinctrl_drive_e4_conf[] = { ++static const struct airoha_pinctrl_conf en7581_pinctrl_drive_e4_conf[] = { + PINCTRL_CONF_DESC(0, REG_I2C_SDA_E4, UART1_TXD_E4_MASK), + PINCTRL_CONF_DESC(1, REG_I2C_SDA_E4, UART1_RXD_E4_MASK), + PINCTRL_CONF_DESC(2, REG_I2C_SDA_E4, I2C_SDA_E4_MASK), +@@ -2230,7 +2260,7 @@ static const struct airoha_pinctrl_conf + PINCTRL_CONF_DESC(63, REG_I2C_SDA_E4, PCIE2_RESET_E4_MASK), + }; + +-static const struct airoha_pinctrl_conf airoha_pinctrl_pcie_rst_od_conf[] = { ++static const struct airoha_pinctrl_conf en7581_pinctrl_pcie_rst_od_conf[] = { + PINCTRL_CONF_DESC(61, REG_PCIE_RESET_OD, PCIE0_RESET_OD_MASK), + PINCTRL_CONF_DESC(62, REG_PCIE_RESET_OD, PCIE1_RESET_OD_MASK), + PINCTRL_CONF_DESC(63, REG_PCIE_RESET_OD, PCIE2_RESET_OD_MASK), +@@ -2552,12 +2582,17 @@ airoha_pinctrl_get_conf_reg(const struct + } + + static int airoha_pinctrl_get_conf(struct airoha_pinctrl *pinctrl, +- const struct airoha_pinctrl_conf *conf, +- int conf_size, int pin, u32 *val) ++ enum airoha_pinctrl_confs_type conf_type, ++ int pin, u32 *val) + { ++ const struct airoha_pinctrl_confs_info *confs_info; + const struct airoha_pinctrl_reg *reg; + +- reg = airoha_pinctrl_get_conf_reg(conf, conf_size, pin); ++ confs_info = &pinctrl->confs_info[conf_type]; ++ ++ reg = airoha_pinctrl_get_conf_reg(confs_info->confs, ++ confs_info->num_confs, ++ pin); + if (!reg) + return -EINVAL; + +@@ -2570,12 +2605,17 @@ static int airoha_pinctrl_get_conf(struc + } + + static int airoha_pinctrl_set_conf(struct airoha_pinctrl *pinctrl, +- const struct airoha_pinctrl_conf *conf, +- int conf_size, int pin, u32 val) ++ enum airoha_pinctrl_confs_type conf_type, ++ int pin, u32 val) + { ++ const struct airoha_pinctrl_confs_info *confs_info; + const struct airoha_pinctrl_reg *reg = NULL; + +- reg = airoha_pinctrl_get_conf_reg(conf, conf_size, pin); ++ confs_info = &pinctrl->confs_info[conf_type]; ++ ++ reg = airoha_pinctrl_get_conf_reg(confs_info->confs, ++ confs_info->num_confs, ++ pin); + if (!reg) + return -EINVAL; + +@@ -2588,44 +2628,34 @@ static int airoha_pinctrl_set_conf(struc + } + + #define airoha_pinctrl_get_pullup_conf(pinctrl, pin, val) \ +- airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_pullup_conf, \ +- ARRAY_SIZE(airoha_pinctrl_pullup_conf), \ ++ airoha_pinctrl_get_conf((pinctrl), AIROHA_PINCTRL_CONFS_PULLUP, \ + (pin), (val)) + #define airoha_pinctrl_get_pulldown_conf(pinctrl, pin, val) \ +- airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_pulldown_conf, \ +- ARRAY_SIZE(airoha_pinctrl_pulldown_conf), \ ++ airoha_pinctrl_get_conf((pinctrl), AIROHA_PINCTRL_CONFS_PULLDOWN, \ + (pin), (val)) + #define airoha_pinctrl_get_drive_e2_conf(pinctrl, pin, val) \ +- airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_drive_e2_conf, \ +- ARRAY_SIZE(airoha_pinctrl_drive_e2_conf), \ ++ airoha_pinctrl_get_conf((pinctrl), AIROHA_PINCTRL_CONFS_DRIVE_E2, \ + (pin), (val)) + #define airoha_pinctrl_get_drive_e4_conf(pinctrl, pin, val) \ +- airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_drive_e4_conf, \ +- ARRAY_SIZE(airoha_pinctrl_drive_e4_conf), \ ++ airoha_pinctrl_get_conf((pinctrl), AIROHA_PINCTRL_CONFS_DRIVE_E4, \ + (pin), (val)) + #define airoha_pinctrl_get_pcie_rst_od_conf(pinctrl, pin, val) \ +- airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_pcie_rst_od_conf, \ +- ARRAY_SIZE(airoha_pinctrl_pcie_rst_od_conf), \ ++ airoha_pinctrl_get_conf((pinctrl), AIROHA_PINCTRL_CONFS_PCIE_RST_OD, \ + (pin), (val)) + #define airoha_pinctrl_set_pullup_conf(pinctrl, pin, val) \ +- airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_pullup_conf, \ +- ARRAY_SIZE(airoha_pinctrl_pullup_conf), \ ++ airoha_pinctrl_set_conf((pinctrl), AIROHA_PINCTRL_CONFS_PULLUP, \ + (pin), (val)) + #define airoha_pinctrl_set_pulldown_conf(pinctrl, pin, val) \ +- airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_pulldown_conf, \ +- ARRAY_SIZE(airoha_pinctrl_pulldown_conf), \ ++ airoha_pinctrl_set_conf((pinctrl), AIROHA_PINCTRL_CONFS_PULLDOWN, \ + (pin), (val)) + #define airoha_pinctrl_set_drive_e2_conf(pinctrl, pin, val) \ +- airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_drive_e2_conf, \ +- ARRAY_SIZE(airoha_pinctrl_drive_e2_conf), \ ++ airoha_pinctrl_set_conf((pinctrl), AIROHA_PINCTRL_CONFS_DRIVE_E2, \ + (pin), (val)) + #define airoha_pinctrl_set_drive_e4_conf(pinctrl, pin, val) \ +- airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_drive_e4_conf, \ +- ARRAY_SIZE(airoha_pinctrl_drive_e4_conf), \ ++ airoha_pinctrl_set_conf((pinctrl), AIROHA_PINCTRL_CONFS_DRIVE_E4, \ + (pin), (val)) + #define airoha_pinctrl_set_pcie_rst_od_conf(pinctrl, pin, val) \ +- airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_pcie_rst_od_conf, \ +- ARRAY_SIZE(airoha_pinctrl_pcie_rst_od_conf), \ ++ airoha_pinctrl_set_conf((pinctrl), AIROHA_PINCTRL_CONFS_PCIE_RST_OD, \ + (pin), (val)) + + static int airoha_pinconf_get_direction(struct pinctrl_dev *pctrl_dev, u32 p) +@@ -2804,12 +2834,13 @@ static int airoha_pinconf_set(struct pin + static int airoha_pinconf_group_get(struct pinctrl_dev *pctrl_dev, + unsigned int group, unsigned long *config) + { ++ struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); + u32 cur_config = 0; + int i; + +- for (i = 0; i < airoha_pinctrl_groups[group].npins; i++) { ++ for (i = 0; i < pinctrl->grps[group].npins; i++) { + if (airoha_pinconf_get(pctrl_dev, +- airoha_pinctrl_groups[group].pins[i], ++ pinctrl->grps[group].pins[i], + config)) + return -ENOTSUPP; + +@@ -2826,13 +2857,14 @@ static int airoha_pinconf_group_set(stru + unsigned int group, unsigned long *configs, + unsigned int num_configs) + { ++ struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); + int i; + +- for (i = 0; i < airoha_pinctrl_groups[group].npins; i++) { ++ for (i = 0; i < pinctrl->grps[group].npins; i++) { + int err; + + err = airoha_pinconf_set(pctrl_dev, +- airoha_pinctrl_groups[group].pins[i], ++ pinctrl->grps[group].pins[i], + configs, num_configs); + if (err) + return err; +@@ -2858,23 +2890,16 @@ static const struct pinctrl_ops airoha_p + .dt_free_map = pinconf_generic_dt_free_map, + }; + +-static struct pinctrl_desc airoha_pinctrl_desc = { +- .name = KBUILD_MODNAME, +- .owner = THIS_MODULE, +- .pctlops = &airoha_pctlops, +- .pmxops = &airoha_pmxops, +- .confops = &airoha_confops, +- .pins = airoha_pinctrl_pins, +- .npins = ARRAY_SIZE(airoha_pinctrl_pins), +-}; +- + static int airoha_pinctrl_probe(struct platform_device *pdev) + { ++ const struct airoha_pinctrl_match_data *data; + struct device *dev = &pdev->dev; + struct airoha_pinctrl *pinctrl; + struct regmap *map; + int err, i; + ++ data = device_get_match_data(dev); ++ + pinctrl = devm_kzalloc(dev, sizeof(*pinctrl), GFP_KERNEL); + if (!pinctrl) + return -ENOMEM; +@@ -2889,14 +2914,23 @@ static int airoha_pinctrl_probe(struct p + + pinctrl->chip_scu = map; + +- err = devm_pinctrl_register_and_init(dev, &airoha_pinctrl_desc, ++ /* Init pinctrl desc struct */ ++ pinctrl->desc.name = KBUILD_MODNAME; ++ pinctrl->desc.owner = THIS_MODULE, ++ pinctrl->desc.pctlops = &airoha_pctlops, ++ pinctrl->desc.pmxops = &airoha_pmxops, ++ pinctrl->desc.confops = &airoha_confops, ++ pinctrl->desc.pins = data->pins, ++ pinctrl->desc.npins = data->num_pins, ++ ++ err = devm_pinctrl_register_and_init(dev, &pinctrl->desc, + pinctrl, &pinctrl->ctrl); + if (err) + return err; + + /* build pin groups */ +- for (i = 0; i < ARRAY_SIZE(airoha_pinctrl_groups); i++) { +- const struct pingroup *grp = &airoha_pinctrl_groups[i]; ++ for (i = 0; i < data->num_grps; i++) { ++ const struct pingroup *grp = &data->grps[i]; + + err = pinctrl_generic_add_group(pinctrl->ctrl, grp->name, + grp->pins, grp->npins, +@@ -2909,10 +2943,10 @@ static int airoha_pinctrl_probe(struct p + } + + /* build functions */ +- for (i = 0; i < ARRAY_SIZE(airoha_pinctrl_funcs); i++) { ++ for (i = 0; i < data->num_funcs; i++) { + const struct airoha_pinctrl_func *func; + +- func = &airoha_pinctrl_funcs[i]; ++ func = &data->funcs[i]; + err = pinmux_generic_add_function(pinctrl->ctrl, + func->desc.func.name, + func->desc.func.groups, +@@ -2925,6 +2959,10 @@ static int airoha_pinctrl_probe(struct p + } + } + ++ pinctrl->grps = data->grps; ++ pinctrl->funcs = data->funcs; ++ pinctrl->confs_info = data->confs_info; ++ + err = pinctrl_enable(pinctrl->ctrl); + if (err) + return err; +@@ -2933,8 +2971,39 @@ static int airoha_pinctrl_probe(struct p + return airoha_pinctrl_add_gpiochip(pinctrl, pdev); + } + ++static const struct airoha_pinctrl_match_data en7581_pinctrl_match_data = { ++ .pins = en7581_pinctrl_pins, ++ .num_pins = ARRAY_SIZE(en7581_pinctrl_pins), ++ .grps = en7581_pinctrl_groups, ++ .num_grps = ARRAY_SIZE(en7581_pinctrl_groups), ++ .funcs = en7581_pinctrl_funcs, ++ .num_funcs = ARRAY_SIZE(en7581_pinctrl_funcs), ++ .confs_info = { ++ [AIROHA_PINCTRL_CONFS_PULLUP] = { ++ .confs = en7581_pinctrl_pullup_conf, ++ .num_confs = ARRAY_SIZE(en7581_pinctrl_pullup_conf), ++ }, ++ [AIROHA_PINCTRL_CONFS_PULLDOWN] = { ++ .confs = en7581_pinctrl_pulldown_conf, ++ .num_confs = ARRAY_SIZE(en7581_pinctrl_pulldown_conf), ++ }, ++ [AIROHA_PINCTRL_CONFS_DRIVE_E2] = { ++ .confs = en7581_pinctrl_drive_e2_conf, ++ .num_confs = ARRAY_SIZE(en7581_pinctrl_drive_e2_conf), ++ }, ++ [AIROHA_PINCTRL_CONFS_DRIVE_E4] = { ++ .confs = en7581_pinctrl_drive_e4_conf, ++ .num_confs = ARRAY_SIZE(en7581_pinctrl_drive_e4_conf), ++ }, ++ [AIROHA_PINCTRL_CONFS_PCIE_RST_OD] = { ++ .confs = en7581_pinctrl_pcie_rst_od_conf, ++ .num_confs = ARRAY_SIZE(en7581_pinctrl_pcie_rst_od_conf), ++ }, ++ }, ++}; ++ + static const struct of_device_id airoha_pinctrl_of_match[] = { +- { .compatible = "airoha,en7581-pinctrl" }, ++ { .compatible = "airoha,en7581-pinctrl", .data = &en7581_pinctrl_match_data }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, airoha_pinctrl_of_match); diff --git a/lede/target/linux/airoha/patches-6.12/109-02-v6.19-pinctrl-airoha-convert-PHY-LED-GPIO-to-macro.patch b/lede/target/linux/airoha/patches-6.12/109-02-v6.19-pinctrl-airoha-convert-PHY-LED-GPIO-to-macro.patch new file mode 100644 index 0000000000..24f18e1096 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/109-02-v6.19-pinctrl-airoha-convert-PHY-LED-GPIO-to-macro.patch @@ -0,0 +1,635 @@ +From 579839c9548cf2a85e873ad787bc2fa6610bf8ab Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 7 Nov 2025 00:57:05 +0100 +Subject: [PATCH 2/5] pinctrl: airoha: convert PHY LED GPIO to macro + +PHY LED GPIO pinctrl struct definition is very similar across the +different 4 PHY and 2 LED and it can be generelized to a macro. + +To reduce code size, convert them to a common macro. + +Signed-off-by: Christian Marangi +Signed-off-by: Linus Walleij +--- + drivers/pinctrl/mediatek/pinctrl-airoha.c | 588 ++++------------------ + 1 file changed, 100 insertions(+), 488 deletions(-) + +--- a/drivers/pinctrl/mediatek/pinctrl-airoha.c ++++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c +@@ -1478,516 +1478,128 @@ static const struct airoha_pinctrl_func_ + }, + }; + ++#define AIROHA_PINCTRL_PHY_LED0(gpio, mux_val, map_mask, map_val) \ ++ { \ ++ .name = (gpio), \ ++ .regmap[0] = { \ ++ AIROHA_FUNC_MUX, \ ++ REG_GPIO_2ND_I2C_MODE, \ ++ (mux_val), \ ++ (mux_val), \ ++ }, \ ++ .regmap[1] = { \ ++ AIROHA_FUNC_MUX, \ ++ REG_LAN_LED0_MAPPING, \ ++ (map_mask), \ ++ (map_val), \ ++ }, \ ++ .regmap_size = 2, \ ++ } ++ ++#define AIROHA_PINCTRL_PHY_LED1(gpio, mux_val, map_mask, map_val) \ ++ { \ ++ .name = (gpio), \ ++ .regmap[0] = { \ ++ AIROHA_FUNC_MUX, \ ++ REG_GPIO_2ND_I2C_MODE, \ ++ (mux_val), \ ++ (mux_val), \ ++ }, \ ++ .regmap[1] = { \ ++ AIROHA_FUNC_MUX, \ ++ REG_LAN_LED1_MAPPING, \ ++ (map_mask), \ ++ (map_val), \ ++ }, \ ++ .regmap_size = 2, \ ++ } ++ + static const struct airoha_pinctrl_func_group phy1_led0_func_group[] = { +- { +- .name = "gpio33", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN0_LED0_MODE_MASK, +- GPIO_LAN0_LED0_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED0_MAPPING, +- LAN0_LED_MAPPING_MASK, +- LAN0_PHY_LED_MAP(0) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio34", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN1_LED0_MODE_MASK, +- GPIO_LAN1_LED0_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED0_MAPPING, +- LAN1_LED_MAPPING_MASK, +- LAN1_PHY_LED_MAP(0) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio35", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN2_LED0_MODE_MASK, +- GPIO_LAN2_LED0_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED0_MAPPING, +- LAN2_LED_MAPPING_MASK, +- LAN2_PHY_LED_MAP(0) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio42", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN3_LED0_MODE_MASK, +- GPIO_LAN3_LED0_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED0_MAPPING, +- LAN3_LED_MAPPING_MASK, +- LAN3_PHY_LED_MAP(0) +- }, +- .regmap_size = 2, +- }, ++ AIROHA_PINCTRL_PHY_LED0("gpio33", GPIO_LAN0_LED0_MODE_MASK, ++ LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(0)), ++ AIROHA_PINCTRL_PHY_LED0("gpio34", GPIO_LAN1_LED0_MODE_MASK, ++ LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(0)), ++ AIROHA_PINCTRL_PHY_LED0("gpio35", GPIO_LAN2_LED0_MODE_MASK, ++ LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(0)), ++ AIROHA_PINCTRL_PHY_LED0("gpio42", GPIO_LAN3_LED0_MODE_MASK, ++ LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(0)), + }; + + static const struct airoha_pinctrl_func_group phy2_led0_func_group[] = { +- { +- .name = "gpio33", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN0_LED0_MODE_MASK, +- GPIO_LAN0_LED0_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED0_MAPPING, +- LAN0_LED_MAPPING_MASK, +- LAN0_PHY_LED_MAP(1) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio34", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN1_LED0_MODE_MASK, +- GPIO_LAN1_LED0_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED0_MAPPING, +- LAN1_LED_MAPPING_MASK, +- LAN1_PHY_LED_MAP(1) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio35", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN2_LED0_MODE_MASK, +- GPIO_LAN2_LED0_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED0_MAPPING, +- LAN2_LED_MAPPING_MASK, +- LAN2_PHY_LED_MAP(1) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio42", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN3_LED0_MODE_MASK, +- GPIO_LAN3_LED0_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED0_MAPPING, +- LAN3_LED_MAPPING_MASK, +- LAN3_PHY_LED_MAP(1) +- }, +- .regmap_size = 2, +- }, ++ AIROHA_PINCTRL_PHY_LED0("gpio33", GPIO_LAN0_LED0_MODE_MASK, ++ LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(1)), ++ AIROHA_PINCTRL_PHY_LED0("gpio34", GPIO_LAN1_LED0_MODE_MASK, ++ LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(1)), ++ AIROHA_PINCTRL_PHY_LED0("gpio35", GPIO_LAN2_LED0_MODE_MASK, ++ LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(1)), ++ AIROHA_PINCTRL_PHY_LED0("gpio42", GPIO_LAN3_LED0_MODE_MASK, ++ LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(1)), + }; + + static const struct airoha_pinctrl_func_group phy3_led0_func_group[] = { +- { +- .name = "gpio33", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN0_LED0_MODE_MASK, +- GPIO_LAN0_LED0_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED0_MAPPING, +- LAN0_LED_MAPPING_MASK, +- LAN0_PHY_LED_MAP(2) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio34", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN1_LED0_MODE_MASK, +- GPIO_LAN1_LED0_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED0_MAPPING, +- LAN1_LED_MAPPING_MASK, +- LAN1_PHY_LED_MAP(2) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio35", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN2_LED0_MODE_MASK, +- GPIO_LAN2_LED0_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED0_MAPPING, +- LAN2_LED_MAPPING_MASK, +- LAN2_PHY_LED_MAP(2) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio42", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN3_LED0_MODE_MASK, +- GPIO_LAN3_LED0_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED0_MAPPING, +- LAN3_LED_MAPPING_MASK, +- LAN3_PHY_LED_MAP(2) +- }, +- .regmap_size = 2, +- }, ++ AIROHA_PINCTRL_PHY_LED0("gpio33", GPIO_LAN0_LED0_MODE_MASK, ++ LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(2)), ++ AIROHA_PINCTRL_PHY_LED0("gpio34", GPIO_LAN1_LED0_MODE_MASK, ++ LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(2)), ++ AIROHA_PINCTRL_PHY_LED0("gpio35", GPIO_LAN2_LED0_MODE_MASK, ++ LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(2)), ++ AIROHA_PINCTRL_PHY_LED0("gpio42", GPIO_LAN3_LED0_MODE_MASK, ++ LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)), + }; + + static const struct airoha_pinctrl_func_group phy4_led0_func_group[] = { +- { +- .name = "gpio33", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN0_LED0_MODE_MASK, +- GPIO_LAN0_LED0_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED0_MAPPING, +- LAN0_LED_MAPPING_MASK, +- LAN0_PHY_LED_MAP(3) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio34", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN1_LED0_MODE_MASK, +- GPIO_LAN1_LED0_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED0_MAPPING, +- LAN1_LED_MAPPING_MASK, +- LAN1_PHY_LED_MAP(3) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio35", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN2_LED0_MODE_MASK, +- GPIO_LAN2_LED0_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED0_MAPPING, +- LAN2_LED_MAPPING_MASK, +- LAN2_PHY_LED_MAP(3) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio42", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN3_LED0_MODE_MASK, +- GPIO_LAN3_LED0_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED0_MAPPING, +- LAN3_LED_MAPPING_MASK, +- LAN3_PHY_LED_MAP(3) +- }, +- .regmap_size = 2, +- }, ++ AIROHA_PINCTRL_PHY_LED0("gpio33", GPIO_LAN0_LED0_MODE_MASK, ++ LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(3)), ++ AIROHA_PINCTRL_PHY_LED0("gpio34", GPIO_LAN1_LED0_MODE_MASK, ++ LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(3)), ++ AIROHA_PINCTRL_PHY_LED0("gpio35", GPIO_LAN2_LED0_MODE_MASK, ++ LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(3)), ++ AIROHA_PINCTRL_PHY_LED0("gpio42", GPIO_LAN3_LED0_MODE_MASK, ++ LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(3)), + }; + + static const struct airoha_pinctrl_func_group phy1_led1_func_group[] = { +- { +- .name = "gpio43", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN0_LED1_MODE_MASK, +- GPIO_LAN0_LED1_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED1_MAPPING, +- LAN0_LED_MAPPING_MASK, +- LAN0_PHY_LED_MAP(0) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio44", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN1_LED1_MODE_MASK, +- GPIO_LAN1_LED1_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED1_MAPPING, +- LAN1_LED_MAPPING_MASK, +- LAN1_PHY_LED_MAP(0) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio45", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN2_LED1_MODE_MASK, +- GPIO_LAN2_LED1_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED1_MAPPING, +- LAN2_LED_MAPPING_MASK, +- LAN2_PHY_LED_MAP(0) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio46", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN3_LED1_MODE_MASK, +- GPIO_LAN3_LED1_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED1_MAPPING, +- LAN3_LED_MAPPING_MASK, +- LAN3_PHY_LED_MAP(0) +- }, +- .regmap_size = 2, +- }, ++ AIROHA_PINCTRL_PHY_LED1("gpio43", GPIO_LAN0_LED1_MODE_MASK, ++ LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(0)), ++ AIROHA_PINCTRL_PHY_LED1("gpio44", GPIO_LAN1_LED1_MODE_MASK, ++ LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(0)), ++ AIROHA_PINCTRL_PHY_LED1("gpio45", GPIO_LAN2_LED1_MODE_MASK, ++ LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(0)), ++ AIROHA_PINCTRL_PHY_LED1("gpio46", GPIO_LAN3_LED1_MODE_MASK, ++ LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(0)), + }; + + static const struct airoha_pinctrl_func_group phy2_led1_func_group[] = { +- { +- .name = "gpio43", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN0_LED1_MODE_MASK, +- GPIO_LAN0_LED1_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED1_MAPPING, +- LAN0_LED_MAPPING_MASK, +- LAN0_PHY_LED_MAP(1) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio44", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN1_LED1_MODE_MASK, +- GPIO_LAN1_LED1_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED1_MAPPING, +- LAN1_LED_MAPPING_MASK, +- LAN1_PHY_LED_MAP(1) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio45", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN2_LED1_MODE_MASK, +- GPIO_LAN2_LED1_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED1_MAPPING, +- LAN2_LED_MAPPING_MASK, +- LAN2_PHY_LED_MAP(1) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio46", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN3_LED1_MODE_MASK, +- GPIO_LAN3_LED1_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED1_MAPPING, +- LAN3_LED_MAPPING_MASK, +- LAN3_PHY_LED_MAP(1) +- }, +- .regmap_size = 2, +- }, ++ AIROHA_PINCTRL_PHY_LED1("gpio43", GPIO_LAN0_LED1_MODE_MASK, ++ LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(1)), ++ AIROHA_PINCTRL_PHY_LED1("gpio44", GPIO_LAN1_LED1_MODE_MASK, ++ LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(1)), ++ AIROHA_PINCTRL_PHY_LED1("gpio45", GPIO_LAN2_LED1_MODE_MASK, ++ LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(1)), ++ AIROHA_PINCTRL_PHY_LED1("gpio46", GPIO_LAN3_LED1_MODE_MASK, ++ LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(1)), + }; + + static const struct airoha_pinctrl_func_group phy3_led1_func_group[] = { +- { +- .name = "gpio43", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN0_LED1_MODE_MASK, +- GPIO_LAN0_LED1_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED1_MAPPING, +- LAN0_LED_MAPPING_MASK, +- LAN0_PHY_LED_MAP(2) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio44", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN1_LED1_MODE_MASK, +- GPIO_LAN1_LED1_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED1_MAPPING, +- LAN1_LED_MAPPING_MASK, +- LAN1_PHY_LED_MAP(2) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio45", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN2_LED1_MODE_MASK, +- GPIO_LAN2_LED1_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED1_MAPPING, +- LAN2_LED_MAPPING_MASK, +- LAN2_PHY_LED_MAP(2) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio46", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN3_LED1_MODE_MASK, +- GPIO_LAN3_LED1_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED1_MAPPING, +- LAN3_LED_MAPPING_MASK, +- LAN3_PHY_LED_MAP(2) +- }, +- .regmap_size = 2, +- }, ++ AIROHA_PINCTRL_PHY_LED1("gpio43", GPIO_LAN0_LED1_MODE_MASK, ++ LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(2)), ++ AIROHA_PINCTRL_PHY_LED1("gpio44", GPIO_LAN1_LED1_MODE_MASK, ++ LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(2)), ++ AIROHA_PINCTRL_PHY_LED1("gpio45", GPIO_LAN2_LED1_MODE_MASK, ++ LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(2)), ++ AIROHA_PINCTRL_PHY_LED1("gpio46", GPIO_LAN3_LED1_MODE_MASK, ++ LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)), + }; + + static const struct airoha_pinctrl_func_group phy4_led1_func_group[] = { +- { +- .name = "gpio43", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN0_LED1_MODE_MASK, +- GPIO_LAN0_LED1_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED1_MAPPING, +- LAN0_LED_MAPPING_MASK, +- LAN0_PHY_LED_MAP(3) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio44", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN1_LED1_MODE_MASK, +- GPIO_LAN1_LED1_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED1_MAPPING, +- LAN1_LED_MAPPING_MASK, +- LAN1_PHY_LED_MAP(3) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio45", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN2_LED1_MODE_MASK, +- GPIO_LAN2_LED1_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED1_MAPPING, +- LAN2_LED_MAPPING_MASK, +- LAN2_PHY_LED_MAP(3) +- }, +- .regmap_size = 2, +- }, { +- .name = "gpio46", +- .regmap[0] = { +- AIROHA_FUNC_MUX, +- REG_GPIO_2ND_I2C_MODE, +- GPIO_LAN3_LED1_MODE_MASK, +- GPIO_LAN3_LED1_MODE_MASK +- }, +- .regmap[1] = { +- AIROHA_FUNC_MUX, +- REG_LAN_LED1_MAPPING, +- LAN3_LED_MAPPING_MASK, +- LAN3_PHY_LED_MAP(3) +- }, +- .regmap_size = 2, +- }, ++ AIROHA_PINCTRL_PHY_LED1("gpio43", GPIO_LAN0_LED1_MODE_MASK, ++ LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(2)), ++ AIROHA_PINCTRL_PHY_LED1("gpio44", GPIO_LAN1_LED1_MODE_MASK, ++ LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(2)), ++ AIROHA_PINCTRL_PHY_LED1("gpio45", GPIO_LAN2_LED1_MODE_MASK, ++ LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(2)), ++ AIROHA_PINCTRL_PHY_LED1("gpio46", GPIO_LAN3_LED1_MODE_MASK, ++ LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)), + }; + + static const struct airoha_pinctrl_func en7581_pinctrl_funcs[] = { diff --git a/lede/target/linux/airoha/patches-6.12/109-03-v6.19-pinctrl-airoha-convert-PWM-GPIO-to-macro.patch b/lede/target/linux/airoha/patches-6.12/109-03-v6.19-pinctrl-airoha-convert-PWM-GPIO-to-macro.patch new file mode 100644 index 0000000000..2c71bd2d19 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/109-03-v6.19-pinctrl-airoha-convert-PWM-GPIO-to-macro.patch @@ -0,0 +1,492 @@ +From 1552ad5d649cff9d170e5bc1d13ab1487333b4b7 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 7 Nov 2025 00:57:06 +0100 +Subject: [PATCH 3/5] pinctrl: airoha: convert PWM GPIO to macro + +The PWM GPIO struct definition follow the same pattern for every GPIO +pin hence it can be converted to a macro. + +Create 2 macro one for normal mux and one for ext mux and convert all +the entry to these new macro to reduce code size. + +Signed-off-by: Christian Marangi +Signed-off-by: Linus Walleij +--- + drivers/pinctrl/mediatek/pinctrl-airoha.c | 465 ++++------------------ + 1 file changed, 68 insertions(+), 397 deletions(-) + +--- a/drivers/pinctrl/mediatek/pinctrl-airoha.c ++++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c +@@ -1078,404 +1078,75 @@ static const struct airoha_pinctrl_func_ + }; + + /* PWM */ ++#define AIROHA_PINCTRL_PWM(gpio, mux_val) \ ++ { \ ++ .name = (gpio), \ ++ .regmap[0] = { \ ++ AIROHA_FUNC_PWM_MUX, \ ++ REG_GPIO_FLASH_MODE_CFG, \ ++ (mux_val), \ ++ (mux_val) \ ++ }, \ ++ .regmap_size = 1, \ ++ } \ ++ ++#define AIROHA_PINCTRL_PWM_EXT(gpio, mux_val) \ ++ { \ ++ .name = (gpio), \ ++ .regmap[0] = { \ ++ AIROHA_FUNC_PWM_EXT_MUX, \ ++ REG_GPIO_FLASH_MODE_CFG_EXT, \ ++ (mux_val), \ ++ (mux_val) \ ++ }, \ ++ .regmap_size = 1, \ ++ } \ ++ + static const struct airoha_pinctrl_func_group pwm_func_group[] = { +- { +- .name = "gpio0", +- .regmap[0] = { +- AIROHA_FUNC_PWM_MUX, +- REG_GPIO_FLASH_MODE_CFG, +- GPIO0_FLASH_MODE_CFG, +- GPIO0_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio1", +- .regmap[0] = { +- AIROHA_FUNC_PWM_MUX, +- REG_GPIO_FLASH_MODE_CFG, +- GPIO1_FLASH_MODE_CFG, +- GPIO1_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio2", +- .regmap[0] = { +- AIROHA_FUNC_PWM_MUX, +- REG_GPIO_FLASH_MODE_CFG, +- GPIO2_FLASH_MODE_CFG, +- GPIO2_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio3", +- .regmap[0] = { +- AIROHA_FUNC_PWM_MUX, +- REG_GPIO_FLASH_MODE_CFG, +- GPIO3_FLASH_MODE_CFG, +- GPIO3_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio4", +- .regmap[0] = { +- AIROHA_FUNC_PWM_MUX, +- REG_GPIO_FLASH_MODE_CFG, +- GPIO4_FLASH_MODE_CFG, +- GPIO4_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio5", +- .regmap[0] = { +- AIROHA_FUNC_PWM_MUX, +- REG_GPIO_FLASH_MODE_CFG, +- GPIO5_FLASH_MODE_CFG, +- GPIO5_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio6", +- .regmap[0] = { +- AIROHA_FUNC_PWM_MUX, +- REG_GPIO_FLASH_MODE_CFG, +- GPIO6_FLASH_MODE_CFG, +- GPIO6_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio7", +- .regmap[0] = { +- AIROHA_FUNC_PWM_MUX, +- REG_GPIO_FLASH_MODE_CFG, +- GPIO7_FLASH_MODE_CFG, +- GPIO7_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio8", +- .regmap[0] = { +- AIROHA_FUNC_PWM_MUX, +- REG_GPIO_FLASH_MODE_CFG, +- GPIO8_FLASH_MODE_CFG, +- GPIO8_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio9", +- .regmap[0] = { +- AIROHA_FUNC_PWM_MUX, +- REG_GPIO_FLASH_MODE_CFG, +- GPIO9_FLASH_MODE_CFG, +- GPIO9_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio10", +- .regmap[0] = { +- AIROHA_FUNC_PWM_MUX, +- REG_GPIO_FLASH_MODE_CFG, +- GPIO10_FLASH_MODE_CFG, +- GPIO10_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio11", +- .regmap[0] = { +- AIROHA_FUNC_PWM_MUX, +- REG_GPIO_FLASH_MODE_CFG, +- GPIO11_FLASH_MODE_CFG, +- GPIO11_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio12", +- .regmap[0] = { +- AIROHA_FUNC_PWM_MUX, +- REG_GPIO_FLASH_MODE_CFG, +- GPIO12_FLASH_MODE_CFG, +- GPIO12_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio13", +- .regmap[0] = { +- AIROHA_FUNC_PWM_MUX, +- REG_GPIO_FLASH_MODE_CFG, +- GPIO13_FLASH_MODE_CFG, +- GPIO13_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio14", +- .regmap[0] = { +- AIROHA_FUNC_PWM_MUX, +- REG_GPIO_FLASH_MODE_CFG, +- GPIO14_FLASH_MODE_CFG, +- GPIO14_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio15", +- .regmap[0] = { +- AIROHA_FUNC_PWM_MUX, +- REG_GPIO_FLASH_MODE_CFG, +- GPIO15_FLASH_MODE_CFG, +- GPIO15_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio16", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO16_FLASH_MODE_CFG, +- GPIO16_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio17", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO17_FLASH_MODE_CFG, +- GPIO17_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio18", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO18_FLASH_MODE_CFG, +- GPIO18_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio19", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO19_FLASH_MODE_CFG, +- GPIO19_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio20", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO20_FLASH_MODE_CFG, +- GPIO20_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio21", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO21_FLASH_MODE_CFG, +- GPIO21_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio22", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO22_FLASH_MODE_CFG, +- GPIO22_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio23", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO23_FLASH_MODE_CFG, +- GPIO23_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio24", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO24_FLASH_MODE_CFG, +- GPIO24_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio25", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO25_FLASH_MODE_CFG, +- GPIO25_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio26", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO26_FLASH_MODE_CFG, +- GPIO26_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio27", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO27_FLASH_MODE_CFG, +- GPIO27_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio28", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO28_FLASH_MODE_CFG, +- GPIO28_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio29", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO29_FLASH_MODE_CFG, +- GPIO29_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio30", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO30_FLASH_MODE_CFG, +- GPIO30_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio31", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO31_FLASH_MODE_CFG, +- GPIO31_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio36", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO36_FLASH_MODE_CFG, +- GPIO36_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio37", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO37_FLASH_MODE_CFG, +- GPIO37_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio38", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO38_FLASH_MODE_CFG, +- GPIO38_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio39", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO39_FLASH_MODE_CFG, +- GPIO39_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio40", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO40_FLASH_MODE_CFG, +- GPIO40_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio41", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO41_FLASH_MODE_CFG, +- GPIO41_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio42", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO42_FLASH_MODE_CFG, +- GPIO42_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio43", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO43_FLASH_MODE_CFG, +- GPIO43_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio44", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO44_FLASH_MODE_CFG, +- GPIO44_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio45", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO45_FLASH_MODE_CFG, +- GPIO45_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio46", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO46_FLASH_MODE_CFG, +- GPIO46_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, { +- .name = "gpio47", +- .regmap[0] = { +- AIROHA_FUNC_PWM_EXT_MUX, +- REG_GPIO_FLASH_MODE_CFG_EXT, +- GPIO47_FLASH_MODE_CFG, +- GPIO47_FLASH_MODE_CFG +- }, +- .regmap_size = 1, +- }, ++ AIROHA_PINCTRL_PWM("gpio0", GPIO0_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM("gpio1", GPIO1_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM("gpio2", GPIO2_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM("gpio3", GPIO3_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM("gpio4", GPIO4_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM("gpio5", GPIO5_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM("gpio6", GPIO6_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM("gpio7", GPIO7_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM("gpio8", GPIO8_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM("gpio9", GPIO9_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM("gpio10", GPIO10_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM("gpio11", GPIO11_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM("gpio12", GPIO12_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM("gpio13", GPIO13_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM("gpio14", GPIO14_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM("gpio15", GPIO15_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio16", GPIO16_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio17", GPIO17_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio18", GPIO18_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio19", GPIO19_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio20", GPIO20_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio21", GPIO21_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio22", GPIO22_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio23", GPIO23_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio24", GPIO24_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio25", GPIO25_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio26", GPIO26_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio27", GPIO27_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio28", GPIO28_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio29", GPIO29_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio30", GPIO30_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio31", GPIO31_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio36", GPIO36_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio37", GPIO37_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio38", GPIO38_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio39", GPIO39_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio40", GPIO40_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio41", GPIO41_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio42", GPIO42_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio43", GPIO43_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio44", GPIO44_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio45", GPIO45_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio46", GPIO46_FLASH_MODE_CFG), ++ AIROHA_PINCTRL_PWM_EXT("gpio47", GPIO47_FLASH_MODE_CFG), + }; + + #define AIROHA_PINCTRL_PHY_LED0(gpio, mux_val, map_mask, map_val) \ diff --git a/lede/target/linux/airoha/patches-6.12/109-05-v6.19-pinctrl-airoha-add-support-for-Airoha-AN7583-PINs.patch b/lede/target/linux/airoha/patches-6.12/109-05-v6.19-pinctrl-airoha-add-support-for-Airoha-AN7583-PINs.patch new file mode 100644 index 0000000000..f5eee2d0ac --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/109-05-v6.19-pinctrl-airoha-add-support-for-Airoha-AN7583-PINs.patch @@ -0,0 +1,969 @@ +From 3ffeb17a9a27a668efb6fbd074835e187910a9bb Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 7 Nov 2025 00:57:08 +0100 +Subject: [PATCH 5/5] pinctrl: airoha: add support for Airoha AN7583 PINs + +Add all the required entry to add suppot for Airoha AN7583 PINs. + +Where possible the same function group are used from Airoha EN7581 to +reduce code duplication. + +Signed-off-by: Christian Marangi +Signed-off-by: Linus Walleij +--- + drivers/pinctrl/mediatek/pinctrl-airoha.c | 747 +++++++++++++++++++++- + 1 file changed, 740 insertions(+), 7 deletions(-) + +--- a/drivers/pinctrl/mediatek/pinctrl-airoha.c ++++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c +@@ -75,6 +75,7 @@ + #define GPIO_PCM_SPI_CS3_MODE_MASK BIT(20) + #define GPIO_PCM_SPI_CS2_MODE_P156_MASK BIT(19) + #define GPIO_PCM_SPI_CS2_MODE_P128_MASK BIT(18) ++#define AN7583_GPIO_PCM_SPI_CS2_MODE_MASK BIT(18) + #define GPIO_PCM_SPI_CS1_MODE_MASK BIT(17) + #define GPIO_PCM_SPI_MODE_MASK BIT(16) + #define GPIO_PCM2_MODE_MASK BIT(13) +@@ -132,6 +133,8 @@ + + /* CONF */ + #define REG_I2C_SDA_E2 0x001c ++#define AN7583_I2C1_SCL_E2_MASK BIT(16) ++#define AN7583_I2C1_SDA_E2_MASK BIT(15) + #define SPI_MISO_E2_MASK BIT(14) + #define SPI_MOSI_E2_MASK BIT(13) + #define SPI_CLK_E2_MASK BIT(12) +@@ -139,12 +142,16 @@ + #define PCIE2_RESET_E2_MASK BIT(10) + #define PCIE1_RESET_E2_MASK BIT(9) + #define PCIE0_RESET_E2_MASK BIT(8) ++#define AN7583_MDIO_0_E2_MASK BIT(5) ++#define AN7583_MDC_0_E2_MASK BIT(4) + #define UART1_RXD_E2_MASK BIT(3) + #define UART1_TXD_E2_MASK BIT(2) + #define I2C_SCL_E2_MASK BIT(1) + #define I2C_SDA_E2_MASK BIT(0) + + #define REG_I2C_SDA_E4 0x0020 ++#define AN7583_I2C1_SCL_E4_MASK BIT(16) ++#define AN7583_I2C1_SDA_E4_MASK BIT(15) + #define SPI_MISO_E4_MASK BIT(14) + #define SPI_MOSI_E4_MASK BIT(13) + #define SPI_CLK_E4_MASK BIT(12) +@@ -152,6 +159,8 @@ + #define PCIE2_RESET_E4_MASK BIT(10) + #define PCIE1_RESET_E4_MASK BIT(9) + #define PCIE0_RESET_E4_MASK BIT(8) ++#define AN7583_MDIO_0_E4_MASK BIT(5) ++#define AN7583_MDC_0_E4_MASK BIT(4) + #define UART1_RXD_E4_MASK BIT(3) + #define UART1_TXD_E4_MASK BIT(2) + #define I2C_SCL_E4_MASK BIT(1) +@@ -163,6 +172,8 @@ + #define REG_GPIO_H_E4 0x0030 + + #define REG_I2C_SDA_PU 0x0044 ++#define AN7583_I2C1_SCL_PU_MASK BIT(16) ++#define AN7583_I2C1_SDA_PU_MASK BIT(15) + #define SPI_MISO_PU_MASK BIT(14) + #define SPI_MOSI_PU_MASK BIT(13) + #define SPI_CLK_PU_MASK BIT(12) +@@ -170,12 +181,16 @@ + #define PCIE2_RESET_PU_MASK BIT(10) + #define PCIE1_RESET_PU_MASK BIT(9) + #define PCIE0_RESET_PU_MASK BIT(8) ++#define AN7583_MDIO_0_PU_MASK BIT(5) ++#define AN7583_MDC_0_PU_MASK BIT(4) + #define UART1_RXD_PU_MASK BIT(3) + #define UART1_TXD_PU_MASK BIT(2) + #define I2C_SCL_PU_MASK BIT(1) + #define I2C_SDA_PU_MASK BIT(0) + + #define REG_I2C_SDA_PD 0x0048 ++#define AN7583_I2C1_SDA_PD_MASK BIT(16) ++#define AN7583_I2C1_SCL_PD_MASK BIT(15) + #define SPI_MISO_PD_MASK BIT(14) + #define SPI_MOSI_PD_MASK BIT(13) + #define SPI_CLK_PD_MASK BIT(12) +@@ -183,6 +198,8 @@ + #define PCIE2_RESET_PD_MASK BIT(10) + #define PCIE1_RESET_PD_MASK BIT(9) + #define PCIE0_RESET_PD_MASK BIT(8) ++#define AN7583_MDIO_0_PD_MASK BIT(5) ++#define AN7583_MDC_0_PD_MASK BIT(4) + #define UART1_RXD_PD_MASK BIT(3) + #define UART1_TXD_PD_MASK BIT(2) + #define I2C_SCL_PD_MASK BIT(1) +@@ -630,10 +647,223 @@ static const struct pingroup en7581_pinc + PINCTRL_PIN_GROUP("pcie_reset2", en7581_pcie_reset2), + }; + ++static struct pinctrl_pin_desc an7583_pinctrl_pins[] = { ++ PINCTRL_PIN(2, "gpio0"), ++ PINCTRL_PIN(3, "gpio1"), ++ PINCTRL_PIN(4, "gpio2"), ++ PINCTRL_PIN(5, "gpio3"), ++ PINCTRL_PIN(6, "gpio4"), ++ PINCTRL_PIN(7, "gpio5"), ++ PINCTRL_PIN(8, "gpio6"), ++ PINCTRL_PIN(9, "gpio7"), ++ PINCTRL_PIN(10, "gpio8"), ++ PINCTRL_PIN(11, "gpio9"), ++ PINCTRL_PIN(12, "gpio10"), ++ PINCTRL_PIN(13, "gpio11"), ++ PINCTRL_PIN(14, "gpio12"), ++ PINCTRL_PIN(15, "gpio13"), ++ PINCTRL_PIN(16, "gpio14"), ++ PINCTRL_PIN(17, "gpio15"), ++ PINCTRL_PIN(18, "gpio16"), ++ PINCTRL_PIN(19, "gpio17"), ++ PINCTRL_PIN(20, "gpio18"), ++ PINCTRL_PIN(21, "gpio19"), ++ PINCTRL_PIN(22, "gpio20"), ++ PINCTRL_PIN(23, "gpio21"), ++ PINCTRL_PIN(24, "gpio22"), ++ PINCTRL_PIN(25, "gpio23"), ++ PINCTRL_PIN(26, "gpio24"), ++ PINCTRL_PIN(27, "gpio25"), ++ PINCTRL_PIN(28, "gpio26"), ++ PINCTRL_PIN(29, "gpio27"), ++ PINCTRL_PIN(30, "gpio28"), ++ PINCTRL_PIN(31, "gpio29"), ++ PINCTRL_PIN(32, "gpio30"), ++ PINCTRL_PIN(33, "gpio31"), ++ PINCTRL_PIN(34, "gpio32"), ++ PINCTRL_PIN(35, "gpio33"), ++ PINCTRL_PIN(36, "gpio34"), ++ PINCTRL_PIN(37, "gpio35"), ++ PINCTRL_PIN(38, "gpio36"), ++ PINCTRL_PIN(39, "gpio37"), ++ PINCTRL_PIN(40, "gpio38"), ++ PINCTRL_PIN(41, "i2c0_scl"), ++ PINCTRL_PIN(42, "i2c0_sda"), ++ PINCTRL_PIN(43, "i2c1_scl"), ++ PINCTRL_PIN(44, "i2c1_sda"), ++ PINCTRL_PIN(45, "spi_clk"), ++ PINCTRL_PIN(46, "spi_cs"), ++ PINCTRL_PIN(47, "spi_mosi"), ++ PINCTRL_PIN(48, "spi_miso"), ++ PINCTRL_PIN(49, "uart_txd"), ++ PINCTRL_PIN(50, "uart_rxd"), ++ PINCTRL_PIN(51, "pcie_reset0"), ++ PINCTRL_PIN(52, "pcie_reset1"), ++ PINCTRL_PIN(53, "mdc_0"), ++ PINCTRL_PIN(54, "mdio_0"), ++}; ++ ++static const int an7583_pon_pins[] = { 15, 16, 17, 18, 19, 20 }; ++static const int an7583_pon_tod_1pps_pins[] = { 32 }; ++static const int an7583_gsw_tod_1pps_pins[] = { 32 }; ++static const int an7583_sipo_pins[] = { 34, 35 }; ++static const int an7583_sipo_rclk_pins[] = { 34, 35, 33 }; ++static const int an7583_mdio_pins[] = { 43, 44 }; ++static const int an7583_uart2_pins[] = { 34, 35 }; ++static const int an7583_uart2_cts_rts_pins[] = { 32, 33 }; ++static const int an7583_hsuart_pins[] = { 30, 31 }; ++static const int an7583_hsuart_cts_rts_pins[] = { 28, 29 }; ++static const int an7583_npu_uart_pins[] = { 7, 8 }; ++static const int an7583_uart4_pins[] = { 7, 8 }; ++static const int an7583_uart5_pins[] = { 23, 24 }; ++static const int an7583_i2c0_pins[] = { 41, 42 }; ++static const int an7583_i2c1_pins[] = { 43, 44 }; ++static const int an7583_jtag_udi_pins[] = { 23, 24, 22, 25, 26 }; ++static const int an7583_jtag_dfd_pins[] = { 23, 24, 22, 25, 26 }; ++static const int an7583_pcm1_pins[] = { 10, 11, 12, 13, 14 }; ++static const int an7583_pcm2_pins[] = { 28, 29, 30, 31, 24 }; ++static const int an7583_spi_pins[] = { 28, 29, 30, 31 }; ++static const int an7583_spi_quad_pins[] = { 25, 26 }; ++static const int an7583_spi_cs1_pins[] = { 27 }; ++static const int an7583_pcm_spi_pins[] = { 28, 29, 30, 31, 10, 11, 12, 13 }; ++static const int an7583_pcm_spi_rst_pins[] = { 14 }; ++static const int an7583_pcm_spi_cs1_pins[] = { 24 }; ++static const int an7583_emmc_pins[] = { 7, 8, 9, 22, 23, 24, 25, 26, 45, 46, 47 }; ++static const int an7583_pnand_pins[] = { 7, 8, 9, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 45, 46, 47, 48 }; ++static const int an7583_gpio0_pins[] = { 2 }; ++static const int an7583_gpio1_pins[] = { 3 }; ++static const int an7583_gpio2_pins[] = { 4 }; ++static const int an7583_gpio3_pins[] = { 5 }; ++static const int an7583_gpio4_pins[] = { 6 }; ++static const int an7583_gpio5_pins[] = { 7 }; ++static const int an7583_gpio6_pins[] = { 8 }; ++static const int an7583_gpio7_pins[] = { 9 }; ++static const int an7583_gpio8_pins[] = { 10 }; ++static const int an7583_gpio9_pins[] = { 11 }; ++static const int an7583_gpio10_pins[] = { 12 }; ++static const int an7583_gpio11_pins[] = { 13 }; ++static const int an7583_gpio12_pins[] = { 14 }; ++static const int an7583_gpio13_pins[] = { 15 }; ++static const int an7583_gpio14_pins[] = { 16 }; ++static const int an7583_gpio15_pins[] = { 17 }; ++static const int an7583_gpio16_pins[] = { 18 }; ++static const int an7583_gpio17_pins[] = { 19 }; ++static const int an7583_gpio18_pins[] = { 20 }; ++static const int an7583_gpio19_pins[] = { 21 }; ++static const int an7583_gpio20_pins[] = { 22 }; ++static const int an7583_gpio21_pins[] = { 24 }; ++static const int an7583_gpio23_pins[] = { 25 }; ++static const int an7583_gpio24_pins[] = { 26 }; ++static const int an7583_gpio25_pins[] = { 27 }; ++static const int an7583_gpio26_pins[] = { 28 }; ++static const int an7583_gpio27_pins[] = { 29 }; ++static const int an7583_gpio28_pins[] = { 30 }; ++static const int an7583_gpio29_pins[] = { 31 }; ++static const int an7583_gpio30_pins[] = { 32 }; ++static const int an7583_gpio31_pins[] = { 33 }; ++static const int an7583_gpio33_pins[] = { 35 }; ++static const int an7583_gpio34_pins[] = { 36 }; ++static const int an7583_gpio35_pins[] = { 37 }; ++static const int an7583_gpio36_pins[] = { 38 }; ++static const int an7583_gpio37_pins[] = { 39 }; ++static const int an7583_gpio38_pins[] = { 40 }; ++static const int an7583_gpio39_pins[] = { 41 }; ++static const int an7583_gpio40_pins[] = { 42 }; ++static const int an7583_gpio41_pins[] = { 43 }; ++static const int an7583_gpio42_pins[] = { 44 }; ++static const int an7583_gpio43_pins[] = { 45 }; ++static const int an7583_gpio44_pins[] = { 46 }; ++static const int an7583_gpio45_pins[] = { 47 }; ++static const int an7583_gpio46_pins[] = { 48 }; ++static const int an7583_gpio47_pins[] = { 49 }; ++static const int an7583_gpio48_pins[] = { 50 }; ++static const int an7583_pcie_reset0_pins[] = { 51 }; ++static const int an7583_pcie_reset1_pins[] = { 52 }; ++ ++static const struct pingroup an7583_pinctrl_groups[] = { ++ PINCTRL_PIN_GROUP("pon", an7583_pon), ++ PINCTRL_PIN_GROUP("pon_tod_1pps", an7583_pon_tod_1pps), ++ PINCTRL_PIN_GROUP("gsw_tod_1pps", an7583_gsw_tod_1pps), ++ PINCTRL_PIN_GROUP("sipo", an7583_sipo), ++ PINCTRL_PIN_GROUP("sipo_rclk", an7583_sipo_rclk), ++ PINCTRL_PIN_GROUP("mdio", an7583_mdio), ++ PINCTRL_PIN_GROUP("uart2", an7583_uart2), ++ PINCTRL_PIN_GROUP("uart2_cts_rts", an7583_uart2_cts_rts), ++ PINCTRL_PIN_GROUP("hsuart", an7583_hsuart), ++ PINCTRL_PIN_GROUP("hsuart_cts_rts", an7583_hsuart_cts_rts), ++ PINCTRL_PIN_GROUP("npu_uart", an7583_npu_uart), ++ PINCTRL_PIN_GROUP("uart4", an7583_uart4), ++ PINCTRL_PIN_GROUP("uart5", an7583_uart5), ++ PINCTRL_PIN_GROUP("i2c0", an7583_i2c0), ++ PINCTRL_PIN_GROUP("i2c1", an7583_i2c1), ++ PINCTRL_PIN_GROUP("jtag_udi", an7583_jtag_udi), ++ PINCTRL_PIN_GROUP("jtag_dfd", an7583_jtag_dfd), ++ PINCTRL_PIN_GROUP("pcm1", an7583_pcm1), ++ PINCTRL_PIN_GROUP("pcm2", an7583_pcm2), ++ PINCTRL_PIN_GROUP("spi", an7583_spi), ++ PINCTRL_PIN_GROUP("spi_quad", an7583_spi_quad), ++ PINCTRL_PIN_GROUP("spi_cs1", an7583_spi_cs1), ++ PINCTRL_PIN_GROUP("pcm_spi", an7583_pcm_spi), ++ PINCTRL_PIN_GROUP("pcm_spi_rst", an7583_pcm_spi_rst), ++ PINCTRL_PIN_GROUP("pcm_spi_cs1", an7583_pcm_spi_cs1), ++ PINCTRL_PIN_GROUP("emmc", an7583_emmc), ++ PINCTRL_PIN_GROUP("pnand", an7583_pnand), ++ PINCTRL_PIN_GROUP("gpio0", an7583_gpio0), ++ PINCTRL_PIN_GROUP("gpio1", an7583_gpio1), ++ PINCTRL_PIN_GROUP("gpio2", an7583_gpio2), ++ PINCTRL_PIN_GROUP("gpio3", an7583_gpio3), ++ PINCTRL_PIN_GROUP("gpio4", an7583_gpio4), ++ PINCTRL_PIN_GROUP("gpio5", an7583_gpio5), ++ PINCTRL_PIN_GROUP("gpio6", an7583_gpio6), ++ PINCTRL_PIN_GROUP("gpio7", an7583_gpio7), ++ PINCTRL_PIN_GROUP("gpio8", an7583_gpio8), ++ PINCTRL_PIN_GROUP("gpio9", an7583_gpio9), ++ PINCTRL_PIN_GROUP("gpio10", an7583_gpio10), ++ PINCTRL_PIN_GROUP("gpio11", an7583_gpio11), ++ PINCTRL_PIN_GROUP("gpio12", an7583_gpio12), ++ PINCTRL_PIN_GROUP("gpio13", an7583_gpio13), ++ PINCTRL_PIN_GROUP("gpio14", an7583_gpio14), ++ PINCTRL_PIN_GROUP("gpio15", an7583_gpio15), ++ PINCTRL_PIN_GROUP("gpio16", an7583_gpio16), ++ PINCTRL_PIN_GROUP("gpio17", an7583_gpio17), ++ PINCTRL_PIN_GROUP("gpio18", an7583_gpio18), ++ PINCTRL_PIN_GROUP("gpio19", an7583_gpio19), ++ PINCTRL_PIN_GROUP("gpio20", an7583_gpio20), ++ PINCTRL_PIN_GROUP("gpio21", an7583_gpio21), ++ PINCTRL_PIN_GROUP("gpio23", an7583_gpio23), ++ PINCTRL_PIN_GROUP("gpio24", an7583_gpio24), ++ PINCTRL_PIN_GROUP("gpio25", an7583_gpio25), ++ PINCTRL_PIN_GROUP("gpio26", an7583_gpio26), ++ PINCTRL_PIN_GROUP("gpio27", an7583_gpio27), ++ PINCTRL_PIN_GROUP("gpio28", an7583_gpio28), ++ PINCTRL_PIN_GROUP("gpio29", an7583_gpio29), ++ PINCTRL_PIN_GROUP("gpio30", an7583_gpio30), ++ PINCTRL_PIN_GROUP("gpio31", an7583_gpio31), ++ PINCTRL_PIN_GROUP("gpio33", an7583_gpio33), ++ PINCTRL_PIN_GROUP("gpio34", an7583_gpio34), ++ PINCTRL_PIN_GROUP("gpio35", an7583_gpio35), ++ PINCTRL_PIN_GROUP("gpio36", an7583_gpio36), ++ PINCTRL_PIN_GROUP("gpio37", an7583_gpio37), ++ PINCTRL_PIN_GROUP("gpio38", an7583_gpio38), ++ PINCTRL_PIN_GROUP("gpio39", an7583_gpio39), ++ PINCTRL_PIN_GROUP("gpio40", an7583_gpio40), ++ PINCTRL_PIN_GROUP("gpio41", an7583_gpio41), ++ PINCTRL_PIN_GROUP("gpio42", an7583_gpio42), ++ PINCTRL_PIN_GROUP("gpio43", an7583_gpio43), ++ PINCTRL_PIN_GROUP("gpio44", an7583_gpio44), ++ PINCTRL_PIN_GROUP("gpio45", an7583_gpio45), ++ PINCTRL_PIN_GROUP("gpio46", an7583_gpio46), ++ PINCTRL_PIN_GROUP("gpio47", an7583_gpio47), ++ PINCTRL_PIN_GROUP("gpio48", an7583_gpio48), ++ PINCTRL_PIN_GROUP("pcie_reset0", an7583_pcie_reset0), ++ PINCTRL_PIN_GROUP("pcie_reset1", an7583_pcie_reset1), ++}; ++ + static const char *const pon_groups[] = { "pon" }; + static const char *const tod_1pps_groups[] = { "pon_tod_1pps", "gsw_tod_1pps" }; + static const char *const sipo_groups[] = { "sipo", "sipo_rclk" }; + static const char *const mdio_groups[] = { "mdio" }; ++static const char *const an7583_mdio_groups[] = { "mdio" }; + static const char *const uart_groups[] = { "uart2", "uart2_cts_rts", "hsuart", + "hsuart_cts_rts", "uart4", + "uart5" }; +@@ -646,11 +876,16 @@ static const char *const pcm_spi_groups[ + "pcm_spi_cs2_p156", + "pcm_spi_cs2_p128", + "pcm_spi_cs3", "pcm_spi_cs4" }; ++static const char *const an7583_pcm_spi_groups[] = { "pcm_spi", "pcm_spi_int", ++ "pcm_spi_rst", "pcm_spi_cs1", ++ "pcm_spi_cs2", "pcm_spi_cs3", ++ "pcm_spi_cs4" }; + static const char *const i2s_groups[] = { "i2s" }; + static const char *const emmc_groups[] = { "emmc" }; + static const char *const pnand_groups[] = { "pnand" }; + static const char *const pcie_reset_groups[] = { "pcie_reset0", "pcie_reset1", + "pcie_reset2" }; ++static const char *const an7583_pcie_reset_groups[] = { "pcie_reset0", "pcie_reset1" }; + static const char *const pwm_groups[] = { "gpio0", "gpio1", + "gpio2", "gpio3", + "gpio4", "gpio5", +@@ -689,6 +924,22 @@ static const char *const phy3_led1_group + "gpio45", "gpio46" }; + static const char *const phy4_led1_groups[] = { "gpio43", "gpio44", + "gpio45", "gpio46" }; ++static const char *const an7583_phy1_led0_groups[] = { "gpio1", "gpio2", ++ "gpio3", "gpio4" }; ++static const char *const an7583_phy2_led0_groups[] = { "gpio1", "gpio2", ++ "gpio3", "gpio4" }; ++static const char *const an7583_phy3_led0_groups[] = { "gpio1", "gpio2", ++ "gpio3", "gpio4" }; ++static const char *const an7583_phy4_led0_groups[] = { "gpio1", "gpio2", ++ "gpio3", "gpio4" }; ++static const char *const an7583_phy1_led1_groups[] = { "gpio8", "gpio9", ++ "gpio10", "gpio11" }; ++static const char *const an7583_phy2_led1_groups[] = { "gpio8", "gpio9", ++ "gpio10", "gpio11" }; ++static const char *const an7583_phy3_led1_groups[] = { "gpio8", "gpio9", ++ "gpio10", "gpio11" }; ++static const char *const an7583_phy4_led1_groups[] = { "gpio8", "gpio9", ++ "gpio10", "gpio11" }; + + static const struct airoha_pinctrl_func_group pon_func_group[] = { + { +@@ -766,6 +1017,25 @@ static const struct airoha_pinctrl_func_ + }, + }; + ++static const struct airoha_pinctrl_func_group an7583_mdio_func_group[] = { ++ { ++ .name = "mdio", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_PON_MODE, ++ GPIO_SGMII_MDIO_MODE_MASK, ++ GPIO_SGMII_MDIO_MODE_MASK ++ }, ++ .regmap[1] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_MDC_IO_MASTER_MODE_MODE, ++ GPIO_MDC_IO_MASTER_MODE_MODE ++ }, ++ .regmap_size = 2, ++ }, ++}; ++ + static const struct airoha_pinctrl_func_group uart_func_group[] = { + { + .name = "uart2", +@@ -1007,6 +1277,73 @@ static const struct airoha_pinctrl_func_ + }, + }; + ++static const struct airoha_pinctrl_func_group an7583_pcm_spi_func_group[] = { ++ { ++ .name = "pcm_spi", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_PCM_SPI_MODE_MASK, ++ GPIO_PCM_SPI_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "pcm_spi_int", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_PCM_INT_MODE_MASK, ++ GPIO_PCM_INT_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "pcm_spi_rst", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_PCM_RESET_MODE_MASK, ++ GPIO_PCM_RESET_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "pcm_spi_cs1", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_PCM_SPI_CS1_MODE_MASK, ++ GPIO_PCM_SPI_CS1_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "pcm_spi_cs2", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ AN7583_GPIO_PCM_SPI_CS2_MODE_MASK, ++ AN7583_GPIO_PCM_SPI_CS2_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "pcm_spi_cs3", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_PCM_SPI_CS3_MODE_MASK, ++ GPIO_PCM_SPI_CS3_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "pcm_spi_cs4", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_SPI_CS1_MODE, ++ GPIO_PCM_SPI_CS4_MODE_MASK, ++ GPIO_PCM_SPI_CS4_MODE_MASK ++ }, ++ .regmap_size = 1, ++ }, ++}; ++ + static const struct airoha_pinctrl_func_group i2s_func_group[] = { + { + .name = "i2s", +@@ -1077,6 +1414,28 @@ static const struct airoha_pinctrl_func_ + }, + }; + ++static const struct airoha_pinctrl_func_group an7583_pcie_reset_func_group[] = { ++ { ++ .name = "pcie_reset0", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_PON_MODE, ++ GPIO_PCIE_RESET0_MASK, ++ GPIO_PCIE_RESET0_MASK ++ }, ++ .regmap_size = 1, ++ }, { ++ .name = "pcie_reset1", ++ .regmap[0] = { ++ AIROHA_FUNC_MUX, ++ REG_GPIO_PON_MODE, ++ GPIO_PCIE_RESET1_MASK, ++ GPIO_PCIE_RESET1_MASK ++ }, ++ .regmap_size = 1, ++ }, ++}; ++ + /* PWM */ + #define AIROHA_PINCTRL_PWM(gpio, mux_val) \ + { \ +@@ -1273,6 +1632,94 @@ static const struct airoha_pinctrl_func_ + LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)), + }; + ++static const struct airoha_pinctrl_func_group an7583_phy1_led0_func_group[] = { ++ AIROHA_PINCTRL_PHY_LED0("gpio1", GPIO_LAN0_LED0_MODE_MASK, ++ LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(0)), ++ AIROHA_PINCTRL_PHY_LED0("gpio2", GPIO_LAN1_LED0_MODE_MASK, ++ LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(0)), ++ AIROHA_PINCTRL_PHY_LED0("gpio3", GPIO_LAN2_LED0_MODE_MASK, ++ LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(0)), ++ AIROHA_PINCTRL_PHY_LED0("gpio4", GPIO_LAN3_LED0_MODE_MASK, ++ LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(0)), ++}; ++ ++static const struct airoha_pinctrl_func_group an7583_phy2_led0_func_group[] = { ++ AIROHA_PINCTRL_PHY_LED0("gpio1", GPIO_LAN0_LED0_MODE_MASK, ++ LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(1)), ++ AIROHA_PINCTRL_PHY_LED0("gpio2", GPIO_LAN1_LED0_MODE_MASK, ++ LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(1)), ++ AIROHA_PINCTRL_PHY_LED0("gpio3", GPIO_LAN2_LED0_MODE_MASK, ++ LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(1)), ++ AIROHA_PINCTRL_PHY_LED0("gpio4", GPIO_LAN3_LED0_MODE_MASK, ++ LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(1)), ++}; ++ ++static const struct airoha_pinctrl_func_group an7583_phy3_led0_func_group[] = { ++ AIROHA_PINCTRL_PHY_LED0("gpio1", GPIO_LAN0_LED0_MODE_MASK, ++ LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(2)), ++ AIROHA_PINCTRL_PHY_LED0("gpio2", GPIO_LAN1_LED0_MODE_MASK, ++ LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(2)), ++ AIROHA_PINCTRL_PHY_LED0("gpio3", GPIO_LAN2_LED0_MODE_MASK, ++ LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(2)), ++ AIROHA_PINCTRL_PHY_LED0("gpio4", GPIO_LAN3_LED0_MODE_MASK, ++ LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)), ++}; ++ ++static const struct airoha_pinctrl_func_group an7583_phy4_led0_func_group[] = { ++ AIROHA_PINCTRL_PHY_LED0("gpio1", GPIO_LAN0_LED0_MODE_MASK, ++ LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(3)), ++ AIROHA_PINCTRL_PHY_LED0("gpio2", GPIO_LAN1_LED0_MODE_MASK, ++ LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(3)), ++ AIROHA_PINCTRL_PHY_LED0("gpio3", GPIO_LAN2_LED0_MODE_MASK, ++ LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(3)), ++ AIROHA_PINCTRL_PHY_LED0("gpio4", GPIO_LAN3_LED0_MODE_MASK, ++ LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(3)), ++}; ++ ++static const struct airoha_pinctrl_func_group an7583_phy1_led1_func_group[] = { ++ AIROHA_PINCTRL_PHY_LED1("gpio8", GPIO_LAN0_LED1_MODE_MASK, ++ LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(0)), ++ AIROHA_PINCTRL_PHY_LED1("gpio9", GPIO_LAN1_LED1_MODE_MASK, ++ LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(0)), ++ AIROHA_PINCTRL_PHY_LED1("gpio10", GPIO_LAN2_LED1_MODE_MASK, ++ LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(0)), ++ AIROHA_PINCTRL_PHY_LED1("gpio1", GPIO_LAN3_LED1_MODE_MASK, ++ LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(0)), ++}; ++ ++static const struct airoha_pinctrl_func_group an7583_phy2_led1_func_group[] = { ++ AIROHA_PINCTRL_PHY_LED1("gpio8", GPIO_LAN0_LED1_MODE_MASK, ++ LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(1)), ++ AIROHA_PINCTRL_PHY_LED1("gpio9", GPIO_LAN1_LED1_MODE_MASK, ++ LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(1)), ++ AIROHA_PINCTRL_PHY_LED1("gpio10", GPIO_LAN2_LED1_MODE_MASK, ++ LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(1)), ++ AIROHA_PINCTRL_PHY_LED1("gpio11", GPIO_LAN3_LED1_MODE_MASK, ++ LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(1)), ++}; ++ ++static const struct airoha_pinctrl_func_group an7583_phy3_led1_func_group[] = { ++ AIROHA_PINCTRL_PHY_LED1("gpio8", GPIO_LAN0_LED1_MODE_MASK, ++ LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(2)), ++ AIROHA_PINCTRL_PHY_LED1("gpio9", GPIO_LAN1_LED1_MODE_MASK, ++ LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(2)), ++ AIROHA_PINCTRL_PHY_LED1("gpio10", GPIO_LAN2_LED1_MODE_MASK, ++ LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(2)), ++ AIROHA_PINCTRL_PHY_LED1("gpio11", GPIO_LAN3_LED1_MODE_MASK, ++ LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)), ++}; ++ ++static const struct airoha_pinctrl_func_group an7583_phy4_led1_func_group[] = { ++ AIROHA_PINCTRL_PHY_LED1("gpio8", GPIO_LAN0_LED1_MODE_MASK, ++ LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(2)), ++ AIROHA_PINCTRL_PHY_LED1("gpio9", GPIO_LAN1_LED1_MODE_MASK, ++ LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(2)), ++ AIROHA_PINCTRL_PHY_LED1("gpio10", GPIO_LAN2_LED1_MODE_MASK, ++ LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(2)), ++ AIROHA_PINCTRL_PHY_LED1("gpio11", GPIO_LAN3_LED1_MODE_MASK, ++ LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)), ++}; ++ + static const struct airoha_pinctrl_func en7581_pinctrl_funcs[] = { + PINCTRL_FUNC_DESC("pon", pon), + PINCTRL_FUNC_DESC("tod_1pps", tod_1pps), +@@ -1299,6 +1746,31 @@ static const struct airoha_pinctrl_func + PINCTRL_FUNC_DESC("phy4_led1", phy4_led1), + }; + ++static const struct airoha_pinctrl_func an7583_pinctrl_funcs[] = { ++ PINCTRL_FUNC_DESC("pon", pon), ++ PINCTRL_FUNC_DESC("tod_1pps", tod_1pps), ++ PINCTRL_FUNC_DESC("sipo", sipo), ++ PINCTRL_FUNC_DESC("mdio", an7583_mdio), ++ PINCTRL_FUNC_DESC("uart", uart), ++ PINCTRL_FUNC_DESC("i2c", i2c), ++ PINCTRL_FUNC_DESC("jtag", jtag), ++ PINCTRL_FUNC_DESC("pcm", pcm), ++ PINCTRL_FUNC_DESC("spi", spi), ++ PINCTRL_FUNC_DESC("pcm_spi", an7583_pcm_spi), ++ PINCTRL_FUNC_DESC("emmc", emmc), ++ PINCTRL_FUNC_DESC("pnand", pnand), ++ PINCTRL_FUNC_DESC("pcie_reset", an7583_pcie_reset), ++ PINCTRL_FUNC_DESC("pwm", pwm), ++ PINCTRL_FUNC_DESC("phy1_led0", an7583_phy1_led0), ++ PINCTRL_FUNC_DESC("phy2_led0", an7583_phy2_led0), ++ PINCTRL_FUNC_DESC("phy3_led0", an7583_phy3_led0), ++ PINCTRL_FUNC_DESC("phy4_led0", an7583_phy4_led0), ++ PINCTRL_FUNC_DESC("phy1_led1", an7583_phy1_led1), ++ PINCTRL_FUNC_DESC("phy2_led1", an7583_phy2_led1), ++ PINCTRL_FUNC_DESC("phy3_led1", an7583_phy3_led1), ++ PINCTRL_FUNC_DESC("phy4_led1", an7583_phy4_led1), ++}; ++ + static const struct airoha_pinctrl_conf en7581_pinctrl_pullup_conf[] = { + PINCTRL_CONF_DESC(0, REG_I2C_SDA_PU, UART1_TXD_PU_MASK), + PINCTRL_CONF_DESC(1, REG_I2C_SDA_PU, UART1_RXD_PU_MASK), +@@ -1360,6 +1832,62 @@ static const struct airoha_pinctrl_conf + PINCTRL_CONF_DESC(63, REG_I2C_SDA_PU, PCIE2_RESET_PU_MASK), + }; + ++static const struct airoha_pinctrl_conf an7583_pinctrl_pullup_conf[] = { ++ PINCTRL_CONF_DESC(2, REG_GPIO_L_PU, BIT(0)), ++ PINCTRL_CONF_DESC(3, REG_GPIO_L_PU, BIT(1)), ++ PINCTRL_CONF_DESC(4, REG_GPIO_L_PU, BIT(2)), ++ PINCTRL_CONF_DESC(5, REG_GPIO_L_PU, BIT(3)), ++ PINCTRL_CONF_DESC(6, REG_GPIO_L_PU, BIT(4)), ++ PINCTRL_CONF_DESC(7, REG_GPIO_L_PU, BIT(5)), ++ PINCTRL_CONF_DESC(8, REG_GPIO_L_PU, BIT(6)), ++ PINCTRL_CONF_DESC(9, REG_GPIO_L_PU, BIT(7)), ++ PINCTRL_CONF_DESC(10, REG_GPIO_L_PU, BIT(8)), ++ PINCTRL_CONF_DESC(11, REG_GPIO_L_PU, BIT(9)), ++ PINCTRL_CONF_DESC(12, REG_GPIO_L_PU, BIT(10)), ++ PINCTRL_CONF_DESC(13, REG_GPIO_L_PU, BIT(11)), ++ PINCTRL_CONF_DESC(14, REG_GPIO_L_PU, BIT(12)), ++ PINCTRL_CONF_DESC(15, REG_GPIO_L_PU, BIT(13)), ++ PINCTRL_CONF_DESC(16, REG_GPIO_L_PU, BIT(14)), ++ PINCTRL_CONF_DESC(17, REG_GPIO_L_PU, BIT(15)), ++ PINCTRL_CONF_DESC(18, REG_GPIO_L_PU, BIT(16)), ++ PINCTRL_CONF_DESC(19, REG_GPIO_L_PU, BIT(17)), ++ PINCTRL_CONF_DESC(20, REG_GPIO_L_PU, BIT(18)), ++ PINCTRL_CONF_DESC(21, REG_GPIO_L_PU, BIT(18)), ++ PINCTRL_CONF_DESC(22, REG_GPIO_L_PU, BIT(20)), ++ PINCTRL_CONF_DESC(23, REG_GPIO_L_PU, BIT(21)), ++ PINCTRL_CONF_DESC(24, REG_GPIO_L_PU, BIT(22)), ++ PINCTRL_CONF_DESC(25, REG_GPIO_L_PU, BIT(23)), ++ PINCTRL_CONF_DESC(26, REG_GPIO_L_PU, BIT(24)), ++ PINCTRL_CONF_DESC(27, REG_GPIO_L_PU, BIT(25)), ++ PINCTRL_CONF_DESC(28, REG_GPIO_L_PU, BIT(26)), ++ PINCTRL_CONF_DESC(29, REG_GPIO_L_PU, BIT(27)), ++ PINCTRL_CONF_DESC(30, REG_GPIO_L_PU, BIT(28)), ++ PINCTRL_CONF_DESC(31, REG_GPIO_L_PU, BIT(29)), ++ PINCTRL_CONF_DESC(32, REG_GPIO_L_PU, BIT(30)), ++ PINCTRL_CONF_DESC(33, REG_GPIO_L_PU, BIT(31)), ++ PINCTRL_CONF_DESC(34, REG_GPIO_H_PU, BIT(0)), ++ PINCTRL_CONF_DESC(35, REG_GPIO_H_PU, BIT(1)), ++ PINCTRL_CONF_DESC(36, REG_GPIO_H_PU, BIT(2)), ++ PINCTRL_CONF_DESC(37, REG_GPIO_H_PU, BIT(3)), ++ PINCTRL_CONF_DESC(38, REG_GPIO_H_PU, BIT(4)), ++ PINCTRL_CONF_DESC(39, REG_GPIO_H_PU, BIT(5)), ++ PINCTRL_CONF_DESC(40, REG_GPIO_H_PU, BIT(6)), ++ PINCTRL_CONF_DESC(41, REG_I2C_SDA_PU, I2C_SCL_PU_MASK), ++ PINCTRL_CONF_DESC(42, REG_I2C_SDA_PU, I2C_SDA_PU_MASK), ++ PINCTRL_CONF_DESC(43, REG_I2C_SDA_PU, AN7583_I2C1_SCL_PU_MASK), ++ PINCTRL_CONF_DESC(44, REG_I2C_SDA_PU, AN7583_I2C1_SDA_PU_MASK), ++ PINCTRL_CONF_DESC(45, REG_I2C_SDA_PU, SPI_CLK_PU_MASK), ++ PINCTRL_CONF_DESC(46, REG_I2C_SDA_PU, SPI_CS0_PU_MASK), ++ PINCTRL_CONF_DESC(47, REG_I2C_SDA_PU, SPI_MOSI_PU_MASK), ++ PINCTRL_CONF_DESC(48, REG_I2C_SDA_PU, SPI_MISO_PU_MASK), ++ PINCTRL_CONF_DESC(49, REG_I2C_SDA_PU, UART1_TXD_PU_MASK), ++ PINCTRL_CONF_DESC(50, REG_I2C_SDA_PU, UART1_RXD_PU_MASK), ++ PINCTRL_CONF_DESC(51, REG_I2C_SDA_PU, PCIE0_RESET_PU_MASK), ++ PINCTRL_CONF_DESC(52, REG_I2C_SDA_PU, PCIE1_RESET_PU_MASK), ++ PINCTRL_CONF_DESC(53, REG_I2C_SDA_PU, AN7583_MDC_0_PU_MASK), ++ PINCTRL_CONF_DESC(54, REG_I2C_SDA_PU, AN7583_MDIO_0_PU_MASK), ++}; ++ + static const struct airoha_pinctrl_conf en7581_pinctrl_pulldown_conf[] = { + PINCTRL_CONF_DESC(0, REG_I2C_SDA_PD, UART1_TXD_PD_MASK), + PINCTRL_CONF_DESC(1, REG_I2C_SDA_PD, UART1_RXD_PD_MASK), +@@ -1421,6 +1949,62 @@ static const struct airoha_pinctrl_conf + PINCTRL_CONF_DESC(63, REG_I2C_SDA_PD, PCIE2_RESET_PD_MASK), + }; + ++static const struct airoha_pinctrl_conf an7583_pinctrl_pulldown_conf[] = { ++ PINCTRL_CONF_DESC(2, REG_GPIO_L_PD, BIT(0)), ++ PINCTRL_CONF_DESC(3, REG_GPIO_L_PD, BIT(1)), ++ PINCTRL_CONF_DESC(4, REG_GPIO_L_PD, BIT(2)), ++ PINCTRL_CONF_DESC(5, REG_GPIO_L_PD, BIT(3)), ++ PINCTRL_CONF_DESC(6, REG_GPIO_L_PD, BIT(4)), ++ PINCTRL_CONF_DESC(7, REG_GPIO_L_PD, BIT(5)), ++ PINCTRL_CONF_DESC(8, REG_GPIO_L_PD, BIT(6)), ++ PINCTRL_CONF_DESC(9, REG_GPIO_L_PD, BIT(7)), ++ PINCTRL_CONF_DESC(10, REG_GPIO_L_PD, BIT(8)), ++ PINCTRL_CONF_DESC(11, REG_GPIO_L_PD, BIT(9)), ++ PINCTRL_CONF_DESC(12, REG_GPIO_L_PD, BIT(10)), ++ PINCTRL_CONF_DESC(13, REG_GPIO_L_PD, BIT(11)), ++ PINCTRL_CONF_DESC(14, REG_GPIO_L_PD, BIT(12)), ++ PINCTRL_CONF_DESC(15, REG_GPIO_L_PD, BIT(13)), ++ PINCTRL_CONF_DESC(16, REG_GPIO_L_PD, BIT(14)), ++ PINCTRL_CONF_DESC(17, REG_GPIO_L_PD, BIT(15)), ++ PINCTRL_CONF_DESC(18, REG_GPIO_L_PD, BIT(16)), ++ PINCTRL_CONF_DESC(19, REG_GPIO_L_PD, BIT(17)), ++ PINCTRL_CONF_DESC(20, REG_GPIO_L_PD, BIT(18)), ++ PINCTRL_CONF_DESC(21, REG_GPIO_L_PD, BIT(18)), ++ PINCTRL_CONF_DESC(22, REG_GPIO_L_PD, BIT(20)), ++ PINCTRL_CONF_DESC(23, REG_GPIO_L_PD, BIT(21)), ++ PINCTRL_CONF_DESC(24, REG_GPIO_L_PD, BIT(22)), ++ PINCTRL_CONF_DESC(25, REG_GPIO_L_PD, BIT(23)), ++ PINCTRL_CONF_DESC(26, REG_GPIO_L_PD, BIT(24)), ++ PINCTRL_CONF_DESC(27, REG_GPIO_L_PD, BIT(25)), ++ PINCTRL_CONF_DESC(28, REG_GPIO_L_PD, BIT(26)), ++ PINCTRL_CONF_DESC(29, REG_GPIO_L_PD, BIT(27)), ++ PINCTRL_CONF_DESC(30, REG_GPIO_L_PD, BIT(28)), ++ PINCTRL_CONF_DESC(31, REG_GPIO_L_PD, BIT(29)), ++ PINCTRL_CONF_DESC(32, REG_GPIO_L_PD, BIT(30)), ++ PINCTRL_CONF_DESC(33, REG_GPIO_L_PD, BIT(31)), ++ PINCTRL_CONF_DESC(34, REG_GPIO_H_PD, BIT(0)), ++ PINCTRL_CONF_DESC(35, REG_GPIO_H_PD, BIT(1)), ++ PINCTRL_CONF_DESC(36, REG_GPIO_H_PD, BIT(2)), ++ PINCTRL_CONF_DESC(37, REG_GPIO_H_PD, BIT(3)), ++ PINCTRL_CONF_DESC(38, REG_GPIO_H_PD, BIT(4)), ++ PINCTRL_CONF_DESC(39, REG_GPIO_H_PD, BIT(5)), ++ PINCTRL_CONF_DESC(40, REG_GPIO_H_PD, BIT(6)), ++ PINCTRL_CONF_DESC(41, REG_I2C_SDA_PD, I2C_SCL_PD_MASK), ++ PINCTRL_CONF_DESC(42, REG_I2C_SDA_PD, I2C_SDA_PD_MASK), ++ PINCTRL_CONF_DESC(43, REG_I2C_SDA_PD, AN7583_I2C1_SCL_PD_MASK), ++ PINCTRL_CONF_DESC(44, REG_I2C_SDA_PD, AN7583_I2C1_SDA_PD_MASK), ++ PINCTRL_CONF_DESC(45, REG_I2C_SDA_PD, SPI_CLK_PD_MASK), ++ PINCTRL_CONF_DESC(46, REG_I2C_SDA_PD, SPI_CS0_PD_MASK), ++ PINCTRL_CONF_DESC(47, REG_I2C_SDA_PD, SPI_MOSI_PD_MASK), ++ PINCTRL_CONF_DESC(48, REG_I2C_SDA_PD, SPI_MISO_PD_MASK), ++ PINCTRL_CONF_DESC(49, REG_I2C_SDA_PD, UART1_TXD_PD_MASK), ++ PINCTRL_CONF_DESC(50, REG_I2C_SDA_PD, UART1_RXD_PD_MASK), ++ PINCTRL_CONF_DESC(51, REG_I2C_SDA_PD, PCIE0_RESET_PD_MASK), ++ PINCTRL_CONF_DESC(52, REG_I2C_SDA_PD, PCIE1_RESET_PD_MASK), ++ PINCTRL_CONF_DESC(53, REG_I2C_SDA_PD, AN7583_MDC_0_PD_MASK), ++ PINCTRL_CONF_DESC(54, REG_I2C_SDA_PD, AN7583_MDIO_0_PD_MASK), ++}; ++ + static const struct airoha_pinctrl_conf en7581_pinctrl_drive_e2_conf[] = { + PINCTRL_CONF_DESC(0, REG_I2C_SDA_E2, UART1_TXD_E2_MASK), + PINCTRL_CONF_DESC(1, REG_I2C_SDA_E2, UART1_RXD_E2_MASK), +@@ -1482,6 +2066,62 @@ static const struct airoha_pinctrl_conf + PINCTRL_CONF_DESC(63, REG_I2C_SDA_E2, PCIE2_RESET_E2_MASK), + }; + ++static const struct airoha_pinctrl_conf an7583_pinctrl_drive_e2_conf[] = { ++ PINCTRL_CONF_DESC(2, REG_GPIO_L_E2, BIT(0)), ++ PINCTRL_CONF_DESC(3, REG_GPIO_L_E2, BIT(1)), ++ PINCTRL_CONF_DESC(4, REG_GPIO_L_E2, BIT(2)), ++ PINCTRL_CONF_DESC(5, REG_GPIO_L_E2, BIT(3)), ++ PINCTRL_CONF_DESC(6, REG_GPIO_L_E2, BIT(4)), ++ PINCTRL_CONF_DESC(7, REG_GPIO_L_E2, BIT(5)), ++ PINCTRL_CONF_DESC(8, REG_GPIO_L_E2, BIT(6)), ++ PINCTRL_CONF_DESC(9, REG_GPIO_L_E2, BIT(7)), ++ PINCTRL_CONF_DESC(10, REG_GPIO_L_E2, BIT(8)), ++ PINCTRL_CONF_DESC(11, REG_GPIO_L_E2, BIT(9)), ++ PINCTRL_CONF_DESC(12, REG_GPIO_L_E2, BIT(10)), ++ PINCTRL_CONF_DESC(13, REG_GPIO_L_E2, BIT(11)), ++ PINCTRL_CONF_DESC(14, REG_GPIO_L_E2, BIT(12)), ++ PINCTRL_CONF_DESC(15, REG_GPIO_L_E2, BIT(13)), ++ PINCTRL_CONF_DESC(16, REG_GPIO_L_E2, BIT(14)), ++ PINCTRL_CONF_DESC(17, REG_GPIO_L_E2, BIT(15)), ++ PINCTRL_CONF_DESC(18, REG_GPIO_L_E2, BIT(16)), ++ PINCTRL_CONF_DESC(19, REG_GPIO_L_E2, BIT(17)), ++ PINCTRL_CONF_DESC(20, REG_GPIO_L_E2, BIT(18)), ++ PINCTRL_CONF_DESC(21, REG_GPIO_L_E2, BIT(18)), ++ PINCTRL_CONF_DESC(22, REG_GPIO_L_E2, BIT(20)), ++ PINCTRL_CONF_DESC(23, REG_GPIO_L_E2, BIT(21)), ++ PINCTRL_CONF_DESC(24, REG_GPIO_L_E2, BIT(22)), ++ PINCTRL_CONF_DESC(25, REG_GPIO_L_E2, BIT(23)), ++ PINCTRL_CONF_DESC(26, REG_GPIO_L_E2, BIT(24)), ++ PINCTRL_CONF_DESC(27, REG_GPIO_L_E2, BIT(25)), ++ PINCTRL_CONF_DESC(28, REG_GPIO_L_E2, BIT(26)), ++ PINCTRL_CONF_DESC(29, REG_GPIO_L_E2, BIT(27)), ++ PINCTRL_CONF_DESC(30, REG_GPIO_L_E2, BIT(28)), ++ PINCTRL_CONF_DESC(31, REG_GPIO_L_E2, BIT(29)), ++ PINCTRL_CONF_DESC(32, REG_GPIO_L_E2, BIT(30)), ++ PINCTRL_CONF_DESC(33, REG_GPIO_L_E2, BIT(31)), ++ PINCTRL_CONF_DESC(34, REG_GPIO_H_E2, BIT(0)), ++ PINCTRL_CONF_DESC(35, REG_GPIO_H_E2, BIT(1)), ++ PINCTRL_CONF_DESC(36, REG_GPIO_H_E2, BIT(2)), ++ PINCTRL_CONF_DESC(37, REG_GPIO_H_E2, BIT(3)), ++ PINCTRL_CONF_DESC(38, REG_GPIO_H_E2, BIT(4)), ++ PINCTRL_CONF_DESC(39, REG_GPIO_H_E2, BIT(5)), ++ PINCTRL_CONF_DESC(40, REG_GPIO_H_E2, BIT(6)), ++ PINCTRL_CONF_DESC(41, REG_I2C_SDA_E2, I2C_SCL_E2_MASK), ++ PINCTRL_CONF_DESC(42, REG_I2C_SDA_E2, I2C_SDA_E2_MASK), ++ PINCTRL_CONF_DESC(43, REG_I2C_SDA_E2, AN7583_I2C1_SCL_E2_MASK), ++ PINCTRL_CONF_DESC(44, REG_I2C_SDA_E2, AN7583_I2C1_SDA_E2_MASK), ++ PINCTRL_CONF_DESC(45, REG_I2C_SDA_E2, SPI_CLK_E2_MASK), ++ PINCTRL_CONF_DESC(46, REG_I2C_SDA_E2, SPI_CS0_E2_MASK), ++ PINCTRL_CONF_DESC(47, REG_I2C_SDA_E2, SPI_MOSI_E2_MASK), ++ PINCTRL_CONF_DESC(48, REG_I2C_SDA_E2, SPI_MISO_E2_MASK), ++ PINCTRL_CONF_DESC(49, REG_I2C_SDA_E2, UART1_TXD_E2_MASK), ++ PINCTRL_CONF_DESC(50, REG_I2C_SDA_E2, UART1_RXD_E2_MASK), ++ PINCTRL_CONF_DESC(51, REG_I2C_SDA_E2, PCIE0_RESET_E2_MASK), ++ PINCTRL_CONF_DESC(52, REG_I2C_SDA_E2, PCIE1_RESET_E2_MASK), ++ PINCTRL_CONF_DESC(53, REG_I2C_SDA_E2, AN7583_MDC_0_E2_MASK), ++ PINCTRL_CONF_DESC(54, REG_I2C_SDA_E2, AN7583_MDIO_0_E2_MASK), ++}; ++ + static const struct airoha_pinctrl_conf en7581_pinctrl_drive_e4_conf[] = { + PINCTRL_CONF_DESC(0, REG_I2C_SDA_E4, UART1_TXD_E4_MASK), + PINCTRL_CONF_DESC(1, REG_I2C_SDA_E4, UART1_RXD_E4_MASK), +@@ -1543,12 +2183,73 @@ static const struct airoha_pinctrl_conf + PINCTRL_CONF_DESC(63, REG_I2C_SDA_E4, PCIE2_RESET_E4_MASK), + }; + ++static const struct airoha_pinctrl_conf an7583_pinctrl_drive_e4_conf[] = { ++ PINCTRL_CONF_DESC(2, REG_GPIO_L_E4, BIT(0)), ++ PINCTRL_CONF_DESC(3, REG_GPIO_L_E4, BIT(1)), ++ PINCTRL_CONF_DESC(4, REG_GPIO_L_E4, BIT(2)), ++ PINCTRL_CONF_DESC(5, REG_GPIO_L_E4, BIT(3)), ++ PINCTRL_CONF_DESC(6, REG_GPIO_L_E4, BIT(4)), ++ PINCTRL_CONF_DESC(7, REG_GPIO_L_E4, BIT(5)), ++ PINCTRL_CONF_DESC(8, REG_GPIO_L_E4, BIT(6)), ++ PINCTRL_CONF_DESC(9, REG_GPIO_L_E4, BIT(7)), ++ PINCTRL_CONF_DESC(10, REG_GPIO_L_E4, BIT(8)), ++ PINCTRL_CONF_DESC(11, REG_GPIO_L_E4, BIT(9)), ++ PINCTRL_CONF_DESC(12, REG_GPIO_L_E4, BIT(10)), ++ PINCTRL_CONF_DESC(13, REG_GPIO_L_E4, BIT(11)), ++ PINCTRL_CONF_DESC(14, REG_GPIO_L_E4, BIT(12)), ++ PINCTRL_CONF_DESC(15, REG_GPIO_L_E4, BIT(13)), ++ PINCTRL_CONF_DESC(16, REG_GPIO_L_E4, BIT(14)), ++ PINCTRL_CONF_DESC(17, REG_GPIO_L_E4, BIT(15)), ++ PINCTRL_CONF_DESC(18, REG_GPIO_L_E4, BIT(16)), ++ PINCTRL_CONF_DESC(19, REG_GPIO_L_E4, BIT(17)), ++ PINCTRL_CONF_DESC(20, REG_GPIO_L_E4, BIT(18)), ++ PINCTRL_CONF_DESC(21, REG_GPIO_L_E4, BIT(18)), ++ PINCTRL_CONF_DESC(22, REG_GPIO_L_E4, BIT(20)), ++ PINCTRL_CONF_DESC(23, REG_GPIO_L_E4, BIT(21)), ++ PINCTRL_CONF_DESC(24, REG_GPIO_L_E4, BIT(22)), ++ PINCTRL_CONF_DESC(25, REG_GPIO_L_E4, BIT(23)), ++ PINCTRL_CONF_DESC(26, REG_GPIO_L_E4, BIT(24)), ++ PINCTRL_CONF_DESC(27, REG_GPIO_L_E4, BIT(25)), ++ PINCTRL_CONF_DESC(28, REG_GPIO_L_E4, BIT(26)), ++ PINCTRL_CONF_DESC(29, REG_GPIO_L_E4, BIT(27)), ++ PINCTRL_CONF_DESC(30, REG_GPIO_L_E4, BIT(28)), ++ PINCTRL_CONF_DESC(31, REG_GPIO_L_E4, BIT(29)), ++ PINCTRL_CONF_DESC(32, REG_GPIO_L_E4, BIT(30)), ++ PINCTRL_CONF_DESC(33, REG_GPIO_L_E4, BIT(31)), ++ PINCTRL_CONF_DESC(34, REG_GPIO_H_E4, BIT(0)), ++ PINCTRL_CONF_DESC(35, REG_GPIO_H_E4, BIT(1)), ++ PINCTRL_CONF_DESC(36, REG_GPIO_H_E4, BIT(2)), ++ PINCTRL_CONF_DESC(37, REG_GPIO_H_E4, BIT(3)), ++ PINCTRL_CONF_DESC(38, REG_GPIO_H_E4, BIT(4)), ++ PINCTRL_CONF_DESC(39, REG_GPIO_H_E4, BIT(5)), ++ PINCTRL_CONF_DESC(40, REG_GPIO_H_E4, BIT(6)), ++ PINCTRL_CONF_DESC(41, REG_I2C_SDA_E4, I2C_SCL_E4_MASK), ++ PINCTRL_CONF_DESC(42, REG_I2C_SDA_E4, I2C_SDA_E4_MASK), ++ PINCTRL_CONF_DESC(43, REG_I2C_SDA_E4, AN7583_I2C1_SCL_E4_MASK), ++ PINCTRL_CONF_DESC(44, REG_I2C_SDA_E4, AN7583_I2C1_SDA_E4_MASK), ++ PINCTRL_CONF_DESC(45, REG_I2C_SDA_E4, SPI_CLK_E4_MASK), ++ PINCTRL_CONF_DESC(46, REG_I2C_SDA_E4, SPI_CS0_E4_MASK), ++ PINCTRL_CONF_DESC(47, REG_I2C_SDA_E4, SPI_MOSI_E4_MASK), ++ PINCTRL_CONF_DESC(48, REG_I2C_SDA_E4, SPI_MISO_E4_MASK), ++ PINCTRL_CONF_DESC(49, REG_I2C_SDA_E4, UART1_TXD_E4_MASK), ++ PINCTRL_CONF_DESC(50, REG_I2C_SDA_E4, UART1_RXD_E4_MASK), ++ PINCTRL_CONF_DESC(51, REG_I2C_SDA_E4, PCIE0_RESET_E4_MASK), ++ PINCTRL_CONF_DESC(52, REG_I2C_SDA_E4, PCIE1_RESET_E4_MASK), ++ PINCTRL_CONF_DESC(53, REG_I2C_SDA_E4, AN7583_MDC_0_E4_MASK), ++ PINCTRL_CONF_DESC(54, REG_I2C_SDA_E4, AN7583_MDIO_0_E4_MASK), ++}; ++ + static const struct airoha_pinctrl_conf en7581_pinctrl_pcie_rst_od_conf[] = { + PINCTRL_CONF_DESC(61, REG_PCIE_RESET_OD, PCIE0_RESET_OD_MASK), + PINCTRL_CONF_DESC(62, REG_PCIE_RESET_OD, PCIE1_RESET_OD_MASK), + PINCTRL_CONF_DESC(63, REG_PCIE_RESET_OD, PCIE2_RESET_OD_MASK), + }; + ++static const struct airoha_pinctrl_conf an7583_pinctrl_pcie_rst_od_conf[] = { ++ PINCTRL_CONF_DESC(51, REG_PCIE_RESET_OD, PCIE0_RESET_OD_MASK), ++ PINCTRL_CONF_DESC(52, REG_PCIE_RESET_OD, PCIE1_RESET_OD_MASK), ++}; ++ + static int airoha_convert_pin_to_reg_offset(struct pinctrl_dev *pctrl_dev, + struct pinctrl_gpio_range *range, + int pin) +@@ -1714,7 +2415,7 @@ static const struct irq_chip airoha_gpio + }; + + static int airoha_pinctrl_add_gpiochip(struct airoha_pinctrl *pinctrl, +- struct platform_device *pdev) ++ struct platform_device *pdev) + { + struct airoha_pinctrl_gpiochip *chip = &pinctrl->gpiochip; + struct gpio_chip *gc = &chip->chip; +@@ -1749,7 +2450,7 @@ static int airoha_pinctrl_add_gpiochip(s + return irq; + + err = devm_request_irq(dev, irq, airoha_irq_handler, IRQF_SHARED, +- dev_name(dev), pinctrl); ++ dev_name(dev), pinctrl); + if (err) { + dev_err(dev, "error requesting irq %d: %d\n", irq, err); + return err; +@@ -1813,8 +2514,8 @@ static int airoha_pinmux_set_mux(struct + } + + static int airoha_pinmux_set_direction(struct pinctrl_dev *pctrl_dev, +- struct pinctrl_gpio_range *range, +- unsigned int p, bool input) ++ struct pinctrl_gpio_range *range, ++ unsigned int p, bool input) + { + struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev); + u32 mask, index; +@@ -1904,7 +2605,7 @@ static int airoha_pinctrl_set_conf(struc + + + if (regmap_update_bits(pinctrl->chip_scu, reg->offset, reg->mask, +- val << __ffs(reg->mask))) ++ val << __ffs(reg->mask))) + return -EINVAL; + + return 0; +@@ -2123,8 +2824,8 @@ static int airoha_pinconf_group_get(stru + + for (i = 0; i < pinctrl->grps[group].npins; i++) { + if (airoha_pinconf_get(pctrl_dev, +- pinctrl->grps[group].pins[i], +- config)) ++ pinctrl->grps[group].pins[i], ++ config)) + return -ENOTSUPP; + + if (i && cur_config != *config) +@@ -2285,8 +2986,40 @@ static const struct airoha_pinctrl_match + }, + }; + ++static const struct airoha_pinctrl_match_data an7583_pinctrl_match_data = { ++ .pins = an7583_pinctrl_pins, ++ .num_pins = ARRAY_SIZE(an7583_pinctrl_pins), ++ .grps = an7583_pinctrl_groups, ++ .num_grps = ARRAY_SIZE(an7583_pinctrl_groups), ++ .funcs = an7583_pinctrl_funcs, ++ .num_funcs = ARRAY_SIZE(an7583_pinctrl_funcs), ++ .confs_info = { ++ [AIROHA_PINCTRL_CONFS_PULLUP] = { ++ .confs = an7583_pinctrl_pullup_conf, ++ .num_confs = ARRAY_SIZE(an7583_pinctrl_pullup_conf), ++ }, ++ [AIROHA_PINCTRL_CONFS_PULLDOWN] = { ++ .confs = an7583_pinctrl_pulldown_conf, ++ .num_confs = ARRAY_SIZE(an7583_pinctrl_pulldown_conf), ++ }, ++ [AIROHA_PINCTRL_CONFS_DRIVE_E2] = { ++ .confs = en7581_pinctrl_drive_e2_conf, ++ .num_confs = ARRAY_SIZE(an7583_pinctrl_drive_e2_conf), ++ }, ++ [AIROHA_PINCTRL_CONFS_DRIVE_E4] = { ++ .confs = an7583_pinctrl_drive_e4_conf, ++ .num_confs = ARRAY_SIZE(an7583_pinctrl_drive_e4_conf), ++ }, ++ [AIROHA_PINCTRL_CONFS_PCIE_RST_OD] = { ++ .confs = an7583_pinctrl_pcie_rst_od_conf, ++ .num_confs = ARRAY_SIZE(an7583_pinctrl_pcie_rst_od_conf), ++ }, ++ }, ++}; ++ + static const struct of_device_id airoha_pinctrl_of_match[] = { + { .compatible = "airoha,en7581-pinctrl", .data = &en7581_pinctrl_match_data }, ++ { .compatible = "airoha,an7583-pinctrl", .data = &an7583_pinctrl_match_data }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, airoha_pinctrl_of_match); diff --git a/lede/target/linux/airoha/patches-6.12/116-02-net-airoha-deassert-XSI-line-on-hw-init.patch b/lede/target/linux/airoha/patches-6.12/116-02-net-airoha-deassert-XSI-line-on-hw-init.patch new file mode 100644 index 0000000000..41425bbc69 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/116-02-net-airoha-deassert-XSI-line-on-hw-init.patch @@ -0,0 +1,26 @@ +From 5cb5f11469dfcbd7568fbca8b79c0f20a21cfbf5 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 17 Jan 2025 10:09:15 +0100 +Subject: [PATCH 2/9] net: airoha: deassert XSI line on hw init + +In preparation for phylink support, deassert XSI line as we will naw +make actual use of them for external PHY/SFP cage support. + +Signed-off-by: Christian Marangi +--- + drivers/net/ethernet/airoha/airoha_eth.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -1382,6 +1382,10 @@ static int airoha_hw_init(struct platfor + if (err) + return err; + ++ err = reset_control_bulk_deassert(eth->soc->num_xsi_rsts, eth->xsi_rsts); ++ if (err) ++ return err; ++ + msleep(20); + err = reset_control_bulk_deassert(ARRAY_SIZE(eth->rsts), eth->rsts); + if (err) diff --git a/lede/target/linux/airoha/patches-6.12/116-03-net-airoha-add-reference-for-SPORT-GDM4-in-qdma_get_.patch b/lede/target/linux/airoha/patches-6.12/116-03-net-airoha-add-reference-for-SPORT-GDM4-in-qdma_get_.patch new file mode 100644 index 0000000000..2407246861 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/116-03-net-airoha-add-reference-for-SPORT-GDM4-in-qdma_get_.patch @@ -0,0 +1,31 @@ +From ad29054f9b0e96e30a5d0bb6967d1204b8ea8bd1 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 17 Jan 2025 10:12:02 +0100 +Subject: [PATCH 3/9] net: airoha: add reference for SPORT GDM4 in + qdma_get_gdm_port + +Add SPORT reference in get gdm port as the on receive the SPORT 0x18 is +assigned for the GDM4 port. + +While at it also add comments to better identify GDM1 ports. + +Signed-off-by: Christian Marangi +--- + drivers/net/ethernet/airoha/airoha_eth.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -588,8 +588,11 @@ static int airoha_qdma_get_gdm_port(stru + + sport = FIELD_GET(QDMA_ETH_RXMSG_SPORT_MASK, msg1); + switch (sport) { ++ case 0x18: ++ port = 3; /* GDM4 */ ++ break; + case 0x10 ... 0x14: +- port = 0; ++ port = 0; /* GDM1 */ + break; + case 0x2 ... 0x4: + port = sport - 1; diff --git a/lede/target/linux/airoha/patches-6.12/116-06-net-airoha-add-initial-fixup-for-GDM3-4-port-support.patch b/lede/target/linux/airoha/patches-6.12/116-06-net-airoha-add-initial-fixup-for-GDM3-4-port-support.patch new file mode 100644 index 0000000000..3805febe71 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/116-06-net-airoha-add-initial-fixup-for-GDM3-4-port-support.patch @@ -0,0 +1,40 @@ +From a3cd6eb3259282a68b608fc923121460c0d3d2f7 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 17 Jan 2025 10:35:41 +0100 +Subject: [PATCH 6/9] net: airoha: add initial fixup for GDM3/4 port support + +GDM3 and GDM4 require different configuration for max long frame +definition, needs the QDMA to strip CRC on RX and require the SPORT to +be enabled to correctly be identified. + +Signed-off-by: Christian Marangi +--- + drivers/net/ethernet/airoha/airoha_eth.c | 12 ++++++++++-- + drivers/net/ethernet/airoha/airoha_regs.h | 1 + + 2 files changed, 11 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -514,8 +514,10 @@ static int airoha_fe_init(struct airoha_ + FIELD_PREP(IP_ASSEMBLE_PORT_MASK, 0) | + FIELD_PREP(IP_ASSEMBLE_NBQ_MASK, 22)); + +- airoha_fe_set(eth, REG_GDM_FWD_CFG(3), GDM_PAD_EN_MASK); +- airoha_fe_set(eth, REG_GDM_FWD_CFG(4), GDM_PAD_EN_MASK); ++ airoha_fe_set(eth, REG_GDM_FWD_CFG(3), ++ GDM_PAD_EN_MASK | GDM_STRIP_CRC_MASK); ++ airoha_fe_set(eth, REG_GDM_FWD_CFG(4), ++ GDM_PAD_EN_MASK | GDM_STRIP_CRC_MASK); + + airoha_fe_crsn_qsel_init(eth); + +@@ -1624,7 +1626,8 @@ static int airoha_dev_open(struct net_de + if (err) + return err; + +- if (netdev_uses_dsa(dev)) ++ /* It seems GDM3 and GDM4 needs SPORT enabled to correctly work */ ++ if (netdev_uses_dsa(dev) || port->id > 2) + airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id), + GDM_STAG_EN_MASK); + else diff --git a/lede/target/linux/airoha/patches-6.12/116-07-airoha-ethernet-drop-xsi-mac-reset.patch b/lede/target/linux/airoha/patches-6.12/116-07-airoha-ethernet-drop-xsi-mac-reset.patch new file mode 100644 index 0000000000..7e0fc5a798 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/116-07-airoha-ethernet-drop-xsi-mac-reset.patch @@ -0,0 +1,33 @@ +From fecb65813ddf52abf310bc2227a0ac869dc897d1 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 29 Jan 2025 14:47:41 +0100 +Subject: [PATCH 1/3] airoha: ethernet: drop xsi-mac reset + +In preparation for support for Ethernet and PON PCS, drop the xsi-mac +reset from airoha_eth. This reset is related to the Ethernet PCS and +should be handled in the dedicated driver. + +Signed-off-by: Christian Marangi +--- + drivers/net/ethernet/airoha/airoha_eth.c | 9 ++++----- + drivers/net/ethernet/airoha/airoha_eth.h | 2 +- + 2 files changed, 5 insertions(+), 6 deletions(-) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -3088,7 +3088,6 @@ static void airoha_remove(struct platfor + } + + static const char * const en7581_xsi_rsts_names[] = { +- "xsi-mac", + "hsi0-mac", + "hsi1-mac", + "hsi-mac", +@@ -3120,7 +3119,6 @@ static int airoha_en7581_get_src_port_id + } + + static const char * const an7583_xsi_rsts_names[] = { +- "xsi-mac", + "hsi0-mac", + "hsi1-mac", + "xfp-mac", diff --git a/lede/target/linux/airoha/patches-6.12/116-08-net-phylink-add-.pcs_link_down-PCS-OP.patch b/lede/target/linux/airoha/patches-6.12/116-08-net-phylink-add-.pcs_link_down-PCS-OP.patch new file mode 100644 index 0000000000..5e7c537378 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/116-08-net-phylink-add-.pcs_link_down-PCS-OP.patch @@ -0,0 +1,64 @@ +From d5fb4ad1beec53ca5d3b44d9b88598ed4ab0b34d Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 9 May 2025 16:36:22 +0200 +Subject: [PATCH 1/6] net: phylink: add .pcs_link_down PCS OP + +Permit for PCS driver to define specific operation to torn down the link +between the MAC and the PCS. + +This might be needed for some PCS that reset counter or require special +reset to correctly work if the link needs to be restored later. + +On phylink_link_down() call, the additional phylink_pcs_link_down() will +be called before .mac_link_down to torn down the link. + +PCS driver will need to define .pcs_link_down to make use of this. + +Signed-off-by: Christian Marangi +--- + drivers/net/phy/phylink.c | 8 ++++++++ + include/linux/phylink.h | 2 ++ + 2 files changed, 10 insertions(+) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -1088,6 +1088,12 @@ static unsigned int phylink_inband_caps( + return phylink_pcs_inband_caps(pcs, interface); + } + ++static void phylink_pcs_link_down(struct phylink_pcs *pcs) ++{ ++ if (pcs && pcs->ops->pcs_link_down) ++ pcs->ops->pcs_link_down(pcs); ++} ++ + static void phylink_pcs_poll_stop(struct phylink *pl) + { + if (pl->cfg_link_an_mode == MLO_AN_INBAND) +@@ -1642,6 +1648,8 @@ static void phylink_link_down(struct phy + + if (ndev) + netif_carrier_off(ndev); ++ phylink_pcs_link_down(pl->pcs); ++ + pl->mac_ops->mac_link_down(pl->config, pl->cur_link_an_mode, + pl->cur_interface); + phylink_info(pl, "Link is Down\n"); +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -431,6 +431,7 @@ struct phylink_pcs { + * (where necessary). + * @pcs_pre_init: configure PCS components necessary for MAC hardware + * initialization e.g. RX clock for stmmac. ++ * @pcs_link_down: torn down link between MAC and PCS. + */ + struct phylink_pcs_ops { + int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported, +@@ -453,6 +454,7 @@ struct phylink_pcs_ops { + void (*pcs_link_up)(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, int speed, int duplex); + int (*pcs_pre_init)(struct phylink_pcs *pcs); ++ void (*pcs_link_down)(struct phylink_pcs *pcs); + }; + + #if 0 /* For kernel-doc purposes only. */ diff --git a/lede/target/linux/airoha/patches-6.12/116-09-net-pcs-airoha-add-PCS-driver-for-Airoha-SoC.patch b/lede/target/linux/airoha/patches-6.12/116-09-net-pcs-airoha-add-PCS-driver-for-Airoha-SoC.patch new file mode 100644 index 0000000000..5bd7da4a43 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/116-09-net-pcs-airoha-add-PCS-driver-for-Airoha-SoC.patch @@ -0,0 +1,3369 @@ +From ddee0533ac9906ea5a40ac2e0474034135aa074d Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 17 Jan 2025 12:40:32 +0100 +Subject: [PATCH 4/8] net: pcs: airoha: add PCS driver for Airoha AN7581 SoC + +Add PCS driver for Airoha AN7581 SoC for ethernet SERDES and permit usage of +external PHY or connected SFP cage. Supported modes are USXGMII, +10G-BASER, 2500BASE-X, 1000BASE-X and SGMII. + +The driver probe and register the various needed registers and expose +the pcs_create and pcs_destroy symbol to make them usable by the Airoha +Ethernet driver. + +Signed-off-by: Christian Marangi +--- + drivers/net/pcs/Kconfig | 2 + + drivers/net/pcs/Makefile | 2 + + drivers/net/pcs/airoha/Kconfig | 11 + + drivers/net/pcs/airoha/Makefile | 7 + + drivers/net/pcs/airoha/pcs-airoha-common.c | 1033 ++++++++++++++ + drivers/net/pcs/airoha/pcs-airoha.h | 822 ++++++++++++ + drivers/net/pcs/airoha/pcs-an7581.c | 1419 ++++++++++++++++++++ + include/linux/pcs/pcs-airoha.h | 9 + + 8 files changed, 3305 insertions(+) + create mode 100644 drivers/net/pcs/airoha/Kconfig + create mode 100644 drivers/net/pcs/airoha/Makefile + create mode 100644 drivers/net/pcs/airoha/pcs-airoha-common.c + create mode 100644 drivers/net/pcs/airoha/pcs-airoha.h + create mode 100644 drivers/net/pcs/airoha/pcs-an7581.c + create mode 100644 include/linux/pcs/pcs-airoha.h + +--- a/drivers/net/pcs/Kconfig ++++ b/drivers/net/pcs/Kconfig +@@ -44,4 +44,6 @@ config PCS_RZN1_MIIC + on RZ/N1 SoCs. This PCS converts MII to RMII/RGMII or can be set in + pass-through mode for MII. + ++source "drivers/net/pcs/airoha/Kconfig" ++ + endmenu +--- a/drivers/net/pcs/Makefile ++++ b/drivers/net/pcs/Makefile +@@ -9,3 +9,5 @@ obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o + obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o + obj-$(CONFIG_PCS_RZN1_MIIC) += pcs-rzn1-miic.o + obj-$(CONFIG_PCS_MTK_USXGMII) += pcs-mtk-usxgmii.o ++ ++obj-$(CONFIG_PCS_AIROHA) += airoha/ +--- /dev/null ++++ b/drivers/net/pcs/airoha/Kconfig +@@ -0,0 +1,11 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++config PCS_AIROHA ++ tristate ++ ++config PCS_AIROHA_AN7581 ++ tristate "Airoha AN7581 PCS driver" ++ select PCS_AIROHA ++ help ++ This module provides helper to phylink for managing the Airoha ++ AN7581 PCS for SoC Ethernet and PON SERDES. +--- /dev/null ++++ b/drivers/net/pcs/airoha/Makefile +@@ -0,0 +1,7 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++obj-y := pcs-airoha.o ++pcs-airoha-objs := pcs-airoha-common.o ++ifdef CONFIG_PCS_AIROHA_AN7581 ++pcs-airoha-objs += pcs-an7581.o ++endif +--- /dev/null ++++ b/drivers/net/pcs/airoha/pcs-airoha-common.c +@@ -0,0 +1,1035 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2024 AIROHA Inc ++ * Author: Christian Marangi ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "pcs-airoha.h" ++ ++static void airoha_pcs_setup_scu_eth(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ u32 xsi_sel; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ xsi_sel = AIROHA_SCU_ETH_XSI_HSGMII; ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ default: ++ xsi_sel = AIROHA_SCU_ETH_XSI_USXGMII; ++ } ++ ++ regmap_update_bits(priv->scu, AIROHA_SCU_SSR3, ++ AIROHA_SCU_ETH_XSI_SEL, ++ xsi_sel); ++} ++ ++static void airoha_pcs_setup_scu_pon(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ u32 xsi_sel, wan_sel; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ wan_sel = AIROHA_SCU_WAN_SEL_SGMII; ++ xsi_sel = AIROHA_SCU_PON_XSI_HSGMII; ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: ++ wan_sel = AIROHA_SCU_WAN_SEL_HSGMII; ++ xsi_sel = AIROHA_SCU_PON_XSI_HSGMII; ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ default: ++ wan_sel = AIROHA_SCU_WAN_SEL_USXGMII; ++ xsi_sel = AIROHA_SCU_PON_XSI_USXGMII; ++ } ++ ++ regmap_update_bits(priv->scu, AIROHA_SCU_SSTR, ++ AIROHA_SCU_PON_XSI_SEL, ++ xsi_sel); ++ ++ regmap_update_bits(priv->scu, AIROHA_SCU_WAN_CONF, ++ AIROHA_SCU_WAN_SEL, ++ wan_sel); ++} ++ ++static int airoha_pcs_setup_scu(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ const struct airoha_pcs_match_data *data = priv->data; ++ int ret; ++ ++ switch (data->port_type) { ++ case AIROHA_PCS_ETH: ++ airoha_pcs_setup_scu_eth(priv, interface); ++ break; ++ case AIROHA_PCS_PON: ++ airoha_pcs_setup_scu_pon(priv, interface); ++ break; ++ } ++ ++ /* TODO better handle reset from MAC */ ++ ret = reset_control_bulk_assert(ARRAY_SIZE(priv->rsts), ++ priv->rsts); ++ if (ret) ++ return ret; ++ ++ ret = reset_control_bulk_deassert(ARRAY_SIZE(priv->rsts), ++ priv->rsts); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static void airoha_pcs_init_usxgmii(struct airoha_pcs_priv *priv) ++{ ++ regmap_set_bits(priv->multi_sgmii, AIROHA_PCS_MULTI_SGMII_MSG_RX_CTRL_0, ++ AIROHA_PCS_HSGMII_XFI_SEL); ++ ++ /* Disable Hibernation */ ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTROL_1, ++ AIROHA_PCS_USXGMII_SPEED_SEL_H); ++ ++ /* FIXME: wait Airoha */ ++ /* Avoid PCS sending garbage to MAC in some HW revision (E0) */ ++ regmap_write(priv->usxgmii_pcs, AIROHA_PCS_USGMII_VENDOR_DEFINE_116, 0); ++} ++ ++static void airoha_pcs_init_hsgmii(struct airoha_pcs_priv *priv) ++{ ++ regmap_clear_bits(priv->multi_sgmii, AIROHA_PCS_MULTI_SGMII_MSG_RX_CTRL_0, ++ AIROHA_PCS_HSGMII_XFI_SEL); ++ ++ regmap_set_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_1, ++ AIROHA_PCS_TBI_10B_MODE); ++} ++ ++static void airoha_pcs_init_sgmii(struct airoha_pcs_priv *priv) ++{ ++ regmap_clear_bits(priv->multi_sgmii, AIROHA_PCS_MULTI_SGMII_MSG_RX_CTRL_0, ++ AIROHA_PCS_HSGMII_XFI_SEL); ++ ++ regmap_set_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_1, ++ AIROHA_PCS_TBI_10B_MODE); ++ ++ regmap_update_bits(priv->hsgmii_rate_adp, AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_6, ++ AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_DOUT_L, ++ FIELD_PREP(AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_DOUT_L, 0x07070707)); ++ ++ regmap_update_bits(priv->hsgmii_rate_adp, AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_8, ++ AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_DOUT_C, ++ FIELD_PREP(AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_DOUT_C, 0xff)); ++} ++ ++static void airoha_pcs_init(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ airoha_pcs_init_sgmii(priv); ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: ++ airoha_pcs_init_hsgmii(priv); ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ airoha_pcs_init_usxgmii(priv); ++ break; ++ default: ++ return; ++ } ++} ++ ++static void airoha_pcs_interrupt_init_sgmii(struct airoha_pcs_priv *priv) ++{ ++ /* Disable every interrupt */ ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_HSGMII_PCS_HSGMII_MODE_INTERRUPT, ++ AIROHA_PCS_HSGMII_MODE2_REMOVE_FAULT_OCCUR_INT | ++ AIROHA_PCS_HSGMII_MODE2_AN_CL37_TIMERDONE_INT | ++ AIROHA_PCS_HSGMII_MODE2_AN_MIS_INT | ++ AIROHA_PCS_HSGMII_MODE2_RX_SYN_DONE_INT | ++ AIROHA_PCS_HSGMII_MODE2_AN_DONE_INT); ++ ++ /* Clear interrupt */ ++ regmap_set_bits(priv->usxgmii_pcs, AIROHA_PCS_HSGMII_PCS_HSGMII_MODE_INTERRUPT, ++ AIROHA_PCS_HSGMII_MODE2_REMOVE_FAULT_OCCUR_INT_CLEAR | ++ AIROHA_PCS_HSGMII_MODE2_AN_CL37_TIMERDONE_INT_CLEAR | ++ AIROHA_PCS_HSGMII_MODE2_AN_MIS_INT_CLEAR | ++ AIROHA_PCS_HSGMII_MODE2_RX_SYN_DONE_INT_CLEAR | ++ AIROHA_PCS_HSGMII_MODE2_AN_DONE_INT_CLEAR); ++ ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_HSGMII_PCS_HSGMII_MODE_INTERRUPT, ++ AIROHA_PCS_HSGMII_MODE2_REMOVE_FAULT_OCCUR_INT_CLEAR | ++ AIROHA_PCS_HSGMII_MODE2_AN_CL37_TIMERDONE_INT_CLEAR | ++ AIROHA_PCS_HSGMII_MODE2_AN_MIS_INT_CLEAR | ++ AIROHA_PCS_HSGMII_MODE2_RX_SYN_DONE_INT_CLEAR | ++ AIROHA_PCS_HSGMII_MODE2_AN_DONE_INT_CLEAR); ++} ++ ++static void airoha_pcs_interrupt_init_usxgmii(struct airoha_pcs_priv *priv) ++{ ++ /* Disable every Interrupt */ ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTRL_0, ++ AIROHA_PCS_USXGMII_T_TYPE_T_INT_EN | ++ AIROHA_PCS_USXGMII_T_TYPE_D_INT_EN | ++ AIROHA_PCS_USXGMII_T_TYPE_C_INT_EN | ++ AIROHA_PCS_USXGMII_T_TYPE_S_INT_EN); ++ ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTRL_1, ++ AIROHA_PCS_USXGMII_R_TYPE_C_INT_EN | ++ AIROHA_PCS_USXGMII_R_TYPE_S_INT_EN | ++ AIROHA_PCS_USXGMII_TXPCS_FSM_ENC_ERR_INT_EN | ++ AIROHA_PCS_USXGMII_T_TYPE_E_INT_EN); ++ ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTRL_2, ++ AIROHA_PCS_USXGMII_RPCS_FSM_DEC_ERR_INT_EN | ++ AIROHA_PCS_USXGMII_R_TYPE_E_INT_EN | ++ AIROHA_PCS_USXGMII_R_TYPE_T_INT_EN | ++ AIROHA_PCS_USXGMII_R_TYPE_D_INT_EN); ++ ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTRL_3, ++ AIROHA_PCS_USXGMII_FAIL_SYNC_XOR_ST_INT_EN | ++ AIROHA_PCS_USXGMII_RX_BLOCK_LOCK_ST_INT_EN | ++ AIROHA_PCS_USXGMII_LINK_UP_ST_INT_EN | ++ AIROHA_PCS_USXGMII_HI_BER_ST_INT_EN); ++ ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTRL_4, ++ AIROHA_PCS_USXGMII_LINK_DOWN_ST_INT_EN); ++ ++ /* Clear any pending interrupt */ ++ regmap_set_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_INT_STA_2, ++ AIROHA_PCS_USXGMII_RPCS_FSM_DEC_ERR_INT | ++ AIROHA_PCS_USXGMII_R_TYPE_E_INT | ++ AIROHA_PCS_USXGMII_R_TYPE_T_INT | ++ AIROHA_PCS_USXGMII_R_TYPE_D_INT); ++ ++ regmap_set_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_INT_STA_3, ++ AIROHA_PCS_USXGMII_FAIL_SYNC_XOR_ST_INT | ++ AIROHA_PCS_USXGMII_RX_BLOCK_LOCK_ST_INT | ++ AIROHA_PCS_USXGMII_LINK_UP_ST_INT | ++ AIROHA_PCS_USXGMII_HI_BER_ST_INT); ++ ++ regmap_set_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_INT_STA_4, ++ AIROHA_PCS_USXGMII_LINK_DOWN_ST_INT); ++ ++ /* Interrupt saddly seems to be not weel supported for Link Down. ++ * PCS Poll is a must to correctly read and react on Cable Deatch ++ * as only cable attach interrupt are fired and Link Down interrupt ++ * are fired only in special case like AN restart. ++ */ ++} ++ ++static void airoha_pcs_interrupt_init(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ return airoha_pcs_interrupt_init_sgmii(priv); ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ return airoha_pcs_interrupt_init_usxgmii(priv); ++ default: ++ return; ++ } ++} ++ ++static void airoha_pcs_get_state_sgmii(struct airoha_pcs_priv *priv, ++ struct phylink_link_state *state) ++{ ++ u32 bmsr, lpa; ++ ++ regmap_read(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_1, ++ &bmsr); ++ regmap_read(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_5, ++ &lpa); ++ ++ bmsr = (AIROHA_PCS_HSGMII_AN_SGMII_AN_COMPLETE | ++ AIROHA_PCS_HSGMII_AN_SGMII_REMOTE_FAULT | ++ AIROHA_PCS_HSGMII_AN_SGMII_AN_ABILITY | ++ AIROHA_PCS_HSGMII_AN_SGMII_LINK_STATUS) & bmsr; ++ lpa = AIROHA_PCS_HSGMII_AN_SGMII_PARTNER_ABILITY & lpa; ++ ++ phylink_mii_c22_pcs_decode_state(state, bmsr, lpa); ++} ++ ++static void airoha_pcs_get_state_hsgmii(struct airoha_pcs_priv *priv, ++ struct phylink_link_state *state) ++{ ++ u32 bmsr; ++ ++ regmap_read(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_1, ++ &bmsr); ++ ++ bmsr = (AIROHA_PCS_HSGMII_AN_SGMII_AN_COMPLETE | ++ AIROHA_PCS_HSGMII_AN_SGMII_REMOTE_FAULT | ++ AIROHA_PCS_HSGMII_AN_SGMII_AN_ABILITY | ++ AIROHA_PCS_HSGMII_AN_SGMII_LINK_STATUS) & bmsr; ++ ++ state->link = !!(bmsr & BMSR_LSTATUS); ++ state->an_complete = !!(bmsr & BMSR_ANEGCOMPLETE); ++ state->speed = SPEED_2500; ++ state->duplex = DUPLEX_FULL; ++} ++ ++static void airoha_pcs_get_state_usxgmii(struct airoha_pcs_priv *priv, ++ struct phylink_link_state *state) ++{ ++ const struct airoha_pcs_match_data *data = priv->data; ++ u32 an_done, lpa; ++ ++ /* Trigger HW workaround if needed. If an error is reported, ++ * consider link down and test again later. ++ */ ++ if (data->rxlock_workaround && data->rxlock_workaround(priv)) { ++ state->link = false; ++ return; ++ } ++ ++ /* Toggle AN Status */ ++ regmap_set_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_AN_CONTROL_6, ++ AIROHA_PCS_USXGMII_TOG_PCS_AUTONEG_STS); ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_AN_CONTROL_6, ++ AIROHA_PCS_USXGMII_TOG_PCS_AUTONEG_STS); ++ ++ regmap_read(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_AN_STATS_0, &lpa); ++ regmap_read(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_AN_STATS_2, &an_done); ++ ++ state->link = !!(lpa & MDIO_USXGMII_LINK); ++ state->an_complete = !!(an_done & AIROHA_PCS_USXGMII_PCS_AN_COMPLETE); ++ ++ phylink_decode_usxgmii_word(state, lpa); ++} ++ ++static void airoha_pcs_get_state_10gbaser(struct airoha_pcs_priv *priv, ++ struct phylink_link_state *state) ++{ ++ u32 status, curr_mode; ++ ++ /* Toggle AN Status */ ++ regmap_set_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_AN_CONTROL_6, ++ AIROHA_PCS_USXGMII_TOG_PCS_AUTONEG_STS); ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_AN_CONTROL_6, ++ AIROHA_PCS_USXGMII_TOG_PCS_AUTONEG_STS); ++ ++ regmap_read(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_BASE_R_10GB_T_PCS_STUS_1, ++ &status); ++ regmap_read(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_AN_STATS_0, &curr_mode); ++ ++ state->link = !!(status & AIROHA_PCS_USXGMII_RX_LINK_STUS); ++ ++ switch (curr_mode & AIROHA_PCS_USXGMII_CUR_USXGMII_MODE) { ++ case AIROHA_PCS_USXGMII_CUR_USXGMII_MODE_10G: ++ state->speed = SPEED_10000; ++ break; ++ case AIROHA_PCS_USXGMII_CUR_USXGMII_MODE_5G: ++ state->speed = SPEED_5000; ++ break; ++ case AIROHA_PCS_USXGMII_CUR_USXGMII_MODE_2_5G: ++ state->speed = SPEED_2500; ++ break; ++ default: ++ state->speed = SPEED_UNKNOWN; ++ return; ++ } ++ ++ state->duplex = DUPLEX_FULL; ++} ++ ++static void airoha_pcs_get_state(struct phylink_pcs *pcs, ++ struct phylink_link_state *state) ++{ ++ struct airoha_pcs_port *port = to_airoha_pcs_port(pcs); ++ struct airoha_pcs_priv *priv = port->priv; ++ ++ switch (state->interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ airoha_pcs_get_state_sgmii(priv, state); ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: ++ airoha_pcs_get_state_hsgmii(priv, state); ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ airoha_pcs_get_state_usxgmii(priv, state); ++ break; ++ case PHY_INTERFACE_MODE_10GBASER: ++ airoha_pcs_get_state_10gbaser(priv, state); ++ break; ++ default: ++ return; ++ } ++} ++ ++static int airoha_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, ++ phy_interface_t interface, ++ const unsigned long *advertising, ++ bool permit_pause_to_mac) ++{ ++ struct airoha_pcs_port *port = to_airoha_pcs_port(pcs); ++ struct airoha_pcs_priv *priv = port->priv; ++ const struct airoha_pcs_match_data *data; ++ u32 rate_adapt; ++ int ret; ++ ++ priv->interface = interface; ++ data = priv->data; ++ ++ /* Apply Analog and Digital configuration for PCS */ ++ if (data->bringup) { ++ ret = data->bringup(priv, interface); ++ if (ret) ++ return ret; ++ } ++ ++ /* Set final configuration for various modes */ ++ airoha_pcs_init(priv, interface); ++ ++ /* Configure Interrupt for various modes */ ++ airoha_pcs_interrupt_init(priv, interface); ++ ++ rate_adapt = AIROHA_PCS_HSGMII_RATE_ADAPT_RX_EN | ++ AIROHA_PCS_HSGMII_RATE_ADAPT_TX_EN; ++ ++ if (interface == PHY_INTERFACE_MODE_SGMII) ++ rate_adapt |= AIROHA_PCS_HSGMII_RATE_ADAPT_RX_BYPASS | ++ AIROHA_PCS_HSGMII_RATE_ADAPT_TX_BYPASS; ++ ++ /* AN Auto Settings (Rate Adaptation) */ ++ regmap_update_bits(priv->hsgmii_rate_adp, AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_0, ++ AIROHA_PCS_HSGMII_RATE_ADAPT_RX_BYPASS | ++ AIROHA_PCS_HSGMII_RATE_ADAPT_TX_BYPASS | ++ AIROHA_PCS_HSGMII_RATE_ADAPT_RX_EN | ++ AIROHA_PCS_HSGMII_RATE_ADAPT_TX_EN, rate_adapt); ++ ++ /* FIXME: With an attached Aeonsemi PHY, AN is needed ++ * even with no inband. ++ */ ++ if (interface == PHY_INTERFACE_MODE_USXGMII || ++ interface == PHY_INTERFACE_MODE_10GBASER) { ++ if (interface == PHY_INTERFACE_MODE_USXGMII) ++ regmap_set_bits(priv->usxgmii_pcs, ++ AIROHA_PCS_USXGMII_PCS_AN_CONTROL_0, ++ AIROHA_PCS_USXGMII_AN_ENABLE); ++ else ++ regmap_clear_bits(priv->usxgmii_pcs, ++ AIROHA_PCS_USXGMII_PCS_AN_CONTROL_0, ++ AIROHA_PCS_USXGMII_AN_ENABLE); ++ } ++ ++ /* Clear any force bit that my be set by bootloader */ ++ if (interface == PHY_INTERFACE_MODE_SGMII || ++ interface == PHY_INTERFACE_MODE_1000BASEX || ++ interface == PHY_INTERFACE_MODE_2500BASEX) { ++ regmap_clear_bits(priv->multi_sgmii, AIROHA_PCS_MULTI_SGMII_SGMII_STS_CTRL_0, ++ AIROHA_PCS_LINK_MODE_P0 | ++ AIROHA_PCS_FORCE_SPD_MODE_P0 | ++ AIROHA_PCS_FORCE_LINKDOWN_P0 | ++ AIROHA_PCS_FORCE_LINKUP_P0); ++ } ++ ++ /* Toggle Rate Adaption for SGMII/HSGMII mode */ ++ if (interface == PHY_INTERFACE_MODE_SGMII || ++ interface == PHY_INTERFACE_MODE_1000BASEX || ++ interface == PHY_INTERFACE_MODE_2500BASEX) { ++ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) ++ regmap_clear_bits(priv->hsgmii_rate_adp, ++ AIROHA_PCS_HSGMII_RATE_ADP_P0_CTRL_0, ++ AIROHA_PCS_HSGMII_P0_DIS_MII_MODE); ++ else ++ regmap_set_bits(priv->hsgmii_rate_adp, ++ AIROHA_PCS_HSGMII_RATE_ADP_P0_CTRL_0, ++ AIROHA_PCS_HSGMII_P0_DIS_MII_MODE); ++ } ++ ++ /* Setup AN Link Timer */ ++ if (interface == PHY_INTERFACE_MODE_SGMII || ++ interface == PHY_INTERFACE_MODE_1000BASEX) { ++ u32 an_timer; ++ ++ an_timer = phylink_get_link_timer_ns(interface); ++ ++ /* Value needs to be shifted by 4, seems value is internally * 16 */ ++ regmap_update_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_11, ++ AIROHA_PCS_HSGMII_AN_SGMII_LINK_TIMER, ++ FIELD_PREP(AIROHA_PCS_HSGMII_AN_SGMII_LINK_TIMER, ++ an_timer >> 4)); ++ ++ regmap_update_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_3, ++ AIROHA_PCS_HSGMII_PCS_LINK_STSTIME, ++ FIELD_PREP(AIROHA_PCS_HSGMII_PCS_LINK_STSTIME, ++ an_timer >> 4)); ++ } ++ ++ /* Setup SGMII AN and advertisement in DEV_ABILITY */ ++ if (interface == PHY_INTERFACE_MODE_SGMII) { ++ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { ++ int advertise = phylink_mii_c22_pcs_encode_advertisement(interface, ++ advertising); ++ if (advertise < 0) ++ return advertise; ++ ++ regmap_update_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_4, ++ AIROHA_PCS_HSGMII_AN_SGMII_DEV_ABILITY, ++ FIELD_PREP(AIROHA_PCS_HSGMII_AN_SGMII_DEV_ABILITY, ++ advertise)); ++ ++ regmap_set_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_0, ++ AIROHA_PCS_HSGMII_AN_SGMII_RA_ENABLE); ++ } else { ++ regmap_clear_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_0, ++ AIROHA_PCS_HSGMII_AN_SGMII_RA_ENABLE); ++ } ++ } ++ ++ if (interface == PHY_INTERFACE_MODE_2500BASEX) { ++ regmap_clear_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_0, ++ AIROHA_PCS_HSGMII_AN_SGMII_RA_ENABLE); ++ ++ regmap_set_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_6, ++ AIROHA_PCS_HSGMII_PCS_TX_ENABLE); ++ } ++ ++ if (interface == PHY_INTERFACE_MODE_SGMII || ++ interface == PHY_INTERFACE_MODE_1000BASEX) { ++ u32 if_mode = AIROHA_PCS_HSGMII_AN_SIDEBAND_EN; ++ ++ /* Toggle SGMII or 1000base-x mode */ ++ if (interface == PHY_INTERFACE_MODE_SGMII) ++ if_mode |= AIROHA_PCS_HSGMII_AN_SGMII_EN; ++ ++ if (neg_mode & PHYLINK_PCS_NEG_INBAND) ++ regmap_set_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_13, ++ AIROHA_PCS_HSGMII_AN_SGMII_REMOTE_FAULT_DIS); ++ else ++ regmap_clear_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_13, ++ AIROHA_PCS_HSGMII_AN_SGMII_REMOTE_FAULT_DIS); ++ ++ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { ++ /* Clear force speed bits and MAC mode */ ++ regmap_clear_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_6, ++ AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_10 | ++ AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_100 | ++ AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_1000 | ++ AIROHA_PCS_HSGMII_PCS_MAC_MODE | ++ AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL | ++ AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT); ++ } else { ++ /* Enable compatibility with MAC PCS Layer */ ++ if_mode |= AIROHA_PCS_HSGMII_AN_SGMII_COMPAT_EN; ++ ++ /* AN off force rate adaption, speed is set later in Link Up */ ++ regmap_set_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_6, ++ AIROHA_PCS_HSGMII_PCS_MAC_MODE | ++ AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT); ++ } ++ ++ regmap_update_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_13, ++ AIROHA_PCS_HSGMII_AN_SGMII_IF_MODE_5_0, if_mode); ++ ++ regmap_set_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_6, ++ AIROHA_PCS_HSGMII_PCS_TX_ENABLE | ++ AIROHA_PCS_HSGMII_PCS_MODE2_EN); ++ } ++ ++ if (interface == PHY_INTERFACE_MODE_1000BASEX && ++ neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) { ++ regmap_set_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_1, ++ AIROHA_PCS_SGMII_SEND_AN_ERR_EN); ++ ++ regmap_set_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_FORCE_CL37, ++ AIROHA_PCS_HSGMII_AN_FORCE_AN_DONE); ++ } ++ ++ /* Configure Flow Control on XFI */ ++ regmap_update_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_GIB_CFG, ++ AIROHA_PCS_XFI_TX_FC_EN | AIROHA_PCS_XFI_RX_FC_EN, ++ permit_pause_to_mac ? ++ AIROHA_PCS_XFI_TX_FC_EN | AIROHA_PCS_XFI_RX_FC_EN : ++ 0); ++ ++ return 0; ++} ++ ++static void airoha_pcs_an_restart(struct phylink_pcs *pcs) ++{ ++ struct airoha_pcs_port *port = to_airoha_pcs_port(pcs); ++ struct airoha_pcs_priv *priv = port->priv; ++ ++ switch (priv->interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ regmap_set_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_0, ++ AIROHA_PCS_HSGMII_AN_SGMII_AN_RESTART); ++ udelay(3); ++ regmap_clear_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_0, ++ AIROHA_PCS_HSGMII_AN_SGMII_AN_RESTART); ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ regmap_set_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_AN_CONTROL_0, ++ AIROHA_PCS_USXGMII_AN_RESTART); ++ udelay(3); ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_AN_CONTROL_0, ++ AIROHA_PCS_USXGMII_AN_RESTART); ++ default: ++ return; ++ } ++} ++ ++static void airoha_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode, ++ phy_interface_t interface, int speed, int duplex) ++{ ++ struct airoha_pcs_port *port = to_airoha_pcs_port(pcs); ++ struct airoha_pcs_priv *priv = port->priv; ++ const struct airoha_pcs_match_data *data; ++ ++ data = priv->data; ++ ++ if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { ++ if (interface == PHY_INTERFACE_MODE_SGMII) { ++ regmap_update_bits(priv->hsgmii_rate_adp, ++ AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_1, ++ AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_WR_THR | ++ AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_RD_THR, ++ FIELD_PREP(AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_WR_THR, 0x0) | ++ FIELD_PREP(AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_RD_THR, 0x0)); ++ udelay(1); ++ regmap_update_bits(priv->hsgmii_rate_adp, ++ AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_1, ++ AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_WR_THR | ++ AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_RD_THR, ++ FIELD_PREP(AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_WR_THR, 0xf) | ++ FIELD_PREP(AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_RD_THR, 0x5)); ++ } ++ } else { ++ if (interface == PHY_INTERFACE_MODE_USXGMII || ++ interface == PHY_INTERFACE_MODE_10GBASER) { ++ u32 mode; ++ u32 rate_adapt; ++ ++ switch (speed) { ++ case SPEED_10000: ++ rate_adapt = AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_10000; ++ mode = AIROHA_PCS_USXGMII_MODE_10000; ++ break; ++ case SPEED_5000: ++ rate_adapt = AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_5000; ++ mode = AIROHA_PCS_USXGMII_MODE_5000; ++ break; ++ case SPEED_2500: ++ rate_adapt = AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_2500; ++ mode = AIROHA_PCS_USXGMII_MODE_2500; ++ break; ++ case SPEED_1000: ++ rate_adapt = AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_1000; ++ mode = AIROHA_PCS_USXGMII_MODE_1000; ++ break; ++ case SPEED_100: ++ rate_adapt = AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_100; ++ mode = AIROHA_PCS_USXGMII_MODE_100; ++ break; ++ } ++ ++ /* Trigger USXGMII change mode and force selected speed */ ++ regmap_update_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_AN_CONTROL_7, ++ AIROHA_PCS_USXGMII_RATE_UPDATE_MODE | ++ AIROHA_PCS_USXGMII_MODE, ++ AIROHA_PCS_USXGMII_RATE_UPDATE_MODE | mode); ++ ++ regmap_update_bits(priv->hsgmii_rate_adp, AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_11, ++ AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_EN | ++ AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE, ++ AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_EN | ++ rate_adapt); ++ } ++ ++ if (interface == PHY_INTERFACE_MODE_SGMII || ++ interface == PHY_INTERFACE_MODE_1000BASEX) { ++ u32 force_speed; ++ u32 rate_adapt; ++ ++ switch (speed) { ++ case SPEED_1000: ++ force_speed = AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_1000; ++ rate_adapt = AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL_1000; ++ break; ++ case SPEED_100: ++ force_speed = AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_100; ++ rate_adapt = AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL_100; ++ break; ++ case SPEED_10: ++ force_speed = AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_10; ++ rate_adapt = AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL_10; ++ break; ++ } ++ ++ regmap_update_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_6, ++ AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_10 | ++ AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_100 | ++ AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_1000 | ++ AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL, ++ force_speed | rate_adapt); ++ } ++ ++ if (interface == PHY_INTERFACE_MODE_SGMII || ++ interface == PHY_INTERFACE_MODE_2500BASEX) { ++ u32 ck_gen_mode; ++ u32 speed_reg; ++ u32 if_mode; ++ ++ switch (speed) { ++ case SPEED_2500: ++ speed_reg = AIROHA_PCS_LINK_MODE_P0_2_5G; ++ break; ++ case SPEED_1000: ++ speed_reg = AIROHA_PCS_LINK_MODE_P0_1G; ++ if_mode = AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE_1000; ++ ck_gen_mode = AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_1000; ++ break; ++ case SPEED_100: ++ speed_reg = AIROHA_PCS_LINK_MODE_P0_100M; ++ if_mode = AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE_100; ++ ck_gen_mode = AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_100; ++ break; ++ case SPEED_10: ++ speed_reg = AIROHA_PCS_LINK_MODE_P0_100M; ++ if_mode = AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE_10; ++ ck_gen_mode = AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_10; ++ break; ++ } ++ ++ if (interface == PHY_INTERFACE_MODE_SGMII) { ++ regmap_update_bits(priv->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_13, ++ AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE, ++ if_mode); ++ ++ regmap_update_bits(priv->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_AN_SGMII_MODE_FORCE, ++ AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE | ++ AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_SEL, ++ ck_gen_mode | ++ AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_SEL); ++ } ++ ++ regmap_update_bits(priv->multi_sgmii, AIROHA_PCS_MULTI_SGMII_SGMII_STS_CTRL_0, ++ AIROHA_PCS_LINK_MODE_P0 | ++ AIROHA_PCS_FORCE_SPD_MODE_P0, ++ speed_reg | ++ AIROHA_PCS_FORCE_SPD_MODE_P0); ++ } ++ } ++ ++ if (data->link_up) ++ data->link_up(priv); ++ ++ /* BPI BMI enable */ ++ regmap_clear_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_GIB_CFG, ++ AIROHA_PCS_XFI_RXMPI_STOP | ++ AIROHA_PCS_XFI_RXMBI_STOP | ++ AIROHA_PCS_XFI_TXMPI_STOP | ++ AIROHA_PCS_XFI_TXMBI_STOP); ++} ++ ++static void airoha_pcs_link_down(struct phylink_pcs *pcs) ++{ ++ struct airoha_pcs_port *port = to_airoha_pcs_port(pcs); ++ struct airoha_pcs_priv *priv = port->priv; ++ ++ /* MPI MBI disable */ ++ regmap_set_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_GIB_CFG, ++ AIROHA_PCS_XFI_RXMPI_STOP | ++ AIROHA_PCS_XFI_RXMBI_STOP | ++ AIROHA_PCS_XFI_TXMPI_STOP | ++ AIROHA_PCS_XFI_TXMBI_STOP); ++} ++ ++static void airoha_pcs_pre_config(struct phylink_pcs *pcs, ++ phy_interface_t interface) ++{ ++ struct airoha_pcs_port *port = to_airoha_pcs_port(pcs); ++ struct airoha_pcs_priv *priv = port->priv; ++ ++ /* Select HSGMII or USXGMII in SCU regs */ ++ airoha_pcs_setup_scu(priv, interface); ++ ++ /* MPI MBI disable */ ++ regmap_set_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_GIB_CFG, ++ AIROHA_PCS_XFI_RXMPI_STOP | ++ AIROHA_PCS_XFI_RXMBI_STOP | ++ AIROHA_PCS_XFI_TXMPI_STOP | ++ AIROHA_PCS_XFI_TXMBI_STOP); ++ ++ /* Write 1 to trigger reset and clear */ ++ regmap_clear_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_LOGIC_RST, ++ AIROHA_PCS_XFI_MAC_LOGIC_RST); ++ regmap_set_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_LOGIC_RST, ++ AIROHA_PCS_XFI_MAC_LOGIC_RST); ++ ++ usleep_range(1000, 2000); ++ ++ /* Clear XFI MAC counter */ ++ regmap_set_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_CNT_CLR, ++ AIROHA_PCS_XFI_GLB_CNT_CLR); ++} ++ ++static int airoha_pcs_post_config(struct phylink_pcs *pcs, ++ phy_interface_t interface) ++{ ++ struct airoha_pcs_port *port = to_airoha_pcs_port(pcs); ++ struct airoha_pcs_priv *priv = port->priv; ++ ++ /* Frag disable */ ++ regmap_update_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_GIB_CFG, ++ AIROHA_PCS_XFI_RX_FRAG_LEN, ++ FIELD_PREP(AIROHA_PCS_XFI_RX_FRAG_LEN, 31)); ++ regmap_update_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_GIB_CFG, ++ AIROHA_PCS_XFI_TX_FRAG_LEN, ++ FIELD_PREP(AIROHA_PCS_XFI_TX_FRAG_LEN, 31)); ++ ++ /* IPG NUM */ ++ regmap_update_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_GIB_CFG, ++ AIROHA_PCS_XFI_IPG_NUM, ++ FIELD_PREP(AIROHA_PCS_XFI_IPG_NUM, 10)); ++ ++ /* Enable TX/RX flow control */ ++ regmap_set_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_GIB_CFG, ++ AIROHA_PCS_XFI_TX_FC_EN); ++ regmap_set_bits(priv->xfi_mac, AIROHA_PCS_XFI_MAC_XFI_GIB_CFG, ++ AIROHA_PCS_XFI_RX_FC_EN); ++ ++ return 0; ++} ++ ++static const struct phylink_pcs_ops airoha_pcs_ops = { ++ .pcs_pre_config = airoha_pcs_pre_config, ++ .pcs_post_config = airoha_pcs_post_config, ++ .pcs_get_state = airoha_pcs_get_state, ++ .pcs_config = airoha_pcs_config, ++ .pcs_an_restart = airoha_pcs_an_restart, ++ .pcs_link_up = airoha_pcs_link_up, ++ .pcs_link_down = airoha_pcs_link_down, ++}; ++ ++struct phylink_pcs *airoha_pcs_create(struct device *dev) ++{ ++ struct platform_device *pdev; ++ struct airoha_pcs_port *port; ++ struct device_node *np; ++ ++ np = of_parse_phandle(dev->of_node, "pcs", 0); ++ if (!np) ++ return ERR_PTR(-ENODEV); ++ ++ if (!of_device_is_available(np)) { ++ of_node_put(np); ++ return ERR_PTR(-ENODEV); ++ } ++ ++ pdev = of_find_device_by_node(np); ++ of_node_put(np); ++ if (!pdev || !platform_get_drvdata(pdev)) { ++ if (pdev) ++ put_device(&pdev->dev); ++ return ERR_PTR(-EPROBE_DEFER); ++ } ++ ++ port = kzalloc(sizeof(*port), GFP_KERNEL); ++ if (!port) ++ return ERR_PTR(-ENOMEM); ++ ++ port->priv = platform_get_drvdata(pdev); ++ port->pcs.ops = &airoha_pcs_ops; ++ port->pcs.neg_mode = true; ++ port->pcs.poll = true; ++ ++ return &port->pcs; ++} ++EXPORT_SYMBOL(airoha_pcs_create); ++ ++void airoha_pcs_destroy(struct phylink_pcs *pcs) ++{ ++ struct airoha_pcs_port *port = to_airoha_pcs_port(pcs); ++ ++ kfree(port); ++} ++EXPORT_SYMBOL(airoha_pcs_destroy); ++ ++static const struct regmap_config airoha_pcs_regmap_config = { ++ .reg_bits = 32, ++ .val_bits = 32, ++ .reg_stride = 4, ++}; ++ ++static int airoha_pcs_probe(struct platform_device *pdev) ++{ ++ struct regmap_config syscon_config = airoha_pcs_regmap_config; ++ const struct airoha_pcs_match_data *data; ++ struct device *dev = &pdev->dev; ++ struct airoha_pcs_priv *priv; ++ void *base; ++ int ret; ++ ++ data = of_device_get_match_data(dev); ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->dev = dev; ++ priv->data = data; ++ ++ base = devm_platform_ioremap_resource_byname(pdev, "xfi_mac"); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ syscon_config.name = "xfi_mac"; ++ priv->xfi_mac = devm_regmap_init_mmio(dev, base, &syscon_config); ++ if (IS_ERR(priv->xfi_mac)) ++ return PTR_ERR(priv->xfi_mac); ++ ++ base = devm_platform_ioremap_resource_byname(pdev, "hsgmii_an"); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ syscon_config.name = "hsgmii_an"; ++ priv->hsgmii_an = devm_regmap_init_mmio(dev, base, &syscon_config); ++ if (IS_ERR(priv->hsgmii_an)) ++ return PTR_ERR(priv->hsgmii_an); ++ ++ base = devm_platform_ioremap_resource_byname(pdev, "hsgmii_pcs"); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ syscon_config.name = "hsgmii_pcs"; ++ priv->hsgmii_pcs = devm_regmap_init_mmio(dev, base, &syscon_config); ++ if (IS_ERR(priv->hsgmii_pcs)) ++ return PTR_ERR(priv->hsgmii_pcs); ++ ++ base = devm_platform_ioremap_resource_byname(pdev, "hsgmii_rate_adp"); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ syscon_config.name = "hsgmii_rate_adp"; ++ priv->hsgmii_rate_adp = devm_regmap_init_mmio(dev, base, &syscon_config); ++ if (IS_ERR(priv->hsgmii_rate_adp)) ++ return PTR_ERR(priv->hsgmii_rate_adp); ++ ++ base = devm_platform_ioremap_resource_byname(pdev, "multi_sgmii"); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ syscon_config.name = "multi_sgmii"; ++ priv->multi_sgmii = devm_regmap_init_mmio(dev, base, &syscon_config); ++ if (IS_ERR(priv->multi_sgmii)) ++ return PTR_ERR(priv->multi_sgmii); ++ ++ base = devm_platform_ioremap_resource_byname(pdev, "usxgmii"); ++ if (IS_ERR(base) && PTR_ERR(base) != -ENOENT) ++ return PTR_ERR(base); ++ ++ syscon_config.name = "usxgmii"; ++ priv->usxgmii_pcs = devm_regmap_init_mmio(dev, base, &syscon_config); ++ if (IS_ERR(priv->usxgmii_pcs)) ++ return PTR_ERR(priv->usxgmii_pcs); ++ ++ base = devm_platform_ioremap_resource_byname(pdev, "xfi_pma"); ++ if (IS_ERR(base) && PTR_ERR(base) != -ENOENT) ++ return PTR_ERR(base); ++ ++ syscon_config.name = "xfi_pma"; ++ priv->xfi_pma = devm_regmap_init_mmio(dev, base, &syscon_config); ++ if (IS_ERR(priv->xfi_pma)) ++ return PTR_ERR(priv->xfi_pma); ++ ++ base = devm_platform_ioremap_resource_byname(pdev, "xfi_ana"); ++ if (IS_ERR(base) && PTR_ERR(base) != -ENOENT) ++ return PTR_ERR(base); ++ ++ syscon_config.name = "xfi_ana"; ++ priv->xfi_ana = devm_regmap_init_mmio(dev, base, &syscon_config); ++ if (IS_ERR(priv->xfi_ana)) ++ return PTR_ERR(priv->xfi_ana); ++ ++ /* SCU is used to toggle XFI or HSGMII in global SoC registers */ ++ priv->scu = syscon_regmap_lookup_by_phandle(dev->of_node, "airoha,scu"); ++ if (IS_ERR(priv->scu)) ++ return PTR_ERR(priv->scu); ++ ++ priv->rsts[0].id = "mac"; ++ priv->rsts[1].id = "phy"; ++ ret = devm_reset_control_bulk_get_exclusive(dev, ARRAY_SIZE(priv->rsts), ++ priv->rsts); ++ if (ret) ++ return dev_err_probe(dev, ret, "failed to get bulk reset lines\n"); ++ ++ /* For Ethernet PCS, read the AN7581 SoC revision to check if ++ * manual rx calibration is needed. This is only limited to ++ * any SoC revision before E2. ++ */ ++ if (data->port_type == AIROHA_PCS_ETH) { ++ u32 val; ++ ++ ret = regmap_read(priv->scu, AIROHA_SCU_PDIDR, &val); ++ if (ret) ++ return ret; ++ ++ if (FIELD_GET(AIROHA_SCU_PRODUCT_ID, val) < 0x2) ++ priv->manual_rx_calib = true; ++ } ++ ++ platform_set_drvdata(pdev, priv); ++ ++ return 0; ++} ++ ++static const struct airoha_pcs_match_data an7581_pcs_eth = { ++ .port_type = AIROHA_PCS_ETH, ++ .bringup = an7581_pcs_bringup, ++ .link_up = an7581_pcs_phya_link_up, ++ .rxlock_workaround = an7581_pcs_rxlock_workaround, ++}; ++ ++static const struct airoha_pcs_match_data an7581_pcs_pon = { ++ .port_type = AIROHA_PCS_PON, ++ .bringup = an7581_pcs_bringup, ++ .link_up = an7581_pcs_phya_link_up, ++}; ++ ++static const struct of_device_id airoha_pcs_of_table[] = { ++ { .compatible = "airoha,an7581-pcs-eth", .data = &an7581_pcs_eth }, ++ { .compatible = "airoha,an7581-pcs-pon", .data = &an7581_pcs_pon }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, airoha_pcs_of_table); ++ ++static struct platform_driver airoha_pcs_driver = { ++ .driver = { ++ .name = "airoha-pcs", ++ .of_match_table = airoha_pcs_of_table, ++ }, ++ .probe = airoha_pcs_probe, ++}; ++module_platform_driver(airoha_pcs_driver); ++ ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("Airoha PCS driver"); ++MODULE_AUTHOR("Christian Marangi "); +--- /dev/null ++++ b/drivers/net/pcs/airoha/pcs-airoha.h +@@ -0,0 +1,822 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2024 AIROHA Inc ++ * Author: Christian Marangi ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* SCU*/ ++#define AIROHA_SCU_PDIDR 0x5c ++#define AIROHA_SCU_PRODUCT_ID GENMASK(15, 0) ++#define AIROHA_SCU_WAN_CONF 0x70 ++#define AIROHA_SCU_WAN_SEL GENMASK(7, 0) ++#define AIROHA_SCU_WAN_SEL_SGMII FIELD_PREP_CONST(AIROHA_SCU_WAN_SEL, 0x10) ++#define AIROHA_SCU_WAN_SEL_HSGMII FIELD_PREP_CONST(AIROHA_SCU_WAN_SEL, 0x11) ++#define AIROHA_SCU_WAN_SEL_USXGMII FIELD_PREP_CONST(AIROHA_SCU_WAN_SEL, 0x12) ++#define AIROHA_SCU_SSR3 0x94 ++#define AIROHA_SCU_ETH_XSI_SEL GENMASK(14, 13) ++#define AIROHA_SCU_ETH_XSI_USXGMII FIELD_PREP_CONST(AIROHA_SCU_ETH_XSI_SEL, 0x1) ++#define AIROHA_SCU_ETH_XSI_HSGMII FIELD_PREP_CONST(AIROHA_SCU_ETH_XSI_SEL, 0x2) ++#define AIROHA_SCU_SSTR 0x9c ++#define AIROHA_SCU_PON_XSI_SEL GENMASK(10, 9) ++#define AIROHA_SCU_PON_XSI_USXGMII FIELD_PREP_CONST(AIROHA_SCU_PON_XSI_SEL, 0x1) ++#define AIROHA_SCU_PON_XSI_HSGMII FIELD_PREP_CONST(AIROHA_SCU_PON_XSI_SEL, 0x2) ++ ++/* XFI_MAC */ ++#define AIROHA_PCS_XFI_MAC_XFI_GIB_CFG 0x0 ++#define AIROHA_PCS_XFI_RX_FRAG_LEN GENMASK(26, 22) ++#define AIROHA_PCS_XFI_TX_FRAG_LEN GENMASK(21, 17) ++#define AIROHA_PCS_XFI_IPG_NUM GENMASK(15, 10) ++#define AIROHA_PCS_XFI_TX_FC_EN BIT(5) ++#define AIROHA_PCS_XFI_RX_FC_EN BIT(4) ++#define AIROHA_PCS_XFI_RXMPI_STOP BIT(3) ++#define AIROHA_PCS_XFI_RXMBI_STOP BIT(2) ++#define AIROHA_PCS_XFI_TXMPI_STOP BIT(1) ++#define AIROHA_PCS_XFI_TXMBI_STOP BIT(0) ++#define AIROHA_PCS_XFI_MAC_XFI_LOGIC_RST 0x10 ++#define AIROHA_PCS_XFI_MAC_LOGIC_RST BIT(0) ++#define AIROHA_PCS_XFI_MAC_XFI_MACADDRH 0x60 ++#define AIROHA_PCS_XFI_MAC_MACADDRH GENMASK(15, 0) ++#define AIROHA_PCS_XFI_MAC_XFI_MACADDRL 0x64 ++#define AIROHA_PCS_XFI_MAC_MACADDRL GENMASK(31, 0) ++#define AIROHA_PCS_XFI_MAC_XFI_CNT_CLR 0x100 ++#define AIROHA_PCS_XFI_GLB_CNT_CLR BIT(0) ++ ++/* HSGMII_AN */ ++#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_0 0x0 ++#define AIROHA_PCS_HSGMII_AN_SGMII_RA_ENABLE BIT(12) ++#define AIROHA_PCS_HSGMII_AN_SGMII_AN_RESTART BIT(9) ++#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_1 0x4 /* BMSR */ ++#define AIROHA_PCS_HSGMII_AN_SGMII_UNIDIR_ABILITY BIT(6) ++#define AIROHA_PCS_HSGMII_AN_SGMII_AN_COMPLETE BIT(5) ++#define AIROHA_PCS_HSGMII_AN_SGMII_REMOTE_FAULT BIT(4) ++#define AIROHA_PCS_HSGMII_AN_SGMII_AN_ABILITY BIT(3) ++#define AIROHA_PCS_HSGMII_AN_SGMII_LINK_STATUS BIT(2) ++#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_4 0x10 ++#define AIROHA_PCS_HSGMII_AN_SGMII_DEV_ABILITY GENMASK(15, 0) ++#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_5 0x14 /* LPA */ ++#define AIROHA_PCS_HSGMII_AN_SGMII_PARTNER_ABILITY GENMASK(15, 0) ++#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_11 0x2c ++#define AIROHA_PCS_HSGMII_AN_SGMII_LINK_TIMER GENMASK(19, 0) ++#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_13 0x34 ++#define AIROHA_PCS_HSGMII_AN_SGMII_REMOTE_FAULT_DIS BIT(8) ++#define AIROHA_PCS_HSGMII_AN_SGMII_IF_MODE_5_0 GENMASK(5, 0) ++#define AIROHA_PCS_HSGMII_AN_SGMII_COMPAT_EN BIT(5) ++#define AIROHA_PCS_HSGMII_AN_DUPLEX_FORCE_MODE BIT(4) ++#define AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE GENMASK(3, 2) ++#define AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE_1000 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE, 0x2) ++#define AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE_100 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE, 0x1) ++#define AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE_10 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_AN_SPEED_FORCE_MODE, 0x0) ++#define AIROHA_PCS_HSGMII_AN_SIDEBAND_EN BIT(1) ++#define AIROHA_PCS_HSGMII_AN_SGMII_EN BIT(0) ++#define AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_FORCE_CL37 0x60 ++#define AIROHA_PCS_HSGMII_AN_FORCE_AN_DONE BIT(0) ++ ++/* HSGMII_PCS */ ++#define AIROHA_PCS_HSGMII_PCS_CTROL_1 0x0 ++#define AIROHA_PCS_TBI_10B_MODE BIT(30) ++#define AIROHA_PCS_SGMII_SEND_AN_ERR_EN BIT(24) ++#define AIROHA_PCS_REMOTE_FAULT_DIS BIT(12) ++#define AIROHA_PCS_HSGMII_PCS_CTROL_3 0x8 ++#define AIROHA_PCS_HSGMII_PCS_LINK_STSTIME GENMASK(19, 0) ++#define AIROHA_PCS_HSGMII_PCS_CTROL_6 0x14 ++#define AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_10 BIT(14) ++#define AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_100 BIT(13) ++#define AIROHA_PCS_HSGMII_PCS_SGMII_SPD_FORCE_1000 BIT(12) ++#define AIROHA_PCS_HSGMII_PCS_MAC_MODE BIT(8) ++#define AIROHA_PCS_HSGMII_PCS_TX_ENABLE BIT(4) ++#define AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL GENMASK(3, 2) ++#define AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL_1000 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL, 0x0) ++#define AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL_100 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL, 0x1) ++#define AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL_10 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT_VAL, 0x2) ++#define AIROHA_PCS_HSGMII_PCS_FORCE_RATEADAPT BIT(1) ++#define AIROHA_PCS_HSGMII_PCS_MODE2_EN BIT(0) ++#define AIROHA_PCS_HSGMII_PCS_HSGMII_MODE_INTERRUPT 0x20 ++#define AIROHA_PCS_HSGMII_MODE2_REMOVE_FAULT_OCCUR_INT_CLEAR BIT(11) ++#define AIROHA_PCS_HSGMII_MODE2_REMOVE_FAULT_OCCUR_INT BIT(10) ++#define AIROHA_PCS_HSGMII_MODE2_AN_CL37_TIMERDONE_INT_CLEAR BIT(9) ++#define AIROHA_PCS_HSGMII_MODE2_AN_CL37_TIMERDONE_INT BIT(8) ++#define AIROHA_PCS_HSGMII_MODE2_AN_MIS_INT_CLEAR BIT(5) ++#define AIROHA_PCS_HSGMII_MODE2_AN_MIS_INT BIT(4) ++#define AIROHA_PCS_HSGMII_MODE2_RX_SYN_DONE_INT_CLEAR BIT(3) ++#define AIROHA_PCS_HSGMII_MODE2_AN_DONE_INT_CLEAR BIT(2) ++#define AIROHA_PCS_HSGMII_MODE2_RX_SYN_DONE_INT BIT(1) ++#define AIROHA_PCS_HSGMII_MODE2_AN_DONE_INT BIT(0) ++#define AIROHA_PCS_HSGMII_PCS_AN_SGMII_MODE_FORCE 0x24 ++#define AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE GENMASK(5, 4) ++#define AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_1000 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE, 0x0) ++#define AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_100 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE, 0x1) ++#define AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_10 FIELD_PREP_CONST(AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE, 0x2) ++#define AIROHA_PCS_HSGMII_PCS_FORCE_CUR_SGMII_MODE_SEL BIT(0) ++#define ARIOHA_PCS_HSGMII_PCS_STATE_2 0x104 ++#define AIROHA_PCS_HSGMII_PCS_RX_SYNC BIT(5) ++#define AIROHA_PCS_HSGMII_PCS_AN_DONE BIT(0) ++#define AIROHA_PCS_HSGMII_PCS_INT_STATE 0x15c ++#define AIROHA_PCS_HSGMII_PCS_MODE2_REMOTE_FAULT_OCCUR_INT BIT(4) ++#define AIROHA_PCS_HSGMII_PCS_MODE2_AN_MLS BIT(3) ++#define AIROHA_PCS_HSGMII_PCS_MODE2_AN_CL37_TIMERDONE_INT BIT(2) ++#define AIROHA_PCS_HSGMII_PCS_MODE2_RX_SYNC BIT(1) ++#define AIROHA_PCS_HSGMII_PCS_MODE2_AN_DONE BIT(0) ++ ++/* MULTI_SGMII */ ++#define AIROHA_PCS_MULTI_SGMII_INTERRUPT_EN_0 0x14 ++#define AIROHA_PCS_MULTI_SGMII_PCS_INT_EN_0 BIT(0) ++#define AIROHA_PCS_MULTI_SGMII_SGMII_STS_CTRL_0 0x18 ++#define AIROHA_PCS_LINK_MODE_P0 GENMASK(5, 4) ++#define AIROHA_PCS_LINK_MODE_P0_2_5G FIELD_PREP_CONST(AIROHA_PCS_LINK_MODE_P0, 0x3) ++#define AIROHA_PCS_LINK_MODE_P0_1G FIELD_PREP_CONST(AIROHA_PCS_LINK_MODE_P0, 0x2) ++#define AIROHA_PCS_LINK_MODE_P0_100M FIELD_PREP_CONST(AIROHA_PCS_LINK_MODE_P0, 0x1) ++#define AIROHA_PCS_LINK_MODE_P0_10M FIELD_PREP_CONST(AIROHA_PCS_LINK_MODE_P0, 0x0) ++#define AIROHA_PCS_FORCE_SPD_MODE_P0 BIT(2) ++#define AIROHA_PCS_FORCE_LINKDOWN_P0 BIT(1) ++#define AIROHA_PCS_FORCE_LINKUP_P0 BIT(0) ++#define AIROHA_PCS_MULTI_SGMII_MSG_RX_CTRL_0 0x100 ++#define AIROHA_PCS_HSGMII_XFI_SEL BIT(28) ++#define AIROHA_PCS_MULTI_SGMII_INTERRUPT_SEL 0x14c ++#define AIROHA_PCS_HSGMII_PCS_INT BIT(0) ++#define AIROHA_PCS_MULTI_SGMII_MSG_RX_STS_15 0x43c ++#define AIROHA_PCS_LINK_STS_P0 BIT(3) ++#define AIROHA_PCS_SPEED_STS_P0 GENMASK(2, 0) ++#define AIROHA_PCS_SPEED_STS_P0_1G FIELD_PREP_CONST(AIROHA_PCS_SPEED_STS_P0, 0x2) ++#define AIROHA_PCS_SPEED_STS_P0_100M FIELD_PREP_CONST(AIROHA_PCS_SPEED_STS_P0, 0x1) ++#define AIROHA_PCS_SPEED_STS_P0_10M FIELD_PREP_CONST(AIROHA_PCS_SPEED_STS_P0, 0x0) ++#define AIROHA_PCS_MULTI_SGMII_MSG_RX_STS_18 0x448 ++#define AIROHA_PCS_P0_SGMII_IS_10 BIT(2) ++#define AIROHA_PCS_P0_SGMII_IS_100 BIT(1) ++#define AIROHA_PCS_P0_SGMII_IS_1000 BIT(0) ++ ++/* HSGMII_RATE_ADP */ ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_0 0x0 ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_RX_BYPASS BIT(27) ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_TX_BYPASS BIT(26) ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_RX_EN BIT(4) ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_TX_EN BIT(0) ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_1 0x4 ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_WR_THR GENMASK(20, 16) ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_RD_THR GENMASK(28, 24) ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_6 0x18 ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_DOUT_L GENMASK(31, 0) ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_8 0x20 ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_RX_AFIFO_DOUT_C GENMASK(7, 0) ++#define AIROHA_PCS_HSGMII_RATE_ADAPT_CTRL_11 0x2c ++#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_EN BIT(8) ++#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE GENMASK(15, 12) ++#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_10000 \ ++ FIELD_PREP_CONST(AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE, 0x0) ++#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_5000 \ ++ FIELD_PREP_CONST(AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE, 0x1) ++#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_2500 \ ++ FIELD_PREP_CONST(AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE, 0x2) ++#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_1000 \ ++ FIELD_PREP_CONST(AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE, 0x4) ++#define AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE_100 \ ++ FIELD_PREP_CONST(AIROHA_PCS_HSGMII_RATE_ADPT_FORCE_RATE_ADAPT_MODE, 0x6) ++#define AIROHA_PCS_HSGMII_RATE_ADP_P0_CTRL_0 0x100 ++#define AIROHA_PCS_HSGMII_P0_DIS_MII_MODE BIT(31) ++ ++/* USXGMII */ ++#define AIROHA_PCS_USXGMII_PCS_CTROL_1 0x0 ++#define AIROHA_PCS_USXGMII_SPEED_SEL_H BIT(13) ++#define AIROHA_PCS_USXGMII_PCS_STUS_1 0x4 ++#define AIROHA_PCS_USXGMII_PCS_RX_LINK_STATUS BIT(2) ++#define AIROHA_PCS_USXGMII_PCS_RX_LINK_STATUS_UP \ ++ FIELD_PREP_CONST(AIROHA_PCS_USXGMII_PCS_RX_LINK_STATUS, 0x1) ++#define AIROHA_PCS_USXGMII_PCS_RX_LINK_STATUS_DOWN \ ++ FIELD_PREP_CONST(AIROHA_PCS_USXGMII_PCS_RX_LINK_STATUS, 0x0) ++#define AIROHA_PCS_USXGMII_BASE_R_10GB_T_PCS_STUS_1 0x30 ++#define AIROHA_PCS_USXGMII_RX_LINK_STUS BIT(12) ++#define AIROHA_PCS_USXGMII_PRBS9_PATT_TST_ABILITY BIT(3) ++#define AIROHA_PCS_USXGMII_PRBS31_PATT_TST_ABILITY BIT(2) ++#define AIROHA_PCS_USXGMII_PCS_BLK_LK BIT(0) ++#define AIROHA_PCS_USGMII_VENDOR_DEFINE_116 0x22c ++#define AIROHA_PCS_USXGMII_PCS_CTRL_0 0x2c0 ++#define AIROHA_PCS_USXGMII_T_TYPE_T_INT_EN BIT(24) ++#define AIROHA_PCS_USXGMII_T_TYPE_D_INT_EN BIT(16) ++#define AIROHA_PCS_USXGMII_T_TYPE_C_INT_EN BIT(8) ++#define AIROHA_PCS_USXGMII_T_TYPE_S_INT_EN BIT(0) ++#define AIROHA_PCS_USXGMII_PCS_CTRL_1 0x2c4 ++#define AIROHA_PCS_USXGMII_R_TYPE_C_INT_EN BIT(24) ++#define AIROHA_PCS_USXGMII_R_TYPE_S_INT_EN BIT(16) ++#define AIROHA_PCS_USXGMII_TXPCS_FSM_ENC_ERR_INT_EN BIT(8) ++#define AIROHA_PCS_USXGMII_T_TYPE_E_INT_EN BIT(0) ++#define AIROHA_PCS_USXGMII_PCS_CTRL_2 0x2c8 ++#define AIROHA_PCS_USXGMII_RPCS_FSM_DEC_ERR_INT_EN BIT(24) ++#define AIROHA_PCS_USXGMII_R_TYPE_E_INT_EN BIT(16) ++#define AIROHA_PCS_USXGMII_R_TYPE_T_INT_EN BIT(8) ++#define AIROHA_PCS_USXGMII_R_TYPE_D_INT_EN BIT(0) ++#define AIROHA_PCS_USXGMII_PCS_CTRL_3 0x2cc ++#define AIROHA_PCS_USXGMII_FAIL_SYNC_XOR_ST_INT_EN BIT(24) ++#define AIROHA_PCS_USXGMII_RX_BLOCK_LOCK_ST_INT_EN BIT(16) ++#define AIROHA_PCS_USXGMII_LINK_UP_ST_INT_EN BIT(8) ++#define AIROHA_PCS_USXGMII_HI_BER_ST_INT_EN BIT(0) ++#define AIROHA_PCS_USXGMII_PCS_INT_STA_2 0x2d8 ++#define AIROHA_PCS_USXGMII_RPCS_FSM_DEC_ERR_INT BIT(24) ++#define AIROHA_PCS_USXGMII_R_TYPE_E_INT BIT(16) ++#define AIROHA_PCS_USXGMII_R_TYPE_T_INT BIT(8) ++#define AIROHA_PCS_USXGMII_R_TYPE_D_INT BIT(0) ++#define AIROHA_PCS_USXGMII_PCS_INT_STA_3 0x2dc ++#define AIROHA_PCS_USXGMII_FAIL_SYNC_XOR_ST_INT BIT(24) ++#define AIROHA_PCS_USXGMII_RX_BLOCK_LOCK_ST_INT BIT(16) ++#define AIROHA_PCS_USXGMII_LINK_UP_ST_INT BIT(8) ++#define AIROHA_PCS_USXGMII_HI_BER_ST_INT BIT(0) ++#define AIROHA_PCS_USXGMII_PCS_CTRL_4 0x2e0 ++#define AIROHA_PCS_USXGMII_LINK_DOWN_ST_INT_EN BIT(0) ++#define AIROHA_PCS_USXGMII_PCS_INT_STA_4 0x2e4 ++#define AIROHA_PCS_USXGMII_LINK_DOWN_ST_INT BIT(0) ++#define AIROHA_PCS_USXGMII_PCS_AN_CONTROL_0 0x2f8 ++#define AIROHA_PCS_USXGMII_AN_RESTART BIT(8) ++#define AIROHA_PCS_USXGMII_AN_ENABLE BIT(0) ++#define AIROHA_PCS_USXGMII_PCS_AN_STATS_0 0x310 ++#define AIROHA_PCS_USXGMII_CUR_USXGMII_MODE GENMASK(30, 28) ++#define AIROHA_PCS_USXGMII_CUR_USXGMII_MODE_10G FIELD_PREP_CONST(AIROHA_PCS_USXGMII_CUR_USXGMII_MODE, 0x0) ++#define AIROHA_PCS_USXGMII_CUR_USXGMII_MODE_5G FIELD_PREP_CONST(AIROHA_PCS_USXGMII_CUR_USXGMII_MODE, 0x1) ++#define AIROHA_PCS_USXGMII_CUR_USXGMII_MODE_2_5G FIELD_PREP_CONST(AIROHA_PCS_USXGMII_CUR_USXGMII_MODE, 0x2) ++#define AIROHA_PCS_USXGMII_CUR_USXGMII_MODE_1G FIELD_PREP_CONST(AIROHA_PCS_USXGMII_CUR_USXGMII_MODE, 0x3) ++#define AIROHA_PCS_USXGMII_CUR_USXGMII_MODE_100M FIELD_PREP_CONST(AIROHA_PCS_USXGMII_CUR_USXGMII_MODE, 0x4) ++#define AIROHA_PCS_USXGMII_PARTNER_ABILITY GENMASK(15, 0) ++#define AIROHA_PCS_USXGMII_PCS_AN_STATS_2 0x318 ++#define AIROHA_PCS_USXGMII_PCS_AN_COMPLETE BIT(24) ++#define AIROHA_PCS_USXGMII_PCS_AN_CONTROL_6 0x31c ++#define AIROHA_PCS_USXGMII_TOG_PCS_AUTONEG_STS BIT(0) ++#define AIROHA_PCS_USXGMII_PCS_AN_CONTROL_7 0x320 ++#define AIROHA_PCS_USXGMII_RATE_UPDATE_MODE BIT(12) ++#define AIROHA_PCS_USXGMII_MODE GENMASK(10, 8) ++#define AIROHA_PCS_USXGMII_MODE_10000 FIELD_PREP_CONST(AIROHA_PCS_USXGMII_MODE, 0x0) ++#define AIROHA_PCS_USXGMII_MODE_5000 FIELD_PREP_CONST(AIROHA_PCS_USXGMII_MODE, 0x1) ++#define AIROHA_PCS_USXGMII_MODE_2500 FIELD_PREP_CONST(AIROHA_PCS_USXGMII_MODE, 0x2) ++#define AIROHA_PCS_USXGMII_MODE_1000 FIELD_PREP_CONST(AIROHA_PCS_USXGMII_MODE, 0x3) ++#define AIROHA_PCS_USXGMII_MODE_100 FIELD_PREP_CONST(AIROHA_PCS_USXGMII_MODE, 0x4) ++ ++/* PMA_PHYA */ ++#define AIROHA_PCS_ANA_PXP_CMN_EN 0x0 ++#define AIROHA_PCS_ANA_CMN_EN BIT(0) ++#define AIROHA_PCS_ANA_PXP_JCPLL_IB_EXT_EN 0x4 ++#define AIROHA_PCS_ANA_JCPLL_CHP_IOFST GENMASK(29, 24) ++#define AIROHA_PCS_ANA_JCPLL_CHP_IBIAS GENMASK(21, 16) ++#define AIROHA_PCS_ANA_JCPLL_LPF_SHCK_EN BIT(8) ++#define AIROHA_PCS_ANA_PXP_JCPLL_LPF_BR 0x8 ++#define AIROHA_PCS_ANA_JCPLL_LPF_BWR GENMASK(28, 24) ++#define AIROHA_PCS_ANA_JCPLL_LPF_BP GENMASK(20, 16) ++#define AIROHA_PCS_ANA_JCPLL_LPF_BC GENMASK(12, 8) ++#define AIROHA_PCS_ANA_JCPLL_LPF_BR GENMASK(4, 0) ++#define AIROHA_PCS_ANA_PXP_JCPLL_LPF_BWC 0xc ++#define AIROHA_PCS_ANA_JCPLL_KBAND_DIV GENMASK(26, 24) ++#define AIROHA_PCS_ANA_JCPLL_KBAND_CODE GENMASK(23, 16) ++#define AIROHA_PCS_ANA_JCPLL_KBAND_OPTION BIT(8) ++#define AIROHA_PCS_ANA_JCPLL_LPF_BWC GENMASK(4, 0) ++#define AIROHA_PCS_ANA_PXP_JCPLL_KBAND_KFC 0x10 ++#define AIROHA_PCS_ANA_JCPLL_KBAND_KS GENMASK(17, 16) ++#define AIROHA_PCS_ANA_JCPLL_KBAND_KF GENMASK(9, 8) ++#define AIROHA_PCS_ANA_JCPLL_KBAND_KFC GENMASK(1, 0) ++#define AIROHA_PCS_ANA_PXP_JCPLL_MMD_PREDIV_MODE 0x14 ++#define AIROHA_PCS_ANA_JCPLL_POSTDIV_D5 BIT(24) ++#define AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE GENMASK(1, 0) ++#define AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE, 0x0) ++#define AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE_3 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE, 0x1) ++#define AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE, 0x2) ++#define AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE, 0x3) ++#define AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY 0x1c ++#define AIROHA_PCS_ANA_JCPLL_SDM_DI_LS GENMASK(25, 24) ++#define AIROHA_PCS_ANA_JCPLL_SDM_DI_LS_2_23 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_DI_LS, 0x0) ++#define AIROHA_PCS_ANA_JCPLL_SDM_DI_LS_2_21 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_DI_LS, 0x1) ++#define AIROHA_PCS_ANA_JCPLL_SDM_DI_LS_2_19 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_DI_LS, 0x2) ++#define AIROHA_PCS_ANA_JCPLL_SDM_DI_LS_2_15 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_DI_LS, 0x3) ++#define AIROHA_PCS_ANA_JCPLL_SDM_DI_EN BIT(16) ++#define AIROHA_PCS_ANA_JCPLL_PLL_RSTB BIT(8) ++#define AIROHA_PCS_ANA_JCPLL_RST_DLY GENMASK(2, 0) ++#define AIROHA_PCS_ANA_JCPLL_RST_DLY_20_25 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_RST_DLY, 0x1) ++#define AIROHA_PCS_ANA_JCPLL_RST_DLY_40_50 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_RST_DLY, 0x2) ++#define AIROHA_PCS_ANA_JCPLL_RST_DLY_80_100 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_RST_DLY, 0x3) ++#define AIROHA_PCS_ANA_JCPLL_RST_DLY_150_200 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_RST_DLY, 0x4) ++#define AIROHA_PCS_ANA_JCPLL_RST_DLY_300_400 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_RST_DLY, 0x5) ++#define AIROHA_PCS_ANA_JCPLL_RST_DLY_600_800 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_RST_DLY, 0x6) ++#define AIROHA_PCS_ANA_PXP_JCPLL_SDM_IFM 0x20 ++#define AIROHA_PCS_ANA_JCPLL_SDM_OUT BIT(24) ++#define AIROHA_PCS_ANA_JCPLL_SDM_ORD GENMASK(17, 16) ++#define AIROHA_PCS_ANA_JCPLL_SDM_ORD_INT FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_ORD, 0x0) ++#define AIROHA_PCS_ANA_JCPLL_SDM_ORD_1SDM FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_ORD, 0x1) ++#define AIROHA_PCS_ANA_JCPLL_SDM_ORD_2SDM FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_ORD, 0x2) ++#define AIROHA_PCS_ANA_JCPLL_SDM_ORD_3SDM FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SDM_ORD, 0x3) ++#define AIROHA_PCS_ANA_JCPLL_SDM_MODE GENMASK(9, 8) ++#define AIROHA_PCS_ANA_JCPLL_SDM_IFM BIT(0) ++#define AIROHA_PCS_ANA_PXP_JCPLL_SDM_HREN 0x24 ++#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_VREF GENMASK(28, 24) ++#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN GENMASK(18, 16) ++#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN, 0x0) ++#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN, 0x1) ++#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN_6 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN, 0x2) ++#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN_8 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN, 0x3) ++#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN_10 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN, 0x4) ++#define AIROHA_PCS_ANA_JCPLL_TCL_AMP_EN BIT(8) ++#define AIROHA_PCS_ANA_JCPLL_SDM_HREN BIT(0) ++#define AIROHA_PCS_ANA_PXP_JCPLL_TCL_CMP_EN 0x28 ++#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW GENMASK(26, 24) ++#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_0_5 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW, 0x0) ++#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW, 0x1) ++#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW, 0x2) ++#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW, 0x3) ++#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_8 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW, 0x4) ++#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_16 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW, 0x6) ++#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_EN BIT(16) ++#define AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW GENMASK(26, 24) ++#define AIROHA_PCS_ANA_PXP_JCPLL_VCODIV 0x2c ++#define AIROHA_PCS_ANA_JCPLL_VCO_SCAPWR GENMASK(26, 24) ++#define AIROHA_PCS_ANA_JCPLL_VCO_HALFLSB_EN BIT(16) ++#define AIROHA_PCS_ANA_JCPLL_VCO_CFIX GENMASK(9, 8) ++#define AIROHA_PCS_ANA_JCPLL_VCODIV GENMASK(1, 0) ++#define AIROHA_PCS_ANA_JCPLL_VCODIV_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_VCODIV, 0x0) ++#define AIROHA_PCS_ANA_JCPLL_VCODIV_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_VCODIV, 0x1) ++#define AIROHA_PCS_ANA_PXP_JCPLL_VCO_TCLVAR 0x30 ++#define AIROHA_PCS_ANA_JCPLL_SSC_PHASE_INI BIT(17) ++#define AIROHA_PCS_ANA_JCPLL_SSC_EN BIT(16) ++#define AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_L GENMASK(10, 8) ++#define AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_H GENMASK(5, 3) ++#define AIROHA_PCS_ANA_JCPLL_VCO_TCLVAR GENMASK(2, 0) ++#define AIROHA_PCS_ANA_PXP_JCPLL_SSC_TRI_EN 0x34 ++#define AIROHA_PCS_ANA_JCPLL_SSC_DELTA1 GENMASK(23, 8) ++#define AIROHA_PCS_ANA_JCPLL_SSC_TRI_EN BIT(0) ++#define AIROHA_PCS_ANA_PXP_JCPLL_SSC_DELTA 0x38 ++#define AIROHA_PCS_ANA_JCPLL_SSC_PERIOD GENMASK(31, 16) ++#define AIROHA_PCS_ANA_JCPLL_SSC_DELTA GENMASK(15, 0) ++#define AIROHA_PCS_ANA_PXP_JCPLL_SPARE_H 0x48 ++#define AIROHA_PCS_ANA_JCPLL_TCL_KBAND_VREF GENMASK(20, 16) ++#define AIROHA_PCS_ANA_JCPLL_SPARE_L GENMASK(15, 8) ++#define AIROHA_PCS_ANA_JCPLL_SPARE_L_LDO FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SPARE_L, BIT(5)) ++#define AIROHA_PCS_ANA_PXP_TXPLL_CHP_IBIAS 0x50 ++#define AIROHA_PCS_ANA_TXPLL_LPF_BC GENMASK(28, 24) ++#define AIROHA_PCS_ANA_TXPLL_LPF_BR GENMASK(20, 16) ++#define AIROHA_PCS_ANA_TXPLL_CHP_IOFST GENMASK(13, 8) ++#define AIROHA_PCS_ANA_TXPLL_CHP_IBIAS GENMASK(5, 0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_LPF_BP 0x54 ++#define AIROHA_PCS_ANA_TXPLL_KBAND_OPTION BIT(24) ++#define AIROHA_PCS_ANA_TXPLL_LPF_BWC GENMASK(20, 16) ++#define AIROHA_PCS_ANA_TXPLL_LPF_BWR GENMASK(12, 8) ++#define AIROHA_PCS_ANA_TXPLL_LPF_BP GENMASK(4, 0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_KBAND_CODE 0x58 ++#define AIROHA_PCS_ANA_TXPLL_KBAND_KF GENMASK(25, 24) ++#define AIROHA_PCS_ANA_TXPLL_KBAND_KFC GENMASK(17, 16) ++#define AIROHA_PCS_ANA_TXPLL_KBAND_DIV GENMASK(10, 8) ++#define AIROHA_PCS_ANA_TXPLL_KBAND_CODE GENMASK(7, 0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_KBAND_KS 0x5c ++#define AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE GENMASK(17, 16) ++#define AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE, 0x0) ++#define AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE_3 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE, 0x1) ++#define AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE, 0x2) ++#define AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE, 0x3) ++#define AIROHA_PCS_ANA_TXPLL_POSTDIV_EN BIT(8) ++#define AIROHA_PCS_ANA_TXPLL_KBAND_KS GENMASK(1, 0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_REFIN_INTERNAL 0x64 ++#define AIROHA_PCS_ANA_TXPLL_PLL_RSTB BIT(24) ++#define AIROHA_PCS_ANA_TXPLL_RST_DLY GENMASK(18, 16) ++#define AIROHA_PCS_ANA_TXPLL_REFIN_DIV GENMASK(9, 8) ++#define AIROHA_PCS_ANA_TXPLL_REFIN_DIV_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_REFIN_DIV, 0x0) ++#define AIROHA_PCS_ANA_TXPLL_REFIN_DIV_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_REFIN_DIV, 0x1) ++#define AIROHA_PCS_ANA_TXPLL_REFIN_DIV_3 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_REFIN_DIV, 0x2) ++#define AIROHA_PCS_ANA_TXPLL_REFIN_DIV_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_REFIN_DIV, 0x3) ++#define AIROHA_PCS_ANA_TXPLL_REFIN_INTERNAL BIT(0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_SDM_DI_EN 0x68 ++#define AIROHA_PCS_ANA_TXPLL_SDM_MODE GENMASK(25, 24) ++#define AIROHA_PCS_ANA_TXPLL_SDM_IFM BIT(16) ++#define AIROHA_PCS_ANA_TXPLL_SDM_DI_LS GENMASK(9, 8) ++#define AIROHA_PCS_ANA_TXPLL_SDM_DI_LS_2_23 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_DI_LS, 0x0) ++#define AIROHA_PCS_ANA_TXPLL_SDM_DI_LS_2_21 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_DI_LS, 0x1) ++#define AIROHA_PCS_ANA_TXPLL_SDM_DI_LS_2_19 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_DI_LS, 0x2) ++#define AIROHA_PCS_ANA_TXPLL_SDM_DI_LS_2_15 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_DI_LS, 0x3) ++#define AIROHA_PCS_ANA_TXPLL_SDM_DI_EN BIT(0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_SDM_ORD 0x6c ++#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_EN BIT(24) ++#define AIROHA_PCS_ANA_TXPLL_SDM_HREN BIT(16) ++#define AIROHA_PCS_ANA_TXPLL_SDM_OUT BIT(8) ++#define AIROHA_PCS_ANA_TXPLL_SDM_ORD GENMASK(1, 0) ++#define AIROHA_PCS_ANA_TXPLL_SDM_ORD_INT FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_ORD, 0x0) ++#define AIROHA_PCS_ANA_TXPLL_SDM_ORD_1SDM FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_ORD, 0x1) ++#define AIROHA_PCS_ANA_TXPLL_SDM_ORD_2SDM FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_ORD, 0x2) ++#define AIROHA_PCS_ANA_TXPLL_SDM_ORD_3SDM FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_SDM_ORD, 0x3) ++#define AIROHA_PCS_ANA_PXP_TXPLL_TCL_AMP_GAIN 0x70 ++#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_VREF GENMASK(12, 8) ++#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN GENMASK(2, 0) ++#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN, 0x0) ++#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN_2_5 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN, 0x1) ++#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN_3 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN, 0x2) ++#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN, 0x3) ++#define AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN_6 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN, 0x4) ++#define AIROHA_PCS_ANA_PXP_TXPLL_TCL_LPF_EN 0x74 ++#define AIROHA_PCS_ANA_TXPLL_VCO_CFIX GENMASK(25, 24) ++#define AIROHA_PCS_ANA_TXPLL_VCODIV GENMASK(17, 16) ++#define AIROHA_PCS_ANA_TXPLL_VCODIV_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_VCODIV, 0x0) ++#define AIROHA_PCS_ANA_TXPLL_VCODIV_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_VCODIV, 0x1) ++#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW GENMASK(10, 8) ++#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_0_5 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW, 0x0) ++#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW, 0x1) ++#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW, 0x2) ++#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW, 0x3) ++#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_8 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW, 0x4) ++#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_16 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW, 0x6) ++#define AIROHA_PCS_ANA_TXPLL_TCL_LPF_EN BIT(0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_VCO_HALFLSB_EN 0x78 ++#define AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_L GENMASK(29, 27) ++#define AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_H GENMASK(26, 24) ++#define AIROHA_PCS_ANA_TXPLL_VCO_TCLVAR GENMASK(18, 16) ++#define AIROHA_PCS_ANA_TXPLL_VCO_SCAPWR GENMASK(10, 8) ++#define AIROHA_PCS_ANA_TXPLL_VCO_HALFLSB_EN BIT(0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_SSC_EN 0x7c ++#define AIROHA_PCS_ANA_TXPLL_SSC_TRI_EN BIT(16) ++#define AIROHA_PCS_ANA_TXPLL_SSC_PHASE_INI BIT(8) ++#define AIROHA_PCS_ANA_TXPLL_SSC_EN BIT(0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_SSC_DELTA1 0x80 ++#define AIROHA_PCS_ANA_TXPLL_SSC_DELTA GENMASK(31, 16) ++#define AIROHA_PCS_ANA_TXPLL_SSC_DELTA1 GENMASK(15, 0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_SSC_PERIOD 0x84 ++#define AIROHA_PCS_ANA_TXPLL_LDO_VCO_OUT GENMASK(25, 24) ++#define AIROHA_PCS_ANA_TXPLL_LDO_OUT GENMASK(17, 16) ++#define AIROHA_PCS_ANA_TXPLL_SSC_PERIOD GENMASK(15, 0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_TCL_KBAND_VREF 0x94 ++#define AIROHA_PCS_ANA_TXPLL_TCL_KBAND_VREF GENMASK(4, 0) ++#define AIROHA_PCS_ANA_PXP_TX_CKLDO_EN 0xc4 ++#define AIROHA_PCS_ANA_TX_DMEDGEGEN_EN BIT(24) ++#define AIROHA_PCS_ANA_TX_CKLDO_EN BIT(0) ++#define AIROHA_PCS_ANA_PXP_RX_BUSBIT_SEL 0xcc ++#define AIROHA_PCS_ANA_RX_PHY_CK_SEL_FORCE BIT(24) ++#define AIROHA_PCS_ANA_RX_PHY_CK_SEL BIT(16) ++#define AIROHA_PCS_ANA_RX_PHY_CK_SEL_FROM_PR FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_PHY_CK_SEL, 0x0) ++#define AIROHA_PCS_ANA_RX_PHY_CK_SEL_FROM_DES FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_PHY_CK_SEL, 0x1) ++#define AIROHA_PCS_ANA_PXP_RX_REV_0 0xd4 ++#define AIROHA_PCS_ANA_RX_REV_1 GENMASK(31, 16) ++#define AIROHA_PCS_ANA_REV_1_FE_EQ_BIAS_CTRL GENMASK(30, 28) ++#define AIROHA_PCS_ANA_REV_1_FE_BUF1_BIAS_CTRL GENMASK(26, 24) ++#define AIROHA_PCS_ANA_REV_1_FE_BUF2_BIAS_CTRL GENMASK(22, 20) ++#define AIROHA_PCS_ANA_REV_1_SIGDET_ILEAK GENMASK(19, 18) ++#define AIROHA_PCS_ANA_REV_1_FECUR_PWDB BIT(16) ++#define AIROHA_PCS_ANA_PXP_RX_PHYCK_DIV 0xd8 ++#define AIROHA_PCS_ANA_RX_TDC_CK_SEL BIT(24) ++#define AIROHA_PCS_ANA_RX_PHYCK_RSTB BIT(16) ++#define AIROHA_PCS_ANA_RX_PHYCK_SEL GENMASK(9, 8) ++#define AIROHA_PCS_ANA_RX_PHYCK_DIV GENMASK(7, 0) ++#define AIROHA_PCS_ANA_PXP_CDR_PD_PICAL_CKD8_INV 0xdc ++#define AIROHA_PCS_ANA_CDR_PD_EDGE_DIS BIT(8) ++#define AIROHA_PCS_ANA_CDR_PD_PICAL_CKD8_INV BIT(0) ++#define AIROHA_PCS_ANA_PXP_CDR_LPF_RATIO 0xe8 ++#define AIROHA_PCS_ANA_CDR_LPF_TOP_LIM GENMASK(26, 8) ++#define AIROHA_PCS_ANA_CDR_LPF_RATIO GENMASK(1, 0) ++#define AIROHA_PCS_ANA_PXP_CDR_PR_INJ_MODE 0xf4 ++#define AIROHA_PCS_ANA_CDR_PR_INJ_FORCE_OFF BIT(24) ++#define AIROHA_PCS_ANA_PXP_CDR_PR_BETA_DAC 0xf8 ++#define AIROHA_PCS_ANA_CDR_PR_KBAND_DIV GENMASK(26, 24) ++#define AIROHA_PCS_ANA_CDR_PR_BETA_SEL GENMASK(19, 16) ++#define AIROHA_PCS_ANA_CDR_PR_VCOADC_OS GENMASK(11, 8) ++#define AIROHA_PCS_ANA_CDR_PR_BETA_DAC GENMASK(6, 0) ++#define AIROHA_PCS_ANA_PXP_CDR_PR_VREG_IBAND_VAL 0xfc ++#define AIROHA_PCS_ANA_CDR_PR_FBKSEL GENMASK(25, 24) ++#define AIROHA_PCS_ANA_CDR_PR_DAC_BAND GENMASK(20, 16) ++#define AIROHA_PCS_ANA_CDR_PR_VREG_CKBUF_VAL GENMASK(10, 8) ++#define AIROHA_PCS_ANA_CDR_PR_VREG_IBAND_VAL GENMASK(2, 0) ++#define AIROHA_PCS_ANA_PXP_CDR_PR_MONPR_EN 0x10c ++#define AIROHA_PCS_ANA_RX_DAC_MON GENMASK(28, 24) ++#define AIROHA_PCS_ANA_CDR_PR_CAP_EN BIT(19) ++#define AIROHA_PCS_ANA_CDR_BUF_IN_SR GENMASK(18, 16) ++#define AIROHA_PCS_ANA_CDR_PR_XFICK_EN BIT(2) ++#define AIROHA_PCS_ANA_CDR_PR_MONDPI_EN BIT(1) ++#define AIROHA_PCS_ANA_CDR_PR_MONDPR_EN BIT(0) ++#define AIROHA_PCS_ANA_PXP_RX_DAC_RANGE 0x110 ++#define AIROHA_PCS_ANA_RX_SIGDET_LPF_CTRL GENMASK(25, 24) ++#define AIROHA_PCS_ANA_PXP_RX_SIGDET_NOVTH 0x114 ++#define AIROHA_PCS_ANA_RX_FE_50OHMS_SEL GENMASK(25, 24) ++#define AIROHA_PCS_ANA_RX_SIGDET_VTH_SEL GENMASK(20, 16) ++#define AIROHA_PCS_ANA_RX_SIGDET_PEAK GENMASK(9, 8) ++#define AIROHA_PCS_ANA_PXP_RX_FE_EQ_HZEN 0x118 ++#define AIROHA_PCS_ANA_RX_FE_VB_EQ3_EN BIT(24) ++#define AIROHA_PCS_ANA_RX_FE_VB_EQ2_EN BIT(16) ++#define AIROHA_PCS_ANA_RX_FE_VB_EQ1_EN BIT(8) ++#define AIROHA_PCS_ANA_RX_FE_EQ_HZEN BIT(0) ++#define AIROHA_PCS_ANA_PXP_RX_FE_VCM_GEN_PWDB 0x11c ++#define AIROHA_PCS_ANA_FE_VCM_GEN_PWDB BIT(0) ++#define AIROHA_PCS_ANA_PXP_RX_OSCAL_WATCH_WNDW 0x120 ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE GENMASK(17, 8) ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA2VOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(0)) ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA2IOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(1)) ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA1VOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(2)) ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA1IOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(3)) ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE2VOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(4)) ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE2IOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(5)) ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE1VOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(6)) ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE1IOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(7)) ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_LVSH FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(8)) ++#define AIROHA_PCS_ANA_RX_OSCAL_FORCE_COMPOS FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_OSCAL_FORCE, BIT(9)) ++#define AIROHA_PCS_ANA_PXP_AEQ_CFORCE 0x13c ++#define AIROHA_PCS_ANA_AEQ_OFORCE GENMASK(19, 8) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_SAOS FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(0)) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP1 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(1)) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP2 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(2)) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP3 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(3)) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP4 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(4)) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP5 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(5)) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP6 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(6)) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_DFETP7 FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(7)) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_VGA FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(8)) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_CTLE FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(9)) ++#define AIROHA_PCS_ANA_AEQ_OFORCE_ATT FIELD_PREP_CONST(AIROHA_PCS_ANA_AEQ_OFORCE, BIT(10)) ++#define AIROHA_PCS_ANA_PXP_RX_FE_PEAKING_CTRL_MSB 0x144 ++#define AIROHA_PCS_ANA_RX_DAC_D0_BYPASS_AEQ BIT(24) ++#define AIROHA_PCS_ANA_PXP_RX_DAC_D1_BYPASS_AEQ 0x148 ++#define AIROHA_PCS_ANA_RX_DAC_EYE_BYPASS_AEQ BIT(24) ++#define AIROHA_PCS_ANA_RX_DAC_E1_BYPASS_AEQ BIT(16) ++#define AIROHA_PCS_ANA_RX_DAC_E0_BYPASS_AEQ BIT(8) ++#define AIROHA_PCS_ANA_RX_DAC_D1_BYPASS_AEQ BIT(0) ++ ++/* PMA_PHYD */ ++#define AIROHA_PCS_PMA_SS_LCPLL_PWCTL_SETTING_0 0x0 ++#define AIROHA_PCS_PMA_SW_LCPLL_EN BIT(24) ++#define AIROHA_PCS_PMA_SS_LCPLL_PWCTL_SETTING_1 0x4 ++#define AIROHA_PCS_PMA_LCPLL_MAN_PWDB BIT(0) ++#define AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_2 0x88 ++#define AIROHA_PCS_PMA_DATA_SHIFT BIT(8) ++#define AIROHA_PCS_PMA_EYECNT_FAST BIT(0) ++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_0 0x8c ++#define AIROHA_PCS_PMA_RX_OS_START GENMASK(23, 8) ++#define AIROHA_PCS_PMA_OSC_SPEED_OPT GENMASK(2, 0) ++#define AIROHA_PCS_PMA_OSC_SPEED_OPT_0_05 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x0) ++#define AIROHA_PCS_PMA_OSC_SPEED_OPT_0_1 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x1) ++#define AIROHA_PCS_PMA_OSC_SPEED_OPT_0_2 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x2) ++#define AIROHA_PCS_PMA_OSC_SPEED_OPT_0_4 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x3) ++#define AIROHA_PCS_PMA_OSC_SPEED_OPT_0_8 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x4) ++#define AIROHA_PCS_PMA_OSC_SPEED_OPT_1_6 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x5) ++#define AIROHA_PCS_PMA_OSC_SPEED_OPT_3_2 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x6) ++#define AIROHA_PCS_PMA_OSC_SPEED_OPT_6_4 FIELD_PREP_CONST(AIROHA_PCS_PMA_OSC_SPEED_OPT, 0x7) ++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_1 0x90 ++#define AIROHA_PCS_PMA_RX_PICAL_END GENMASK(31, 16) ++#define AIROHA_PCS_PMA_RX_PICAL_START GENMASK(15, 0) ++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_2 0x94 ++#define AIROHA_PCS_PMA_RX_PDOS_END GENMASK(31, 16) ++#define AIROHA_PCS_PMA_RX_PDOS_START GENMASK(15, 0) ++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_3 0x98 ++#define AIROHA_PCS_PMA_RX_FEOS_END GENMASK(31, 16) ++#define AIROHA_PCS_PMA_RX_FEOS_START GENMASK(15, 0) ++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_4 0x9c ++#define AIROHA_PCS_PMA_RX_SDCAL_END GENMASK(31, 16) ++#define AIROHA_PCS_PMA_RX_SDCAL_START GENMASK(15, 0) ++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_5 0x100 ++#define AIROHA_PCS_PMA_RX_RDY GENMASK(31, 16) ++#define AIROHA_PCS_PMA_RX_BLWC_RDY_EN GENMASK(15, 0) ++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_6 0x104 ++#define AIROHA_PCS_PMA_RX_OS_END GENMASK(15, 0) ++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1 0x10c ++#define AIROHA_PCS_PMA_DISB_RX_RDY BIT(24) ++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1 0x114 ++#define AIROHA_PCS_PMA_FORCE_RX_RDY BIT(24) ++#define AIROHA_PCS_PMA_PHY_EQ_CTRL_2 0x120 ++#define AIROHA_PCS_PMA_EQ_DEBUG_SEL GENMASK(17, 16) ++#define AIROHA_PCS_PMA_FOM_NUM_ORDER GENMASK(12, 8) ++#define AIROHA_PCS_PMA_A_SEL GENMASK(1, 0) ++#define AIROHA_PCS_PMA_SS_RX_FREQ_DET_1 0x14c ++#define AIROHA_PCS_PMA_UNLOCK_CYCLECNT GENMASK(31, 16) ++#define AIROHA_PCS_PMA_LOCK_CYCLECNT GENMASK(15, 0) ++#define AIROHA_PCS_PMA_SS_RX_FREQ_DET_2 0x150 ++#define AIROHA_PCS_PMA_LOCK_TARGET_END GENMASK(31, 16) ++#define AIROHA_PCS_PMA_LOCK_TARGET_BEG GENMASK(15, 0) ++#define AIROHA_PCS_PMA_SS_RX_FREQ_DET_3 0x154 ++#define AIROHA_PCS_PMA_UNLOCK_TARGET_END GENMASK(31, 16) ++#define AIROHA_PCS_PMA_UNLOCK_TARGET_BEG GENMASK(15, 0) ++#define AIROHA_PCS_PMA_SS_RX_FREQ_DET_4 0x158 ++#define AIROHA_PCS_PMA_LOCK_UNLOCKTH GENMASK(15, 12) ++#define AIROHA_PCS_PMA_LOCK_LOCKTH GENMASK(11, 8) ++#define AIROHA_PCS_PMA_FREQLOCK_DET_EN GENMASK(2, 0) ++#define AIROHA_PCS_PMA_FREQLOCK_DET_EN_FORCE_0 FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x0) ++#define AIROHA_PCS_PMA_FREQLOCK_DET_EN_FORCE_1 FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x1) ++#define AIROHA_PCS_PMA_FREQLOCK_DET_EN_WAIT FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x2) ++#define AIROHA_PCS_PMA_FREQLOCK_DET_EN_NORMAL FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x3) ++#define AIROHA_PCS_PMA_FREQLOCK_DET_EN_RX_STATE FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x7) ++#define AIROHA_PCS_PMA_SS_RX_SIGDET_1 0x16c ++#define AIROHA_PCS_PMA_SIGDET_EN BIT(0) ++#define AIROHA_PCS_PMA_RX_FLL_1 0x174 ++#define AIROHA_PCS_PMA_LPATH_IDAC GENMASK(10, 0) ++#define AIROHA_PCS_PMA_RX_FLL_2 0x178 ++#define AIROHA_PCS_PMA_CK_RATE GENMASK(18, 16) ++#define AIROHA_PCS_PMA_CK_RATE_20 FIELD_PREP_CONST(AIROHA_PCS_PMA_CK_RATE, 0x0) ++#define AIROHA_PCS_PMA_CK_RATE_10 FIELD_PREP_CONST(AIROHA_PCS_PMA_CK_RATE, 0x1) ++#define AIROHA_PCS_PMA_CK_RATE_5 FIELD_PREP_CONST(AIROHA_PCS_PMA_CK_RATE, 0x2) ++#define AIROHA_PCS_PMA_RX_FLL_5 0x184 ++#define AIROHA_PCS_PMA_FLL_IDAC_MIN GENMASK(26, 16) ++#define AIROHA_PCS_PMA_FLL_IDAC_MAX GENMASK(10, 0) ++#define AIROHA_PCS_PMA_RX_FLL_B 0x19c ++#define AIROHA_PCS_PMA_LOAD_EN BIT(0) ++#define AIROHA_PCS_PMA_RX_RESET_1 0x208 ++#define AIROHA_PCS_PMA_SIGDET_RST_B BIT(8) ++#define AIROHA_PCS_PMA_TX_RST_B 0x260 ++#define AIROHA_PCS_PMA_TXCALIB_RST_B BIT(8) ++#define AIROHA_PCS_PMA_TX_TOP_RST_B BIT(0) ++#define AIROHA_PCS_PMA_RX_DISB_MODE_4 0x320 ++#define AIROHA_PCS_PMA_DISB_BLWC_OFFSET BIT(24) ++#define AIROHA_PCS_PMA_RX_FORCE_MODE_9 0x330 ++#define AIROHA_PCS_PMA_FORCE_FBCK_LOCK BIT(0) ++#define AIROHA_PCS_PMA_RX_DISB_MODE_8 0x33c ++#define AIROHA_PCS_PMA_DISB_FBCK_LOCK BIT(0) ++#define AIROHA_PCS_PMA_SS_DA_XPON_PWDB_0 0x34c ++#define AIROHA_PCS_PMA_XPON_CDR_PD_PWDB BIT(24) ++#define AIROHA_PCS_PMA_XPON_CDR_PR_PIEYE_PWDB BIT(16) ++#define AIROHA_PCS_PMA_XPON_CDR_PW_PWDB BIT(8) ++#define AIROHA_PCS_PMA_XPON_RX_FE_PWDB BIT(0) ++#define AIROHA_PCS_PMA_SS_DA_XPON_PWDB_1 0x350 ++#define AIROHA_PCS_PMA_RX_SIDGET_PWDB BIT(0) ++#define AIROHA_PCS_PMA_DIG_RESERVE_0 0x360 ++#define AIROHA_PCS_TRIGGER_RX_SIDGET_SCAN GENMASK(17, 16) ++#define AIROHA_PCS_PMA_XPON_RX_RESERVED_1 0x374 ++#define AIROHA_PCS_PMA_XPON_RX_RATE_CTRL GENMASK(1, 0) ++#define AIROHA_PCS_PMA_DIG_RO_RESERVE_2 0x380 ++#define AIROHA_PCS_RX_SIGDET BIT(8) ++#define AIROHA_PCS_PMA_RX_SYS_EN_SEL_0 0x38c ++#define AIROHA_PCS_PMA_RX_SYS_EN_SEL GENMASK(1, 0) ++#define AIROHA_PCS_PMA_PLL_TDC_FREQDET_0 0x390 ++#define AIROHA_PCS_PMA_PLL_LOCK_CYCLECNT GENMASK(15, 0) ++#define AIROHA_PCS_PMA_PLL_TDC_FREQDET_1 0x394 ++#define AIROHA_PCS_PMA_PLL_LOCK_TARGET_END GENMASK(31, 16) ++#define AIROHA_PCS_PMA_PLL_LOCK_TARGET_BEG GENMASK(15, 0) ++#define AIROHA_PCS_PMA_PLL_TDC_FREQDET_3 0x39c ++#define AIROHA_PCS_PMA_PLL_LOCK_LOCKTH GENMASK(11, 8) ++#define AIROHA_PCS_PMA_SW_RST_SET 0x460 ++#define AIROHA_PCS_PMA_SW_HSG_RXPCS_RST_N BIT(11) ++#define AIROHA_PCS_PMA_SW_HSG_TXPCS_RST_N BIT(10) ++#define AIROHA_PCS_PMA_SW_XFI_RXPCS_BIST_RST_N BIT(9) ++#define AIROHA_PCS_PMA_SW_XFI_RXPCS_RST_N BIT(8) ++#define AIROHA_PCS_PMA_SW_XFI_TXPCS_RST_N BIT(7) ++#define AIROHA_PCS_PMA_SW_TX_FIFO_RST_N BIT(6) ++#define AIROHA_PCS_PMA_SW_REF_RST_N BIT(5) ++#define AIROHA_PCS_PMA_SW_ALLPCS_RST_N BIT(4) ++#define AIROHA_PCS_PMA_SW_PMA_RST_N BIT(3) ++#define AIROHA_PCS_PMA_SW_TX_RST_N BIT(2) ++#define AIROHA_PCS_PMA_SW_RX_RST_N BIT(1) ++#define AIROHA_PCS_PMA_SW_RX_FIFO_RST_N BIT(0) ++#define AIROHA_PCS_PMA_XPON_INT_EN_3 0x474 ++#define AIROHA_PCS_PMA_RX_SIGDET_INT_EN BIT(16) ++#define AIROHA_PCS_PMA_XPON_INT_STA_3 0x47c ++#define AIROHA_PCS_PMA_RX_SIGDET_INT BIT(16) ++#define AIROHA_PCS_PMA_RX_EXTRAL_CTRL 0x48c ++#define AIROHA_PCS_PMA_DISB_LEQ BIT(0) ++#define AIROHA_PCS_PMA_RX_FREQDET 0x530 ++#define AIROHA_PCS_PMA_FL_OUT GENMASK(31, 16) ++#define AIROHA_PCS_PMA_FBCK_LOCK BIT(0) ++#define AIROHA_PCS_PMA_XPON_TX_RATE_CTRL 0x580 ++#define AIROHA_PCS_PMA_PON_TX_RATE_CTRL GENMASK(1, 0) ++#define AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN 0x768 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PEAKING_CTRL BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL GENMASK(19, 16) ++#define AIROHA_PCS_PMA_PXP_AEQ_SPEED 0x76c ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_OSR_SEL BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_OSR_SEL GENMASK(17, 16) ++#define AIROHA_PCS_PMA_PXP_TX_FIR_C0B 0x778 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_CN1 BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_TX_FIR_CN1 GENMASK(20, 16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C0B BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C0B GENMASK(5, 0) ++#define AIROHA_PCS_PMA_PXP_TX_TERM_SEL 0x77c ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_DIVISOR BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_DIVISOR GENMASK(19, 16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_TERM_SEL BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_TX_TERM_SEL GENMASK(2, 0) ++#define AIROHA_PCS_PMA_PXP_TX_FIR_C1 0x780 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C2 BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C2 GENMASK(20, 16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C1 BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C1 GENMASK(5, 0) ++#define AIROHA_PCS_PMA_PXP_TX_RATE_CTRL 0x784 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_RATE_CTRL BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_TX_RATE_CTRL GENMASK(1, 0) ++#define AIROHA_PCS_PMA_PXP_CDR_PR_IDAC 0x794 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_SDM_PCW BIT(24) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_IDAC BIT(16) ++#define AIROHA_PCS_PMA_FORCE_CDR_PR_IDAC GENMASK(10, 0) ++#define AIROHA_PCS_PMA_FORCE_CDR_PR_IDAC_MAJOR GENMASK(10, 8) ++#define AIROHA_PCS_PMA_PXP_TXPLL_SDM_PCW 0x798 ++#define AIROHA_PCS_PMA_FORCE_DA_TXPLL_SDM_PCW GENMASK(30, 0) ++#define AIROHA_PCS_PMA_PXP_RX_FE_VOS 0x79c ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_SDM_PCW BIT(16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_FE_VOS BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_FE_VOS GENMASK(5, 0) ++#define AIROHA_PCS_PMA_PXP_JCPLL_SDM_PCW 0x800 ++#define AIROHA_PCS_PMA_FORCE_DA_JCPLL_SDM_PCW GENMASK(30, 0) ++#define AIROHA_PCS_PMA_PXP_AEQ_BYPASS 0x80c ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_AEQ_CKON BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_AEQ_CKON BIT(16) ++#define AIROHA_PCS_PMA_PXP_AEQ_RSTB 0x814 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_INJCK_SEL BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_CDR_INJCK_SEL BIT(16) ++#define AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA 0x818 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB BIT(16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA BIT(0) ++#define AIROHA_PCS_PMA_PXP_CDR_PD_PWDB 0x81c ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_KBAND_RSTB BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_CDR_PR_KBAND_RSTB BIT(16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PD_PWDB BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PD_PWDB BIT(0) ++#define AIROHA_PCS_PMA_PXP_CDR_PR_LPF_C_EN 0x820 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_R_EN BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_CDR_PR_LPF_R_EN BIT(16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_C_EN BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_CDR_PR_LPF_C_EN BIT(0) ++#define AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB 0x824 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PWDB BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB BIT(16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PIEYE_PWDB BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PIEYE_PWDB BIT(0) ++#define AIROHA_PCS_PMA_PXP_JCPLL_CKOUT_EN 0x828 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_EN BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_JCPLL_EN BIT(16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_CKOUT_EN BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_JCPLL_CKOUT_EN BIT(0) ++#define AIROHA_PCS_PMA_PXP_RX_SCAN_RST_B 0x84c ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_PWDB BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_RX_SIGDET_PWDB BIT(16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SCAN_RST_B BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_RX_SCAN_RST_B BIT(0) ++#define AIROHA_PCS_PMA_PXP_TXPLL_CKOUT_EN 0x854 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_EN BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_TXPLL_EN BIT(16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_CKOUT_EN BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_TXPLL_CKOUT_EN BIT(0) ++#define AIROHA_PCS_PMA_PXP_TX_ACJTAG_EN 0x874 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_SEL BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_SEL BIT(16) ++#define AIROHA_PCS_PMA_PXP_FE_GAIN_CTRL 0x88c ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_GAIN_CTRL BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL GENMASK(1, 0) ++#define AIROHA_PCS_PMA_PXP_RX_FE_PWDB 0x894 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_PDOSCAL_EN BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_RX_PDOSCAL_EN BIT(16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PWDB BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_RX_FE_PWDB BIT(0) ++ ++#define AIROHA_PCS_MAX_CALIBRATION_TRY 50 ++#define AIROHA_PCS_MAX_NUM_RSTS 2 ++ ++enum xfi_port_type { ++ AIROHA_PCS_ETH, ++ AIROHA_PCS_PON, ++}; ++ ++struct airoha_pcs_priv { ++ struct device *dev; ++ const struct airoha_pcs_match_data *data; ++ phy_interface_t interface; ++ ++ struct regmap *scu; ++ ++ struct regmap *xfi_mac; ++ struct regmap *hsgmii_an; ++ struct regmap *hsgmii_pcs; ++ struct regmap *hsgmii_rate_adp; ++ struct regmap *multi_sgmii; ++ struct regmap *usxgmii_pcs; ++ ++ struct regmap *xfi_pma; ++ struct regmap *xfi_ana; ++ ++ struct reset_control_bulk_data rsts[AIROHA_PCS_MAX_NUM_RSTS]; ++ ++ bool manual_rx_calib; ++}; ++ ++struct airoha_pcs_port { ++ struct airoha_pcs_priv *priv; ++ ++ struct phylink_pcs pcs; ++}; ++ ++struct airoha_pcs_match_data { ++ enum xfi_port_type port_type; ++ ++ int (*bringup)(struct airoha_pcs_priv *priv, ++ phy_interface_t interface); ++ void (*link_up)(struct airoha_pcs_priv *priv); ++ int (*rxlock_workaround)(struct airoha_pcs_priv *priv); ++}; ++ ++#define to_airoha_pcs_port(n) container_of(n, struct airoha_pcs_port, pcs); ++ ++#ifdef CONFIG_PCS_AIROHA_AN7581 ++int an7581_pcs_bringup(struct airoha_pcs_priv *priv, ++ phy_interface_t interface); ++ ++void an7581_pcs_phya_link_up(struct airoha_pcs_priv *priv); ++int an7581_pcs_rxlock_workaround(struct airoha_pcs_priv *priv); ++#else ++static inline int an7581_pcs_bringup(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static inline void an7581_pcs_phya_link_up(struct airoha_pcs_priv *priv) ++{ ++} ++ ++static inline int an7581_pcs_rxlock_workaround(struct airoha_pcs_priv *priv) ++{ ++ return 0; ++} ++#endif +--- /dev/null ++++ b/drivers/net/pcs/airoha/pcs-an7581.c +@@ -0,0 +1,1419 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2024 AIROHA Inc ++ * Author: Christian Marangi ++ */ ++#include ++#include ++ ++#include "pcs-airoha.h" ++ ++static void an7581_pcs_jcpll_bringup(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ u32 kband_vref; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ kband_vref = 0x10; ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ kband_vref = 0xf; ++ break; ++ default: ++ return; ++ } ++ ++ /* Setup LDO */ ++ usleep_range(200, 300); ++ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SPARE_H, ++ AIROHA_PCS_ANA_JCPLL_SPARE_L_LDO); ++ ++ /* Setup RSTB */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, ++ AIROHA_PCS_ANA_JCPLL_RST_DLY, ++ AIROHA_PCS_ANA_JCPLL_RST_DLY_150_200); ++ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, ++ AIROHA_PCS_ANA_JCPLL_PLL_RSTB); ++ ++ /* Enable PLL force selection and Force Disable */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_CKOUT_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_EN | ++ AIROHA_PCS_PMA_FORCE_DA_JCPLL_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_EN); ++ ++ /* Setup SDM */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_RST_DLY, ++ AIROHA_PCS_ANA_JCPLL_SDM_DI_LS | ++ AIROHA_PCS_ANA_JCPLL_SDM_DI_EN, ++ AIROHA_PCS_ANA_JCPLL_SDM_DI_LS_2_23); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SDM_IFM, ++ AIROHA_PCS_ANA_JCPLL_SDM_OUT | ++ AIROHA_PCS_ANA_JCPLL_SDM_ORD | ++ AIROHA_PCS_ANA_JCPLL_SDM_MODE | ++ AIROHA_PCS_ANA_JCPLL_SDM_IFM, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_SDM_ORD, 0x0) | ++ AIROHA_PCS_ANA_JCPLL_SDM_ORD_3SDM | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_SDM_MODE, 0x0)); ++ ++ regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SDM_HREN, ++ AIROHA_PCS_ANA_JCPLL_SDM_HREN); ++ ++ /* Setup SSC */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SSC_DELTA, ++ AIROHA_PCS_ANA_JCPLL_SSC_PERIOD | ++ AIROHA_PCS_ANA_JCPLL_SSC_DELTA, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_SSC_PERIOD, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_SSC_DELTA, 0x0)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SSC_TRI_EN, ++ AIROHA_PCS_ANA_JCPLL_SSC_DELTA1 | ++ AIROHA_PCS_ANA_JCPLL_SSC_TRI_EN, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_SSC_DELTA1, 0x0)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_VCO_TCLVAR, ++ AIROHA_PCS_ANA_JCPLL_SSC_PHASE_INI | ++ AIROHA_PCS_ANA_JCPLL_SSC_EN | ++ AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_L | ++ AIROHA_PCS_ANA_JCPLL_VCO_TCLVAR, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_L, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_TCLVAR, 0x0)); ++ ++ /* Setup LPF */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_IB_EXT_EN, ++ AIROHA_PCS_ANA_JCPLL_CHP_IOFST | ++ AIROHA_PCS_ANA_JCPLL_CHP_IBIAS | ++ AIROHA_PCS_ANA_JCPLL_LPF_SHCK_EN, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_CHP_IOFST, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_CHP_IBIAS, 0x18)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_LPF_BR, ++ AIROHA_PCS_ANA_JCPLL_LPF_BWR | ++ AIROHA_PCS_ANA_JCPLL_LPF_BP | ++ AIROHA_PCS_ANA_JCPLL_LPF_BC | ++ AIROHA_PCS_ANA_JCPLL_LPF_BR, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_LPF_BWR, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_LPF_BP, 0x10) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_LPF_BC, 0x1f) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_LPF_BR, BIT(3) | BIT(1))); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_LPF_BWC, ++ AIROHA_PCS_ANA_JCPLL_LPF_BWC, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_LPF_BWC, 0x0)); ++ ++ /* Setup VCO */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_VCODIV, ++ AIROHA_PCS_ANA_JCPLL_VCO_SCAPWR | ++ AIROHA_PCS_ANA_JCPLL_VCO_HALFLSB_EN | ++ AIROHA_PCS_ANA_JCPLL_VCO_CFIX, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_SCAPWR, 0x4) | ++ AIROHA_PCS_ANA_JCPLL_VCO_HALFLSB_EN | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_CFIX, 0x1)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_VCO_TCLVAR, ++ AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_L | ++ AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_H | ++ AIROHA_PCS_ANA_JCPLL_VCO_TCLVAR, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_L, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_VCOVAR_BIAS_H, 0x3) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_VCO_TCLVAR, 0x3)); ++ ++ /* Setup PCW */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_SDM_PCW, ++ AIROHA_PCS_PMA_FORCE_DA_JCPLL_SDM_PCW, ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_JCPLL_SDM_PCW, 0x25800000)); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_FE_VOS, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_SDM_PCW); ++ ++ /* Setup DIV */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_MMD_PREDIV_MODE, ++ AIROHA_PCS_ANA_JCPLL_POSTDIV_D5 | ++ AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE, ++ AIROHA_PCS_ANA_JCPLL_MMD_PREDIV_MODE_2); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_VCODIV, ++ AIROHA_PCS_ANA_JCPLL_VCODIV, ++ AIROHA_PCS_ANA_JCPLL_VCODIV_1); ++ ++ /* Setup KBand */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_KBAND_KFC, ++ AIROHA_PCS_ANA_JCPLL_KBAND_KS | ++ AIROHA_PCS_ANA_JCPLL_KBAND_KF | ++ AIROHA_PCS_ANA_JCPLL_KBAND_KFC, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_KBAND_KS, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_KBAND_KF, 0x3) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_KBAND_KFC, 0x0)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_LPF_BWC, ++ AIROHA_PCS_ANA_JCPLL_KBAND_DIV | ++ AIROHA_PCS_ANA_JCPLL_KBAND_CODE | ++ AIROHA_PCS_ANA_JCPLL_KBAND_OPTION, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_KBAND_DIV, 0x2) | ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_KBAND_CODE, 0xe4)); ++ ++ /* Setup TCL */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SPARE_H, ++ AIROHA_PCS_ANA_JCPLL_TCL_KBAND_VREF, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_TCL_KBAND_VREF, kband_vref)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_SDM_HREN, ++ AIROHA_PCS_ANA_JCPLL_TCL_AMP_VREF | ++ AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN | ++ AIROHA_PCS_ANA_JCPLL_TCL_AMP_EN, ++ FIELD_PREP(AIROHA_PCS_ANA_JCPLL_TCL_AMP_VREF, 0x5) | ++ AIROHA_PCS_ANA_JCPLL_TCL_AMP_GAIN_4 | ++ AIROHA_PCS_ANA_JCPLL_TCL_AMP_EN); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_TCL_CMP_EN, ++ AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW | ++ AIROHA_PCS_ANA_JCPLL_TCL_LPF_EN, ++ AIROHA_PCS_ANA_JCPLL_TCL_LPF_BW_1 | ++ AIROHA_PCS_ANA_JCPLL_TCL_LPF_EN); ++ ++ /* Enable PLL */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_CKOUT_EN, ++ AIROHA_PCS_PMA_FORCE_DA_JCPLL_EN); ++ ++ /* Enale PLL Output */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_CKOUT_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_CKOUT_EN | ++ AIROHA_PCS_PMA_FORCE_DA_JCPLL_CKOUT_EN); ++} ++ ++static void an7581_pcs_txpll_bringup(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ u32 lpf_chp_ibias, lpf_bp, lpf_bwr, lpf_bwc; ++ u32 vco_cfix; ++ u32 pcw; ++ u32 tcl_amp_vref; ++ bool sdm_hren; ++ bool vcodiv; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ lpf_chp_ibias = 0xf; ++ lpf_bp = BIT(1); ++ lpf_bwr = BIT(3) | BIT(1) | BIT(0); ++ lpf_bwc = BIT(4) | BIT(3); ++ vco_cfix = BIT(1) | BIT(0); ++ pcw = BIT(27); ++ tcl_amp_vref = BIT(3) | BIT(1) | BIT(0); ++ vcodiv = false; ++ sdm_hren = false; ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: ++ lpf_chp_ibias = 0xa; ++ lpf_bp = BIT(2) | BIT(0); ++ lpf_bwr = 0; ++ lpf_bwc = 0; ++ vco_cfix = 0; ++ pcw = BIT(27) | BIT(25); ++ tcl_amp_vref = BIT(3) | BIT(2) | BIT(0); ++ vcodiv = true; ++ sdm_hren = false; ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ lpf_chp_ibias = 0xf; ++ lpf_bp = BIT(1); ++ lpf_bwr = BIT(3) | BIT(1) | BIT(0); ++ lpf_bwc = BIT(4) | BIT(3); ++ vco_cfix = BIT(0); ++ pcw = BIT(27) | BIT(22); ++ tcl_amp_vref = BIT(3) | BIT(1) | BIT(0); ++ vcodiv = false; ++ sdm_hren = true; ++ break; ++ default: ++ return; ++ } ++ ++ /* Setup VCO LDO Output */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SSC_PERIOD, ++ AIROHA_PCS_ANA_TXPLL_LDO_VCO_OUT | ++ AIROHA_PCS_ANA_TXPLL_LDO_OUT, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LDO_VCO_OUT, 0x1) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LDO_OUT, 0x1)); ++ ++ /* Setup RSTB */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_REFIN_INTERNAL, ++ AIROHA_PCS_ANA_TXPLL_PLL_RSTB | ++ AIROHA_PCS_ANA_TXPLL_RST_DLY | ++ AIROHA_PCS_ANA_TXPLL_REFIN_DIV | ++ AIROHA_PCS_ANA_TXPLL_REFIN_INTERNAL, ++ AIROHA_PCS_ANA_TXPLL_PLL_RSTB | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_RST_DLY, 0x4) | ++ AIROHA_PCS_ANA_TXPLL_REFIN_DIV_1 | ++ AIROHA_PCS_ANA_TXPLL_REFIN_INTERNAL); ++ ++ /* Enable PLL force selection and Force Disable */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_CKOUT_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_EN | ++ AIROHA_PCS_PMA_FORCE_DA_TXPLL_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_EN); ++ ++ /* Setup SDM */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SDM_DI_EN, ++ AIROHA_PCS_ANA_TXPLL_SDM_MODE | ++ AIROHA_PCS_ANA_TXPLL_SDM_IFM | ++ AIROHA_PCS_ANA_TXPLL_SDM_DI_LS | ++ AIROHA_PCS_ANA_TXPLL_SDM_DI_EN, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_SDM_MODE, 0) | ++ AIROHA_PCS_ANA_TXPLL_SDM_DI_LS_2_23); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SDM_ORD, ++ AIROHA_PCS_ANA_TXPLL_SDM_HREN | ++ AIROHA_PCS_ANA_TXPLL_SDM_OUT | ++ AIROHA_PCS_ANA_TXPLL_SDM_ORD, ++ (sdm_hren ? AIROHA_PCS_ANA_TXPLL_SDM_HREN : 0) | ++ AIROHA_PCS_ANA_TXPLL_SDM_ORD_3SDM); ++ ++ /* Setup SSC */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SSC_DELTA1, ++ AIROHA_PCS_ANA_TXPLL_SSC_DELTA | ++ AIROHA_PCS_ANA_TXPLL_SSC_DELTA1, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_SSC_DELTA, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_SSC_DELTA1, 0x0)); ++ ++ regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SSC_EN, ++ AIROHA_PCS_ANA_TXPLL_SSC_TRI_EN | ++ AIROHA_PCS_ANA_TXPLL_SSC_PHASE_INI | ++ AIROHA_PCS_ANA_TXPLL_SSC_EN); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SSC_PERIOD, ++ AIROHA_PCS_ANA_TXPLL_SSC_PERIOD, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_SSC_PERIOD, 0x0)); ++ ++ /* Setup LPF */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_CHP_IBIAS, ++ AIROHA_PCS_ANA_TXPLL_LPF_BC | ++ AIROHA_PCS_ANA_TXPLL_LPF_BR | ++ AIROHA_PCS_ANA_TXPLL_CHP_IOFST | ++ AIROHA_PCS_ANA_TXPLL_CHP_IBIAS, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BC, 0x1f) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BR, 0x5) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_CHP_IOFST, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_CHP_IBIAS, lpf_chp_ibias)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_LPF_BP, ++ AIROHA_PCS_ANA_TXPLL_LPF_BWC | ++ AIROHA_PCS_ANA_TXPLL_LPF_BWR | ++ AIROHA_PCS_ANA_TXPLL_LPF_BP, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BWC, lpf_bwc) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BWR, lpf_bwr) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BP, lpf_bp)); ++ ++ /* Setup VCO */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_LPF_EN, ++ AIROHA_PCS_ANA_TXPLL_VCO_CFIX, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_CFIX, vco_cfix)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_VCO_HALFLSB_EN, ++ AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_L | ++ AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_H | ++ AIROHA_PCS_ANA_TXPLL_VCO_TCLVAR | ++ AIROHA_PCS_ANA_TXPLL_VCO_SCAPWR | ++ AIROHA_PCS_ANA_TXPLL_VCO_HALFLSB_EN, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_L, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_H, 0x4) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_TCLVAR, 0x4) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_SCAPWR, 0x7) | ++ AIROHA_PCS_ANA_TXPLL_VCO_HALFLSB_EN); ++ ++ /* Setup PCW */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_SDM_PCW, ++ AIROHA_PCS_PMA_FORCE_DA_TXPLL_SDM_PCW, pcw); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_IDAC, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_SDM_PCW); ++ ++ /* Setup KBand */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_KBAND_CODE, ++ AIROHA_PCS_ANA_TXPLL_KBAND_KF | ++ AIROHA_PCS_ANA_TXPLL_KBAND_KFC | ++ AIROHA_PCS_ANA_TXPLL_KBAND_DIV | ++ AIROHA_PCS_ANA_TXPLL_KBAND_CODE, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_KF, 0x3) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_KFC, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_DIV, 0x4) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_CODE, 0xe4)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_KBAND_KS, ++ AIROHA_PCS_ANA_TXPLL_KBAND_KS, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_KS, 0x1)); ++ ++ regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_LPF_BP, ++ AIROHA_PCS_ANA_TXPLL_KBAND_OPTION); ++ ++ /* Setup DIV */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_KBAND_KS, ++ AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE | ++ AIROHA_PCS_ANA_TXPLL_POSTDIV_EN, ++ AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE_2); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_LPF_EN, ++ AIROHA_PCS_ANA_TXPLL_VCODIV, ++ vcodiv ? AIROHA_PCS_ANA_TXPLL_VCODIV_2 : ++ AIROHA_PCS_ANA_TXPLL_VCODIV_1); ++ ++ /* Setup TCL */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_KBAND_VREF, ++ AIROHA_PCS_ANA_TXPLL_TCL_KBAND_VREF, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_TCL_KBAND_VREF, 0xf)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_AMP_GAIN, ++ AIROHA_PCS_ANA_TXPLL_TCL_AMP_VREF | ++ AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_TCL_AMP_VREF, tcl_amp_vref) | ++ AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN_4); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_LPF_EN, ++ AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW | ++ AIROHA_PCS_ANA_TXPLL_TCL_LPF_EN, ++ AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_0_5 | ++ AIROHA_PCS_ANA_TXPLL_TCL_LPF_EN); ++ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SDM_ORD, ++ AIROHA_PCS_ANA_TXPLL_TCL_AMP_EN); ++ ++ /* Enable PLL */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_CKOUT_EN, ++ AIROHA_PCS_PMA_FORCE_DA_TXPLL_EN); ++ ++ /* Enale PLL Output */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_CKOUT_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_CKOUT_EN | ++ AIROHA_PCS_PMA_FORCE_DA_TXPLL_CKOUT_EN); ++} ++ ++static void an7581_pcs_tx_bringup(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ u32 tx_rate_ctrl; ++ u32 ckin_divisor; ++ u32 fir_cn1, fir_c0b, fir_c1; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ ckin_divisor = BIT(1); ++ tx_rate_ctrl = BIT(0); ++ fir_cn1 = 0; ++ fir_c0b = 12; ++ fir_c1 = 0; ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: ++ ckin_divisor = BIT(2); ++ tx_rate_ctrl = BIT(0); ++ fir_cn1 = 0; ++ fir_c0b = 11; ++ fir_c1 = 1; ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ ckin_divisor = BIT(2) | BIT(0); ++ tx_rate_ctrl = BIT(1); ++ fir_cn1 = 1; ++ fir_c0b = 1; ++ fir_c1 = 11; ++ break; ++ default: ++ return; ++ } ++ ++ /* Set TX rate ctrl */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_XPON_TX_RATE_CTRL, ++ AIROHA_PCS_PMA_PON_TX_RATE_CTRL, ++ FIELD_PREP(AIROHA_PCS_PMA_PON_TX_RATE_CTRL, ++ tx_rate_ctrl)); ++ ++ /* Setup TX Config */ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TX_CKLDO_EN, ++ AIROHA_PCS_ANA_TX_DMEDGEGEN_EN | ++ AIROHA_PCS_ANA_TX_CKLDO_EN); ++ ++ udelay(1); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_ACJTAG_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_SEL | ++ AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_SEL); ++ ++ /* FIXME: Ask Airoha TX term is OK to reset? */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_TERM_SEL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_DIVISOR | ++ AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_DIVISOR | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_TERM_SEL | ++ AIROHA_PCS_PMA_FORCE_DA_TX_TERM_SEL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_DIVISOR | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_DIVISOR, ++ ckin_divisor) | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_TERM_SEL, 0x0)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_RATE_CTRL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_RATE_CTRL | ++ AIROHA_PCS_PMA_FORCE_DA_TX_RATE_CTRL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_RATE_CTRL | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_RATE_CTRL, ++ tx_rate_ctrl)); ++ ++ /* Setup TX FIR Load Parameters (Reference 660mV) */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_FIR_C0B, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_CN1 | ++ AIROHA_PCS_PMA_FORCE_DA_TX_FIR_CN1 | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C0B | ++ AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C0B, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_CN1 | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_FIR_CN1, fir_cn1) | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C0B | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C0B, fir_c0b)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_FIR_C1, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C2 | ++ AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C2 | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C1 | ++ AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C1, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C1 | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C1, fir_c1)); ++ ++ /* Reset TX Bar */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_TX_RST_B, ++ AIROHA_PCS_PMA_TXCALIB_RST_B | AIROHA_PCS_PMA_TX_TOP_RST_B); ++} ++ ++static void an7581_pcs_rx_bringup(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ u32 rx_rate_ctrl; ++ u32 osr; ++ u32 pr_cdr_beta_dac; ++ u32 cdr_pr_buf_in_sr; ++ bool cdr_pr_cap_en; ++ u32 sigdet_vth_sel; ++ u32 phyck_div, phyck_sel; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ osr = BIT(1) | BIT(0); /* 1.25G */ ++ pr_cdr_beta_dac = BIT(3); ++ rx_rate_ctrl = 0; ++ cdr_pr_cap_en = false; ++ cdr_pr_buf_in_sr = BIT(2) | BIT(1) | BIT(0); ++ sigdet_vth_sel = BIT(2) | BIT(1); ++ phyck_div = BIT(5) | BIT(3) | BIT(0); ++ phyck_sel = BIT(0); ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: ++ osr = BIT(0); /* 2.5G */ ++ pr_cdr_beta_dac = BIT(2) | BIT(1); ++ rx_rate_ctrl = 0; ++ cdr_pr_cap_en = true; ++ cdr_pr_buf_in_sr = BIT(2) | BIT(1); ++ sigdet_vth_sel = BIT(2) | BIT(1); ++ phyck_div = BIT(3) | BIT(1) | BIT(0); ++ phyck_sel = BIT(0); ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ osr = 0; /* 10G */ ++ cdr_pr_cap_en = false; ++ pr_cdr_beta_dac = BIT(3); ++ rx_rate_ctrl = BIT(1); ++ cdr_pr_buf_in_sr = BIT(2) | BIT(1) | BIT(0); ++ sigdet_vth_sel = BIT(1); ++ phyck_div = BIT(6) | BIT(1); ++ phyck_sel = BIT(1); ++ break; ++ default: ++ return; ++ } ++ ++ /* Set RX rate ctrl */ ++ if (interface == PHY_INTERFACE_MODE_2500BASEX) ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_2, ++ AIROHA_PCS_PMA_CK_RATE, ++ AIROHA_PCS_PMA_CK_RATE_10); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_XPON_RX_RESERVED_1, ++ AIROHA_PCS_PMA_XPON_RX_RATE_CTRL, ++ FIELD_PREP(AIROHA_PCS_PMA_XPON_RX_RATE_CTRL, rx_rate_ctrl)); ++ ++ /* Setup RX Path */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_5, ++ AIROHA_PCS_PMA_FLL_IDAC_MIN | ++ AIROHA_PCS_PMA_FLL_IDAC_MAX, ++ FIELD_PREP(AIROHA_PCS_PMA_FLL_IDAC_MIN, 0x400) | ++ FIELD_PREP(AIROHA_PCS_PMA_FLL_IDAC_MAX, 0x3ff)); ++ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_DAC_D1_BYPASS_AEQ, ++ AIROHA_PCS_ANA_RX_DAC_EYE_BYPASS_AEQ | ++ AIROHA_PCS_ANA_RX_DAC_E1_BYPASS_AEQ | ++ AIROHA_PCS_ANA_RX_DAC_E0_BYPASS_AEQ | ++ AIROHA_PCS_ANA_RX_DAC_D1_BYPASS_AEQ); ++ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_FE_PEAKING_CTRL_MSB, ++ AIROHA_PCS_ANA_RX_DAC_D0_BYPASS_AEQ); ++ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_FE_VCM_GEN_PWDB, ++ AIROHA_PCS_ANA_FE_VCM_GEN_PWDB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_LCPLL_PWCTL_SETTING_1, ++ AIROHA_PCS_PMA_LCPLL_MAN_PWDB); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_AEQ_CFORCE, ++ AIROHA_PCS_ANA_AEQ_OFORCE, ++ AIROHA_PCS_ANA_AEQ_OFORCE_CTLE); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_OSCAL_WATCH_WNDW, ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE, ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA2VOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA2IOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA1VOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA1IOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE2VOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE2IOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE1VOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE1IOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_LVSH | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_COMPOS); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_4, ++ AIROHA_PCS_PMA_DISB_BLWC_OFFSET); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EXTRAL_CTRL, ++ AIROHA_PCS_PMA_DISB_LEQ); ++ ++ regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PD_PICAL_CKD8_INV, ++ AIROHA_PCS_ANA_CDR_PD_EDGE_DIS | ++ AIROHA_PCS_ANA_CDR_PD_PICAL_CKD8_INV); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_AEQ_BYPASS, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_AEQ_CKON | ++ AIROHA_PCS_PMA_FORCE_DA_AEQ_CKON, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_AEQ_CKON); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_AEQ_RSTB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_INJCK_SEL | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_INJCK_SEL); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_MONPR_EN, ++ AIROHA_PCS_ANA_RX_DAC_MON | ++ AIROHA_PCS_ANA_CDR_PR_XFICK_EN | ++ AIROHA_PCS_ANA_CDR_PR_MONDPI_EN | ++ AIROHA_PCS_ANA_CDR_PR_MONDPR_EN, ++ FIELD_PREP(AIROHA_PCS_ANA_RX_DAC_MON, 0x0) | ++ AIROHA_PCS_ANA_CDR_PR_XFICK_EN); ++ ++ /* Setup FE Gain and FE Peacking */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_FE_GAIN_CTRL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_GAIN_CTRL | ++ AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL, ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL, 0x0)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PEAKING_CTRL | ++ AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL, ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL, 0x0)); ++ ++ /* Setup FE VOS */ ++ if (interface != PHY_INTERFACE_MODE_USXGMII && ++ interface != PHY_INTERFACE_MODE_10GBASER) ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_FE_VOS, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_FE_VOS | ++ AIROHA_PCS_PMA_FORCE_DA_FE_VOS, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_FE_VOS | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_FE_VOS, 0x0)); ++ ++ /* Setup FLL PR FMeter (no bypass mode)*/ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PLL_TDC_FREQDET_0, ++ AIROHA_PCS_PMA_PLL_LOCK_CYCLECNT, ++ FIELD_PREP(AIROHA_PCS_PMA_PLL_LOCK_CYCLECNT, 0x1)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PLL_TDC_FREQDET_1, ++ AIROHA_PCS_PMA_PLL_LOCK_TARGET_END | ++ AIROHA_PCS_PMA_PLL_LOCK_TARGET_BEG, ++ FIELD_PREP(AIROHA_PCS_PMA_PLL_LOCK_TARGET_END, 0xffff) | ++ FIELD_PREP(AIROHA_PCS_PMA_PLL_LOCK_TARGET_BEG, 0x0)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PLL_TDC_FREQDET_3, ++ AIROHA_PCS_PMA_PLL_LOCK_LOCKTH, ++ FIELD_PREP(AIROHA_PCS_PMA_PLL_LOCK_LOCKTH, 0x1)); ++ ++ /* FIXME: Warn and Ask Airoha about typo in air_eth_xsgmii.c line 1391 */ ++ /* AIROHA_PCS_ANA_REV_1_FE_BUF1_BIAS_CTRL is set 0x0 in SDK but seems a typo */ ++ /* Setup REV */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_REV_0, ++ AIROHA_PCS_ANA_REV_1_FE_BUF1_BIAS_CTRL | ++ AIROHA_PCS_ANA_REV_1_FE_BUF2_BIAS_CTRL | ++ AIROHA_PCS_ANA_REV_1_SIGDET_ILEAK, ++ FIELD_PREP(AIROHA_PCS_ANA_REV_1_FE_BUF1_BIAS_CTRL, BIT(2)) | ++ FIELD_PREP(AIROHA_PCS_ANA_REV_1_FE_BUF2_BIAS_CTRL, BIT(2)) | ++ FIELD_PREP(AIROHA_PCS_ANA_REV_1_SIGDET_ILEAK, 0x0)); ++ ++ /* Setup Rdy Timeout */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_5, ++ AIROHA_PCS_PMA_RX_RDY | ++ AIROHA_PCS_PMA_RX_BLWC_RDY_EN, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_RDY, 0xa) | ++ FIELD_PREP(AIROHA_PCS_PMA_RX_BLWC_RDY_EN, 0x5)); ++ ++ /* Setup CaBoundry Init */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_0, ++ AIROHA_PCS_PMA_RX_OS_START | ++ AIROHA_PCS_PMA_OSC_SPEED_OPT, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_OS_START, 0x1) | ++ AIROHA_PCS_PMA_OSC_SPEED_OPT_0_1); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_6, ++ AIROHA_PCS_PMA_RX_OS_END, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_OS_END, 0x2)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_1, ++ AIROHA_PCS_PMA_RX_PICAL_END | ++ AIROHA_PCS_PMA_RX_PICAL_START, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_PICAL_END, 0x32) | ++ FIELD_PREP(AIROHA_PCS_PMA_RX_PICAL_START, 0x2)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_4, ++ AIROHA_PCS_PMA_RX_SDCAL_END | ++ AIROHA_PCS_PMA_RX_SDCAL_START, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_SDCAL_END, 0x32) | ++ FIELD_PREP(AIROHA_PCS_PMA_RX_SDCAL_START, 0x2)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_2, ++ AIROHA_PCS_PMA_RX_PDOS_END | ++ AIROHA_PCS_PMA_RX_PDOS_START, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_PDOS_END, 0x32) | ++ FIELD_PREP(AIROHA_PCS_PMA_RX_PDOS_START, 0x2)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_3, ++ AIROHA_PCS_PMA_RX_FEOS_END | ++ AIROHA_PCS_PMA_RX_FEOS_START, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_FEOS_END, 0x32) | ++ FIELD_PREP(AIROHA_PCS_PMA_RX_FEOS_START, 0x2)); ++ ++ /* Setup By Serdes*/ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_AEQ_SPEED, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_OSR_SEL | ++ AIROHA_PCS_PMA_FORCE_DA_OSR_SEL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_OSR_SEL | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_OSR_SEL, osr)); ++ ++ /* Setup RX OSR */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PD_PICAL_CKD8_INV, ++ AIROHA_PCS_ANA_CDR_PD_EDGE_DIS, ++ osr ? AIROHA_PCS_ANA_CDR_PD_EDGE_DIS : 0); ++ ++ /* Setup CDR LPF Ratio */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_LPF_RATIO, ++ AIROHA_PCS_ANA_CDR_LPF_TOP_LIM | ++ AIROHA_PCS_ANA_CDR_LPF_RATIO, ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_LPF_TOP_LIM, 0x20000) | ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_LPF_RATIO, osr)); ++ ++ /* Setup CDR PR */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_BETA_DAC, ++ AIROHA_PCS_ANA_CDR_PR_KBAND_DIV | ++ AIROHA_PCS_ANA_CDR_PR_BETA_SEL | ++ AIROHA_PCS_ANA_CDR_PR_VCOADC_OS | ++ AIROHA_PCS_ANA_CDR_PR_BETA_DAC, ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_KBAND_DIV, 0x4) | ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_BETA_SEL, 0x1) | ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_VCOADC_OS, 0x8) | ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_BETA_DAC, pr_cdr_beta_dac)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_VREG_IBAND_VAL, ++ AIROHA_PCS_ANA_CDR_PR_FBKSEL | ++ AIROHA_PCS_ANA_CDR_PR_DAC_BAND | ++ AIROHA_PCS_ANA_CDR_PR_VREG_CKBUF_VAL | ++ AIROHA_PCS_ANA_CDR_PR_VREG_IBAND_VAL, ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_FBKSEL, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_DAC_BAND, pr_cdr_beta_dac) | ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_VREG_CKBUF_VAL, 0x6) | ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_VREG_IBAND_VAL, 0x6)); ++ ++ /* Setup Eye Mon */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PHY_EQ_CTRL_2, ++ AIROHA_PCS_PMA_EQ_DEBUG_SEL | ++ AIROHA_PCS_PMA_FOM_NUM_ORDER | ++ AIROHA_PCS_PMA_A_SEL, ++ FIELD_PREP(AIROHA_PCS_PMA_EQ_DEBUG_SEL, 0x0) | ++ FIELD_PREP(AIROHA_PCS_PMA_FOM_NUM_ORDER, 0x1) | ++ FIELD_PREP(AIROHA_PCS_PMA_A_SEL, 0x3)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_2, ++ AIROHA_PCS_PMA_DATA_SHIFT | ++ AIROHA_PCS_PMA_EYECNT_FAST, ++ AIROHA_PCS_PMA_EYECNT_FAST); ++ ++ /* Calibration Start */ ++ ++ /* Enable SYS */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_SYS_EN_SEL_0, ++ AIROHA_PCS_PMA_RX_SYS_EN_SEL, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_SYS_EN_SEL, 0x1)); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_LCPLL_PWCTL_SETTING_0, ++ AIROHA_PCS_PMA_SW_LCPLL_EN); ++ ++ usleep_range(500, 600); ++ ++ /* Setup FLL PR FMeter (bypass mode)*/ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_8, ++ AIROHA_PCS_PMA_DISB_FBCK_LOCK); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9, ++ AIROHA_PCS_PMA_FORCE_FBCK_LOCK); ++ ++ /* Enable CMLEQ */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_FE_EQ_HZEN, ++ AIROHA_PCS_ANA_RX_FE_VB_EQ3_EN | ++ AIROHA_PCS_ANA_RX_FE_VB_EQ2_EN | ++ AIROHA_PCS_ANA_RX_FE_VB_EQ1_EN | ++ AIROHA_PCS_ANA_RX_FE_EQ_HZEN, ++ AIROHA_PCS_ANA_RX_FE_VB_EQ3_EN | ++ AIROHA_PCS_ANA_RX_FE_VB_EQ2_EN | ++ AIROHA_PCS_ANA_RX_FE_VB_EQ1_EN); ++ ++ /* Setup CDR PR */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_MONPR_EN, ++ AIROHA_PCS_ANA_CDR_PR_CAP_EN | ++ AIROHA_PCS_ANA_CDR_BUF_IN_SR, ++ (cdr_pr_cap_en ? AIROHA_PCS_ANA_CDR_PR_CAP_EN : 0) | ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_BUF_IN_SR, cdr_pr_buf_in_sr)); ++ ++ /* Setup CDR xxx Pwdb, set force and disable */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PWDB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PIEYE_PWDB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PWDB | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PIEYE_PWDB); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PD_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_KBAND_RSTB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_KBAND_RSTB | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PD_PWDB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PD_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PD_PWDB); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_FE_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_PDOSCAL_EN | ++ AIROHA_PCS_PMA_FORCE_DA_RX_PDOSCAL_EN | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PWDB | ++ AIROHA_PCS_PMA_FORCE_DA_RX_FE_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PWDB); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_SCAN_RST_B, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_PWDB | ++ AIROHA_PCS_PMA_FORCE_DA_RX_SIGDET_PWDB | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SCAN_RST_B | ++ AIROHA_PCS_PMA_FORCE_DA_RX_SCAN_RST_B, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_PWDB); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_DA_XPON_PWDB_0, ++ AIROHA_PCS_PMA_XPON_CDR_PD_PWDB | ++ AIROHA_PCS_PMA_XPON_CDR_PR_PIEYE_PWDB | ++ AIROHA_PCS_PMA_XPON_CDR_PW_PWDB | ++ AIROHA_PCS_PMA_XPON_RX_FE_PWDB); ++ ++ /* FIXME: Ask Airoha WHY it's cleared? */ ++ /* regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_SIGDET_NOVTH, ++ * AIROHA_PCS_ANA_RX_FE_50OHMS_SEL); ++ */ ++ ++ /* Setup SigDet */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_SIGDET_NOVTH, ++ AIROHA_PCS_ANA_RX_SIGDET_VTH_SEL | ++ AIROHA_PCS_ANA_RX_SIGDET_PEAK, ++ FIELD_PREP(AIROHA_PCS_ANA_RX_SIGDET_VTH_SEL, sigdet_vth_sel) | ++ FIELD_PREP(AIROHA_PCS_ANA_RX_SIGDET_PEAK, BIT(1))); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_DAC_RANGE, ++ AIROHA_PCS_ANA_RX_SIGDET_LPF_CTRL, ++ FIELD_PREP(AIROHA_PCS_ANA_RX_SIGDET_LPF_CTRL, BIT(1) | BIT(0))); ++ ++ /* Disable SigDet Pwdb */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_DA_XPON_PWDB_1, ++ AIROHA_PCS_PMA_RX_SIDGET_PWDB); ++ ++ /* Setup PHYCK */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_PHYCK_DIV, ++ AIROHA_PCS_ANA_RX_TDC_CK_SEL | ++ AIROHA_PCS_ANA_RX_PHYCK_RSTB | ++ AIROHA_PCS_ANA_RX_PHYCK_SEL | ++ AIROHA_PCS_ANA_RX_PHYCK_DIV, ++ AIROHA_PCS_ANA_RX_PHYCK_RSTB | ++ FIELD_PREP(AIROHA_PCS_ANA_RX_PHYCK_SEL, phyck_sel) | ++ FIELD_PREP(AIROHA_PCS_ANA_RX_PHYCK_DIV, phyck_div)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_BUSBIT_SEL, ++ AIROHA_PCS_ANA_RX_PHY_CK_SEL_FORCE | ++ AIROHA_PCS_ANA_RX_PHY_CK_SEL, ++ AIROHA_PCS_ANA_RX_PHY_CK_SEL_FORCE); ++ ++ usleep_range(100, 200); ++ ++ /* Enable CDR xxx Pwdb */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PIEYE_PWDB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PD_PWDB, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PD_PWDB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_FE_PWDB, ++ AIROHA_PCS_PMA_FORCE_DA_RX_FE_PWDB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_SCAN_RST_B, ++ AIROHA_PCS_PMA_FORCE_DA_RX_SIGDET_PWDB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_DA_XPON_PWDB_0, ++ AIROHA_PCS_PMA_XPON_CDR_PD_PWDB | ++ AIROHA_PCS_PMA_XPON_CDR_PR_PIEYE_PWDB | ++ AIROHA_PCS_PMA_XPON_CDR_PW_PWDB | ++ AIROHA_PCS_PMA_XPON_RX_FE_PWDB); ++ ++ /* Enable SigDet Pwdb */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_DA_XPON_PWDB_1, ++ AIROHA_PCS_PMA_RX_SIDGET_PWDB); ++} ++ ++static unsigned int an7581_pcs_apply_cdr_pr_idac(struct airoha_pcs_priv *priv, ++ u32 cdr_pr_idac) ++{ ++ u32 val; ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_IDAC, ++ AIROHA_PCS_PMA_FORCE_CDR_PR_IDAC, ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_CDR_PR_IDAC, ++ cdr_pr_idac)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FREQ_DET_4, ++ AIROHA_PCS_PMA_FREQLOCK_DET_EN, ++ AIROHA_PCS_PMA_FREQLOCK_DET_EN_FORCE_0); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FREQ_DET_4, ++ AIROHA_PCS_PMA_FREQLOCK_DET_EN, ++ AIROHA_PCS_PMA_FREQLOCK_DET_EN_NORMAL); ++ ++ usleep_range(5000, 7000); ++ ++ regmap_read(priv->xfi_pma, AIROHA_PCS_PMA_RX_FREQDET, &val); ++ ++ return FIELD_GET(AIROHA_PCS_PMA_FL_OUT, val); ++} ++ ++static u32 an7581_pcs_rx_prcal_idac_major(struct airoha_pcs_priv *priv, ++ u32 target_fl_out) ++{ ++ unsigned int fl_out_diff = UINT_MAX; ++ unsigned int prcal_search; ++ u32 cdr_pr_idac = 0; ++ ++ for (prcal_search = 0; prcal_search < 8 ; prcal_search++) { ++ unsigned int fl_out_diff_new; ++ unsigned int fl_out; ++ u32 cdr_pr_idac_tmp; ++ ++ /* try to find the upper value by setting the last 3 bit */ ++ cdr_pr_idac_tmp = FIELD_PREP(AIROHA_PCS_PMA_FORCE_CDR_PR_IDAC_MAJOR, ++ prcal_search); ++ fl_out = an7581_pcs_apply_cdr_pr_idac(priv, cdr_pr_idac_tmp); ++ ++ /* Use absolute values to find the closest one to target */ ++ fl_out_diff_new = abs(fl_out - target_fl_out); ++ dev_dbg(priv->dev, "Tested CDR Pr Idac: %x Fl Out: %x Diff: %u\n", ++ cdr_pr_idac_tmp, fl_out, fl_out_diff_new); ++ if (fl_out_diff_new < fl_out_diff) { ++ cdr_pr_idac = cdr_pr_idac_tmp; ++ fl_out_diff = fl_out_diff_new; ++ } ++ } ++ ++ return cdr_pr_idac; ++} ++ ++static u32 an7581_pcs_rx_prcal_idac_minor(struct airoha_pcs_priv *priv, u32 target_fl_out, ++ u32 cdr_pr_idac_major) ++{ ++ unsigned int remaining_prcal_search_bits = 0; ++ u32 cdr_pr_idac = cdr_pr_idac_major; ++ unsigned int fl_out, fl_out_diff; ++ int best_prcal_search_bit = -1; ++ int prcal_search_bit; ++ ++ fl_out = an7581_pcs_apply_cdr_pr_idac(priv, cdr_pr_idac); ++ fl_out_diff = abs(fl_out - target_fl_out); ++ ++ /* Deadline search part. ++ * We start from top bits to bottom as we progressively decrease the ++ * signal. ++ */ ++ for (prcal_search_bit = 7; prcal_search_bit >= 0; prcal_search_bit--) { ++ unsigned int fl_out_diff_new; ++ u32 cdr_pr_idac_tmp; ++ ++ cdr_pr_idac_tmp = cdr_pr_idac | BIT(prcal_search_bit); ++ fl_out = an7581_pcs_apply_cdr_pr_idac(priv, cdr_pr_idac_tmp); ++ ++ /* Use absolute values to find the closest one to target */ ++ fl_out_diff_new = abs(fl_out - target_fl_out); ++ dev_dbg(priv->dev, "Tested CDR Pr Idac: %x Fl Out: %x Diff: %u\n", ++ cdr_pr_idac_tmp, fl_out, fl_out_diff_new); ++ if (fl_out_diff_new < fl_out_diff) { ++ best_prcal_search_bit = prcal_search_bit; ++ fl_out_diff = fl_out_diff_new; ++ } ++ } ++ ++ /* Set the idac with the best value we found and ++ * reset the search bit to start from bottom to top. ++ */ ++ if (best_prcal_search_bit >= 0) { ++ cdr_pr_idac |= BIT(best_prcal_search_bit); ++ remaining_prcal_search_bits = best_prcal_search_bit; ++ prcal_search_bit = 0; ++ } ++ ++ /* Fine tune part. ++ * Test remaining bits to find an even closer signal level to target ++ * by increasing the signal. ++ */ ++ while (remaining_prcal_search_bits) { ++ unsigned int fl_out_diff_new; ++ u32 cdr_pr_idac_tmp; ++ ++ cdr_pr_idac_tmp = cdr_pr_idac | BIT(prcal_search_bit); ++ fl_out = an7581_pcs_apply_cdr_pr_idac(priv, cdr_pr_idac_tmp); ++ ++ /* Use absolute values to find the closest one to target */ ++ fl_out_diff_new = abs(fl_out - target_fl_out); ++ /* Assume we found the deadline when the new absolue signal difference ++ * from target is greater than the previous and the difference is at ++ * least 10% greater between the old and new value. ++ * This is to account for signal detection level tollerance making ++ * sure we are actually over a deadline (AKA we are getting farther ++ * from target) ++ */ ++ dev_dbg(priv->dev, "Tested CDR Pr Idac: %x Fl Out: %x Diff: %u\n", ++ cdr_pr_idac_tmp, fl_out, fl_out_diff_new); ++ if (fl_out_diff_new > fl_out_diff && ++ (abs(fl_out_diff_new - fl_out_diff) * 100) / fl_out_diff > 10) { ++ /* Exit early if we are already at the deadline */ ++ if (prcal_search_bit == 0) ++ break; ++ ++ /* We found the deadline, set the value to the previous ++ * bit, and reset the loop to fine tune with the ++ * remaining values. ++ */ ++ cdr_pr_idac |= BIT(prcal_search_bit - 1); ++ remaining_prcal_search_bits = prcal_search_bit - 1; ++ prcal_search_bit = 0; ++ } else { ++ /* Update the signal level diff and try the next bit */ ++ fl_out_diff = fl_out_diff_new; ++ ++ /* If we didn't found the deadline, set the last bit ++ * and reset the loop to fine tune with the remainig ++ * values. ++ */ ++ if (prcal_search_bit == remaining_prcal_search_bits - 1) { ++ cdr_pr_idac |= BIT(prcal_search_bit); ++ remaining_prcal_search_bits = prcal_search_bit; ++ prcal_search_bit = 0; ++ } else { ++ prcal_search_bit++; ++ } ++ } ++ } ++ ++ return cdr_pr_idac; ++} ++ ++static void an7581_pcs_rx_prcal(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ u32 cdr_pr_idac_major, cdr_pr_idac; ++ unsigned int fl_out, fl_out_diff; ++ ++ u32 target_fl_out; ++ u32 cyclecnt; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: /* DS_1.25G / US_1.25G */ ++ case PHY_INTERFACE_MODE_1000BASEX: ++ target_fl_out = 0xa3d6; ++ cyclecnt = 32767; ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: /* DS_9.95328G / US_9.95328G */ ++ target_fl_out = 0xa000; ++ cyclecnt = 20000; ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: /* DS_10.3125G / US_1.25G */ ++ case PHY_INTERFACE_MODE_10GBASER: ++ target_fl_out = 0x9edf; ++ cyclecnt = 32767; ++ break; ++ default: ++ return; ++ } ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_REF_RST_N); ++ ++ usleep_range(100, 200); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FREQ_DET_2, ++ AIROHA_PCS_PMA_LOCK_TARGET_END | ++ AIROHA_PCS_PMA_LOCK_TARGET_BEG, ++ FIELD_PREP(AIROHA_PCS_PMA_LOCK_TARGET_END, target_fl_out + 100) | ++ FIELD_PREP(AIROHA_PCS_PMA_LOCK_TARGET_BEG, target_fl_out - 100)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FREQ_DET_1, ++ AIROHA_PCS_PMA_UNLOCK_CYCLECNT | ++ AIROHA_PCS_PMA_LOCK_CYCLECNT, ++ FIELD_PREP(AIROHA_PCS_PMA_UNLOCK_CYCLECNT, cyclecnt) | ++ FIELD_PREP(AIROHA_PCS_PMA_LOCK_CYCLECNT, cyclecnt)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FREQ_DET_4, ++ AIROHA_PCS_PMA_LOCK_UNLOCKTH | ++ AIROHA_PCS_PMA_LOCK_LOCKTH, ++ FIELD_PREP(AIROHA_PCS_PMA_LOCK_UNLOCKTH, 3) | ++ FIELD_PREP(AIROHA_PCS_PMA_LOCK_LOCKTH, 3)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FREQ_DET_3, ++ AIROHA_PCS_PMA_UNLOCK_TARGET_END | ++ AIROHA_PCS_PMA_UNLOCK_TARGET_BEG, ++ FIELD_PREP(AIROHA_PCS_PMA_UNLOCK_TARGET_END, target_fl_out + 100) | ++ FIELD_PREP(AIROHA_PCS_PMA_UNLOCK_TARGET_BEG, target_fl_out - 100)); ++ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_INJ_MODE, ++ AIROHA_PCS_ANA_CDR_PR_INJ_FORCE_OFF); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_LPF_C_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_R_EN | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_LPF_R_EN | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_C_EN | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_LPF_C_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_R_EN | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_LPF_R_EN | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_C_EN); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_IDAC, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_IDAC); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PWDB); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB); ++ ++ /* Calibration logic: ++ * First check the major value by looping with every ++ * value in the last 3 bit of CDR_PR_IDAC. ++ * Get the signal level and save the value that is closer to ++ * the target. ++ * ++ * Then check each remaining 7 bits in search of the deadline ++ * where the signal gets farther than signal target. ++ * ++ * Finally fine tune for the remaining bits to find the one that ++ * produce the closest signal level. ++ */ ++ cdr_pr_idac_major = an7581_pcs_rx_prcal_idac_major(priv, target_fl_out); ++ ++ cdr_pr_idac = an7581_pcs_rx_prcal_idac_minor(priv, target_fl_out, cdr_pr_idac_major); ++ ++ fl_out = an7581_pcs_apply_cdr_pr_idac(priv, cdr_pr_idac); ++ fl_out_diff = abs(fl_out - target_fl_out); ++ if (fl_out_diff > 100) { ++ u32 pr_idac_major = FIELD_GET(AIROHA_PCS_PMA_FORCE_CDR_PR_IDAC_MAJOR, ++ cdr_pr_idac_major); ++ unsigned int fl_out_tmp, fl_out_diff_tmp; ++ u32 cdr_pr_idac_tmp; ++ ++ if (pr_idac_major > 0) { ++ cdr_pr_idac_tmp = FIELD_PREP(AIROHA_PCS_PMA_FORCE_CDR_PR_IDAC_MAJOR, ++ pr_idac_major - 1); ++ ++ dev_dbg(priv->dev, "Fl Out is %d far from target %d with Pr Idac %x. Trying with Pr Idac %x.\n", ++ fl_out_diff, target_fl_out, cdr_pr_idac_major, cdr_pr_idac_tmp); ++ ++ cdr_pr_idac_tmp = an7581_pcs_rx_prcal_idac_minor(priv, target_fl_out, ++ cdr_pr_idac_tmp); ++ ++ fl_out_tmp = an7581_pcs_apply_cdr_pr_idac(priv, cdr_pr_idac_tmp); ++ fl_out_diff_tmp = abs(fl_out_tmp - target_fl_out); ++ if (fl_out_diff_tmp < fl_out_diff) { ++ fl_out = fl_out_tmp; ++ fl_out_diff = fl_out_diff_tmp; ++ cdr_pr_idac = cdr_pr_idac_tmp; ++ } ++ } ++ } ++ dev_dbg(priv->dev, "Selected CDR Pr Idac: %x Fl Out: %x\n", cdr_pr_idac, fl_out); ++ if (fl_out_diff > 100) ++ dev_dbg(priv->dev, "Fl Out is %d far from target %d on intermediate calibration.\n", ++ fl_out_diff, target_fl_out); ++ ++ ++ /* Setup Load Band */ ++ regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_INJ_MODE, ++ AIROHA_PCS_ANA_CDR_PR_INJ_FORCE_OFF); ++ ++ /* Disable force of LPF C previously enabled */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_LPF_C_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_LPF_C_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_IDAC, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_IDAC); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_B, ++ AIROHA_PCS_PMA_LOAD_EN); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_1, ++ AIROHA_PCS_PMA_LPATH_IDAC, ++ FIELD_PREP(AIROHA_PCS_PMA_LPATH_IDAC, cdr_pr_idac)); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PWDB); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_REF_RST_N); ++ ++ usleep_range(100, 200); ++} ++ ++/* This is used to both calibrate and lock to signal (after a previous ++ * calibration) after a global reset. ++ */ ++static void an7581_pcs_cdr_reset(struct airoha_pcs_priv *priv, ++ phy_interface_t interface, bool calibrate) ++{ ++ /* Setup LPF L2D force and disable */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA); ++ ++ /* Calibrate IDAC and setup Load Band */ ++ if (calibrate) ++ an7581_pcs_rx_prcal(priv, interface); ++ ++ /* Setup LPF RSTB force and disable */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB); ++ ++ usleep_range(700, 1000); ++ ++ /* Force Enable LPF RSTB */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB); ++ ++ usleep_range(100, 200); ++ ++ /* Force Enable LPF L2D */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA); ++ ++ /* Disable LPF RSTB force bit */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB); ++ ++ /* Disable LPF L2D force bit */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA); ++} ++ ++static int an7581_pcs_phya_bringup(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ int calibration_try = 0; ++ u32 val; ++ ++ an7581_pcs_tx_bringup(priv, interface); ++ an7581_pcs_rx_bringup(priv, interface); ++ ++ usleep_range(100, 200); ++ ++retry_calibration: ++ an7581_pcs_cdr_reset(priv, interface, priv->manual_rx_calib); ++ ++ /* Global reset clear */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_HSG_RXPCS_RST_N | ++ AIROHA_PCS_PMA_SW_HSG_TXPCS_RST_N | ++ AIROHA_PCS_PMA_SW_XFI_RXPCS_BIST_RST_N | ++ AIROHA_PCS_PMA_SW_XFI_RXPCS_RST_N | ++ AIROHA_PCS_PMA_SW_XFI_TXPCS_RST_N | ++ AIROHA_PCS_PMA_SW_TX_FIFO_RST_N | ++ AIROHA_PCS_PMA_SW_REF_RST_N | ++ AIROHA_PCS_PMA_SW_ALLPCS_RST_N | ++ AIROHA_PCS_PMA_SW_PMA_RST_N | ++ AIROHA_PCS_PMA_SW_TX_RST_N | ++ AIROHA_PCS_PMA_SW_RX_RST_N | ++ AIROHA_PCS_PMA_SW_RX_FIFO_RST_N, ++ AIROHA_PCS_PMA_SW_REF_RST_N); ++ ++ usleep_range(100, 200); ++ ++ /* Global reset */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_HSG_RXPCS_RST_N | ++ AIROHA_PCS_PMA_SW_HSG_TXPCS_RST_N | ++ AIROHA_PCS_PMA_SW_XFI_RXPCS_BIST_RST_N | ++ AIROHA_PCS_PMA_SW_XFI_RXPCS_RST_N | ++ AIROHA_PCS_PMA_SW_XFI_TXPCS_RST_N | ++ AIROHA_PCS_PMA_SW_TX_FIFO_RST_N | ++ AIROHA_PCS_PMA_SW_REF_RST_N | ++ AIROHA_PCS_PMA_SW_ALLPCS_RST_N | ++ AIROHA_PCS_PMA_SW_PMA_RST_N | ++ AIROHA_PCS_PMA_SW_TX_RST_N | ++ AIROHA_PCS_PMA_SW_RX_RST_N | ++ AIROHA_PCS_PMA_SW_RX_FIFO_RST_N); ++ ++ usleep_range(5000, 7000); ++ ++ an7581_pcs_cdr_reset(priv, interface, false); ++ ++ /* Manual RX calibration is required only for SoC before E2 ++ * revision. E2+ SoC autocalibrate RX and only CDR reset is needed. ++ */ ++ if (!priv->manual_rx_calib) ++ return 0; ++ ++ /* It was discovered that after a global reset and auto mode gets ++ * actually enabled, the fl_out from calibration might change and ++ * might deviates a lot from the expected value it was calibrated for. ++ * To correctly work, the PCS FreqDet module needs to Lock to the fl_out ++ * (frequency level output) or no signal can correctly be transmitted. ++ * This is detected by checking the FreqDet module Lock bit. ++ * ++ * If it's detected that the FreqDet module is not locked, retry ++ * calibration. From observation on real hardware with a 10g SFP module, ++ * it required a maximum of an additional calibration to actually make ++ * the FreqDet module to lock. Try 10 times before failing to handle ++ * really strange case. ++ */ ++ regmap_read(priv->xfi_pma, AIROHA_PCS_PMA_RX_FREQDET, &val); ++ if (!(val & AIROHA_PCS_PMA_FBCK_LOCK)) { ++ if (calibration_try > AIROHA_PCS_MAX_CALIBRATION_TRY) { ++ dev_err(priv->dev, "No FBCK Lock from FreqDet module after %d calibration try. PCS won't work.\n", ++ AIROHA_PCS_MAX_CALIBRATION_TRY); ++ return -EIO; ++ } ++ ++ calibration_try++; ++ ++ dev_dbg(priv->dev, "No FBCK Lock from FreqDet module, retry calibration.\n"); ++ goto retry_calibration; ++ } ++ ++ return 0; ++} ++ ++static void an7581_pcs_pll_bringup(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ an7581_pcs_jcpll_bringup(priv, interface); ++ ++ usleep_range(200, 300); ++ ++ an7581_pcs_txpll_bringup(priv, interface); ++ ++ usleep_range(200, 300); ++} ++ ++int an7581_pcs_bringup(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ /* Enable Analog Common Lane */ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CMN_EN, ++ AIROHA_PCS_ANA_CMN_EN); ++ ++ /* Setup PLL */ ++ an7581_pcs_pll_bringup(priv, interface); ++ ++ /* Setup PHYA */ ++ return an7581_pcs_phya_bringup(priv, interface); ++} ++ ++void an7581_pcs_phya_link_up(struct airoha_pcs_priv *priv) ++{ ++ /* Reset TXPCS on link up */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_HSG_TXPCS_RST_N); ++ ++ usleep_range(100, 200); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_HSG_TXPCS_RST_N); ++} ++ ++static bool an7581_pcs_have_rx_signal(struct airoha_pcs_priv *priv) ++{ ++ unsigned int count = 0; ++ u32 val; ++ int i; ++ ++ regmap_write(priv->xfi_pma, AIROHA_PCS_PMA_DIG_RESERVE_0, ++ AIROHA_PCS_TRIGGER_RX_SIDGET_SCAN); ++ ++ /* Scan 5 times for RX sigdet module to detect RX signal */ ++ for (i = 0; i <= 5; i++) { ++ regmap_read(priv->xfi_pma, AIROHA_PCS_PMA_DIG_RO_RESERVE_2, ++ &val); ++ if (val & AIROHA_PCS_RX_SIGDET) ++ count++; ++ } ++ ++ /* Consider signal presence if we detect signal at least 4 times */ ++ return count >= 4; ++} ++ ++int an7581_pcs_rxlock_workaround(struct airoha_pcs_priv *priv) ++{ ++ u32 val; ++ ++ /* Check if PCS is UP or Down */ ++ regmap_read(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_STUS_1, &val); ++ if (val & AIROHA_PCS_USXGMII_PCS_RX_LINK_STATUS_UP) ++ return 0; ++ ++ /* Validate if this is consistent with RX SigDet module */ ++ if (!an7581_pcs_have_rx_signal(priv)) ++ return 0; ++ ++ /* If PCS is down but RX SigDet module detected signal, ++ * trigger CDR reset. ++ */ ++ an7581_pcs_cdr_reset(priv, PHY_INTERFACE_MODE_NA, false); ++ ++ /* Report there is an error with Link Detection and we ++ * should test again later. ++ */ ++ return -EINVAL; ++} +--- /dev/null ++++ b/include/linux/pcs/pcs-airoha.h +@@ -0,0 +1,9 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#ifndef __LINUX_PCS_AIROHA_H ++#define __LINUX_PCS_AIROHA_H ++ ++struct phylink_pcs *airoha_pcs_create(struct device *dev); ++void airoha_pcs_destroy(struct phylink_pcs *pcs); ++ ++#endif /* __LINUX_PCS_AIROHA_H */ diff --git a/lede/target/linux/airoha/patches-6.12/116-10-net-airoha-add-phylink-support-for-GDM2-4.patch b/lede/target/linux/airoha/patches-6.12/116-10-net-airoha-add-phylink-support-for-GDM2-4.patch new file mode 100644 index 0000000000..d0e658b81e --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/116-10-net-airoha-add-phylink-support-for-GDM2-4.patch @@ -0,0 +1,257 @@ +From bdcad9ab6b0f071e8492d88064a58323d7155aa7 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 17 Jan 2025 13:23:13 +0100 +Subject: [PATCH] net: airoha: add phylink support for GDM2/4 + +Add phylink support for GDM2/4 port that require configuration of the +PCS to make the external PHY or attached SFP cage work. + +Signed-off-by: Christian Marangi +--- + drivers/net/ethernet/airoha/airoha_eth.c | 133 ++++++++++++++++++++++ + drivers/net/ethernet/airoha/airoha_eth.h | 4 + + drivers/net/ethernet/airoha/airoha_regs.h | 12 ++ + 3 files changed, 149 insertions(+) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -71,6 +72,11 @@ static void airoha_qdma_irq_disable(stru + airoha_qdma_set_irqmask(irq_bank, index, mask, 0); + } + ++static bool airhoa_is_phy_external(struct airoha_gdm_port *port) ++{ ++ return port->id != 1; ++} ++ + static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr) + { + struct airoha_eth *eth = port->qdma->eth; +@@ -1621,6 +1627,17 @@ static int airoha_dev_open(struct net_de + struct airoha_gdm_port *port = netdev_priv(dev); + struct airoha_qdma *qdma = port->qdma; + ++ if (airhoa_is_phy_external(port)) { ++ err = phylink_of_phy_connect(port->phylink, dev->dev.of_node, 0); ++ if (err) { ++ netdev_err(dev, "%s: could not attach PHY: %d\n", __func__, ++ err); ++ return err; ++ } ++ ++ phylink_start(port->phylink); ++ } ++ + netif_tx_start_all_queues(dev); + err = airoha_set_vip_for_gdm_port(port, true); + if (err) +@@ -1674,6 +1691,11 @@ static int airoha_dev_stop(struct net_de + } + } + ++ if (airhoa_is_phy_external(port)) { ++ phylink_stop(port->phylink); ++ phylink_disconnect_phy(port->phylink); ++ } ++ + return 0; + } + +@@ -2816,6 +2838,20 @@ static const struct ethtool_ops airoha_e + .get_link = ethtool_op_get_link, + }; + ++static struct phylink_pcs *airoha_phylink_mac_select_pcs(struct phylink_config *config, ++ phy_interface_t interface) ++{ ++ struct airoha_gdm_port *port = container_of(config, struct airoha_gdm_port, ++ phylink_config); ++ ++ return port->pcs; ++} ++ ++static void airoha_mac_config(struct phylink_config *config, unsigned int mode, ++ const struct phylink_link_state *state) ++{ ++} ++ + static int airoha_metadata_dst_alloc(struct airoha_gdm_port *port) + { + int i; +@@ -2860,6 +2896,99 @@ bool airoha_is_valid_gdm_port(struct air + return false; + } + ++static void airoha_mac_link_up(struct phylink_config *config, struct phy_device *phy, ++ unsigned int mode, phy_interface_t interface, ++ int speed, int duplex, bool tx_pause, bool rx_pause) ++{ ++ struct airoha_gdm_port *port = container_of(config, struct airoha_gdm_port, ++ phylink_config); ++ struct airoha_qdma *qdma = port->qdma; ++ struct airoha_eth *eth = qdma->eth; ++ u32 frag_size_tx, frag_size_rx; ++ ++ switch (speed) { ++ case SPEED_10000: ++ case SPEED_5000: ++ frag_size_tx = 8; ++ frag_size_rx = 8; ++ break; ++ case SPEED_2500: ++ frag_size_tx = 2; ++ frag_size_rx = 1; ++ break; ++ default: ++ frag_size_tx = 1; ++ frag_size_rx = 0; ++ } ++ ++ /* Configure TX/RX frag based on speed */ ++ if (port->id == 4) { ++ airoha_fe_rmw(eth, REG_GDMA4_TMBI_FRAG, GDMA4_SGMII0_TX_FRAG_SIZE, ++ FIELD_PREP(GDMA4_SGMII0_TX_FRAG_SIZE, frag_size_tx)); ++ ++ airoha_fe_rmw(eth, REG_GDMA4_RMBI_FRAG, GDMA4_SGMII0_RX_FRAG_SIZE, ++ FIELD_PREP(GDMA4_SGMII0_RX_FRAG_SIZE, frag_size_rx)); ++ } ++} ++ ++static void airoha_mac_link_down(struct phylink_config *config, unsigned int mode, ++ phy_interface_t interface) ++{ ++} ++ ++static const struct phylink_mac_ops airoha_phylink_ops = { ++ .mac_select_pcs = airoha_phylink_mac_select_pcs, ++ .mac_config = airoha_mac_config, ++ .mac_link_up = airoha_mac_link_up, ++ .mac_link_down = airoha_mac_link_down, ++}; ++ ++static int airoha_setup_phylink(struct net_device *dev) ++{ ++ struct airoha_gdm_port *port = netdev_priv(dev); ++ struct device_node *np = dev->dev.of_node; ++ phy_interface_t phy_mode; ++ struct phylink *phylink; ++ int err; ++ ++ err = of_get_phy_mode(np, &phy_mode); ++ if (err) { ++ dev_err(&dev->dev, "incorrect phy-mode\n"); ++ return err; ++ } ++ ++ port->phylink_config.dev = &dev->dev; ++ port->phylink_config.type = PHYLINK_NETDEV; ++ port->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | ++ MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD | ++ MAC_5000FD | MAC_10000FD; ++ ++ __set_bit(PHY_INTERFACE_MODE_SGMII, ++ port->phylink_config.supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_1000BASEX, ++ port->phylink_config.supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_2500BASEX, ++ port->phylink_config.supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_USXGMII, ++ port->phylink_config.supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_10GBASER, ++ port->phylink_config.supported_interfaces); ++ ++ port->pcs = airoha_pcs_create(&dev->dev); ++ if (IS_ERR(port->pcs)) ++ return PTR_ERR(port->pcs); ++ ++ phylink = phylink_create(&port->phylink_config, ++ of_fwnode_handle(np), ++ phy_mode, &airoha_phylink_ops); ++ if (IS_ERR(phylink)) ++ return PTR_ERR(phylink); ++ ++ port->phylink = phylink; ++ ++ return 0; ++} ++ + static int airoha_alloc_gdm_port(struct airoha_eth *eth, + struct device_node *np, int index) + { +@@ -2938,6 +3067,12 @@ static int airoha_alloc_gdm_port(struct + if (err) + return err; + ++ if (airhoa_is_phy_external(port)) { ++ err = airoha_setup_phylink(dev); ++ if (err) ++ goto free_metadata_dst; ++ } ++ + err = register_netdev(dev); + if (err) + goto free_metadata_dst; +@@ -3053,6 +3188,10 @@ error_hw_cleanup: + if (port && port->dev->reg_state == NETREG_REGISTERED) { + unregister_netdev(port->dev); + airoha_metadata_dst_free(port); ++ if (airhoa_is_phy_external(port)) { ++ phylink_destroy(port->phylink); ++ airoha_pcs_destroy(port->pcs); ++ } + } + } + free_netdev(eth->napi_dev); +@@ -3080,6 +3219,10 @@ static void airoha_remove(struct platfor + airoha_dev_stop(port->dev); + unregister_netdev(port->dev); + airoha_metadata_dst_free(port); ++ if (airhoa_is_phy_external(port)) { ++ phylink_destroy(port->phylink); ++ airoha_pcs_destroy(port->pcs); ++ } + } + free_netdev(eth->napi_dev); + +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -536,6 +536,10 @@ struct airoha_gdm_port { + struct net_device *dev; + int id; + ++ struct phylink *phylink; ++ struct phylink_config phylink_config; ++ struct phylink_pcs *pcs; ++ + struct airoha_hw_stats stats; + + DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS); +--- a/drivers/net/ethernet/airoha/airoha_regs.h ++++ b/drivers/net/ethernet/airoha/airoha_regs.h +@@ -359,6 +359,18 @@ + #define IP_FRAGMENT_PORT_MASK GENMASK(8, 5) + #define IP_FRAGMENT_NBQ_MASK GENMASK(4, 0) + ++#define REG_GDMA4_TMBI_FRAG 0x2028 ++#define GDMA4_SGMII1_TX_WEIGHT GENMASK(31, 26) ++#define GDMA4_SGMII1_TX_FRAG_SIZE GENMASK(25, 16) ++#define GDMA4_SGMII0_TX_WEIGHT GENMASK(15, 10) ++#define GDMA4_SGMII0_TX_FRAG_SIZE GENMASK(9, 0) ++ ++#define REG_GDMA4_RMBI_FRAG 0x202c ++#define GDMA4_SGMII1_RX_WEIGHT GENMASK(31, 26) ++#define GDMA4_SGMII1_RX_FRAG_SIZE GENMASK(25, 16) ++#define GDMA4_SGMII0_RX_WEIGHT GENMASK(15, 10) ++#define GDMA4_SGMII0_RX_FRAG_SIZE GENMASK(9, 0) ++ + #define REG_MC_VLAN_EN 0x2100 + #define MC_VLAN_EN_MASK BIT(0) + diff --git a/lede/target/linux/airoha/patches-6.12/123-01-ASoC-mediatek-move-some-header-to-global-include.patch b/lede/target/linux/airoha/patches-6.12/123-01-ASoC-mediatek-move-some-header-to-global-include.patch new file mode 100644 index 0000000000..c9cdb9a326 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/123-01-ASoC-mediatek-move-some-header-to-global-include.patch @@ -0,0 +1,410 @@ +From 527123b53739a2f73ca924b9c6e2f63dc66739a5 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 1 Aug 2025 11:06:56 +0200 +Subject: [PATCH 1/3] ASoC: mediatek: move some header to global include + +In preparation for support of Airoha SoC sound system based on Mediatek +AFE, move some header to global include to prevent having to use complex +redirection for inclusion. + +Signed-off-by: Christian Marangi +--- + .../common => include/sound/mediatek}/mtk-afe-fe-dai.h | 0 + .../sound/mediatek}/mtk-afe-platform-driver.h | 0 + sound/soc/mediatek/common/mtk-afe-fe-dai.c | 4 ++-- + sound/soc/mediatek/common/mtk-afe-platform-driver.c | 2 +- + sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | 4 ++-- + sound/soc/mediatek/mt6797/mt6797-afe-pcm.c | 4 ++-- + sound/soc/mediatek/mt7986/mt7986-afe-pcm.c | 4 ++-- + sound/soc/mediatek/mt8173/mt8173-afe-pcm.c | 4 ++-- + sound/soc/mediatek/mt8183/mt8183-afe-pcm.c | 4 ++-- + sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c | 2 +- + sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c | 2 +- + sound/soc/mediatek/mt8186/mt8186-afe-pcm.c | 4 ++-- + sound/soc/mediatek/mt8186/mt8186-misc-control.c | 4 ++-- + sound/soc/mediatek/mt8186/mt8186-mt6366-common.c | 2 +- + sound/soc/mediatek/mt8186/mt8186-mt6366.c | 2 +- + sound/soc/mediatek/mt8188/mt8188-afe-pcm.c | 4 ++-- + sound/soc/mediatek/mt8188/mt8188-mt6359.c | 2 +- + sound/soc/mediatek/mt8192/mt8192-afe-pcm.c | 4 ++-- + sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c | 2 +- + sound/soc/mediatek/mt8195/mt8195-afe-pcm.c | 4 ++-- + sound/soc/mediatek/mt8195/mt8195-mt6359.c | 2 +- + sound/soc/mediatek/mt8365/mt8365-afe-pcm.c | 4 ++-- + 22 files changed, 32 insertions(+), 32 deletions(-) + rename {sound/soc/mediatek/common => include/sound/mediatek}/mtk-afe-fe-dai.h (100%) + rename {sound/soc/mediatek/common => include/sound/mediatek}/mtk-afe-platform-driver.h (100%) + +--- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c ++++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c +@@ -11,9 +11,9 @@ + #include + #include + #include +-#include "mtk-afe-platform-driver.h" ++#include + #include +-#include "mtk-afe-fe-dai.h" ++#include + #include "mtk-base-afe.h" + + #define AFE_BASE_END_OFFSET 8 +--- a/sound/soc/mediatek/common/mtk-afe-platform-driver.c ++++ b/sound/soc/mediatek/common/mtk-afe-platform-driver.c +@@ -10,7 +10,7 @@ + #include + #include + +-#include "mtk-afe-platform-driver.h" ++#include + #include "mtk-base-afe.h" + + int mtk_afe_combine_sub_dai(struct mtk_base_afe *afe) +--- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c ++++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +@@ -16,8 +16,8 @@ + + #include "mt2701-afe-common.h" + #include "mt2701-afe-clock-ctrl.h" +-#include "../common/mtk-afe-platform-driver.h" +-#include "../common/mtk-afe-fe-dai.h" ++#include ++#include + + static const struct snd_pcm_hardware mt2701_afe_hardware = { + .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED +--- a/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c ++++ b/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c +@@ -16,8 +16,8 @@ + #include "mt6797-afe-clk.h" + #include "mt6797-interconnection.h" + #include "mt6797-reg.h" +-#include "../common/mtk-afe-platform-driver.h" +-#include "../common/mtk-afe-fe-dai.h" ++#include ++#include + + enum { + MTK_AFE_RATE_8K = 0, +--- a/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c ++++ b/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c +@@ -16,8 +16,8 @@ + + #include "mt7986-afe-common.h" + #include "mt7986-reg.h" +-#include "../common/mtk-afe-platform-driver.h" +-#include "../common/mtk-afe-fe-dai.h" ++#include ++#include + + enum { + MTK_AFE_RATE_8K = 0, +--- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c ++++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +@@ -19,8 +19,8 @@ + #include + #include "mt8173-afe-common.h" + #include "../common/mtk-base-afe.h" +-#include "../common/mtk-afe-platform-driver.h" +-#include "../common/mtk-afe-fe-dai.h" ++#include ++#include + + /***************************************************************************** + * R E G I S T E R D E F I N I T I O N +--- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c ++++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c +@@ -18,8 +18,8 @@ + #include "mt8183-afe-clk.h" + #include "mt8183-interconnection.h" + #include "mt8183-reg.h" +-#include "../common/mtk-afe-platform-driver.h" +-#include "../common/mtk-afe-fe-dai.h" ++#include ++#include + + enum { + MTK_AFE_RATE_8K = 0, +--- a/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c ++++ b/sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c +@@ -16,7 +16,7 @@ + + #include "../../codecs/da7219.h" + #include "../../codecs/rt1015.h" +-#include "../common/mtk-afe-platform-driver.h" ++#include + #include "mt8183-afe-common.h" + + #define DA7219_CODEC_DAI "da7219-hifi" +--- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c ++++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +@@ -15,7 +15,7 @@ + + #include "../../codecs/rt1015.h" + #include "../../codecs/ts3a227e.h" +-#include "../common/mtk-afe-platform-driver.h" ++#include + #include "mt8183-afe-common.h" + + #define RT1015_CODEC_DAI "rt1015-aif" +--- a/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c ++++ b/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c +@@ -15,8 +15,8 @@ + #include + #include + +-#include "../common/mtk-afe-platform-driver.h" +-#include "../common/mtk-afe-fe-dai.h" ++#include ++#include + + #include "mt8186-afe-common.h" + #include "mt8186-afe-clk.h" +--- a/sound/soc/mediatek/mt8186/mt8186-misc-control.c ++++ b/sound/soc/mediatek/mt8186/mt8186-misc-control.c +@@ -11,8 +11,8 @@ + #include + #include + +-#include "../common/mtk-afe-fe-dai.h" +-#include "../common/mtk-afe-platform-driver.h" ++#include ++#include + #include "mt8186-afe-common.h" + + static const char * const mt8186_sgen_mode_str[] = { +--- a/sound/soc/mediatek/mt8186/mt8186-mt6366-common.c ++++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-common.c +@@ -9,7 +9,7 @@ + #include + + #include "../../codecs/mt6358.h" +-#include "../common/mtk-afe-platform-driver.h" ++#include + #include "mt8186-afe-common.h" + #include "mt8186-mt6366-common.h" + +--- a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c ++++ b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c +@@ -24,8 +24,8 @@ + #include "mt8188-afe-common.h" + #include "mt8188-afe-clk.h" + #include "mt8188-reg.h" +-#include "../common/mtk-afe-platform-driver.h" +-#include "../common/mtk-afe-fe-dai.h" ++#include ++#include + + #define MT8188_MEMIF_BUFFER_BYTES_ALIGN (0x40) + #define MT8188_MEMIF_DL7_MAX_PERIOD_SIZE (0x3fff) +--- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c ++++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c +@@ -17,8 +17,8 @@ + #include + #include + +-#include "../common/mtk-afe-fe-dai.h" +-#include "../common/mtk-afe-platform-driver.h" ++#include ++#include + + #include "mt8192-afe-common.h" + #include "mt8192-afe-clk.h" +--- a/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c ++++ b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c +@@ -20,8 +20,8 @@ + #include "mt8195-afe-common.h" + #include "mt8195-afe-clk.h" + #include "mt8195-reg.h" +-#include "../common/mtk-afe-platform-driver.h" +-#include "../common/mtk-afe-fe-dai.h" ++#include ++#include + + #define MT8195_MEMIF_BUFFER_BYTES_ALIGN (0x40) + #define MT8195_MEMIF_DL7_MAX_PERIOD_SIZE (0x3fff) +--- a/sound/soc/mediatek/mt8195/mt8195-mt6359.c ++++ b/sound/soc/mediatek/mt8195/mt8195-mt6359.c +@@ -19,7 +19,7 @@ + #include "../../codecs/mt6359.h" + #include "../../codecs/rt1011.h" + #include "../../codecs/rt5682.h" +-#include "../common/mtk-afe-platform-driver.h" ++#include + #include "../common/mtk-dsp-sof-common.h" + #include "../common/mtk-soc-card.h" + #include "../common/mtk-soundcard-driver.h" +--- /dev/null ++++ b/include/sound/mediatek/mtk-afe-fe-dai.h +@@ -0,0 +1,53 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * mtk-afe-fe-dais.h -- Mediatek afe fe dai operator definition ++ * ++ * Copyright (c) 2016 MediaTek Inc. ++ * Author: Garlic Tseng ++ */ ++ ++#ifndef _MTK_AFE_FE_DAI_H_ ++#define _MTK_AFE_FE_DAI_H_ ++ ++struct snd_soc_dai_ops; ++struct mtk_base_afe; ++struct mtk_base_afe_memif; ++ ++int mtk_afe_fe_startup(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai); ++void mtk_afe_fe_shutdown(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai); ++int mtk_afe_fe_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params, ++ struct snd_soc_dai *dai); ++int mtk_afe_fe_hw_free(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai); ++int mtk_afe_fe_prepare(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai); ++int mtk_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd, ++ struct snd_soc_dai *dai); ++ ++extern const struct snd_soc_dai_ops mtk_afe_fe_ops; ++ ++int mtk_dynamic_irq_acquire(struct mtk_base_afe *afe); ++int mtk_dynamic_irq_release(struct mtk_base_afe *afe, int irq_id); ++int mtk_afe_suspend(struct snd_soc_component *component); ++int mtk_afe_resume(struct snd_soc_component *component); ++ ++int mtk_memif_set_enable(struct mtk_base_afe *afe, int id); ++int mtk_memif_set_disable(struct mtk_base_afe *afe, int id); ++int mtk_memif_set_addr(struct mtk_base_afe *afe, int id, ++ unsigned char *dma_area, ++ dma_addr_t dma_addr, ++ size_t dma_bytes); ++int mtk_memif_set_channel(struct mtk_base_afe *afe, ++ int id, unsigned int channel); ++int mtk_memif_set_rate(struct mtk_base_afe *afe, ++ int id, unsigned int rate); ++int mtk_memif_set_rate_substream(struct snd_pcm_substream *substream, ++ int id, unsigned int rate); ++int mtk_memif_set_format(struct mtk_base_afe *afe, ++ int id, snd_pcm_format_t format); ++int mtk_memif_set_pbuf_size(struct mtk_base_afe *afe, ++ int id, int pbuf_size); ++#endif +--- /dev/null ++++ b/include/sound/mediatek/mtk-afe-platform-driver.h +@@ -0,0 +1,28 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * mtk-afe-platform-driver.h -- Mediatek afe platform driver definition ++ * ++ * Copyright (c) 2016 MediaTek Inc. ++ * Author: Garlic Tseng ++ */ ++ ++#ifndef _MTK_AFE_PLATFORM_DRIVER_H_ ++#define _MTK_AFE_PLATFORM_DRIVER_H_ ++ ++#define AFE_PCM_NAME "mtk-afe-pcm" ++extern const struct snd_soc_component_driver mtk_afe_pcm_platform; ++ ++struct mtk_base_afe; ++struct snd_pcm; ++struct snd_soc_component; ++struct snd_soc_pcm_runtime; ++ ++snd_pcm_uframes_t mtk_afe_pcm_pointer(struct snd_soc_component *component, ++ struct snd_pcm_substream *substream); ++int mtk_afe_pcm_new(struct snd_soc_component *component, ++ struct snd_soc_pcm_runtime *rtd); ++ ++int mtk_afe_combine_sub_dai(struct mtk_base_afe *afe); ++int mtk_afe_add_sub_dai_control(struct snd_soc_component *component); ++#endif ++ +--- a/sound/soc/mediatek/common/mtk-afe-fe-dai.h ++++ /dev/null +@@ -1,53 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ +-/* +- * mtk-afe-fe-dais.h -- Mediatek afe fe dai operator definition +- * +- * Copyright (c) 2016 MediaTek Inc. +- * Author: Garlic Tseng +- */ +- +-#ifndef _MTK_AFE_FE_DAI_H_ +-#define _MTK_AFE_FE_DAI_H_ +- +-struct snd_soc_dai_ops; +-struct mtk_base_afe; +-struct mtk_base_afe_memif; +- +-int mtk_afe_fe_startup(struct snd_pcm_substream *substream, +- struct snd_soc_dai *dai); +-void mtk_afe_fe_shutdown(struct snd_pcm_substream *substream, +- struct snd_soc_dai *dai); +-int mtk_afe_fe_hw_params(struct snd_pcm_substream *substream, +- struct snd_pcm_hw_params *params, +- struct snd_soc_dai *dai); +-int mtk_afe_fe_hw_free(struct snd_pcm_substream *substream, +- struct snd_soc_dai *dai); +-int mtk_afe_fe_prepare(struct snd_pcm_substream *substream, +- struct snd_soc_dai *dai); +-int mtk_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd, +- struct snd_soc_dai *dai); +- +-extern const struct snd_soc_dai_ops mtk_afe_fe_ops; +- +-int mtk_dynamic_irq_acquire(struct mtk_base_afe *afe); +-int mtk_dynamic_irq_release(struct mtk_base_afe *afe, int irq_id); +-int mtk_afe_suspend(struct snd_soc_component *component); +-int mtk_afe_resume(struct snd_soc_component *component); +- +-int mtk_memif_set_enable(struct mtk_base_afe *afe, int id); +-int mtk_memif_set_disable(struct mtk_base_afe *afe, int id); +-int mtk_memif_set_addr(struct mtk_base_afe *afe, int id, +- unsigned char *dma_area, +- dma_addr_t dma_addr, +- size_t dma_bytes); +-int mtk_memif_set_channel(struct mtk_base_afe *afe, +- int id, unsigned int channel); +-int mtk_memif_set_rate(struct mtk_base_afe *afe, +- int id, unsigned int rate); +-int mtk_memif_set_rate_substream(struct snd_pcm_substream *substream, +- int id, unsigned int rate); +-int mtk_memif_set_format(struct mtk_base_afe *afe, +- int id, snd_pcm_format_t format); +-int mtk_memif_set_pbuf_size(struct mtk_base_afe *afe, +- int id, int pbuf_size); +-#endif +--- a/sound/soc/mediatek/common/mtk-afe-platform-driver.h ++++ /dev/null +@@ -1,28 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ +-/* +- * mtk-afe-platform-driver.h -- Mediatek afe platform driver definition +- * +- * Copyright (c) 2016 MediaTek Inc. +- * Author: Garlic Tseng +- */ +- +-#ifndef _MTK_AFE_PLATFORM_DRIVER_H_ +-#define _MTK_AFE_PLATFORM_DRIVER_H_ +- +-#define AFE_PCM_NAME "mtk-afe-pcm" +-extern const struct snd_soc_component_driver mtk_afe_pcm_platform; +- +-struct mtk_base_afe; +-struct snd_pcm; +-struct snd_soc_component; +-struct snd_soc_pcm_runtime; +- +-snd_pcm_uframes_t mtk_afe_pcm_pointer(struct snd_soc_component *component, +- struct snd_pcm_substream *substream); +-int mtk_afe_pcm_new(struct snd_soc_component *component, +- struct snd_soc_pcm_runtime *rtd); +- +-int mtk_afe_combine_sub_dai(struct mtk_base_afe *afe); +-int mtk_afe_add_sub_dai_control(struct snd_soc_component *component); +-#endif +- diff --git a/lede/target/linux/airoha/patches-6.12/123-02-ASoC-airoha-Add-AFE-and-I2S-driver-for-Airoha-AN7581.patch b/lede/target/linux/airoha/patches-6.12/123-02-ASoC-airoha-Add-AFE-and-I2S-driver-for-Airoha-AN7581.patch new file mode 100644 index 0000000000..00578601c4 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/123-02-ASoC-airoha-Add-AFE-and-I2S-driver-for-Airoha-AN7581.patch @@ -0,0 +1,729 @@ +From 9989af6ed0dba86f57ac4aa1574f9ce9b1e640af Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 31 Jul 2025 15:32:32 +0200 +Subject: [PATCH 2/3] ASoC: airoha: Add AFE and I2S driver for Airoha AN7581 + +Add support for the Sound system present on Airoha AN7581 SoC. This is +based on the mediatek AFE drivers. + +Also add the I2S driver to create an actual sound card for the AFE. + +Signed-off-by: Christian Marangi +--- + sound/soc/Kconfig | 1 + + sound/soc/Makefile | 1 + + sound/soc/airoha/Kconfig | 19 + + sound/soc/airoha/Makefile | 2 + + sound/soc/airoha/an7581/Makefile | 8 + + sound/soc/airoha/an7581/an7581-afe-common.h | 35 ++ + sound/soc/airoha/an7581/an7581-afe-pcm.c | 455 ++++++++++++++++++++ + sound/soc/airoha/an7581/an7581-i2s.c | 110 +++++ + sound/soc/airoha/an7581/an7581-reg.h | 29 ++ + 9 files changed, 660 insertions(+) + create mode 100644 sound/soc/airoha/Kconfig + create mode 100644 sound/soc/airoha/Makefile + create mode 100644 sound/soc/airoha/an7581/Makefile + create mode 100644 sound/soc/airoha/an7581/an7581-afe-common.h + create mode 100644 sound/soc/airoha/an7581/an7581-afe-pcm.c + create mode 100644 sound/soc/airoha/an7581/an7581-i2s.c + create mode 100644 sound/soc/airoha/an7581/an7581-reg.h + +--- a/sound/soc/Kconfig ++++ b/sound/soc/Kconfig +@@ -86,6 +86,7 @@ config SND_SOC_ACPI + + # All the supported SoCs + source "sound/soc/adi/Kconfig" ++source "sound/soc/airoha/Kconfig" + source "sound/soc/amd/Kconfig" + source "sound/soc/apple/Kconfig" + source "sound/soc/atmel/Kconfig" +--- a/sound/soc/Makefile ++++ b/sound/soc/Makefile +@@ -40,6 +40,7 @@ obj-$(CONFIG_SND_SOC) += codecs/ + obj-$(CONFIG_SND_SOC) += generic/ + obj-$(CONFIG_SND_SOC) += apple/ + obj-$(CONFIG_SND_SOC) += adi/ ++obj-$(CONFIG_SND_SOC) += airoha/ + obj-$(CONFIG_SND_SOC) += amd/ + obj-$(CONFIG_SND_SOC) += atmel/ + obj-$(CONFIG_SND_SOC) += au1x/ +--- /dev/null ++++ b/sound/soc/airoha/Kconfig +@@ -0,0 +1,19 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++config SND_SOC_AN7581 ++ tristate "ASoC support for Airoha AN7581 chip" ++ depends on ARCH_AIROHA || COMPILE_TEST ++ select SND_SOC_MEDIATEK ++ help ++ This adds ASoC driver for Airoha AN7581 boards ++ that can be used with other codecs. ++ Select Y if you have such device. ++ If unsure select "N". ++ ++config SND_SOC_AN7581_I2S ++ tristate "I2S support for Airoha AN7581 chip" ++ depends on SND_SOC_AN7581 ++ help ++ This adds I2S driver for Airoha AN7581 boards ++ that can be used with other codecs. ++ Select Y if you have such device. ++ If unsure select "N". +--- /dev/null ++++ b/sound/soc/airoha/Makefile +@@ -0,0 +1,2 @@ ++# SPDX-License-Identifier: GPL-2.0 ++obj-$(CONFIG_SND_SOC_AN7581) += an7581/ +--- /dev/null ++++ b/sound/soc/airoha/an7581/Makefile +@@ -0,0 +1,8 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++# platform driver ++snd-soc-an7581-afe-y := \ ++ an7581-afe-pcm.o ++ ++obj-$(CONFIG_SND_SOC_AN7581) += snd-soc-an7581-afe.o ++obj-$(CONFIG_SND_SOC_AN7581_I2S) += an7581-i2s.o +--- /dev/null ++++ b/sound/soc/airoha/an7581/an7581-afe-common.h +@@ -0,0 +1,35 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * an7581-afe-common.h -- Airoha AN7581 audio driver definitions ++ */ ++ ++#ifndef _AN7581_AFE_COMMON_H_ ++#define _AN7581_AFE_COMMON_H_ ++ ++#include ++#include ++#include ++#include "../../mediatek/common/mtk-base-afe.h" ++ ++enum { ++ AN7581_MEMIF_DL1, ++ AN7581_MEMIF_UL1, ++ AN7581_MEMIF_NUM, ++ AN7581_DAI_NUM = AN7581_MEMIF_NUM, ++}; ++ ++enum { ++ AN7581_IRQ_0, ++ AN7581_IRQ_1, ++ AN7581_IRQ_NUM, ++}; ++ ++struct an7581_afe_private { ++ /* dai */ ++ void *dai_priv[AN7581_DAI_NUM]; ++}; ++ ++unsigned int an7581_afe_rate_transform(struct device *dev, ++ unsigned int rate); ++ ++#endif +--- /dev/null ++++ b/sound/soc/airoha/an7581/an7581-afe-pcm.c +@@ -0,0 +1,455 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Airoha ALSA SoC AFE platform driver for AN7581 ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "an7581-afe-common.h" ++#include "an7581-reg.h" ++#include ++#include ++ ++enum { ++ ARH_AFE_RATE_7K = 16, ++ ARH_AFE_RATE_8K = 0, ++ ARH_AFE_RATE_11K = 17, ++ ARH_AFE_RATE_12K = 1, ++ ARH_AFE_RATE_14K = 18, ++ ARH_AFE_RATE_16K = 2, ++ ARH_AFE_RATE_22K = 19, ++ ARH_AFE_RATE_24K = 3, ++ ARH_AFE_RATE_29K = 20, ++ ARH_AFE_RATE_32K = 4, ++ ARH_AFE_RATE_44K = 21, ++ ARH_AFE_RATE_48K = 5, ++ ARH_AFE_RATE_88K = 22, ++ ARH_AFE_RATE_96K = 6, ++ ARH_AFE_RATE_176K = 23, ++ ARH_AFE_RATE_192K = 7, ++ ARH_AFE_RATE_352K = 24, ++ ARH_AFE_RATE_384K = 8, ++}; ++ ++unsigned int an7581_afe_rate_transform(struct device *dev, unsigned int rate) ++{ ++ switch (rate) { ++ case 7350: ++ return ARH_AFE_RATE_7K; ++ case 8000: ++ return ARH_AFE_RATE_8K; ++ case 11025: ++ return ARH_AFE_RATE_11K; ++ case 12000: ++ return ARH_AFE_RATE_12K; ++ case 14700: ++ return ARH_AFE_RATE_14K; ++ case 16000: ++ return ARH_AFE_RATE_16K; ++ case 22050: ++ return ARH_AFE_RATE_22K; ++ case 24000: ++ return ARH_AFE_RATE_24K; ++ case 29400: ++ return ARH_AFE_RATE_29K; ++ case 32000: ++ return ARH_AFE_RATE_32K; ++ case 44100: ++ return ARH_AFE_RATE_44K; ++ case 48000: ++ return ARH_AFE_RATE_48K; ++ case 88200: ++ return ARH_AFE_RATE_88K; ++ case 96000: ++ return ARH_AFE_RATE_96K; ++ case 176400: ++ return ARH_AFE_RATE_176K; ++ case 192000: ++ return ARH_AFE_RATE_192K; ++ case 352800: ++ return ARH_AFE_RATE_352K; ++ case 384000: ++ return ARH_AFE_RATE_384K; ++ default: ++ dev_warn(dev, "%s(), rate %u invalid, using %d!!!\n", ++ __func__, rate, ARH_AFE_RATE_48K); ++ return ARH_AFE_RATE_48K; ++ } ++} ++ ++static const int an7581_memif_specified_irqs[AN7581_MEMIF_NUM] = { ++ [AN7581_MEMIF_DL1] = AN7581_IRQ_0, ++ [AN7581_MEMIF_UL1] = AN7581_IRQ_1, ++}; ++ ++static const struct snd_pcm_hardware an7581_afe_hardware = { ++ .info = SNDRV_PCM_INFO_MMAP | ++ SNDRV_PCM_INFO_INTERLEAVED | ++ SNDRV_PCM_INFO_MMAP_VALID, ++ .formats = SNDRV_PCM_FMTBIT_S16_LE | ++ SNDRV_PCM_FMTBIT_S24_LE | ++ SNDRV_PCM_FMTBIT_S32_LE, ++ .period_bytes_min = 512, ++ .period_bytes_max = 128 * 1024, ++ .periods_min = 2, ++ .periods_max = 256, ++ .buffer_bytes_max = 256 * 1024, ++ .fifo_size = 0, ++}; ++ ++static int an7581_memif_fs(struct snd_pcm_substream *substream, ++ unsigned int rate) ++{ ++ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); ++ struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); ++ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); ++ ++ return an7581_afe_rate_transform(afe->dev, rate); ++} ++ ++static int an7581_irq_fs(struct snd_pcm_substream *substream, ++ unsigned int rate) ++{ ++ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); ++ struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); ++ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); ++ ++ return an7581_afe_rate_transform(afe->dev, rate); ++} ++ ++#define ARH_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ ++ SNDRV_PCM_FMTBIT_S32_LE) ++ ++static struct snd_soc_dai_driver an7581_memif_dai_driver[] = { ++ /* FE DAIs: memory intefaces to CPU */ ++ { ++ .name = "DL1", ++ .id = AN7581_MEMIF_DL1, ++ .playback = { ++ .stream_name = "DL1", ++ .channels_min = 1, ++ .channels_max = 8, ++ .rates = SNDRV_PCM_RATE_8000_192000, ++ .formats = ARH_PCM_FORMATS, ++ }, ++ .ops = &mtk_afe_fe_ops, ++ }, ++ { ++ .name = "UL1", ++ .id = AN7581_MEMIF_UL1, ++ .capture = { ++ .stream_name = "UL1", ++ .channels_min = 1, ++ .channels_max = 2, ++ .rates = SNDRV_PCM_RATE_8000_192000, ++ .formats = ARH_PCM_FORMATS, ++ }, ++ .ops = &mtk_afe_fe_ops, ++ }, ++}; ++ ++static const struct snd_soc_component_driver an7581_afe_pcm_dai_component = { ++ .name = "an7581-afe-pcm-dai", ++}; ++ ++static const struct mtk_base_memif_data memif_data[AN7581_MEMIF_NUM] = { ++ [AN7581_MEMIF_DL1] = { ++ .name = "DL1", ++ .id = AN7581_MEMIF_DL1, ++ .reg_ofs_base = AFE_DL1_BASE, ++ .reg_ofs_cur = AFE_DL1_CUR, ++ .reg_ofs_end = AFE_DL1_END, ++ .fs_reg = -1, ++ .fs_shift = -1, ++ .fs_maskbit = -1, ++ .mono_reg = -1, ++ .mono_shift = -1, ++ .hd_reg = -1, ++ .hd_shift = -1, ++ .enable_reg = AFE_DAC_CON0, ++ .enable_shift = 17, ++ .msb_reg = -1, ++ .msb_shift = -1, ++ .agent_disable_reg = -1, ++ .agent_disable_shift = -1, ++ }, ++ [AN7581_MEMIF_UL1] = { ++ .name = "UL1", ++ .id = AN7581_MEMIF_UL1, ++ .reg_ofs_base = AFE_UL1_BASE, ++ .reg_ofs_cur = AFE_UL1_CUR, ++ .reg_ofs_end = AFE_UL1_END, ++ .fs_reg = -1, ++ .fs_shift = -1, ++ .fs_maskbit = -1, ++ .mono_reg = -1, ++ .mono_shift = -1, ++ .hd_reg = -1, ++ .hd_shift = -1, ++ .enable_reg = AFE_DAC_CON0, ++ .enable_shift = 1, ++ .msb_reg = -1, ++ .msb_shift = -1, ++ .agent_disable_reg = -1, ++ .agent_disable_shift = -1, ++ }, ++}; ++ ++static const struct mtk_base_irq_data irq_data[AN7581_IRQ_NUM] = { ++ [AN7581_IRQ_0] = { ++ .id = AN7581_IRQ_0, ++ .irq_cnt_reg = -1, ++ .irq_cnt_shift = -1, ++ .irq_cnt_maskbit = -1, ++ .irq_en_reg = AFE_IRQ1_CON0, ++ .irq_en_shift = 4, ++ .irq_fs_reg = -1, ++ .irq_fs_shift = -1, ++ .irq_fs_maskbit = -1, ++ .irq_clr_reg = AFE_IRQ1_CON0, ++ .irq_clr_shift = 0, ++ }, ++ [AN7581_IRQ_1] = { ++ .id = AN7581_IRQ_1, ++ .irq_cnt_reg = -1, ++ .irq_cnt_shift = -1, ++ .irq_cnt_maskbit = -1, ++ .irq_en_reg = AFE_IRQ0_CON0, ++ .irq_en_shift = 4, ++ .irq_fs_reg = -1, ++ .irq_fs_shift = -1, ++ .irq_fs_maskbit = -1, ++ .irq_clr_reg = AFE_IRQ0_CON0, ++ .irq_clr_shift = 1, ++ }, ++}; ++ ++static const struct regmap_config an7581_afe_regmap_config = { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .max_register = AFE_MAX_REGISTER, ++ .num_reg_defaults_raw = ((AFE_MAX_REGISTER / 4) + 1), ++}; ++ ++static irqreturn_t an7581_afe_irq_handler(int irq_id, void *dev) ++{ ++ struct mtk_base_afe *afe = dev; ++ struct mtk_base_afe_irq *irq; ++ u32 status; ++ u32 reg; ++ int i; ++ ++ regmap_read(afe->regmap, AFE_IRQ_STS, &status); ++ ++ if (status & AFE_IRQ_STS_RECORD) ++ reg = AFE_IRQ0_CON0; ++ else ++ reg = AFE_IRQ1_CON0; ++ ++ regmap_set_bits(afe->regmap, reg, BIT(2)); ++ regmap_clear_bits(afe->regmap, reg, BIT(2)); ++ ++ regmap_set_bits(afe->regmap, reg, BIT(3)); ++ regmap_clear_bits(afe->regmap, reg, BIT(3)); ++ ++ for (i = 0; i < AN7581_MEMIF_NUM; i++) { ++ struct mtk_base_afe_memif *memif = &afe->memif[i]; ++ ++ if (!memif->substream) ++ continue; ++ ++ if (memif->irq_usage < 0) ++ continue; ++ ++ irq = &afe->irqs[memif->irq_usage]; ++ ++ if (status & (1 << irq->irq_data->irq_clr_shift)) ++ snd_pcm_period_elapsed(memif->substream); ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static int an7581_afe_runtime_suspend(struct device *dev) ++{ ++ return 0; ++} ++ ++static int an7581_afe_runtime_resume(struct device *dev) ++{ ++ return 0; ++} ++ ++static int an7581_dai_memif_register(struct mtk_base_afe *afe) ++{ ++ struct mtk_base_afe_dai *dai; ++ ++ dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); ++ if (!dai) ++ return -ENOMEM; ++ ++ list_add(&dai->list, &afe->sub_dais); ++ ++ dai->dai_drivers = an7581_memif_dai_driver; ++ dai->num_dai_drivers = ARRAY_SIZE(an7581_memif_dai_driver); ++ ++ return 0; ++} ++ ++typedef int (*dai_register_cb)(struct mtk_base_afe *); ++static const dai_register_cb dai_register_cbs[] = { ++ an7581_dai_memif_register, ++}; ++ ++static int an7581_afe_pcm_dev_probe(struct platform_device *pdev) ++{ ++ struct mtk_base_afe *afe; ++ struct an7581_afe_private *afe_priv; ++ struct device *dev; ++ int i, irq_id, ret; ++ ++ afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL); ++ if (!afe) ++ return -ENOMEM; ++ platform_set_drvdata(pdev, afe); ++ ++ afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv), ++ GFP_KERNEL); ++ if (!afe->platform_priv) ++ return -ENOMEM; ++ ++ afe_priv = afe->platform_priv; ++ afe->dev = &pdev->dev; ++ dev = afe->dev; ++ ++ afe->base_addr = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(afe->base_addr)) ++ return PTR_ERR(afe->base_addr); ++ ++ ret = devm_pm_runtime_enable(dev); ++ if (ret) ++ return ret; ++ ++ pm_runtime_get_sync(&pdev->dev); ++ ++ afe->regmap = devm_regmap_init_mmio(&pdev->dev, afe->base_addr, ++ &an7581_afe_regmap_config); ++ ++ pm_runtime_put_sync(&pdev->dev); ++ if (IS_ERR(afe->regmap)) ++ return PTR_ERR(afe->regmap); ++ ++ mutex_init(&afe->irq_alloc_lock); ++ ++ /* irq initialize */ ++ afe->irqs_size = AN7581_IRQ_NUM; ++ afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs), ++ GFP_KERNEL); ++ if (!afe->irqs) ++ return -ENOMEM; ++ ++ for (i = 0; i < afe->irqs_size; i++) ++ afe->irqs[i].irq_data = &irq_data[i]; ++ ++ /* request irq */ ++ irq_id = platform_get_irq(pdev, 0); ++ if (irq_id < 0) ++ return irq_id; ++ ++ ret = devm_request_irq(dev, irq_id, an7581_afe_irq_handler, ++ IRQF_TRIGGER_NONE, "asys-isr", (void *)afe); ++ if (ret) ++ return dev_err_probe(dev, ret, "Failed to request irq for asys-isr\n"); ++ ++ /* init memif */ ++ afe->memif_size = AN7581_MEMIF_NUM; ++ afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif), ++ GFP_KERNEL); ++ if (!afe->memif) ++ return -ENOMEM; ++ ++ for (i = 0; i < afe->memif_size; i++) { ++ int sel_irq = an7581_memif_specified_irqs[i]; ++ ++ afe->memif[i].data = &memif_data[i]; ++ afe->memif[i].irq_usage = sel_irq; ++ afe->memif[i].const_irq = 1; ++ afe->irqs[sel_irq].irq_occupyed = true; ++ } ++ ++ /* init sub_dais */ ++ INIT_LIST_HEAD(&afe->sub_dais); ++ ++ for (i = 0; i < ARRAY_SIZE(dai_register_cbs); i++) { ++ ret = dai_register_cbs[i](afe); ++ if (ret) ++ return dev_err_probe(dev, ret, "DAI register failed, i: %d\n", i); ++ } ++ ++ /* init dai_driver and component_driver */ ++ ret = mtk_afe_combine_sub_dai(afe); ++ if (ret) ++ return dev_err_probe(dev, ret, "mtk_afe_combine_sub_dai fail\n"); ++ ++ afe->mtk_afe_hardware = &an7581_afe_hardware; ++ afe->memif_fs = an7581_memif_fs; ++ afe->irq_fs = an7581_irq_fs; ++ ++ afe->runtime_resume = an7581_afe_runtime_resume; ++ afe->runtime_suspend = an7581_afe_runtime_suspend; ++ ++ /* register component */ ++ ret = devm_snd_soc_register_component(&pdev->dev, ++ &mtk_afe_pcm_platform, ++ NULL, 0); ++ if (ret) ++ return dev_err_probe(dev, ret, "Cannot register AFE component\n"); ++ ++ ret = devm_snd_soc_register_component(afe->dev, ++ &an7581_afe_pcm_dai_component, ++ afe->dai_drivers, ++ afe->num_dai_drivers); ++ if (ret) ++ return dev_err_probe(dev, ret, "Cannot register PCM DAI component\n"); ++ ++ return 0; ++} ++ ++static void an7581_afe_pcm_dev_remove(struct platform_device *pdev) ++{ ++ pm_runtime_disable(&pdev->dev); ++ if (!pm_runtime_status_suspended(&pdev->dev)) ++ an7581_afe_runtime_suspend(&pdev->dev); ++} ++ ++static const struct of_device_id an7581_afe_pcm_dt_match[] = { ++ { .compatible = "airoha,an7581-afe" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, an7581_afe_pcm_dt_match); ++ ++static const struct dev_pm_ops an7581_afe_pm_ops = { ++ RUNTIME_PM_OPS(an7581_afe_runtime_suspend, ++ an7581_afe_runtime_resume, NULL) ++}; ++ ++static struct platform_driver an7581_afe_pcm_driver = { ++ .driver = { ++ .name = "an7581-audio", ++ .of_match_table = an7581_afe_pcm_dt_match, ++ .pm = pm_ptr(&an7581_afe_pm_ops), ++ }, ++ .probe = an7581_afe_pcm_dev_probe, ++ .remove_new = an7581_afe_pcm_dev_remove, ++}; ++module_platform_driver(an7581_afe_pcm_driver); ++ ++MODULE_DESCRIPTION("Airoha SoC AFE platform driver for ALSA AN7581"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/sound/soc/airoha/an7581/an7581-i2s.c +@@ -0,0 +1,110 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Airoha ALSA SoC I2S platform driver for AN7581 ++ * ++ */ ++ ++#include ++#include ++ ++#include "an7581-afe-common.h" ++ ++SND_SOC_DAILINK_DEFS(playback, ++ DAILINK_COMP_ARRAY(COMP_CPU("DL1")), ++ DAILINK_COMP_ARRAY(COMP_DUMMY()), ++ DAILINK_COMP_ARRAY(COMP_EMPTY())); ++ ++SND_SOC_DAILINK_DEFS(capture, ++ DAILINK_COMP_ARRAY(COMP_CPU("UL1")), ++ DAILINK_COMP_ARRAY(COMP_DUMMY()), ++ DAILINK_COMP_ARRAY(COMP_EMPTY())); ++ ++static struct snd_soc_dai_link an7581_i2s_dai_links[] = { ++ { ++ .name = "an7581-i2s-playback", ++ .stream_name = "an7581-i2s-playback", ++ .trigger = {SND_SOC_DPCM_TRIGGER_POST, ++ SND_SOC_DPCM_TRIGGER_POST}, ++ .dynamic = 0, ++ .playback_only = 1, ++ SND_SOC_DAILINK_REG(playback), ++ }, ++ { ++ .name = "an7581-i2s-capture", ++ .stream_name = "an7581-i2s-capture", ++ .trigger = {SND_SOC_DPCM_TRIGGER_POST, ++ SND_SOC_DPCM_TRIGGER_POST}, ++ .dynamic = 0, ++ .capture_only = 1, ++ SND_SOC_DAILINK_REG(capture), ++ }, ++}; ++ ++static struct snd_soc_card an7581_i2s_card = { ++ .name = "an7581-i2s", ++ .owner = THIS_MODULE, ++ .dai_link = an7581_i2s_dai_links, ++ .num_links = ARRAY_SIZE(an7581_i2s_dai_links), ++}; ++ ++static int an7581_i2s_machine_probe(struct platform_device *pdev) ++{ ++ struct snd_soc_card *card = &an7581_i2s_card; ++ struct device_node *platform_dai_node; ++ struct snd_soc_dai_link *dai_link; ++ struct device_node *platform; ++ int ret, i; ++ ++ card->dev = &pdev->dev; ++ ++ platform = of_get_child_by_name(pdev->dev.of_node, "platform"); ++ ++ if (platform) { ++ platform_dai_node = of_parse_phandle(platform, "sound-dai", 0); ++ of_node_put(platform); ++ ++ if (!platform_dai_node) { ++ dev_err(&pdev->dev, "Failed to parse platform/sound-dai property\n"); ++ return -EINVAL; ++ } ++ } else { ++ dev_err(&pdev->dev, "Property 'platform' missing or invalid\n"); ++ return -EINVAL; ++ } ++ ++ for_each_card_prelinks(card, i, dai_link) { ++ if (dai_link->platforms->name) ++ continue; ++ dai_link->platforms->of_node = platform_dai_node; ++ } ++ ++ ret = devm_snd_soc_register_card(&pdev->dev, card); ++ if (ret) { ++ dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", __func__); ++ goto err_of_node_put; ++ } ++ ++ return 0; ++ ++err_of_node_put: ++ of_node_put(platform_dai_node); ++ return ret; ++} ++ ++static const struct of_device_id an7581_i2s_machine_dt_match[] = { ++ { .compatible = "airoha,an7581-i2s" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, an7581_i2s_machine_dt_match); ++ ++static struct platform_driver an7581_i2s_driver = { ++ .driver = { ++ .name = "an7581-i2s", ++ .of_match_table = an7581_i2s_machine_dt_match, ++ }, ++ .probe = an7581_i2s_machine_probe, ++}; ++module_platform_driver(an7581_i2s_driver); ++ ++MODULE_DESCRIPTION("Airoha SoC I2S platform driver for ALSA AN7581"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/sound/soc/airoha/an7581/an7581-reg.h +@@ -0,0 +1,29 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * an7581-reg.h -- Airoha AN7581 audio driver reg definition ++ */ ++ ++#ifndef _AN7581_REG_H_ ++#define _AN7581_REG_H_ ++ ++#define AFE_DAC_CON0 0x0 ++ ++#define AFE_DL1_BASE 0xa8 ++#define AFE_DL1_END 0xac ++#define AFE_DL1_CUR 0xb0 ++ ++#define AFE_UL1_BASE 0xc4 ++#define AFE_UL1_END 0xc8 ++#define AFE_UL1_CUR 0xcc ++ ++#define AFE_IRQ0_CON0 0xe4 ++ ++#define AFE_IRQ_STS 0xf8 ++#define AFE_IRQ_STS_PLAY BIT(1) ++#define AFE_IRQ_STS_RECORD BIT(0) ++ ++#define AFE_IRQ1_CON0 0x100 ++ ++#define AFE_MAX_REGISTER AFE_IRQ1_CON0 ++ ++#endif diff --git a/lede/target/linux/airoha/patches-6.12/201-crypto-Add-Mediatek-EIP-93-crypto-engine-support.patch b/lede/target/linux/airoha/patches-6.12/201-crypto-Add-Mediatek-EIP-93-crypto-engine-support.patch new file mode 100644 index 0000000000..17923afd6e --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/201-crypto-Add-Mediatek-EIP-93-crypto-engine-support.patch @@ -0,0 +1,4206 @@ +From 45260ebcfb17a47bbad37055024dad50f2fcc5d0 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 27 Oct 2021 17:13:29 +0800 +Subject: [RFC PATCH v2 3/3] crypto: Add Mediatek EIP-93 crypto engine support + +Add support for the Mediatek EIP-93 crypto engine used on MT7621 and new +Airoha SoC. + +EIP-93 IP supports AES/DES/3DES ciphers in ECB/CBC and CTR modes as well as +authenc(HMAC(x), cipher(y)) using HMAC MD5, SHA1, SHA224 and SHA256. + +EIP-93 provide regs to signal support for specific chipers and the +driver dynamically register only the supported one by the chip. + +Signed-off-by: Richard van Schagen +Co-developed-by: Christian Marangi +Signed-off-by: Christian Marangi +--- +Changes v2: +- Rename all variables from mtk to eip93 +- Move to inside-secure directory +- Check DMA map errors +- Use guard API for spinlock +- Minor improvements to code + + drivers/crypto/Kconfig | 1 + + drivers/crypto/Makefile | 1 + + drivers/crypto/inside-secure/eip93/Kconfig | 20 + + drivers/crypto/inside-secure/eip93/Makefile | 5 + + .../crypto/inside-secure/eip93/eip93-aead.c | 702 ++++++++++++++ + .../crypto/inside-secure/eip93/eip93-aead.h | 38 + + .../crypto/inside-secure/eip93/eip93-aes.h | 16 + + .../crypto/inside-secure/eip93/eip93-cipher.c | 407 ++++++++ + .../crypto/inside-secure/eip93/eip93-cipher.h | 60 ++ + .../crypto/inside-secure/eip93/eip93-common.c | 824 ++++++++++++++++ + .../crypto/inside-secure/eip93/eip93-common.h | 25 + + .../crypto/inside-secure/eip93/eip93-des.h | 16 + + .../crypto/inside-secure/eip93/eip93-hash.c | 909 ++++++++++++++++++ + .../crypto/inside-secure/eip93/eip93-hash.h | 72 ++ + .../crypto/inside-secure/eip93/eip93-main.c | 502 ++++++++++ + .../crypto/inside-secure/eip93/eip93-main.h | 155 +++ + .../crypto/inside-secure/eip93/eip93-regs.h | 335 +++++++ + 17 files changed, 4088 insertions(+) + create mode 100644 drivers/crypto/inside-secure/eip93/Kconfig + create mode 100644 drivers/crypto/inside-secure/eip93/Makefile + create mode 100644 drivers/crypto/inside-secure/eip93/eip93-aead.c + create mode 100644 drivers/crypto/inside-secure/eip93/eip93-aead.h + create mode 100644 drivers/crypto/inside-secure/eip93/eip93-aes.h + create mode 100644 drivers/crypto/inside-secure/eip93/eip93-cipher.c + create mode 100644 drivers/crypto/inside-secure/eip93/eip93-cipher.h + create mode 100644 drivers/crypto/inside-secure/eip93/eip93-common.c + create mode 100644 drivers/crypto/inside-secure/eip93/eip93-common.h + create mode 100644 drivers/crypto/inside-secure/eip93/eip93-des.h + create mode 100644 drivers/crypto/inside-secure/eip93/eip93-hash.c + create mode 100644 drivers/crypto/inside-secure/eip93/eip93-hash.h + create mode 100644 drivers/crypto/inside-secure/eip93/eip93-main.c + create mode 100644 drivers/crypto/inside-secure/eip93/eip93-main.h + create mode 100644 drivers/crypto/inside-secure/eip93/eip93-regs.h + +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -851,5 +851,6 @@ config CRYPTO_DEV_SA2UL + + source "drivers/crypto/aspeed/Kconfig" + source "drivers/crypto/starfive/Kconfig" ++source "drivers/crypto/inside-secure/eip93/Kconfig" + + endif # CRYPTO_HW +--- a/drivers/crypto/Makefile ++++ b/drivers/crypto/Makefile +@@ -52,3 +52,4 @@ obj-y += hisilicon/ + obj-$(CONFIG_CRYPTO_DEV_AMLOGIC_GXL) += amlogic/ + obj-y += intel/ + obj-y += starfive/ ++obj-y += inside-secure/eip93/ +--- /dev/null ++++ b/drivers/crypto/inside-secure/eip93/Kconfig +@@ -0,0 +1,20 @@ ++# SPDX-License-Identifier: GPL-2.0 ++config CRYPTO_DEV_EIP93 ++ tristate "Support for EIP93 crypto HW accelerators" ++ depends on SOC_MT7621 || ARCH_AIROHA ||COMPILE_TEST ++ select CRYPTO_LIB_AES ++ select CRYPTO_LIB_DES ++ select CRYPTO_SKCIPHER ++ select CRYPTO_AEAD ++ select CRYPTO_AUTHENC ++ select CRYPTO_MD5 ++ select CRYPTO_SHA1 ++ select CRYPTO_SHA256 ++ help ++ EIP93 have various crypto HW accelerators. Select this if ++ you want to use the EIP93 modules for any of the crypto algorithms. ++ ++ If the IP supports it, this provide offload for AES - ECB, CBC and ++ CTR crypto. Also provide DES and 3DES ECB and CBC. ++ ++ Also provide AEAD authenc(hmac(x), cipher(y)) for supported algo. +--- /dev/null ++++ b/drivers/crypto/inside-secure/eip93/Makefile +@@ -0,0 +1,5 @@ ++obj-$(CONFIG_CRYPTO_DEV_EIP93) += crypto-hw-eip93.o ++ ++crypto-hw-eip93-y += eip93-main.o eip93-common.o ++crypto-hw-eip93-y += eip93-cipher.o eip93-aead.o ++crypto-hw-eip93-y += eip93-hash.o +--- /dev/null ++++ b/drivers/crypto/inside-secure/eip93/eip93-aead.c +@@ -0,0 +1,702 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2019 - 2021 ++ * ++ * Richard van Schagen ++ * Christian Marangi ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++ ++#include "eip93-aead.h" ++#include "eip93-cipher.h" ++#include "eip93-common.h" ++#include "eip93-regs.h" ++ ++void eip93_aead_handle_result(struct crypto_async_request *async, int err) ++{ ++ struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(async->tfm); ++ struct eip93_device *mtk = ctx->mtk; ++ struct aead_request *req = aead_request_cast(async); ++ struct eip93_cipher_reqctx *rctx = aead_request_ctx(req); ++ ++ eip93_unmap_dma(mtk, rctx, req->src, req->dst); ++ eip93_handle_result(mtk, rctx, req->iv); ++ ++ aead_request_complete(req, err); ++} ++ ++static int eip93_aead_send_req(struct crypto_async_request *async) ++{ ++ struct aead_request *req = aead_request_cast(async); ++ struct eip93_cipher_reqctx *rctx = aead_request_ctx(req); ++ int err; ++ ++ err = check_valid_request(rctx); ++ if (err) { ++ aead_request_complete(req, err); ++ return err; ++ } ++ ++ return eip93_send_req(async, req->iv, rctx); ++} ++ ++/* Crypto aead API functions */ ++static int eip93_aead_cra_init(struct crypto_tfm *tfm) ++{ ++ struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(tfm); ++ struct eip93_alg_template *tmpl = container_of(tfm->__crt_alg, ++ struct eip93_alg_template, alg.aead.base); ++ ++ crypto_aead_set_reqsize(__crypto_aead_cast(tfm), ++ sizeof(struct eip93_cipher_reqctx)); ++ ++ ctx->mtk = tmpl->mtk; ++ ctx->flags = tmpl->flags; ++ ctx->type = tmpl->type; ++ ctx->set_assoc = true; ++ ++ ctx->sa_record = kzalloc(sizeof(*ctx->sa_record), GFP_KERNEL); ++ if (!ctx->sa_record) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++static void eip93_aead_cra_exit(struct crypto_tfm *tfm) ++{ ++ struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(tfm); ++ ++ dma_unmap_single(ctx->mtk->dev, ctx->sa_record_base, ++ sizeof(*ctx->sa_record), DMA_TO_DEVICE); ++ kfree(ctx->sa_record); ++} ++ ++static int eip93_aead_setkey(struct crypto_aead *ctfm, const u8 *key, ++ unsigned int len) ++{ ++ struct crypto_tfm *tfm = crypto_aead_tfm(ctfm); ++ struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(tfm); ++ struct crypto_authenc_keys keys; ++ struct crypto_aes_ctx aes; ++ struct sa_record *sa_record = ctx->sa_record; ++ u32 nonce = 0; ++ int ret; ++ ++ if (crypto_authenc_extractkeys(&keys, key, len)) ++ return -EINVAL; ++ ++ if (IS_RFC3686(ctx->flags)) { ++ if (keys.enckeylen < CTR_RFC3686_NONCE_SIZE) ++ return -EINVAL; ++ ++ keys.enckeylen -= CTR_RFC3686_NONCE_SIZE; ++ memcpy(&nonce, keys.enckey + keys.enckeylen, ++ CTR_RFC3686_NONCE_SIZE); ++ } ++ ++ switch ((ctx->flags & EIP93_ALG_MASK)) { ++ case EIP93_ALG_DES: ++ ret = verify_aead_des_key(ctfm, keys.enckey, keys.enckeylen); ++ break; ++ case EIP93_ALG_3DES: ++ if (keys.enckeylen != DES3_EDE_KEY_SIZE) ++ return -EINVAL; ++ ++ ret = verify_aead_des3_key(ctfm, keys.enckey, keys.enckeylen); ++ break; ++ case EIP93_ALG_AES: ++ ret = aes_expandkey(&aes, keys.enckey, keys.enckeylen); ++ } ++ if (ret) ++ return ret; ++ ++ ctx->blksize = crypto_aead_blocksize(ctfm); ++ /* Encryption key */ ++ eip93_set_sa_record(sa_record, keys.enckeylen, ctx->flags); ++ sa_record->sa_cmd0_word &= ~EIP93_SA_CMD_OPCODE; ++ sa_record->sa_cmd0_word |= FIELD_PREP(EIP93_SA_CMD_OPCODE, ++ EIP93_SA_CMD_OPCODE_BASIC_OUT_ENC_HASH); ++ sa_record->sa_cmd0_word &= ~EIP93_SA_CMD_DIGEST_LENGTH; ++ sa_record->sa_cmd0_word |= FIELD_PREP(EIP93_SA_CMD_DIGEST_LENGTH, ++ ctx->authsize / sizeof(u32)); ++ ++ memcpy(sa_record->sa_key, keys.enckey, keys.enckeylen); ++ ctx->sa_nonce = nonce; ++ sa_record->sa_nonce = nonce; ++ ++ /* authentication key */ ++ ret = eip93_authenc_setkey(ctfm, sa_record, keys.authkey, ++ keys.authkeylen); ++ ++ ctx->set_assoc = true; ++ ++ return ret; ++} ++ ++static int eip93_aead_setauthsize(struct crypto_aead *ctfm, ++ unsigned int authsize) ++{ ++ struct crypto_tfm *tfm = crypto_aead_tfm(ctfm); ++ struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(tfm); ++ ++ ctx->authsize = authsize; ++ ctx->sa_record->sa_cmd0_word &= ~EIP93_SA_CMD_DIGEST_LENGTH; ++ ctx->sa_record->sa_cmd0_word |= FIELD_PREP(EIP93_SA_CMD_DIGEST_LENGTH, ++ ctx->authsize / sizeof(u32)); ++ ++ return 0; ++} ++ ++static void eip93_aead_setassoc(struct eip93_crypto_ctx *ctx, ++ struct aead_request *req) ++{ ++ struct sa_record *sa_record = ctx->sa_record; ++ ++ sa_record->sa_cmd1_word &= ~EIP93_SA_CMD_HASH_CRYPT_OFFSET; ++ sa_record->sa_cmd1_word |= FIELD_PREP(EIP93_SA_CMD_HASH_CRYPT_OFFSET, ++ req->assoclen / sizeof(u32)); ++ ++ ctx->assoclen = req->assoclen; ++} ++ ++static int eip93_aead_crypt(struct aead_request *req) ++{ ++ struct eip93_cipher_reqctx *rctx = aead_request_ctx(req); ++ struct crypto_async_request *async = &req->base; ++ struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(req->base.tfm); ++ struct crypto_aead *aead = crypto_aead_reqtfm(req); ++ int ret; ++ ++ ctx->sa_record_base = dma_map_single(ctx->mtk->dev, ctx->sa_record, ++ sizeof(*ctx->sa_record), DMA_TO_DEVICE); ++ ret = dma_mapping_error(ctx->mtk->dev, ctx->sa_record_base); ++ if (ret) ++ return ret; ++ ++ rctx->textsize = req->cryptlen; ++ rctx->blksize = ctx->blksize; ++ rctx->assoclen = req->assoclen; ++ rctx->authsize = ctx->authsize; ++ rctx->sg_src = req->src; ++ rctx->sg_dst = req->dst; ++ rctx->ivsize = crypto_aead_ivsize(aead); ++ rctx->desc_flags = EIP93_DESC_AEAD; ++ rctx->sa_record_base = ctx->sa_record_base; ++ ++ if (IS_DECRYPT(rctx->flags)) ++ rctx->textsize -= rctx->authsize; ++ ++ return eip93_aead_send_req(async); ++} ++ ++static int eip93_aead_encrypt(struct aead_request *req) ++{ ++ struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(req->base.tfm); ++ struct eip93_cipher_reqctx *rctx = aead_request_ctx(req); ++ ++ rctx->flags = ctx->flags; ++ rctx->flags |= EIP93_ENCRYPT; ++ if (ctx->set_assoc) { ++ eip93_aead_setassoc(ctx, req); ++ ctx->set_assoc = false; ++ } ++ ++ if (req->assoclen != ctx->assoclen) { ++ dev_err(ctx->mtk->dev, "Request AAD length error\n"); ++ return -EINVAL; ++ } ++ ++ return eip93_aead_crypt(req); ++} ++ ++static int eip93_aead_decrypt(struct aead_request *req) ++{ ++ struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(req->base.tfm); ++ struct eip93_cipher_reqctx *rctx = aead_request_ctx(req); ++ ++ ctx->sa_record->sa_cmd0_word |= EIP93_SA_CMD_DIRECTION_IN; ++ ctx->sa_record->sa_cmd1_word &= ~(EIP93_SA_CMD_COPY_PAD | ++ EIP93_SA_CMD_COPY_DIGEST); ++ ++ rctx->flags = ctx->flags; ++ rctx->flags |= EIP93_DECRYPT; ++ if (ctx->set_assoc) { ++ eip93_aead_setassoc(ctx, req); ++ ctx->set_assoc = false; ++ } ++ ++ if (req->assoclen != ctx->assoclen) { ++ dev_err(ctx->mtk->dev, "Request AAD length error\n"); ++ return -EINVAL; ++ } ++ ++ return eip93_aead_crypt(req); ++} ++ ++/* Available authenc algorithms in this module */ ++struct eip93_alg_template eip93_alg_authenc_hmac_md5_cbc_aes = { ++ .type = EIP93_ALG_TYPE_AEAD, ++ .flags = EIP93_HASH_HMAC | EIP93_HASH_MD5 | EIP93_MODE_CBC | EIP93_ALG_AES, ++ .alg.aead = { ++ .setkey = eip93_aead_setkey, ++ .encrypt = eip93_aead_encrypt, ++ .decrypt = eip93_aead_decrypt, ++ .ivsize = AES_BLOCK_SIZE, ++ .setauthsize = eip93_aead_setauthsize, ++ .maxauthsize = MD5_DIGEST_SIZE, ++ .base = { ++ .cra_name = "authenc(hmac(md5),cbc(aes))", ++ .cra_driver_name = ++ "authenc(hmac(md5-eip93), cbc(aes-eip93))", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = AES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0, ++ .cra_init = eip93_aead_cra_init, ++ .cra_exit = eip93_aead_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_authenc_hmac_sha1_cbc_aes = { ++ .type = EIP93_ALG_TYPE_AEAD, ++ .flags = EIP93_HASH_HMAC | EIP93_HASH_SHA1 | EIP93_MODE_CBC | EIP93_ALG_AES, ++ .alg.aead = { ++ .setkey = eip93_aead_setkey, ++ .encrypt = eip93_aead_encrypt, ++ .decrypt = eip93_aead_decrypt, ++ .ivsize = AES_BLOCK_SIZE, ++ .setauthsize = eip93_aead_setauthsize, ++ .maxauthsize = SHA1_DIGEST_SIZE, ++ .base = { ++ .cra_name = "authenc(hmac(sha1),cbc(aes))", ++ .cra_driver_name = ++ "authenc(hmac(sha1-eip93),cbc(aes-eip93))", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = AES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0, ++ .cra_init = eip93_aead_cra_init, ++ .cra_exit = eip93_aead_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_authenc_hmac_sha224_cbc_aes = { ++ .type = EIP93_ALG_TYPE_AEAD, ++ .flags = EIP93_HASH_HMAC | EIP93_HASH_SHA224 | EIP93_MODE_CBC | EIP93_ALG_AES, ++ .alg.aead = { ++ .setkey = eip93_aead_setkey, ++ .encrypt = eip93_aead_encrypt, ++ .decrypt = eip93_aead_decrypt, ++ .ivsize = AES_BLOCK_SIZE, ++ .setauthsize = eip93_aead_setauthsize, ++ .maxauthsize = SHA224_DIGEST_SIZE, ++ .base = { ++ .cra_name = "authenc(hmac(sha224),cbc(aes))", ++ .cra_driver_name = ++ "authenc(hmac(sha224-eip93),cbc(aes-eip93))", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = AES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0, ++ .cra_init = eip93_aead_cra_init, ++ .cra_exit = eip93_aead_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_authenc_hmac_sha256_cbc_aes = { ++ .type = EIP93_ALG_TYPE_AEAD, ++ .flags = EIP93_HASH_HMAC | EIP93_HASH_SHA256 | EIP93_MODE_CBC | EIP93_ALG_AES, ++ .alg.aead = { ++ .setkey = eip93_aead_setkey, ++ .encrypt = eip93_aead_encrypt, ++ .decrypt = eip93_aead_decrypt, ++ .ivsize = AES_BLOCK_SIZE, ++ .setauthsize = eip93_aead_setauthsize, ++ .maxauthsize = SHA256_DIGEST_SIZE, ++ .base = { ++ .cra_name = "authenc(hmac(sha256),cbc(aes))", ++ .cra_driver_name = ++ "authenc(hmac(sha256-eip93),cbc(aes-eip93))", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = AES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0, ++ .cra_init = eip93_aead_cra_init, ++ .cra_exit = eip93_aead_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_authenc_hmac_md5_rfc3686_aes = { ++ .type = EIP93_ALG_TYPE_AEAD, ++ .flags = EIP93_HASH_HMAC | EIP93_HASH_MD5 | ++ EIP93_MODE_CTR | EIP93_MODE_RFC3686 | EIP93_ALG_AES, ++ .alg.aead = { ++ .setkey = eip93_aead_setkey, ++ .encrypt = eip93_aead_encrypt, ++ .decrypt = eip93_aead_decrypt, ++ .ivsize = CTR_RFC3686_IV_SIZE, ++ .setauthsize = eip93_aead_setauthsize, ++ .maxauthsize = MD5_DIGEST_SIZE, ++ .base = { ++ .cra_name = "authenc(hmac(md5),rfc3686(ctr(aes)))", ++ .cra_driver_name = ++ "authenc(hmac(md5-eip93),rfc3686(ctr(aes-eip93)))", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = 1, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0, ++ .cra_init = eip93_aead_cra_init, ++ .cra_exit = eip93_aead_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_authenc_hmac_sha1_rfc3686_aes = { ++ .type = EIP93_ALG_TYPE_AEAD, ++ .flags = EIP93_HASH_HMAC | EIP93_HASH_SHA1 | ++ EIP93_MODE_CTR | EIP93_MODE_RFC3686 | EIP93_ALG_AES, ++ .alg.aead = { ++ .setkey = eip93_aead_setkey, ++ .encrypt = eip93_aead_encrypt, ++ .decrypt = eip93_aead_decrypt, ++ .ivsize = CTR_RFC3686_IV_SIZE, ++ .setauthsize = eip93_aead_setauthsize, ++ .maxauthsize = SHA1_DIGEST_SIZE, ++ .base = { ++ .cra_name = "authenc(hmac(sha1),rfc3686(ctr(aes)))", ++ .cra_driver_name = ++ "authenc(hmac(sha1-eip93),rfc3686(ctr(aes-eip93)))", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = 1, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0, ++ .cra_init = eip93_aead_cra_init, ++ .cra_exit = eip93_aead_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_authenc_hmac_sha224_rfc3686_aes = { ++ .type = EIP93_ALG_TYPE_AEAD, ++ .flags = EIP93_HASH_HMAC | EIP93_HASH_SHA224 | ++ EIP93_MODE_CTR | EIP93_MODE_RFC3686 | EIP93_ALG_AES, ++ .alg.aead = { ++ .setkey = eip93_aead_setkey, ++ .encrypt = eip93_aead_encrypt, ++ .decrypt = eip93_aead_decrypt, ++ .ivsize = CTR_RFC3686_IV_SIZE, ++ .setauthsize = eip93_aead_setauthsize, ++ .maxauthsize = SHA224_DIGEST_SIZE, ++ .base = { ++ .cra_name = "authenc(hmac(sha224),rfc3686(ctr(aes)))", ++ .cra_driver_name = ++ "authenc(hmac(sha224-eip93),rfc3686(ctr(aes-eip93)))", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = 1, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0, ++ .cra_init = eip93_aead_cra_init, ++ .cra_exit = eip93_aead_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_authenc_hmac_sha256_rfc3686_aes = { ++ .type = EIP93_ALG_TYPE_AEAD, ++ .flags = EIP93_HASH_HMAC | EIP93_HASH_SHA256 | ++ EIP93_MODE_CTR | EIP93_MODE_RFC3686 | EIP93_ALG_AES, ++ .alg.aead = { ++ .setkey = eip93_aead_setkey, ++ .encrypt = eip93_aead_encrypt, ++ .decrypt = eip93_aead_decrypt, ++ .ivsize = CTR_RFC3686_IV_SIZE, ++ .setauthsize = eip93_aead_setauthsize, ++ .maxauthsize = SHA256_DIGEST_SIZE, ++ .base = { ++ .cra_name = "authenc(hmac(sha256),rfc3686(ctr(aes)))", ++ .cra_driver_name = ++ "authenc(hmac(sha256-eip93),rfc3686(ctr(aes-eip93)))", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = 1, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0, ++ .cra_init = eip93_aead_cra_init, ++ .cra_exit = eip93_aead_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_authenc_hmac_md5_cbc_des = { ++ .type = EIP93_ALG_TYPE_AEAD, ++ .flags = EIP93_HASH_HMAC | EIP93_HASH_MD5 | EIP93_MODE_CBC | EIP93_ALG_DES, ++ .alg.aead = { ++ .setkey = eip93_aead_setkey, ++ .encrypt = eip93_aead_encrypt, ++ .decrypt = eip93_aead_decrypt, ++ .ivsize = DES_BLOCK_SIZE, ++ .setauthsize = eip93_aead_setauthsize, ++ .maxauthsize = MD5_DIGEST_SIZE, ++ .base = { ++ .cra_name = "authenc(hmac(md5),cbc(des))", ++ .cra_driver_name = ++ "authenc(hmac(md5-eip93),cbc(des-eip93))", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = DES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0, ++ .cra_init = eip93_aead_cra_init, ++ .cra_exit = eip93_aead_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_authenc_hmac_sha1_cbc_des = { ++ .type = EIP93_ALG_TYPE_AEAD, ++ .flags = EIP93_HASH_HMAC | EIP93_HASH_SHA1 | EIP93_MODE_CBC | EIP93_ALG_DES, ++ .alg.aead = { ++ .setkey = eip93_aead_setkey, ++ .encrypt = eip93_aead_encrypt, ++ .decrypt = eip93_aead_decrypt, ++ .ivsize = DES_BLOCK_SIZE, ++ .setauthsize = eip93_aead_setauthsize, ++ .maxauthsize = SHA1_DIGEST_SIZE, ++ .base = { ++ .cra_name = "authenc(hmac(sha1),cbc(des))", ++ .cra_driver_name = ++ "authenc(hmac(sha1-eip93),cbc(des-eip93))", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = DES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0, ++ .cra_init = eip93_aead_cra_init, ++ .cra_exit = eip93_aead_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_authenc_hmac_sha224_cbc_des = { ++ .type = EIP93_ALG_TYPE_AEAD, ++ .flags = EIP93_HASH_HMAC | EIP93_HASH_SHA224 | EIP93_MODE_CBC | EIP93_ALG_DES, ++ .alg.aead = { ++ .setkey = eip93_aead_setkey, ++ .encrypt = eip93_aead_encrypt, ++ .decrypt = eip93_aead_decrypt, ++ .ivsize = DES_BLOCK_SIZE, ++ .setauthsize = eip93_aead_setauthsize, ++ .maxauthsize = SHA224_DIGEST_SIZE, ++ .base = { ++ .cra_name = "authenc(hmac(sha224),cbc(des))", ++ .cra_driver_name = ++ "authenc(hmac(sha224-eip93),cbc(des-eip93))", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = DES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0, ++ .cra_init = eip93_aead_cra_init, ++ .cra_exit = eip93_aead_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_authenc_hmac_sha256_cbc_des = { ++ .type = EIP93_ALG_TYPE_AEAD, ++ .flags = EIP93_HASH_HMAC | EIP93_HASH_SHA256 | EIP93_MODE_CBC | EIP93_ALG_DES, ++ .alg.aead = { ++ .setkey = eip93_aead_setkey, ++ .encrypt = eip93_aead_encrypt, ++ .decrypt = eip93_aead_decrypt, ++ .ivsize = DES_BLOCK_SIZE, ++ .setauthsize = eip93_aead_setauthsize, ++ .maxauthsize = SHA256_DIGEST_SIZE, ++ .base = { ++ .cra_name = "authenc(hmac(sha256),cbc(des))", ++ .cra_driver_name = ++ "authenc(hmac(sha256-eip93),cbc(des-eip93))", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = DES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0, ++ .cra_init = eip93_aead_cra_init, ++ .cra_exit = eip93_aead_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_authenc_hmac_md5_cbc_des3_ede = { ++ .type = EIP93_ALG_TYPE_AEAD, ++ .flags = EIP93_HASH_HMAC | EIP93_HASH_MD5 | EIP93_MODE_CBC | EIP93_ALG_3DES, ++ .alg.aead = { ++ .setkey = eip93_aead_setkey, ++ .encrypt = eip93_aead_encrypt, ++ .decrypt = eip93_aead_decrypt, ++ .ivsize = DES3_EDE_BLOCK_SIZE, ++ .setauthsize = eip93_aead_setauthsize, ++ .maxauthsize = MD5_DIGEST_SIZE, ++ .base = { ++ .cra_name = "authenc(hmac(md5),cbc(des3_ede))", ++ .cra_driver_name = ++ "authenc(hmac(md5-eip93),cbc(des3_ede-eip93))", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = DES3_EDE_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0x0, ++ .cra_init = eip93_aead_cra_init, ++ .cra_exit = eip93_aead_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_authenc_hmac_sha1_cbc_des3_ede = { ++ .type = EIP93_ALG_TYPE_AEAD, ++ .flags = EIP93_HASH_HMAC | EIP93_HASH_SHA1 | EIP93_MODE_CBC | EIP93_ALG_3DES, ++ .alg.aead = { ++ .setkey = eip93_aead_setkey, ++ .encrypt = eip93_aead_encrypt, ++ .decrypt = eip93_aead_decrypt, ++ .ivsize = DES3_EDE_BLOCK_SIZE, ++ .setauthsize = eip93_aead_setauthsize, ++ .maxauthsize = SHA1_DIGEST_SIZE, ++ .base = { ++ .cra_name = "authenc(hmac(sha1),cbc(des3_ede))", ++ .cra_driver_name = ++ "authenc(hmac(sha1-eip93),cbc(des3_ede-eip93))", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = DES3_EDE_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0x0, ++ .cra_init = eip93_aead_cra_init, ++ .cra_exit = eip93_aead_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_authenc_hmac_sha224_cbc_des3_ede = { ++ .type = EIP93_ALG_TYPE_AEAD, ++ .flags = EIP93_HASH_HMAC | EIP93_HASH_SHA224 | EIP93_MODE_CBC | EIP93_ALG_3DES, ++ .alg.aead = { ++ .setkey = eip93_aead_setkey, ++ .encrypt = eip93_aead_encrypt, ++ .decrypt = eip93_aead_decrypt, ++ .ivsize = DES3_EDE_BLOCK_SIZE, ++ .setauthsize = eip93_aead_setauthsize, ++ .maxauthsize = SHA224_DIGEST_SIZE, ++ .base = { ++ .cra_name = "authenc(hmac(sha224),cbc(des3_ede))", ++ .cra_driver_name = ++ "authenc(hmac(sha224-eip93),cbc(des3_ede-eip93))", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = DES3_EDE_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0x0, ++ .cra_init = eip93_aead_cra_init, ++ .cra_exit = eip93_aead_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_authenc_hmac_sha256_cbc_des3_ede = { ++ .type = EIP93_ALG_TYPE_AEAD, ++ .flags = EIP93_HASH_HMAC | EIP93_HASH_SHA256 | EIP93_MODE_CBC | EIP93_ALG_3DES, ++ .alg.aead = { ++ .setkey = eip93_aead_setkey, ++ .encrypt = eip93_aead_encrypt, ++ .decrypt = eip93_aead_decrypt, ++ .ivsize = DES3_EDE_BLOCK_SIZE, ++ .setauthsize = eip93_aead_setauthsize, ++ .maxauthsize = SHA256_DIGEST_SIZE, ++ .base = { ++ .cra_name = "authenc(hmac(sha256),cbc(des3_ede))", ++ .cra_driver_name = ++ "authenc(hmac(sha256-eip93),cbc(des3_ede-eip93))", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = DES3_EDE_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0x0, ++ .cra_init = eip93_aead_cra_init, ++ .cra_exit = eip93_aead_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; +--- /dev/null ++++ b/drivers/crypto/inside-secure/eip93/eip93-aead.h +@@ -0,0 +1,38 @@ ++/* SPDX-License-Identifier: GPL-2.0 ++ * ++ * Copyright (C) 2019 - 2021 ++ * ++ * Richard van Schagen ++ * Christian Marangi ++ * Christian Marangi ++ * Christian Marangi ++#include ++#include ++#include ++ ++#include "eip93-cipher.h" ++#include "eip93-common.h" ++#include "eip93-regs.h" ++ ++void eip93_skcipher_handle_result(struct crypto_async_request *async, int err) ++{ ++ struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(async->tfm); ++ struct eip93_device *mtk = ctx->mtk; ++ struct skcipher_request *req = skcipher_request_cast(async); ++ struct eip93_cipher_reqctx *rctx = skcipher_request_ctx(req); ++ ++ eip93_unmap_dma(mtk, rctx, req->src, req->dst); ++ eip93_handle_result(mtk, rctx, req->iv); ++ ++ skcipher_request_complete(req, err); ++} ++ ++static int eip93_skcipher_send_req(struct crypto_async_request *async) ++{ ++ struct skcipher_request *req = skcipher_request_cast(async); ++ struct eip93_cipher_reqctx *rctx = skcipher_request_ctx(req); ++ int err; ++ ++ err = check_valid_request(rctx); ++ ++ if (err) { ++ skcipher_request_complete(req, err); ++ return err; ++ } ++ ++ return eip93_send_req(async, req->iv, rctx); ++} ++ ++/* Crypto skcipher API functions */ ++static int eip93_skcipher_cra_init(struct crypto_tfm *tfm) ++{ ++ struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(tfm); ++ struct eip93_alg_template *tmpl = container_of(tfm->__crt_alg, ++ struct eip93_alg_template, alg.skcipher.base); ++ ++ crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm), ++ sizeof(struct eip93_cipher_reqctx)); ++ ++ memset(ctx, 0, sizeof(*ctx)); ++ ++ ctx->mtk = tmpl->mtk; ++ ctx->type = tmpl->type; ++ ++ ctx->sa_record = kzalloc(sizeof(*ctx->sa_record), GFP_KERNEL); ++ if (!ctx->sa_record) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++static void eip93_skcipher_cra_exit(struct crypto_tfm *tfm) ++{ ++ struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(tfm); ++ ++ dma_unmap_single(ctx->mtk->dev, ctx->sa_record_base, ++ sizeof(*ctx->sa_record), DMA_TO_DEVICE); ++ kfree(ctx->sa_record); ++} ++ ++static int eip93_skcipher_setkey(struct crypto_skcipher *ctfm, const u8 *key, ++ unsigned int len) ++{ ++ struct crypto_tfm *tfm = crypto_skcipher_tfm(ctfm); ++ struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(tfm); ++ struct eip93_alg_template *tmpl = container_of(tfm->__crt_alg, ++ struct eip93_alg_template, ++ alg.skcipher.base); ++ struct sa_record *sa_record = ctx->sa_record; ++ unsigned int keylen = len; ++ u32 flags = tmpl->flags; ++ u32 nonce = 0; ++ int ret; ++ ++ if (!key || !keylen) ++ return -EINVAL; ++ ++ if (IS_RFC3686(flags)) { ++ if (len < CTR_RFC3686_NONCE_SIZE) ++ return -EINVAL; ++ ++ keylen = len - CTR_RFC3686_NONCE_SIZE; ++ memcpy(&nonce, key + keylen, CTR_RFC3686_NONCE_SIZE); ++ } ++ ++ if (flags & EIP93_ALG_DES) { ++ ctx->blksize = DES_BLOCK_SIZE; ++ ret = verify_skcipher_des_key(ctfm, key); ++ } ++ if (flags & EIP93_ALG_3DES) { ++ ctx->blksize = DES3_EDE_BLOCK_SIZE; ++ ret = verify_skcipher_des3_key(ctfm, key); ++ } ++ ++ if (flags & EIP93_ALG_AES) { ++ struct crypto_aes_ctx aes; ++ ++ ctx->blksize = AES_BLOCK_SIZE; ++ ret = aes_expandkey(&aes, key, keylen); ++ } ++ if (ret) ++ return ret; ++ ++ eip93_set_sa_record(sa_record, keylen, flags); ++ ++ memcpy(sa_record->sa_key, key, keylen); ++ ctx->sa_nonce = nonce; ++ sa_record->sa_nonce = nonce; ++ ++ return 0; ++} ++ ++static int eip93_skcipher_crypt(struct skcipher_request *req) ++{ ++ struct eip93_cipher_reqctx *rctx = skcipher_request_ctx(req); ++ struct crypto_async_request *async = &req->base; ++ struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(req->base.tfm); ++ struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); ++ int ret; ++ ++ if (!req->cryptlen) ++ return 0; ++ ++ /* ++ * ECB and CBC algorithms require message lengths to be ++ * multiples of block size. ++ */ ++ if (IS_ECB(rctx->flags) || IS_CBC(rctx->flags)) ++ if (!IS_ALIGNED(req->cryptlen, ++ crypto_skcipher_blocksize(skcipher))) ++ return -EINVAL; ++ ++ ctx->sa_record_base = dma_map_single(ctx->mtk->dev, ctx->sa_record, ++ sizeof(*ctx->sa_record), DMA_TO_DEVICE); ++ ret = dma_mapping_error(ctx->mtk->dev, ctx->sa_record_base); ++ if (ret) ++ return ret; ++ ++ rctx->assoclen = 0; ++ rctx->textsize = req->cryptlen; ++ rctx->authsize = 0; ++ rctx->sg_src = req->src; ++ rctx->sg_dst = req->dst; ++ rctx->ivsize = crypto_skcipher_ivsize(skcipher); ++ rctx->blksize = ctx->blksize; ++ rctx->desc_flags = EIP93_DESC_SKCIPHER; ++ rctx->sa_record_base = ctx->sa_record_base; ++ ++ return eip93_skcipher_send_req(async); ++} ++ ++static int eip93_skcipher_encrypt(struct skcipher_request *req) ++{ ++ struct eip93_cipher_reqctx *rctx = skcipher_request_ctx(req); ++ struct eip93_alg_template *tmpl = container_of(req->base.tfm->__crt_alg, ++ struct eip93_alg_template, alg.skcipher.base); ++ ++ rctx->flags = tmpl->flags; ++ rctx->flags |= EIP93_ENCRYPT; ++ ++ return eip93_skcipher_crypt(req); ++} ++ ++static int eip93_skcipher_decrypt(struct skcipher_request *req) ++{ ++ struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(req->base.tfm); ++ struct eip93_cipher_reqctx *rctx = skcipher_request_ctx(req); ++ struct eip93_alg_template *tmpl = container_of(req->base.tfm->__crt_alg, ++ struct eip93_alg_template, alg.skcipher.base); ++ ++ ctx->sa_record->sa_cmd0_word |= EIP93_SA_CMD_DIRECTION_IN; ++ ++ rctx->flags = tmpl->flags; ++ rctx->flags |= EIP93_DECRYPT; ++ ++ return eip93_skcipher_crypt(req); ++} ++ ++/* Available algorithms in this module */ ++struct eip93_alg_template eip93_alg_ecb_aes = { ++ .type = EIP93_ALG_TYPE_SKCIPHER, ++ .flags = EIP93_MODE_ECB | EIP93_ALG_AES, ++ .alg.skcipher = { ++ .setkey = eip93_skcipher_setkey, ++ .encrypt = eip93_skcipher_encrypt, ++ .decrypt = eip93_skcipher_decrypt, ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ .ivsize = 0, ++ .base = { ++ .cra_name = "ecb(aes)", ++ .cra_driver_name = "ecb(aes-eip93)", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_NEED_FALLBACK | ++ CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = AES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0xf, ++ .cra_init = eip93_skcipher_cra_init, ++ .cra_exit = eip93_skcipher_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_cbc_aes = { ++ .type = EIP93_ALG_TYPE_SKCIPHER, ++ .flags = EIP93_MODE_CBC | EIP93_ALG_AES, ++ .alg.skcipher = { ++ .setkey = eip93_skcipher_setkey, ++ .encrypt = eip93_skcipher_encrypt, ++ .decrypt = eip93_skcipher_decrypt, ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ .ivsize = AES_BLOCK_SIZE, ++ .base = { ++ .cra_name = "cbc(aes)", ++ .cra_driver_name = "cbc(aes-eip93)", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_NEED_FALLBACK | ++ CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = AES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0xf, ++ .cra_init = eip93_skcipher_cra_init, ++ .cra_exit = eip93_skcipher_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_ctr_aes = { ++ .type = EIP93_ALG_TYPE_SKCIPHER, ++ .flags = EIP93_MODE_CTR | EIP93_ALG_AES, ++ .alg.skcipher = { ++ .setkey = eip93_skcipher_setkey, ++ .encrypt = eip93_skcipher_encrypt, ++ .decrypt = eip93_skcipher_decrypt, ++ .min_keysize = AES_MIN_KEY_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE, ++ .ivsize = AES_BLOCK_SIZE, ++ .base = { ++ .cra_name = "ctr(aes)", ++ .cra_driver_name = "ctr(aes-eip93)", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_NEED_FALLBACK | ++ CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = 1, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0xf, ++ .cra_init = eip93_skcipher_cra_init, ++ .cra_exit = eip93_skcipher_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_rfc3686_aes = { ++ .type = EIP93_ALG_TYPE_SKCIPHER, ++ .flags = EIP93_MODE_CTR | EIP93_MODE_RFC3686 | EIP93_ALG_AES, ++ .alg.skcipher = { ++ .setkey = eip93_skcipher_setkey, ++ .encrypt = eip93_skcipher_encrypt, ++ .decrypt = eip93_skcipher_decrypt, ++ .min_keysize = AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, ++ .max_keysize = AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE, ++ .ivsize = CTR_RFC3686_IV_SIZE, ++ .base = { ++ .cra_name = "rfc3686(ctr(aes))", ++ .cra_driver_name = "rfc3686(ctr(aes-eip93))", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_NEED_FALLBACK | ++ CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = 1, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0xf, ++ .cra_init = eip93_skcipher_cra_init, ++ .cra_exit = eip93_skcipher_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_ecb_des = { ++ .type = EIP93_ALG_TYPE_SKCIPHER, ++ .flags = EIP93_MODE_ECB | EIP93_ALG_DES, ++ .alg.skcipher = { ++ .setkey = eip93_skcipher_setkey, ++ .encrypt = eip93_skcipher_encrypt, ++ .decrypt = eip93_skcipher_decrypt, ++ .min_keysize = DES_KEY_SIZE, ++ .max_keysize = DES_KEY_SIZE, ++ .ivsize = 0, ++ .base = { ++ .cra_name = "ecb(des)", ++ .cra_driver_name = "ebc(des-eip93)", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = DES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0, ++ .cra_init = eip93_skcipher_cra_init, ++ .cra_exit = eip93_skcipher_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_cbc_des = { ++ .type = EIP93_ALG_TYPE_SKCIPHER, ++ .flags = EIP93_MODE_CBC | EIP93_ALG_DES, ++ .alg.skcipher = { ++ .setkey = eip93_skcipher_setkey, ++ .encrypt = eip93_skcipher_encrypt, ++ .decrypt = eip93_skcipher_decrypt, ++ .min_keysize = DES_KEY_SIZE, ++ .max_keysize = DES_KEY_SIZE, ++ .ivsize = DES_BLOCK_SIZE, ++ .base = { ++ .cra_name = "cbc(des)", ++ .cra_driver_name = "cbc(des-eip93)", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = DES_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0, ++ .cra_init = eip93_skcipher_cra_init, ++ .cra_exit = eip93_skcipher_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_ecb_des3_ede = { ++ .type = EIP93_ALG_TYPE_SKCIPHER, ++ .flags = EIP93_MODE_ECB | EIP93_ALG_3DES, ++ .alg.skcipher = { ++ .setkey = eip93_skcipher_setkey, ++ .encrypt = eip93_skcipher_encrypt, ++ .decrypt = eip93_skcipher_decrypt, ++ .min_keysize = DES3_EDE_KEY_SIZE, ++ .max_keysize = DES3_EDE_KEY_SIZE, ++ .ivsize = 0, ++ .base = { ++ .cra_name = "ecb(des3_ede)", ++ .cra_driver_name = "ecb(des3_ede-eip93)", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = DES3_EDE_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0, ++ .cra_init = eip93_skcipher_cra_init, ++ .cra_exit = eip93_skcipher_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_cbc_des3_ede = { ++ .type = EIP93_ALG_TYPE_SKCIPHER, ++ .flags = EIP93_MODE_CBC | EIP93_ALG_3DES, ++ .alg.skcipher = { ++ .setkey = eip93_skcipher_setkey, ++ .encrypt = eip93_skcipher_encrypt, ++ .decrypt = eip93_skcipher_decrypt, ++ .min_keysize = DES3_EDE_KEY_SIZE, ++ .max_keysize = DES3_EDE_KEY_SIZE, ++ .ivsize = DES3_EDE_BLOCK_SIZE, ++ .base = { ++ .cra_name = "cbc(des3_ede)", ++ .cra_driver_name = "cbc(des3_ede-eip93)", ++ .cra_priority = EIP93_CRA_PRIORITY, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY, ++ .cra_blocksize = DES3_EDE_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_crypto_ctx), ++ .cra_alignmask = 0, ++ .cra_init = eip93_skcipher_cra_init, ++ .cra_exit = eip93_skcipher_cra_exit, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++}; +--- /dev/null ++++ b/drivers/crypto/inside-secure/eip93/eip93-cipher.h +@@ -0,0 +1,60 @@ ++/* SPDX-License-Identifier: GPL-2.0 ++ * ++ * Copyright (C) 2019 - 2021 ++ * ++ * Richard van Schagen ++ * Christian Marangi ++ * Christian Marangi ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "eip93-cipher.h" ++#include "eip93-hash.h" ++#include "eip93-common.h" ++#include "eip93-main.h" ++#include "eip93-regs.h" ++ ++int eip93_parse_ctrl_stat_err(struct eip93_device *mtk, int err) ++{ ++ u32 ext_err; ++ ++ if (!err) ++ return 0; ++ ++ switch (err & ~EIP93_PE_CTRL_PE_EXT_ERR_CODE) { ++ case EIP93_PE_CTRL_PE_AUTH_ERR: ++ case EIP93_PE_CTRL_PE_PAD_ERR: ++ return -EBADMSG; ++ /* let software handle anti-replay errors */ ++ case EIP93_PE_CTRL_PE_SEQNUM_ERR: ++ return 0; ++ case EIP93_PE_CTRL_PE_EXT_ERR: ++ break; ++ default: ++ dev_err(mtk->dev, "Unhandled error 0x%08x\n", err); ++ return -EINVAL; ++ } ++ ++ /* Parse additional ext errors */ ++ ext_err = FIELD_GET(EIP93_PE_CTRL_PE_EXT_ERR_CODE, err); ++ switch (ext_err) { ++ case EIP93_PE_CTRL_PE_EXT_ERR_BUS: ++ case EIP93_PE_CTRL_PE_EXT_ERR_PROCESSING: ++ return -EIO; ++ case EIP93_PE_CTRL_PE_EXT_ERR_DESC_OWNER: ++ return -EACCES; ++ case EIP93_PE_CTRL_PE_EXT_ERR_INVALID_CRYPTO_OP: ++ case EIP93_PE_CTRL_PE_EXT_ERR_INVALID_CRYPTO_ALGO: ++ case EIP93_PE_CTRL_PE_EXT_ERR_SPI: ++ return -EINVAL; ++ case EIP93_PE_CTRL_PE_EXT_ERR_ZERO_LENGTH: ++ case EIP93_PE_CTRL_PE_EXT_ERR_INVALID_PK_LENGTH: ++ case EIP93_PE_CTRL_PE_EXT_ERR_BLOCK_SIZE_ERR: ++ return -EBADMSG; ++ default: ++ dev_err(mtk->dev, "Unhandled ext error 0x%08x\n", ext_err); ++ return -EINVAL; ++ } ++} ++ ++static void *eip93_ring_next_wptr(struct eip93_device *mtk, ++ struct eip93_desc_ring *ring) ++{ ++ void *ptr = ring->write; ++ ++ if ((ring->write == ring->read - ring->offset) || ++ (ring->read == ring->base && ring->write == ring->base_end)) ++ return ERR_PTR(-ENOMEM); ++ ++ if (ring->write == ring->base_end) ++ ring->write = ring->base; ++ else ++ ring->write += ring->offset; ++ ++ return ptr; ++} ++ ++static void *eip93_ring_next_rptr(struct eip93_device *mtk, ++ struct eip93_desc_ring *ring) ++{ ++ void *ptr = ring->read; ++ ++ if (ring->write == ring->read) ++ return ERR_PTR(-ENOENT); ++ ++ if (ring->read == ring->base_end) ++ ring->read = ring->base; ++ else ++ ring->read += ring->offset; ++ ++ return ptr; ++} ++ ++int eip93_put_descriptor(struct eip93_device *mtk, ++ struct eip93_descriptor *desc) ++{ ++ struct eip93_descriptor *cdesc; ++ struct eip93_descriptor *rdesc; ++ ++ guard(spinlock_irqsave)(&mtk->ring->write_lock); ++ ++ rdesc = eip93_ring_next_wptr(mtk, &mtk->ring->rdr); ++ ++ if (IS_ERR(rdesc)) ++ return -ENOENT; ++ ++ cdesc = eip93_ring_next_wptr(mtk, &mtk->ring->cdr); ++ if (IS_ERR(cdesc)) ++ return -ENOENT; ++ ++ memset(rdesc, 0, sizeof(struct eip93_descriptor)); ++ ++ memcpy(cdesc, desc, sizeof(struct eip93_descriptor)); ++ ++ atomic_dec(&mtk->ring->free); ++ ++ return 0; ++} ++ ++void *eip93_get_descriptor(struct eip93_device *mtk) ++{ ++ struct eip93_descriptor *cdesc; ++ void *ptr; ++ ++ guard(spinlock_irqsave)(&mtk->ring->read_lock); ++ ++ cdesc = eip93_ring_next_rptr(mtk, &mtk->ring->cdr); ++ if (IS_ERR(cdesc)) ++ return ERR_PTR(-ENOENT); ++ ++ memset(cdesc, 0, sizeof(struct eip93_descriptor)); ++ ++ ptr = eip93_ring_next_rptr(mtk, &mtk->ring->rdr); ++ if (IS_ERR(ptr)) ++ return ERR_PTR(-ENOENT); ++ ++ atomic_inc(&mtk->ring->free); ++ ++ return ptr; ++} ++ ++static void eip93_free_sg_copy(const int len, struct scatterlist **sg) ++{ ++ if (!*sg || !len) ++ return; ++ ++ free_pages((unsigned long)sg_virt(*sg), get_order(len)); ++ kfree(*sg); ++ *sg = NULL; ++} ++ ++static int eip93_make_sg_copy(struct scatterlist *src, struct scatterlist **dst, ++ const u32 len, const bool copy) ++{ ++ void *pages; ++ ++ *dst = kmalloc(sizeof(**dst), GFP_KERNEL); ++ if (!*dst) ++ return -ENOMEM; ++ ++ pages = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, ++ get_order(len)); ++ if (!pages) { ++ kfree(*dst); ++ *dst = NULL; ++ return -ENOMEM; ++ } ++ ++ sg_init_table(*dst, 1); ++ sg_set_buf(*dst, pages, len); ++ ++ /* copy only as requested */ ++ if (copy) ++ sg_copy_to_buffer(src, sg_nents(src), pages, len); ++ ++ return 0; ++} ++ ++static bool eip93_is_sg_aligned(struct scatterlist *sg, u32 len, ++ const int blksize) ++{ ++ int nents; ++ ++ for (nents = 0; sg; sg = sg_next(sg), ++nents) { ++ if (!IS_ALIGNED(sg->offset, 4)) ++ return false; ++ ++ if (len <= sg->length) { ++ if (!IS_ALIGNED(len, blksize)) ++ return false; ++ ++ return true; ++ } ++ ++ if (!IS_ALIGNED(sg->length, blksize)) ++ return false; ++ ++ len -= sg->length; ++ } ++ return false; ++} ++ ++int check_valid_request(struct eip93_cipher_reqctx *rctx) ++{ ++ struct scatterlist *src = rctx->sg_src; ++ struct scatterlist *dst = rctx->sg_dst; ++ u32 src_nents, dst_nents; ++ u32 textsize = rctx->textsize; ++ u32 authsize = rctx->authsize; ++ u32 blksize = rctx->blksize; ++ u32 totlen_src = rctx->assoclen + rctx->textsize; ++ u32 totlen_dst = rctx->assoclen + rctx->textsize; ++ u32 copy_len; ++ bool src_align, dst_align; ++ int err = -EINVAL; ++ ++ if (!IS_CTR(rctx->flags)) { ++ if (!IS_ALIGNED(textsize, blksize)) ++ return err; ++ } ++ ++ if (authsize) { ++ if (IS_ENCRYPT(rctx->flags)) ++ totlen_dst += authsize; ++ else ++ totlen_src += authsize; ++ } ++ ++ src_nents = sg_nents_for_len(src, totlen_src); ++ dst_nents = sg_nents_for_len(dst, totlen_dst); ++ ++ if (src == dst) { ++ src_nents = max(src_nents, dst_nents); ++ dst_nents = src_nents; ++ if (unlikely((totlen_src || totlen_dst) && src_nents <= 0)) ++ return err; ++ ++ } else { ++ if (unlikely(totlen_src && src_nents <= 0)) ++ return err; ++ ++ if (unlikely(totlen_dst && dst_nents <= 0)) ++ return err; ++ } ++ ++ if (authsize) { ++ if (dst_nents == 1 && src_nents == 1) { ++ src_align = eip93_is_sg_aligned(src, totlen_src, blksize); ++ if (src == dst) ++ dst_align = src_align; ++ else ++ dst_align = eip93_is_sg_aligned(dst, totlen_dst, blksize); ++ } else { ++ src_align = false; ++ dst_align = false; ++ } ++ } else { ++ src_align = eip93_is_sg_aligned(src, totlen_src, blksize); ++ if (src == dst) ++ dst_align = src_align; ++ else ++ dst_align = eip93_is_sg_aligned(dst, totlen_dst, blksize); ++ } ++ ++ copy_len = max(totlen_src, totlen_dst); ++ if (!src_align) { ++ err = eip93_make_sg_copy(src, &rctx->sg_src, copy_len, true); ++ if (err) ++ return err; ++ } ++ ++ if (!dst_align) { ++ err = eip93_make_sg_copy(dst, &rctx->sg_dst, copy_len, false); ++ if (err) ++ return err; ++ } ++ ++ rctx->src_nents = sg_nents_for_len(rctx->sg_src, totlen_src); ++ rctx->dst_nents = sg_nents_for_len(rctx->sg_dst, totlen_dst); ++ ++ return 0; ++} ++ ++/* ++ * Set sa_record function: ++ * Even sa_record is set to "0", keep " = 0" for readability. ++ */ ++void eip93_set_sa_record(struct sa_record *sa_record, const unsigned int keylen, ++ const u32 flags) ++{ ++ /* Reset cmd word */ ++ sa_record->sa_cmd0_word = 0; ++ sa_record->sa_cmd1_word = 0; ++ ++ sa_record->sa_cmd0_word |= EIP93_SA_CMD_IV_FROM_STATE; ++ if (!IS_ECB(flags)) ++ sa_record->sa_cmd0_word |= EIP93_SA_CMD_SAVE_IV; ++ ++ sa_record->sa_cmd0_word |= EIP93_SA_CMD_OP_BASIC; ++ ++ switch ((flags & EIP93_ALG_MASK)) { ++ case EIP93_ALG_AES: ++ sa_record->sa_cmd0_word |= EIP93_SA_CMD_CIPHER_AES; ++ sa_record->sa_cmd1_word |= FIELD_PREP(EIP93_SA_CMD_AES_KEY_LENGTH, ++ keylen >> 3); ++ break; ++ case EIP93_ALG_3DES: ++ sa_record->sa_cmd0_word |= EIP93_SA_CMD_CIPHER_3DES; ++ break; ++ case EIP93_ALG_DES: ++ sa_record->sa_cmd0_word |= EIP93_SA_CMD_CIPHER_DES; ++ break; ++ default: ++ sa_record->sa_cmd0_word |= EIP93_SA_CMD_CIPHER_NULL; ++ } ++ ++ switch ((flags & EIP93_HASH_MASK)) { ++ case EIP93_HASH_SHA256: ++ sa_record->sa_cmd0_word |= EIP93_SA_CMD_HASH_SHA256; ++ break; ++ case EIP93_HASH_SHA224: ++ sa_record->sa_cmd0_word |= EIP93_SA_CMD_HASH_SHA224; ++ break; ++ case EIP93_HASH_SHA1: ++ sa_record->sa_cmd0_word |= EIP93_SA_CMD_HASH_SHA1; ++ break; ++ case EIP93_HASH_MD5: ++ sa_record->sa_cmd0_word |= EIP93_SA_CMD_HASH_MD5; ++ break; ++ default: ++ sa_record->sa_cmd0_word |= EIP93_SA_CMD_HASH_NULL; ++ } ++ ++ sa_record->sa_cmd0_word |= EIP93_SA_CMD_PAD_ZERO; ++ ++ switch ((flags & EIP93_MODE_MASK)) { ++ case EIP93_MODE_CBC: ++ sa_record->sa_cmd1_word |= EIP93_SA_CMD_CHIPER_MODE_CBC; ++ break; ++ case EIP93_MODE_CTR: ++ sa_record->sa_cmd1_word |= EIP93_SA_CMD_CHIPER_MODE_CTR; ++ break; ++ case EIP93_MODE_ECB: ++ sa_record->sa_cmd1_word |= EIP93_SA_CMD_CHIPER_MODE_ECB; ++ break; ++ } ++ ++ sa_record->sa_cmd0_word |= EIP93_SA_CMD_DIGEST_3WORD; ++ if (IS_HASH(flags)) { ++ sa_record->sa_cmd1_word |= EIP93_SA_CMD_COPY_PAD; ++ sa_record->sa_cmd1_word |= EIP93_SA_CMD_COPY_DIGEST; ++ } ++ ++ if (IS_HMAC(flags)) { ++ sa_record->sa_cmd1_word |= EIP93_SA_CMD_HMAC; ++ sa_record->sa_cmd1_word |= EIP93_SA_CMD_COPY_HEADER; ++ } ++ ++ sa_record->sa_spi = 0x0; ++ sa_record->sa_seqmum_mask[0] = 0xFFFFFFFF; ++ sa_record->sa_seqmum_mask[1] = 0x0; ++} ++ ++/* ++ * Poor mans Scatter/gather function: ++ * Create a Descriptor for every segment to avoid copying buffers. ++ * For performance better to wait for hardware to perform multiple DMA ++ */ ++static int eip93_scatter_combine(struct eip93_device *mtk, ++ struct eip93_cipher_reqctx *rctx, ++ u32 datalen, u32 split, int offsetin) ++{ ++ struct eip93_descriptor *cdesc = rctx->cdesc; ++ struct scatterlist *sgsrc = rctx->sg_src; ++ struct scatterlist *sgdst = rctx->sg_dst; ++ unsigned int remainin = sg_dma_len(sgsrc); ++ unsigned int remainout = sg_dma_len(sgdst); ++ dma_addr_t saddr = sg_dma_address(sgsrc); ++ dma_addr_t daddr = sg_dma_address(sgdst); ++ dma_addr_t state_addr; ++ u32 src_addr, dst_addr, len, n; ++ bool nextin = false; ++ bool nextout = false; ++ int offsetout = 0; ++ int ndesc_cdr = 0, err; ++ ++ if (IS_ECB(rctx->flags)) ++ rctx->sa_state_base = 0; ++ ++ if (split < datalen) { ++ state_addr = rctx->sa_state_ctr_base; ++ n = split; ++ } else { ++ state_addr = rctx->sa_state_base; ++ n = datalen; ++ } ++ ++ do { ++ if (nextin) { ++ sgsrc = sg_next(sgsrc); ++ remainin = sg_dma_len(sgsrc); ++ if (remainin == 0) ++ continue; ++ ++ saddr = sg_dma_address(sgsrc); ++ offsetin = 0; ++ nextin = false; ++ } ++ ++ if (nextout) { ++ sgdst = sg_next(sgdst); ++ remainout = sg_dma_len(sgdst); ++ if (remainout == 0) ++ continue; ++ ++ daddr = sg_dma_address(sgdst); ++ offsetout = 0; ++ nextout = false; ++ } ++ src_addr = saddr + offsetin; ++ dst_addr = daddr + offsetout; ++ ++ if (remainin == remainout) { ++ len = remainin; ++ if (len > n) { ++ len = n; ++ remainin -= n; ++ remainout -= n; ++ offsetin += n; ++ offsetout += n; ++ } else { ++ nextin = true; ++ nextout = true; ++ } ++ } else if (remainin < remainout) { ++ len = remainin; ++ if (len > n) { ++ len = n; ++ remainin -= n; ++ remainout -= n; ++ offsetin += n; ++ offsetout += n; ++ } else { ++ offsetout += len; ++ remainout -= len; ++ nextin = true; ++ } ++ } else { ++ len = remainout; ++ if (len > n) { ++ len = n; ++ remainin -= n; ++ remainout -= n; ++ offsetin += n; ++ offsetout += n; ++ } else { ++ offsetin += len; ++ remainin -= len; ++ nextout = true; ++ } ++ } ++ n -= len; ++ ++ cdesc->src_addr = src_addr; ++ cdesc->dst_addr = dst_addr; ++ cdesc->state_addr = state_addr; ++ cdesc->pe_length_word = FIELD_PREP(EIP93_PE_LENGTH_HOST_PE_READY, ++ EIP93_PE_LENGTH_HOST_READY); ++ cdesc->pe_length_word |= FIELD_PREP(EIP93_PE_LENGTH_LENGTH, len); ++ ++ if (n == 0) { ++ n = datalen - split; ++ split = datalen; ++ state_addr = rctx->sa_state_base; ++ } ++ ++ if (n == 0) ++ cdesc->user_id |= FIELD_PREP(EIP93_PE_USER_ID_DESC_FLAGS, ++ EIP93_DESC_LAST); ++ ++ /* ++ * Loop - Delay - No need to rollback ++ * Maybe refine by slowing down at EIP93_RING_BUSY ++ */ ++again: ++ err = eip93_put_descriptor(mtk, cdesc); ++ if (err) { ++ usleep_range(EIP93_RING_BUSY_DELAY, ++ EIP93_RING_BUSY_DELAY * 2); ++ goto again; ++ } ++ /* Writing new descriptor count starts DMA action */ ++ writel(1, mtk->base + EIP93_REG_PE_CD_COUNT); ++ ++ ndesc_cdr++; ++ } while (n); ++ ++ return -EINPROGRESS; ++} ++ ++int eip93_send_req(struct crypto_async_request *async, ++ const u8 *reqiv, struct eip93_cipher_reqctx *rctx) ++{ ++ struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(async->tfm); ++ struct eip93_device *mtk = ctx->mtk; ++ struct scatterlist *src = rctx->sg_src; ++ struct scatterlist *dst = rctx->sg_dst; ++ struct sa_state *sa_state; ++ struct eip93_descriptor cdesc; ++ u32 flags = rctx->flags; ++ int offsetin = 0, err; ++ u32 datalen = rctx->assoclen + rctx->textsize; ++ u32 split = datalen; ++ u32 start, end, ctr, blocks; ++ u32 iv[AES_BLOCK_SIZE / sizeof(u32)]; ++ int crypto_async_idr; ++ ++ rctx->sa_state_ctr = NULL; ++ rctx->sa_state = NULL; ++ ++ if (IS_ECB(flags)) ++ goto skip_iv; ++ ++ memcpy(iv, reqiv, rctx->ivsize); ++ ++ rctx->sa_state = kzalloc(sizeof(*rctx->sa_state), GFP_KERNEL); ++ if (!rctx->sa_state) ++ return -ENOMEM; ++ ++ sa_state = rctx->sa_state; ++ ++ memcpy(sa_state->state_iv, iv, rctx->ivsize); ++ if (IS_RFC3686(flags)) { ++ sa_state->state_iv[0] = ctx->sa_nonce; ++ sa_state->state_iv[1] = iv[0]; ++ sa_state->state_iv[2] = iv[1]; ++ sa_state->state_iv[3] = cpu_to_be32(1); ++ } else if (!IS_HMAC(flags) && IS_CTR(flags)) { ++ /* Compute data length. */ ++ blocks = DIV_ROUND_UP(rctx->textsize, AES_BLOCK_SIZE); ++ ctr = be32_to_cpu(iv[3]); ++ /* Check 32bit counter overflow. */ ++ start = ctr; ++ end = start + blocks - 1; ++ if (end < start) { ++ split = AES_BLOCK_SIZE * -start; ++ /* ++ * Increment the counter manually to cope with ++ * the hardware counter overflow. ++ */ ++ iv[3] = 0xffffffff; ++ crypto_inc((u8 *)iv, AES_BLOCK_SIZE); ++ ++ rctx->sa_state_ctr = kzalloc(sizeof(*rctx->sa_state_ctr), ++ GFP_KERNEL); ++ if (!rctx->sa_state_ctr) ++ goto free_sa_state; ++ ++ memcpy(rctx->sa_state_ctr->state_iv, reqiv, rctx->ivsize); ++ memcpy(sa_state->state_iv, iv, rctx->ivsize); ++ ++ rctx->sa_state_ctr_base = dma_map_single(mtk->dev, rctx->sa_state_ctr, ++ sizeof(*rctx->sa_state_ctr), ++ DMA_TO_DEVICE); ++ err = dma_mapping_error(mtk->dev, rctx->sa_state_ctr_base); ++ if (err) ++ goto free_sa_state_ctr; ++ } ++ } ++ ++ rctx->sa_state_base = dma_map_single(mtk->dev, rctx->sa_state, ++ sizeof(*rctx->sa_state), DMA_TO_DEVICE); ++ err = dma_mapping_error(mtk->dev, rctx->sa_state_base); ++ if (err) ++ goto free_sa_state_ctr_dma; ++ ++skip_iv: ++ ++ cdesc.pe_ctrl_stat_word = FIELD_PREP(EIP93_PE_CTRL_PE_READY_DES_TRING_OWN, ++ EIP93_PE_CTRL_HOST_READY); ++ cdesc.sa_addr = rctx->sa_record_base; ++ cdesc.arc4_addr = 0; ++ ++ scoped_guard(spinlock_bh, &mtk->ring->idr_lock) ++ crypto_async_idr = idr_alloc(&mtk->ring->crypto_async_idr, async, 0, ++ EIP93_RING_NUM - 1, GFP_ATOMIC); ++ ++ cdesc.user_id = FIELD_PREP(EIP93_PE_USER_ID_CRYPTO_IDR, (u16)crypto_async_idr) | ++ FIELD_PREP(EIP93_PE_USER_ID_DESC_FLAGS, rctx->desc_flags); ++ ++ rctx->cdesc = &cdesc; ++ ++ /* map DMA_BIDIRECTIONAL to invalidate cache on destination ++ * implies __dma_cache_wback_inv ++ */ ++ if (!dma_map_sg(mtk->dev, dst, rctx->dst_nents, DMA_BIDIRECTIONAL)) { ++ err = -ENOMEM; ++ goto free_sa_state_ctr_dma; ++ } ++ ++ if (src != dst && ++ !dma_map_sg(mtk->dev, src, rctx->src_nents, DMA_TO_DEVICE)) { ++ err = -ENOMEM; ++ goto free_sg_dma; ++ } ++ ++ return eip93_scatter_combine(mtk, rctx, datalen, split, offsetin); ++ ++free_sg_dma: ++ dma_unmap_sg(mtk->dev, dst, rctx->dst_nents, DMA_BIDIRECTIONAL); ++free_sa_state_ctr_dma: ++ if (rctx->sa_state_ctr) ++ dma_unmap_single(mtk->dev, rctx->sa_state_ctr_base, ++ sizeof(*rctx->sa_state_ctr), ++ DMA_TO_DEVICE); ++free_sa_state_ctr: ++ kfree(rctx->sa_state_ctr); ++ if (rctx->sa_state) ++ dma_unmap_single(mtk->dev, rctx->sa_state_base, ++ sizeof(*rctx->sa_state), ++ DMA_TO_DEVICE); ++free_sa_state: ++ kfree(rctx->sa_state); ++ ++ return err; ++} ++ ++void eip93_unmap_dma(struct eip93_device *mtk, struct eip93_cipher_reqctx *rctx, ++ struct scatterlist *reqsrc, struct scatterlist *reqdst) ++{ ++ u32 len = rctx->assoclen + rctx->textsize; ++ u32 authsize = rctx->authsize; ++ u32 flags = rctx->flags; ++ u32 *otag; ++ int i; ++ ++ if (rctx->sg_src == rctx->sg_dst) { ++ dma_unmap_sg(mtk->dev, rctx->sg_dst, rctx->dst_nents, ++ DMA_BIDIRECTIONAL); ++ goto process_tag; ++ } ++ ++ dma_unmap_sg(mtk->dev, rctx->sg_src, rctx->src_nents, ++ DMA_TO_DEVICE); ++ ++ if (rctx->sg_src != reqsrc) ++ eip93_free_sg_copy(len + rctx->authsize, &rctx->sg_src); ++ ++ dma_unmap_sg(mtk->dev, rctx->sg_dst, rctx->dst_nents, ++ DMA_BIDIRECTIONAL); ++ ++ /* SHA tags need conversion from net-to-host */ ++process_tag: ++ if (IS_DECRYPT(flags)) ++ authsize = 0; ++ ++ if (authsize) { ++ if (!IS_HASH_MD5(flags)) { ++ otag = sg_virt(rctx->sg_dst) + len; ++ for (i = 0; i < (authsize / 4); i++) ++ otag[i] = be32_to_cpu(otag[i]); ++ } ++ } ++ ++ if (rctx->sg_dst != reqdst) { ++ sg_copy_from_buffer(reqdst, sg_nents(reqdst), ++ sg_virt(rctx->sg_dst), len + authsize); ++ eip93_free_sg_copy(len + rctx->authsize, &rctx->sg_dst); ++ } ++} ++ ++void eip93_handle_result(struct eip93_device *mtk, struct eip93_cipher_reqctx *rctx, ++ u8 *reqiv) ++{ ++ if (rctx->sa_state_ctr) ++ dma_unmap_single(mtk->dev, rctx->sa_state_ctr_base, ++ sizeof(*rctx->sa_state_ctr), ++ DMA_FROM_DEVICE); ++ ++ if (rctx->sa_state) ++ dma_unmap_single(mtk->dev, rctx->sa_state_base, ++ sizeof(*rctx->sa_state), ++ DMA_FROM_DEVICE); ++ ++ if (!IS_ECB(rctx->flags)) ++ memcpy(reqiv, rctx->sa_state->state_iv, rctx->ivsize); ++ ++ kfree(rctx->sa_state_ctr); ++ kfree(rctx->sa_state); ++} ++ ++/* basically this is set hmac - key */ ++int eip93_authenc_setkey(struct crypto_aead *aead, struct sa_record *sa, ++ const u8 *authkey, unsigned int authkeylen) ++{ ++ struct crypto_tfm *tfm = crypto_aead_tfm(aead); ++ struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(tfm); ++ struct crypto_ahash *ahash_tfm; ++ struct eip93_hash_reqctx *rctx; ++ struct scatterlist sg[1]; ++ struct ahash_request *req; ++ DECLARE_CRYPTO_WAIT(wait); ++ const char *alg_name; ++ u8 *ipad, *opad; ++ int i, ret; ++ ++ switch ((ctx->flags & EIP93_HASH_MASK)) { ++ case EIP93_HASH_SHA256: ++ alg_name = "sha256-eip93"; ++ break; ++ case EIP93_HASH_SHA224: ++ alg_name = "sha224-eip93"; ++ break; ++ case EIP93_HASH_SHA1: ++ alg_name = "sha1-eip93"; ++ break; ++ case EIP93_HASH_MD5: ++ alg_name = "md5-eip93"; ++ break; ++ default: /* Impossible */ ++ return -EINVAL; ++ } ++ ++ ahash_tfm = crypto_alloc_ahash(alg_name, 0, 0); ++ if (IS_ERR(ahash_tfm)) ++ return PTR_ERR(ahash_tfm); ++ ++ req = ahash_request_alloc(ahash_tfm, GFP_KERNEL); ++ if (!req) { ++ ret = -ENOMEM; ++ goto err_ahash; ++ } ++ ++ ipad = kcalloc(2, SHA256_BLOCK_SIZE, GFP_KERNEL); ++ if (!ipad) { ++ ret = -ENOMEM; ++ goto err_req; ++ } ++ opad = ipad + SHA256_BLOCK_SIZE; ++ ++ rctx = ahash_request_ctx(req); ++ crypto_init_wait(&wait); ++ ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, ++ crypto_req_done, &wait); ++ ++ /* Hash the key if > SHA256_BLOCK_SIZE */ ++ if (authkeylen > SHA256_BLOCK_SIZE) { ++ sg_init_one(&sg[0], authkey, authkeylen); ++ ++ ahash_request_set_crypt(req, sg, ipad, authkeylen); ++ ret = crypto_wait_req(crypto_ahash_digest(req), &wait); ++ ++ authkeylen = ctx->authsize; ++ } else { ++ memcpy(ipad, authkey, authkeylen); ++ } ++ ++ /* Copy to opad */ ++ memset(ipad + authkeylen, 0, SHA256_BLOCK_SIZE - authkeylen); ++ memcpy(opad, ipad, SHA256_BLOCK_SIZE); ++ ++ /* Pad with HMAC constants */ ++ for (i = 0; i < SHA256_BLOCK_SIZE; i++) { ++ ipad[i] ^= HMAC_IPAD_VALUE; ++ opad[i] ^= HMAC_OPAD_VALUE; ++ } ++ ++ /* Disable HASH_FINALIZE for ipad and opad hash */ ++ rctx->no_finalize = true; ++ ++ /* Hash ipad */ ++ sg_init_one(&sg[0], ipad, SHA256_BLOCK_SIZE); ++ ahash_request_set_crypt(req, sg, sa->sa_i_digest, SHA256_BLOCK_SIZE); ++ ret = crypto_ahash_init(req); ++ if (ret) ++ goto exit; ++ ++ /* Disable HASH_FINALIZE for ipad hash */ ++ rctx->no_finalize = true; ++ ++ ret = crypto_wait_req(crypto_ahash_finup(req), &wait); ++ if (ret) ++ goto exit; ++ ++ /* Hash opad */ ++ sg_init_one(&sg[0], opad, SHA256_BLOCK_SIZE); ++ ahash_request_set_crypt(req, sg, sa->sa_o_digest, SHA256_BLOCK_SIZE); ++ ret = crypto_ahash_init(req); ++ if (ret) ++ goto exit; ++ ++ /* Disable HASH_FINALIZE for opad hash */ ++ rctx->no_finalize = true; ++ ++ ret = crypto_wait_req(crypto_ahash_finup(req), &wait); ++ if (ret) ++ goto exit; ++ ++ if (!IS_HASH_MD5(ctx->flags)) { ++ for (i = 0; i < SHA256_DIGEST_SIZE / sizeof(u32); i++) { ++ u32 *ipad_hash = (u32 *)sa->sa_i_digest; ++ u32 *opad_hash = (u32 *)sa->sa_o_digest; ++ ++ ipad_hash[i] = cpu_to_be32(ipad_hash[i]); ++ opad_hash[i] = cpu_to_be32(opad_hash[i]); ++ } ++ } ++ ++exit: ++ kfree(ipad); ++err_req: ++ ahash_request_free(req); ++err_ahash: ++ crypto_free_ahash(ahash_tfm); ++ ++ return ret; ++} +--- /dev/null ++++ b/drivers/crypto/inside-secure/eip93/eip93-common.h +@@ -0,0 +1,25 @@ ++/* SPDX-License-Identifier: GPL-2.0 ++ * ++ * Copyright (C) 2019 - 2021 ++ * ++ * Richard van Schagen ++ * Christian Marangi ++ * Christian Marangi ++#include ++#include ++#include ++#include ++#include ++ ++#include "eip93-cipher.h" ++#include "eip93-hash.h" ++#include "eip93-main.h" ++#include "eip93-common.h" ++#include "eip93-regs.h" ++ ++static void eip93_hash_free_data_blocks(struct ahash_request *req) ++{ ++ struct eip93_hash_reqctx *rctx = ahash_request_ctx(req); ++ struct mkt_hash_block *block; ++ ++ list_for_each_entry(block, &rctx->blocks, list) { ++ dma_unmap_single(rctx->mtk->dev, block->data_dma, ++ SHA256_BLOCK_SIZE, DMA_TO_DEVICE); ++ kfree(block); ++ } ++} ++ ++static void eip93_hash_free_sa_record(struct ahash_request *req) ++{ ++ struct eip93_hash_reqctx *rctx = ahash_request_ctx(req); ++ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); ++ struct eip93_hash_ctx *ctx = crypto_ahash_ctx(ahash); ++ ++ if (IS_HMAC(ctx->flags)) { ++ dma_unmap_single(rctx->mtk->dev, rctx->sa_record_hmac_base, ++ sizeof(*rctx->sa_record_hmac), DMA_TO_DEVICE); ++ kfree(rctx->sa_record_hmac); ++ } ++ ++ dma_unmap_single(rctx->mtk->dev, rctx->sa_record_base, ++ sizeof(*rctx->sa_record), DMA_TO_DEVICE); ++ kfree(rctx->sa_record); ++} ++ ++static void eip93_hash_free_sa_state(struct ahash_request *req) ++{ ++ struct eip93_hash_reqctx *rctx = ahash_request_ctx(req); ++ ++ dma_unmap_single(rctx->mtk->dev, rctx->sa_state_base, ++ sizeof(*rctx->sa_state), DMA_TO_DEVICE); ++ kfree(rctx->sa_state); ++} ++ ++static struct sa_state *eip93_hash_get_sa_state(struct ahash_request *req, ++ dma_addr_t *sa_state_base) ++{ ++ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); ++ struct eip93_hash_ctx *ctx = crypto_ahash_ctx(ahash); ++ struct eip93_device *mtk = ctx->mtk; ++ struct sa_state *sa_state; ++ int ret; ++ ++ sa_state = kzalloc(sizeof(*sa_state), GFP_KERNEL); ++ if (!sa_state) ++ return ERR_PTR(-ENOMEM); ++ ++ /* Init HASH constant */ ++ switch ((ctx->flags & EIP93_HASH_MASK)) { ++ case EIP93_HASH_SHA256: ++ u32 sha256_init[] = { SHA256_H0, SHA256_H1, SHA256_H2, SHA256_H3, ++ SHA256_H4, SHA256_H5, SHA256_H6, SHA256_H7 }; ++ ++ memcpy(sa_state->state_i_digest, sha256_init, sizeof(sha256_init)); ++ break; ++ case EIP93_HASH_SHA224: ++ u32 sha224_init[] = { SHA224_H0, SHA224_H1, SHA224_H2, SHA224_H3, ++ SHA224_H4, SHA224_H5, SHA224_H6, SHA224_H7 }; ++ ++ memcpy(sa_state->state_i_digest, sha224_init, sizeof(sha224_init)); ++ break; ++ case EIP93_HASH_SHA1: ++ u32 sha1_init[] = { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 }; ++ ++ memcpy(sa_state->state_i_digest, sha1_init, sizeof(sha1_init)); ++ break; ++ case EIP93_HASH_MD5: ++ u32 md5_init[] = { MD5_H0, MD5_H1, MD5_H2, MD5_H3 }; ++ ++ memcpy(sa_state->state_i_digest, md5_init, sizeof(md5_init)); ++ break; ++ default: /* Impossible */ ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ *sa_state_base = dma_map_single(mtk->dev, sa_state, ++ sizeof(*sa_state), DMA_TO_DEVICE); ++ ret = dma_mapping_error(mtk->dev, *sa_state_base); ++ if (ret) { ++ kfree(sa_state); ++ return ERR_PTR(ret); ++ } ++ ++ return sa_state; ++} ++ ++static int _eip93_hash_init(struct ahash_request *req, struct sa_state *sa_state, ++ dma_addr_t sa_state_base) ++{ ++ struct eip93_hash_reqctx *rctx = ahash_request_ctx(req); ++ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); ++ struct eip93_hash_ctx *ctx = crypto_ahash_ctx(ahash); ++ struct sa_record *sa_record, *sa_record_hmac; ++ struct eip93_device *mtk = rctx->mtk; ++ int digestsize; ++ int ret; ++ ++ sa_record = kzalloc(sizeof(*sa_record), GFP_KERNEL); ++ if (!sa_record) ++ return -ENOMEM; ++ ++ if (IS_HMAC(ctx->flags)) { ++ sa_record_hmac = kzalloc(sizeof(*sa_record_hmac), GFP_KERNEL); ++ if (!sa_record_hmac) { ++ ret = -ENOMEM; ++ goto free_sa_record; ++ } ++ } ++ ++ digestsize = crypto_ahash_digestsize(ahash); ++ ++ eip93_set_sa_record(sa_record, 0, ctx->flags); ++ sa_record->sa_cmd0_word |= EIP93_SA_CMD_HASH_FROM_STATE; ++ sa_record->sa_cmd0_word |= EIP93_SA_CMD_SAVE_HASH; ++ sa_record->sa_cmd0_word &= ~EIP93_SA_CMD_OPCODE; ++ sa_record->sa_cmd0_word |= FIELD_PREP(EIP93_SA_CMD_OPCODE, ++ EIP93_SA_CMD_OPCODE_BASIC_OUT_HASH); ++ sa_record->sa_cmd0_word &= ~EIP93_SA_CMD_DIGEST_LENGTH; ++ sa_record->sa_cmd0_word |= FIELD_PREP(EIP93_SA_CMD_DIGEST_LENGTH, ++ digestsize / sizeof(u32)); ++ ++ /* ++ * HMAC special handling ++ * Enabling CMD_HMAC force the inner hash to be always finalized. ++ * This cause problems on handling message > 64 byte as we ++ * need to produce intermediate inner hash on sending intermediate ++ * 64 bytes blocks. ++ * ++ * To handle this, enable CMD_HMAC only on the last block. ++ * We make a duplicate of sa_record and on the last descriptor, ++ * we pass a dedicated sa_record with CMD_HMAC enabled to make ++ * EIP93 apply the outer hash. ++ */ ++ if (IS_HMAC(ctx->flags)) { ++ memcpy(sa_record_hmac, sa_record, sizeof(*sa_record)); ++ /* Copy pre-hashed opad for HMAC */ ++ memcpy(sa_record_hmac->sa_o_digest, ctx->opad, SHA256_DIGEST_SIZE); ++ ++ /* Disable HMAC for hash normal sa_record */ ++ sa_record->sa_cmd1_word &= ~EIP93_SA_CMD_HMAC; ++ } ++ ++ rctx->mtk = ctx->mtk; ++ rctx->sa_record = sa_record; ++ rctx->sa_record_base = dma_map_single(mtk->dev, rctx->sa_record, ++ sizeof(*rctx->sa_record), ++ DMA_TO_DEVICE); ++ ret = dma_mapping_error(mtk->dev, rctx->sa_record_base); ++ if (ret) ++ goto free_sa_record; ++ ++ if (IS_HMAC(ctx->flags)) { ++ rctx->sa_record_hmac = sa_record_hmac; ++ rctx->sa_record_hmac_base = dma_map_single(mtk->dev, ++ rctx->sa_record_hmac, ++ sizeof(*rctx->sa_record_hmac), ++ DMA_TO_DEVICE); ++ ret = dma_mapping_error(mtk->dev, rctx->sa_record_hmac_base); ++ if (ret) ++ goto free_sa_record_base; ++ } ++ ++ rctx->sa_state = sa_state; ++ rctx->sa_state_base = sa_state_base; ++ ++ rctx->len = 0; ++ rctx->left_last = 0; ++ rctx->no_finalize = false; ++ INIT_LIST_HEAD(&rctx->blocks); ++ ++ return 0; ++ ++free_sa_record_base: ++ dma_unmap_single(mtk->dev, rctx->sa_record_base, sizeof(*rctx->sa_record), ++ DMA_TO_DEVICE); ++free_sa_record: ++ kfree(sa_record); ++ return ret; ++} ++ ++static int eip93_hash_init(struct ahash_request *req) ++{ ++ struct eip93_hash_reqctx *rctx = ahash_request_ctx(req); ++ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); ++ struct eip93_hash_ctx *ctx = crypto_ahash_ctx(ahash); ++ struct sa_state *sa_state; ++ dma_addr_t sa_state_base; ++ int ret; ++ ++ sa_state = eip93_hash_get_sa_state(req, &sa_state_base); ++ if (IS_ERR(sa_state)) ++ return PTR_ERR(sa_state); ++ ++ ret = _eip93_hash_init(req, sa_state, sa_state_base); ++ if (ret) ++ eip93_hash_free_sa_state(req); ++ ++ /* For HMAC setup the initial block for ipad */ ++ if (IS_HMAC(ctx->flags)) { ++ struct mkt_hash_block *block; ++ ++ block = kzalloc(sizeof(*block), GFP_KERNEL); ++ if (!block) { ++ eip93_hash_free_sa_record(req); ++ eip93_hash_free_sa_state(req); ++ return -ENOMEM; ++ } ++ ++ memcpy(block->data, ctx->ipad, SHA256_BLOCK_SIZE); ++ ++ list_add(&block->list, &rctx->blocks); ++ ++ rctx->len += SHA256_BLOCK_SIZE; ++ } ++ ++ return ret; ++} ++ ++static void eip93_send_hash_req(struct crypto_async_request *async, dma_addr_t src_addr, ++ u32 len, bool last) ++{ ++ struct ahash_request *req = ahash_request_cast(async); ++ struct eip93_hash_reqctx *rctx = ahash_request_ctx(req); ++ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); ++ struct eip93_hash_ctx *ctx = crypto_ahash_ctx(ahash); ++ struct eip93_device *mtk = rctx->mtk; ++ struct eip93_descriptor cdesc = { }; ++ int ret; ++ ++ cdesc.pe_ctrl_stat_word = FIELD_PREP(EIP93_PE_CTRL_PE_READY_DES_TRING_OWN, ++ EIP93_PE_CTRL_HOST_READY); ++ cdesc.sa_addr = rctx->sa_record_base; ++ cdesc.arc4_addr = 0; ++ ++ cdesc.state_addr = rctx->sa_state_base; ++ cdesc.src_addr = src_addr; ++ cdesc.pe_length_word = FIELD_PREP(EIP93_PE_LENGTH_HOST_PE_READY, ++ EIP93_PE_LENGTH_HOST_READY); ++ cdesc.pe_length_word |= FIELD_PREP(EIP93_PE_LENGTH_LENGTH, ++ len); ++ ++ cdesc.user_id |= FIELD_PREP(EIP93_PE_USER_ID_DESC_FLAGS, EIP93_DESC_HASH); ++ ++ if (last) { ++ int crypto_async_idr; ++ ++ /* For last block, pass sa_record with CMD_HMAC enabled */ ++ if (IS_HMAC(ctx->flags)) ++ cdesc.sa_addr = rctx->sa_record_hmac_base; ++ ++ if (!rctx->no_finalize) ++ cdesc.pe_ctrl_stat_word |= EIP93_PE_CTRL_PE_HASH_FINAL; ++ ++ scoped_guard(spinlock_bh, &mtk->ring->idr_lock) ++ crypto_async_idr = idr_alloc(&mtk->ring->crypto_async_idr, async, 0, ++ EIP93_RING_NUM - 1, GFP_ATOMIC); ++ ++ cdesc.user_id |= FIELD_PREP(EIP93_PE_USER_ID_CRYPTO_IDR, (u16)crypto_async_idr) | ++ FIELD_PREP(EIP93_PE_USER_ID_DESC_FLAGS, EIP93_DESC_LAST); ++ } ++ ++again: ++ ret = eip93_put_descriptor(mtk, &cdesc); ++ if (ret) { ++ usleep_range(EIP93_RING_BUSY_DELAY, ++ EIP93_RING_BUSY_DELAY * 2); ++ goto again; ++ } ++ ++ /* Writing new descriptor count starts DMA action */ ++ writel(1, mtk->base + EIP93_REG_PE_CD_COUNT); ++} ++ ++static int eip93_hash_update(struct ahash_request *req) ++{ ++ struct crypto_async_request *async = &req->base; ++ struct eip93_hash_reqctx *rctx = ahash_request_ctx(req); ++ unsigned int to_consume = req->nbytes; ++ struct eip93_device *mtk = rctx->mtk; ++ struct mkt_hash_block *block; ++ int read = 0; ++ int ret; ++ ++ /* If the request is 0 length, do nothing */ ++ if (!to_consume) ++ return 0; ++ ++ /* ++ * Check if we are at a second iteration. ++ * 1. Try to fill the first block to 64byte (if not already) ++ * 2. Send full block (if we have more data to consume) ++ */ ++ if (rctx->len > 0) { ++ int offset = SHA256_BLOCK_SIZE - rctx->left_last; ++ ++ block = list_first_entry(&rctx->blocks, ++ struct mkt_hash_block, list); ++ ++ /* Fill the first block */ ++ if (rctx->left_last) { ++ read += sg_pcopy_to_buffer(req->src, sg_nents(req->src), ++ block->data + offset, ++ min(to_consume, rctx->left_last), ++ 0); ++ to_consume -= read; ++ rctx->left_last -= read; ++ } ++ ++ /* Send descriptor if we have more data to consume */ ++ if (to_consume > 0) { ++ block->data_dma = dma_map_single(mtk->dev, block->data, ++ SHA256_BLOCK_SIZE, ++ DMA_TO_DEVICE); ++ ret = dma_mapping_error(mtk->dev, block->data_dma); ++ if (ret) ++ return ret; ++ ++ eip93_send_hash_req(async, block->data_dma, ++ SHA256_BLOCK_SIZE, false); ++ } ++ } ++ ++ /* ++ * Consume remaining data. ++ * 1. Loop until we consume all the data in block of 64bytes ++ * 2. Send full block of 64bytes ++ * 3. Skip sending last block for future update() or for final() to ++ * enable HASH_FINALIZE bit. ++ */ ++ while (to_consume > 0) { ++ int to_read = min(to_consume, SHA256_BLOCK_SIZE); ++ ++ block = kzalloc(sizeof(*block), GFP_KERNEL); ++ if (!block) ++ return -ENOMEM; ++ ++ read += sg_pcopy_to_buffer(req->src, sg_nents(req->src), ++ block->data, to_read, ++ read); ++ ++ list_add(&block->list, &rctx->blocks); ++ ++ to_consume -= to_read; ++ rctx->left_last = SHA256_BLOCK_SIZE - to_read; ++ ++ /* Send descriptor if we have more data to consume */ ++ if (to_consume > 0) { ++ block->data_dma = dma_map_single(mtk->dev, block->data, ++ SHA256_BLOCK_SIZE, ++ DMA_TO_DEVICE); ++ ret = dma_mapping_error(mtk->dev, block->data_dma); ++ if (ret) ++ return ret; ++ ++ eip93_send_hash_req(async, block->data_dma, ++ SHA256_BLOCK_SIZE, false); ++ } ++ } ++ ++ /* ++ * Update counter with processed bytes. ++ * This is also used to check if we are at the second iteration ++ * of an update(). ++ */ ++ rctx->len += req->nbytes; ++ ++ return 0; ++} ++ ++void eip93_hash_handle_result(struct crypto_async_request *async, int err) ++{ ++ struct ahash_request *req = ahash_request_cast(async); ++ struct eip93_hash_reqctx *rctx = ahash_request_ctx(req); ++ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); ++ struct eip93_hash_ctx *ctx = crypto_ahash_ctx(ahash); ++ int digestsize = crypto_ahash_digestsize(ahash); ++ struct sa_state *sa_state = rctx->sa_state; ++ int i; ++ ++ /* Unmap and sync sa_state for host */ ++ dma_unmap_single(rctx->mtk->dev, rctx->sa_state_base, ++ sizeof(*sa_state), DMA_FROM_DEVICE); ++ ++ /* ++ * With no_finalize assume SHA256_DIGEST_SIZE buffer is passed. ++ * This is to handle SHA224 that have a 32 byte intermediate digest. ++ */ ++ if (rctx->no_finalize) ++ digestsize = SHA256_DIGEST_SIZE; ++ ++ /* bytes needs to be swapped for req->result */ ++ if (!IS_HASH_MD5(ctx->flags)) { ++ for (i = 0; i < digestsize / sizeof(u32); i++) { ++ u32 *digest = (u32 *)sa_state->state_i_digest; ++ ++ digest[i] = be32_to_cpu(digest[i]); ++ } ++ } ++ ++ memcpy(req->result, sa_state->state_i_digest, digestsize); ++ ++ kfree(sa_state); ++ eip93_hash_free_data_blocks(req); ++ eip93_hash_free_sa_record(req); ++ ++ ahash_request_complete(req, err); ++} ++ ++static int eip93_hash_final(struct ahash_request *req) ++{ ++ struct eip93_hash_reqctx *rctx = ahash_request_ctx(req); ++ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); ++ struct eip93_hash_ctx *ctx = crypto_ahash_ctx(ahash); ++ struct crypto_async_request *async = &req->base; ++ struct eip93_device *mtk = rctx->mtk; ++ struct mkt_hash_block *block; ++ int ret; ++ ++ /* EIP93 can't handle zero bytes hash */ ++ if (!rctx->len && !IS_HMAC(ctx->flags)) { ++ switch ((ctx->flags & EIP93_HASH_MASK)) { ++ case EIP93_HASH_SHA256: ++ memcpy(req->result, sha256_zero_message_hash, ++ SHA256_DIGEST_SIZE); ++ break; ++ case EIP93_HASH_SHA224: ++ memcpy(req->result, sha224_zero_message_hash, ++ SHA224_DIGEST_SIZE); ++ break; ++ case EIP93_HASH_SHA1: ++ memcpy(req->result, sha1_zero_message_hash, ++ SHA1_DIGEST_SIZE); ++ break; ++ case EIP93_HASH_MD5: ++ memcpy(req->result, md5_zero_message_hash, ++ MD5_DIGEST_SIZE); ++ break; ++ default: /* Impossible */ ++ return -EINVAL; ++ } ++ ++ eip93_hash_free_sa_state(req); ++ eip93_hash_free_sa_record(req); ++ ++ return 0; ++ } ++ ++ /* Send last block */ ++ block = list_first_entry(&rctx->blocks, struct mkt_hash_block, list); ++ ++ block->data_dma = dma_map_single(mtk->dev, block->data, ++ SHA256_BLOCK_SIZE, DMA_TO_DEVICE); ++ ret = dma_mapping_error(mtk->dev, block->data_dma); ++ if (ret) ++ return ret; ++ ++ eip93_send_hash_req(async, block->data_dma, ++ SHA256_BLOCK_SIZE - rctx->left_last, ++ true); ++ ++ return -EINPROGRESS; ++} ++ ++static int eip93_hash_finup(struct ahash_request *req) ++{ ++ int ret; ++ ++ ret = eip93_hash_update(req); ++ if (ret) ++ return ret; ++ ++ return eip93_hash_final(req); ++} ++ ++static int eip93_hash_hmac_setkey(struct crypto_ahash *ahash, const u8 *key, ++ u32 keylen) ++{ ++ unsigned int digestsize = crypto_ahash_digestsize(ahash); ++ struct crypto_tfm *tfm = crypto_ahash_tfm(ahash); ++ struct eip93_hash_ctx *ctx = crypto_tfm_ctx(tfm); ++ struct crypto_ahash *ahash_tfm; ++ struct eip93_hash_reqctx *rctx; ++ struct scatterlist sg[1]; ++ struct ahash_request *req; ++ DECLARE_CRYPTO_WAIT(wait); ++ const char *alg_name; ++ int i, ret = 0; ++ u8 *opad; ++ ++ switch ((ctx->flags & EIP93_HASH_MASK)) { ++ case EIP93_HASH_SHA256: ++ alg_name = "sha256-eip93"; ++ break; ++ case EIP93_HASH_SHA224: ++ alg_name = "sha224-eip93"; ++ break; ++ case EIP93_HASH_SHA1: ++ alg_name = "sha1-eip93"; ++ break; ++ case EIP93_HASH_MD5: ++ alg_name = "md5-eip93"; ++ break; ++ default: /* Impossible */ ++ return -EINVAL; ++ } ++ ++ ahash_tfm = crypto_alloc_ahash(alg_name, 0, 0); ++ if (IS_ERR(ahash_tfm)) ++ return PTR_ERR(ahash_tfm); ++ ++ req = ahash_request_alloc(ahash_tfm, GFP_KERNEL); ++ if (!req) { ++ ret = -ENOMEM; ++ goto err_ahash; ++ } ++ ++ opad = kzalloc(SHA256_BLOCK_SIZE, GFP_KERNEL); ++ if (!opad) { ++ ret = -ENOMEM; ++ goto err_req; ++ } ++ ++ rctx = ahash_request_ctx(req); ++ crypto_init_wait(&wait); ++ ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, ++ crypto_req_done, &wait); ++ ++ /* Hash the key if > SHA256_BLOCK_SIZE */ ++ if (keylen > SHA256_BLOCK_SIZE) { ++ sg_init_one(&sg[0], key, keylen); ++ ++ ahash_request_set_crypt(req, sg, ctx->ipad, keylen); ++ ret = crypto_wait_req(crypto_ahash_digest(req), &wait); ++ ++ keylen = digestsize; ++ } else { ++ memcpy(ctx->ipad, key, keylen); ++ } ++ ++ /* Copy to opad */ ++ memset(ctx->ipad + keylen, 0, SHA256_BLOCK_SIZE - keylen); ++ memcpy(opad, ctx->ipad, SHA256_BLOCK_SIZE); ++ ++ /* Pad with HMAC constants */ ++ for (i = 0; i < SHA256_BLOCK_SIZE; i++) { ++ ctx->ipad[i] ^= HMAC_IPAD_VALUE; ++ opad[i] ^= HMAC_OPAD_VALUE; ++ } ++ ++ sg_init_one(&sg[0], opad, SHA256_BLOCK_SIZE); ++ ++ /* Hash opad */ ++ ahash_request_set_crypt(req, sg, ctx->opad, SHA256_BLOCK_SIZE); ++ ret = crypto_ahash_init(req); ++ if (ret) ++ goto exit; ++ ++ /* Disable HASH_FINALIZE for opad hash */ ++ rctx->no_finalize = true; ++ ++ ret = crypto_wait_req(crypto_ahash_finup(req), &wait); ++ if (ret) ++ goto exit; ++ ++ if (!IS_HASH_MD5(ctx->flags)) { ++ u32 *opad_hash = (u32 *)ctx->opad; ++ ++ for (i = 0; i < SHA256_DIGEST_SIZE / sizeof(u32); i++) ++ opad_hash[i] = cpu_to_be32(opad_hash[i]); ++ } ++ ++exit: ++ kfree(opad); ++err_req: ++ ahash_request_free(req); ++err_ahash: ++ crypto_free_ahash(ahash_tfm); ++ ++ return ret; ++} ++ ++static int eip93_hash_cra_init(struct crypto_tfm *tfm) ++{ ++ struct eip93_hash_ctx *ctx = crypto_tfm_ctx(tfm); ++ struct eip93_alg_template *tmpl = container_of(tfm->__crt_alg, ++ struct eip93_alg_template, alg.ahash.halg.base); ++ ++ crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), ++ sizeof(struct eip93_hash_reqctx)); ++ ++ ctx->mtk = tmpl->mtk; ++ ctx->flags = tmpl->flags; ++ ++ return 0; ++} ++ ++static int eip93_hash_digest(struct ahash_request *req) ++{ ++ int ret; ++ ++ ret = eip93_hash_init(req); ++ if (ret) ++ return ret; ++ ++ return eip93_hash_finup(req); ++} ++ ++static int eip93_hash_import(struct ahash_request *req, const void *in) ++{ ++ struct eip93_hash_reqctx *rctx = ahash_request_ctx(req); ++ const struct eip93_hash_export_state *state = in; ++ int ret; ++ ++ ret = _eip93_hash_init(req, state->sa_state, state->sa_state_base); ++ if (ret) ++ goto err; ++ ++ rctx->len = state->len; ++ rctx->left_last = state->left_last; ++ memcpy(&rctx->blocks, &state->blocks, sizeof(rctx->blocks)); ++ ++ return 0; ++err: ++ eip93_hash_free_data_blocks(req); ++ eip93_hash_free_sa_state(req); ++ return ret; ++} ++ ++static int eip93_hash_export(struct ahash_request *req, void *out) ++{ ++ struct eip93_hash_reqctx *rctx = ahash_request_ctx(req); ++ struct eip93_hash_export_state *state = out; ++ ++ state->sa_state = rctx->sa_state; ++ state->sa_state_base = rctx->sa_state_base; ++ state->len = rctx->len; ++ state->left_last = rctx->left_last; ++ memcpy(&state->blocks, &rctx->blocks, sizeof(rctx->blocks)); ++ ++ return 0; ++} ++ ++struct eip93_alg_template eip93_alg_md5 = { ++ .type = EIP93_ALG_TYPE_HASH, ++ .flags = EIP93_HASH_MD5, ++ .alg.ahash = { ++ .init = eip93_hash_init, ++ .update = eip93_hash_update, ++ .final = eip93_hash_final, ++ .finup = eip93_hash_finup, ++ .digest = eip93_hash_digest, ++ .export = eip93_hash_export, ++ .import = eip93_hash_import, ++ .halg = { ++ .digestsize = MD5_DIGEST_SIZE, ++ .statesize = sizeof(struct eip93_hash_export_state), ++ .base = { ++ .cra_name = "md5", ++ .cra_driver_name = "md5-eip93", ++ .cra_priority = 300, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = MD5_HMAC_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_hash_ctx), ++ .cra_init = eip93_hash_cra_init, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_sha1 = { ++ .type = EIP93_ALG_TYPE_HASH, ++ .flags = EIP93_HASH_SHA1, ++ .alg.ahash = { ++ .init = eip93_hash_init, ++ .update = eip93_hash_update, ++ .final = eip93_hash_final, ++ .finup = eip93_hash_finup, ++ .digest = eip93_hash_digest, ++ .export = eip93_hash_export, ++ .import = eip93_hash_import, ++ .halg = { ++ .digestsize = SHA1_DIGEST_SIZE, ++ .statesize = sizeof(struct eip93_hash_export_state), ++ .base = { ++ .cra_name = "sha1", ++ .cra_driver_name = "sha1-eip93", ++ .cra_priority = 300, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = SHA1_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_hash_ctx), ++ .cra_init = eip93_hash_cra_init, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_sha224 = { ++ .type = EIP93_ALG_TYPE_HASH, ++ .flags = EIP93_HASH_SHA224, ++ .alg.ahash = { ++ .init = eip93_hash_init, ++ .update = eip93_hash_update, ++ .final = eip93_hash_final, ++ .finup = eip93_hash_finup, ++ .digest = eip93_hash_digest, ++ .export = eip93_hash_export, ++ .import = eip93_hash_import, ++ .halg = { ++ .digestsize = SHA224_DIGEST_SIZE, ++ .statesize = sizeof(struct eip93_hash_export_state), ++ .base = { ++ .cra_name = "sha224", ++ .cra_driver_name = "sha224-eip93", ++ .cra_priority = 300, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = SHA224_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_hash_ctx), ++ .cra_init = eip93_hash_cra_init, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_sha256 = { ++ .type = EIP93_ALG_TYPE_HASH, ++ .flags = EIP93_HASH_SHA256, ++ .alg.ahash = { ++ .init = eip93_hash_init, ++ .update = eip93_hash_update, ++ .final = eip93_hash_final, ++ .finup = eip93_hash_finup, ++ .digest = eip93_hash_digest, ++ .export = eip93_hash_export, ++ .import = eip93_hash_import, ++ .halg = { ++ .digestsize = SHA256_DIGEST_SIZE, ++ .statesize = sizeof(struct eip93_hash_export_state), ++ .base = { ++ .cra_name = "sha256", ++ .cra_driver_name = "sha256-eip93", ++ .cra_priority = 300, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = SHA256_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_hash_ctx), ++ .cra_init = eip93_hash_cra_init, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_hmac_md5 = { ++ .type = EIP93_ALG_TYPE_HASH, ++ .flags = EIP93_HASH_HMAC | EIP93_HASH_MD5, ++ .alg.ahash = { ++ .init = eip93_hash_init, ++ .update = eip93_hash_update, ++ .final = eip93_hash_final, ++ .finup = eip93_hash_finup, ++ .digest = eip93_hash_digest, ++ .setkey = eip93_hash_hmac_setkey, ++ .export = eip93_hash_export, ++ .import = eip93_hash_import, ++ .halg = { ++ .digestsize = MD5_DIGEST_SIZE, ++ .statesize = sizeof(struct eip93_hash_export_state), ++ .base = { ++ .cra_name = "hmac(md5)", ++ .cra_driver_name = "hmac(md5-eip93)", ++ .cra_priority = 300, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = MD5_HMAC_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_hash_ctx), ++ .cra_init = eip93_hash_cra_init, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_hmac_sha1 = { ++ .type = EIP93_ALG_TYPE_HASH, ++ .flags = EIP93_HASH_HMAC | EIP93_HASH_SHA1, ++ .alg.ahash = { ++ .init = eip93_hash_init, ++ .update = eip93_hash_update, ++ .final = eip93_hash_final, ++ .finup = eip93_hash_finup, ++ .digest = eip93_hash_digest, ++ .setkey = eip93_hash_hmac_setkey, ++ .export = eip93_hash_export, ++ .import = eip93_hash_import, ++ .halg = { ++ .digestsize = SHA1_DIGEST_SIZE, ++ .statesize = sizeof(struct eip93_hash_export_state), ++ .base = { ++ .cra_name = "hmac(sha1)", ++ .cra_driver_name = "hmac(sha1-eip93)", ++ .cra_priority = 300, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = SHA1_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_hash_ctx), ++ .cra_init = eip93_hash_cra_init, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_hmac_sha224 = { ++ .type = EIP93_ALG_TYPE_HASH, ++ .flags = EIP93_HASH_HMAC | EIP93_HASH_SHA224, ++ .alg.ahash = { ++ .init = eip93_hash_init, ++ .update = eip93_hash_update, ++ .final = eip93_hash_final, ++ .finup = eip93_hash_finup, ++ .digest = eip93_hash_digest, ++ .setkey = eip93_hash_hmac_setkey, ++ .export = eip93_hash_export, ++ .import = eip93_hash_import, ++ .halg = { ++ .digestsize = SHA224_DIGEST_SIZE, ++ .statesize = sizeof(struct eip93_hash_export_state), ++ .base = { ++ .cra_name = "hmac(sha224)", ++ .cra_driver_name = "hmac(sha224-eip93)", ++ .cra_priority = 300, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = SHA224_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_hash_ctx), ++ .cra_init = eip93_hash_cra_init, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++ }, ++}; ++ ++struct eip93_alg_template eip93_alg_hmac_sha256 = { ++ .type = EIP93_ALG_TYPE_HASH, ++ .flags = EIP93_HASH_HMAC | EIP93_HASH_SHA256, ++ .alg.ahash = { ++ .init = eip93_hash_init, ++ .update = eip93_hash_update, ++ .final = eip93_hash_final, ++ .finup = eip93_hash_finup, ++ .digest = eip93_hash_digest, ++ .setkey = eip93_hash_hmac_setkey, ++ .export = eip93_hash_export, ++ .import = eip93_hash_import, ++ .halg = { ++ .digestsize = SHA256_DIGEST_SIZE, ++ .statesize = sizeof(struct eip93_hash_export_state), ++ .base = { ++ .cra_name = "hmac(sha256)", ++ .cra_driver_name = "hmac(sha256-eip93)", ++ .cra_priority = 300, ++ .cra_flags = CRYPTO_ALG_ASYNC | ++ CRYPTO_ALG_KERN_DRIVER_ONLY | ++ CRYPTO_ALG_ALLOCATES_MEMORY, ++ .cra_blocksize = SHA256_BLOCK_SIZE, ++ .cra_ctxsize = sizeof(struct eip93_hash_ctx), ++ .cra_init = eip93_hash_cra_init, ++ .cra_module = THIS_MODULE, ++ }, ++ }, ++ }, ++}; +--- /dev/null ++++ b/drivers/crypto/inside-secure/eip93/eip93-hash.h +@@ -0,0 +1,72 @@ ++/* SPDX-License-Identifier: GPL-2.0 ++ * ++ * Copyright (C) 2019 - 2021 ++ * ++ * Richard van Schagen ++ * Christian Marangi ++ ++#include "eip93-main.h" ++ ++struct eip93_hash_ctx { ++ struct eip93_device *mtk; ++ u32 flags; ++ ++ u8 ipad[SHA256_BLOCK_SIZE] __aligned(sizeof(u32)); ++ u8 opad[SHA256_DIGEST_SIZE] __aligned(sizeof(u32)); ++}; ++ ++struct eip93_hash_reqctx { ++ struct eip93_device *mtk; ++ ++ struct sa_record *sa_record; ++ dma_addr_t sa_record_base; ++ ++ struct sa_record *sa_record_hmac; ++ dma_addr_t sa_record_hmac_base; ++ ++ struct sa_state *sa_state; ++ dma_addr_t sa_state_base; ++ ++ /* Don't enable HASH_FINALIZE when last block is sent */ ++ bool no_finalize; ++ ++ /* ++ * EIP93 requires data to be accumulated in block of 64 bytes ++ * for intermediate hash calculation. ++ */ ++ u64 len; ++ u32 left_last; ++ struct list_head blocks; ++}; ++ ++struct mkt_hash_block { ++ struct list_head list; ++ u8 data[SHA256_BLOCK_SIZE] __aligned(sizeof(u32)); ++ dma_addr_t data_dma; ++}; ++ ++struct eip93_hash_export_state { ++ u64 len; ++ u32 left_last; ++ struct sa_state *sa_state; ++ dma_addr_t sa_state_base; ++ struct list_head blocks; ++}; ++ ++void eip93_hash_handle_result(struct crypto_async_request *async, int err); ++ ++extern struct eip93_alg_template eip93_alg_md5; ++extern struct eip93_alg_template eip93_alg_sha1; ++extern struct eip93_alg_template eip93_alg_sha224; ++extern struct eip93_alg_template eip93_alg_sha256; ++extern struct eip93_alg_template eip93_alg_hmac_md5; ++extern struct eip93_alg_template eip93_alg_hmac_sha1; ++extern struct eip93_alg_template eip93_alg_hmac_sha224; ++extern struct eip93_alg_template eip93_alg_hmac_sha256; ++ ++#endif /* _EIP93_HASH_H_ */ +--- /dev/null ++++ b/drivers/crypto/inside-secure/eip93/eip93-main.c +@@ -0,0 +1,502 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2019 - 2021 ++ * ++ * Richard van Schagen ++ * Christian Marangi ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "eip93-main.h" ++#include "eip93-regs.h" ++#include "eip93-common.h" ++#include "eip93-cipher.h" ++#include "eip93-aes.h" ++#include "eip93-des.h" ++#include "eip93-aead.h" ++#include "eip93-hash.h" ++ ++static struct eip93_alg_template *eip93_algs[] = { ++ &eip93_alg_ecb_des, ++ &eip93_alg_cbc_des, ++ &eip93_alg_ecb_des3_ede, ++ &eip93_alg_cbc_des3_ede, ++ &eip93_alg_ecb_aes, ++ &eip93_alg_cbc_aes, ++ &eip93_alg_ctr_aes, ++ &eip93_alg_rfc3686_aes, ++ &eip93_alg_authenc_hmac_md5_cbc_des, ++ &eip93_alg_authenc_hmac_sha1_cbc_des, ++ &eip93_alg_authenc_hmac_sha224_cbc_des, ++ &eip93_alg_authenc_hmac_sha256_cbc_des, ++ &eip93_alg_authenc_hmac_md5_cbc_des3_ede, ++ &eip93_alg_authenc_hmac_sha1_cbc_des3_ede, ++ &eip93_alg_authenc_hmac_sha224_cbc_des3_ede, ++ &eip93_alg_authenc_hmac_sha256_cbc_des3_ede, ++ &eip93_alg_authenc_hmac_md5_cbc_aes, ++ &eip93_alg_authenc_hmac_sha1_cbc_aes, ++ &eip93_alg_authenc_hmac_sha224_cbc_aes, ++ &eip93_alg_authenc_hmac_sha256_cbc_aes, ++ &eip93_alg_authenc_hmac_md5_rfc3686_aes, ++ &eip93_alg_authenc_hmac_sha1_rfc3686_aes, ++ &eip93_alg_authenc_hmac_sha224_rfc3686_aes, ++ &eip93_alg_authenc_hmac_sha256_rfc3686_aes, ++ &eip93_alg_md5, ++ &eip93_alg_sha1, ++ &eip93_alg_sha224, ++ &eip93_alg_sha256, ++ &eip93_alg_hmac_md5, ++ &eip93_alg_hmac_sha1, ++ &eip93_alg_hmac_sha224, ++ &eip93_alg_hmac_sha256, ++}; ++ ++inline void eip93_irq_disable(struct eip93_device *mtk, u32 mask) ++{ ++ __raw_writel(mask, mtk->base + EIP93_REG_MASK_DISABLE); ++} ++ ++inline void eip93_irq_enable(struct eip93_device *mtk, u32 mask) ++{ ++ __raw_writel(mask, mtk->base + EIP93_REG_MASK_ENABLE); ++} ++ ++inline void eip93_irq_clear(struct eip93_device *mtk, u32 mask) ++{ ++ __raw_writel(mask, mtk->base + EIP93_REG_INT_CLR); ++} ++ ++static void eip93_unregister_algs(unsigned int i) ++{ ++ unsigned int j; ++ ++ for (j = 0; j < i; j++) { ++ switch (eip93_algs[j]->type) { ++ case EIP93_ALG_TYPE_SKCIPHER: ++ crypto_unregister_skcipher(&eip93_algs[j]->alg.skcipher); ++ break; ++ case EIP93_ALG_TYPE_AEAD: ++ crypto_unregister_aead(&eip93_algs[j]->alg.aead); ++ break; ++ case EIP93_ALG_TYPE_HASH: ++ crypto_unregister_ahash(&eip93_algs[i]->alg.ahash); ++ break; ++ } ++ } ++} ++ ++static int eip93_register_algs(struct eip93_device *mtk, u32 supported_algo_flags) ++{ ++ unsigned int i; ++ int ret = 0; ++ ++ for (i = 0; i < ARRAY_SIZE(eip93_algs); i++) { ++ u32 alg_flags = eip93_algs[i]->flags; ++ ++ eip93_algs[i]->mtk = mtk; ++ ++ if ((IS_DES(alg_flags) || IS_3DES(alg_flags)) && ++ !(supported_algo_flags & EIP93_PE_OPTION_TDES)) ++ continue; ++ ++ if (IS_AES(alg_flags)) { ++ if (!(supported_algo_flags & EIP93_PE_OPTION_AES)) ++ continue; ++ ++ if (!IS_HMAC(alg_flags)) { ++ if (supported_algo_flags & EIP93_PE_OPTION_AES_KEY128) ++ eip93_algs[i]->alg.skcipher.max_keysize = ++ AES_KEYSIZE_128; ++ ++ if (supported_algo_flags & EIP93_PE_OPTION_AES_KEY192) ++ eip93_algs[i]->alg.skcipher.max_keysize = ++ AES_KEYSIZE_192; ++ ++ if (supported_algo_flags & EIP93_PE_OPTION_AES_KEY256) ++ eip93_algs[i]->alg.skcipher.max_keysize = ++ AES_KEYSIZE_256; ++ ++ if (IS_RFC3686(alg_flags)) ++ eip93_algs[i]->alg.skcipher.max_keysize += ++ CTR_RFC3686_NONCE_SIZE; ++ } ++ } ++ ++ if (IS_HASH_MD5(alg_flags) && ++ !(supported_algo_flags & EIP93_PE_OPTION_MD5)) ++ continue; ++ ++ if (IS_HASH_SHA1(alg_flags) && ++ !(supported_algo_flags & EIP93_PE_OPTION_SHA_1)) ++ continue; ++ ++ if (IS_HASH_SHA224(alg_flags) && ++ !(supported_algo_flags & EIP93_PE_OPTION_SHA_224)) ++ continue; ++ ++ if (IS_HASH_SHA256(alg_flags) && ++ !(supported_algo_flags & EIP93_PE_OPTION_SHA_256)) ++ continue; ++ ++ switch (eip93_algs[i]->type) { ++ case EIP93_ALG_TYPE_SKCIPHER: ++ ret = crypto_register_skcipher(&eip93_algs[i]->alg.skcipher); ++ break; ++ case EIP93_ALG_TYPE_AEAD: ++ ret = crypto_register_aead(&eip93_algs[i]->alg.aead); ++ break; ++ case EIP93_ALG_TYPE_HASH: ++ ret = crypto_register_ahash(&eip93_algs[i]->alg.ahash); ++ break; ++ } ++ if (ret) ++ goto fail; ++ } ++ ++ return 0; ++ ++fail: ++ eip93_unregister_algs(i); ++ ++ return ret; ++} ++ ++static void eip93_handle_result_descriptor(struct eip93_device *mtk) ++{ ++ struct crypto_async_request *async; ++ struct eip93_descriptor *rdesc; ++ u16 desc_flags, crypto_idr; ++ bool last_entry; ++ int handled, left, err; ++ u32 pe_ctrl_stat; ++ u32 pe_length; ++ ++get_more: ++ handled = 0; ++ ++ left = readl(mtk->base + EIP93_REG_PE_RD_COUNT) & EIP93_PE_RD_COUNT; ++ ++ if (!left) { ++ eip93_irq_clear(mtk, EIP93_INT_RDR_THRESH); ++ eip93_irq_enable(mtk, EIP93_INT_RDR_THRESH); ++ return; ++ } ++ ++ last_entry = false; ++ ++ while (left) { ++ rdesc = eip93_get_descriptor(mtk); ++ if (IS_ERR(rdesc)) { ++ dev_err(mtk->dev, "Ndesc: %d nreq: %d\n", ++ handled, left); ++ err = -EIO; ++ break; ++ } ++ /* make sure DMA is finished writing */ ++ do { ++ pe_ctrl_stat = READ_ONCE(rdesc->pe_ctrl_stat_word); ++ pe_length = READ_ONCE(rdesc->pe_length_word); ++ } while (FIELD_GET(EIP93_PE_CTRL_PE_READY_DES_TRING_OWN, pe_ctrl_stat) != ++ EIP93_PE_CTRL_PE_READY || ++ FIELD_GET(EIP93_PE_LENGTH_HOST_PE_READY, pe_length) != ++ EIP93_PE_LENGTH_PE_READY); ++ ++ err = rdesc->pe_ctrl_stat_word & (EIP93_PE_CTRL_PE_EXT_ERR_CODE | ++ EIP93_PE_CTRL_PE_EXT_ERR | ++ EIP93_PE_CTRL_PE_SEQNUM_ERR | ++ EIP93_PE_CTRL_PE_PAD_ERR | ++ EIP93_PE_CTRL_PE_AUTH_ERR); ++ ++ desc_flags = FIELD_GET(EIP93_PE_USER_ID_DESC_FLAGS, rdesc->user_id); ++ crypto_idr = FIELD_GET(EIP93_PE_USER_ID_CRYPTO_IDR, rdesc->user_id); ++ ++ writel(1, mtk->base + EIP93_REG_PE_RD_COUNT); ++ eip93_irq_clear(mtk, EIP93_INT_RDR_THRESH); ++ ++ handled++; ++ left--; ++ ++ if (desc_flags & EIP93_DESC_LAST) { ++ last_entry = true; ++ break; ++ } ++ } ++ ++ if (!last_entry) ++ goto get_more; ++ ++ /* Get crypto async ref only for last descriptor */ ++ scoped_guard(spinlock_bh, &mtk->ring->idr_lock) { ++ async = idr_find(&mtk->ring->crypto_async_idr, crypto_idr); ++ idr_remove(&mtk->ring->crypto_async_idr, crypto_idr); ++ } ++ ++ /* Parse error in ctrl stat word */ ++ err = eip93_parse_ctrl_stat_err(mtk, err); ++ ++ if (desc_flags & EIP93_DESC_SKCIPHER) ++ eip93_skcipher_handle_result(async, err); ++ ++ if (desc_flags & EIP93_DESC_AEAD) ++ eip93_aead_handle_result(async, err); ++ ++ if (desc_flags & EIP93_DESC_HASH) ++ eip93_hash_handle_result(async, err); ++ ++ goto get_more; ++} ++ ++static void eip93_done_task(unsigned long data) ++{ ++ struct eip93_device *mtk = (struct eip93_device *)data; ++ ++ eip93_handle_result_descriptor(mtk); ++} ++ ++static irqreturn_t eip93_irq_handler(int irq, void *data) ++{ ++ struct eip93_device *mtk = data; ++ u32 irq_status; ++ ++ irq_status = readl(mtk->base + EIP93_REG_INT_MASK_STAT); ++ if (FIELD_GET(EIP93_INT_RDR_THRESH, irq_status)) { ++ eip93_irq_disable(mtk, EIP93_INT_RDR_THRESH); ++ tasklet_schedule(&mtk->ring->done_task); ++ return IRQ_HANDLED; ++ } ++ ++ /* Ignore errors in AUTO mode, handled by the RDR */ ++ eip93_irq_clear(mtk, irq_status); ++ if (irq_status) ++ eip93_irq_disable(mtk, irq_status); ++ ++ return IRQ_NONE; ++} ++ ++static void eip93_initialize(struct eip93_device *mtk, u32 supported_algo_flags) ++{ ++ u32 val; ++ ++ /* Reset PE and rings */ ++ val = EIP93_PE_CONFIG_RST_PE | EIP93_PE_CONFIG_RST_RING; ++ val |= EIP93_PE_TARGET_AUTO_RING_MODE; ++ /* For Auto more, update the CDR ring owner after processing */ ++ val |= EIP93_PE_CONFIG_EN_CDR_UPDATE; ++ writel(val, mtk->base + EIP93_REG_PE_CONFIG); ++ ++ /* Wait for PE and ring to reset */ ++ usleep_range(10, 20); ++ ++ /* Release PE and ring reset */ ++ val = readl(mtk->base + EIP93_REG_PE_CONFIG); ++ val &= ~(EIP93_PE_CONFIG_RST_PE | EIP93_PE_CONFIG_RST_RING); ++ writel(val, mtk->base + EIP93_REG_PE_CONFIG); ++ ++ /* Config Clocks */ ++ val = EIP93_PE_CLOCK_EN_PE_CLK; ++ if (supported_algo_flags & EIP93_PE_OPTION_TDES) ++ val |= EIP93_PE_CLOCK_EN_DES_CLK; ++ if (supported_algo_flags & EIP93_PE_OPTION_AES) ++ val |= EIP93_PE_CLOCK_EN_AES_CLK; ++ if (supported_algo_flags & ++ (EIP93_PE_OPTION_MD5 | EIP93_PE_OPTION_SHA_1 | EIP93_PE_OPTION_SHA_224 | ++ EIP93_PE_OPTION_SHA_256)) ++ val |= EIP93_PE_CLOCK_EN_HASH_CLK; ++ writel(val, mtk->base + EIP93_REG_PE_CLOCK_CTRL); ++ ++ /* Config DMA thresholds */ ++ val = FIELD_PREP(EIP93_PE_OUTBUF_THRESH, 128) | ++ FIELD_PREP(EIP93_PE_INBUF_THRESH, 128); ++ writel(val, mtk->base + EIP93_REG_PE_BUF_THRESH); ++ ++ /* Clear/ack all interrupts before disable all */ ++ eip93_irq_clear(mtk, EIP93_INT_ALL); ++ eip93_irq_disable(mtk, EIP93_INT_ALL); ++ ++ /* Setup CRD threshold to trigger interrupt */ ++ val = FIELD_PREP(EIPR93_PE_CDR_THRESH, EIP93_RING_NUM - EIP93_RING_BUSY); ++ /* ++ * Configure RDR interrupt to be triggered if RD counter is not 0 ++ * for more than 2^(N+10) system clocks. ++ */ ++ val |= FIELD_PREP(EIPR93_PE_RD_TIMEOUT, 5) | EIPR93_PE_TIMEROUT_EN; ++ writel(val, mtk->base + EIP93_REG_PE_RING_THRESH); ++} ++ ++static void eip93_desc_free(struct eip93_device *mtk) ++{ ++ writel(0, mtk->base + EIP93_REG_PE_RING_CONFIG); ++ writel(0, mtk->base + EIP93_REG_PE_CDR_BASE); ++ writel(0, mtk->base + EIP93_REG_PE_RDR_BASE); ++} ++ ++static int eip93_set_ring(struct eip93_device *mtk, struct eip93_desc_ring *ring) ++{ ++ ring->offset = sizeof(struct eip93_descriptor); ++ ring->base = dmam_alloc_coherent(mtk->dev, ++ sizeof(struct eip93_descriptor) * EIP93_RING_NUM, ++ &ring->base_dma, GFP_KERNEL); ++ if (!ring->base) ++ return -ENOMEM; ++ ++ ring->write = ring->base; ++ ring->base_end = ring->base + sizeof(struct eip93_descriptor) * (EIP93_RING_NUM - 1); ++ ring->read = ring->base; ++ ++ return 0; ++} ++ ++static int eip93_desc_init(struct eip93_device *mtk) ++{ ++ struct eip93_desc_ring *cdr = &mtk->ring->cdr; ++ struct eip93_desc_ring *rdr = &mtk->ring->rdr; ++ int ret; ++ u32 val; ++ ++ ret = eip93_set_ring(mtk, cdr); ++ if (ret) ++ return ret; ++ ++ ret = eip93_set_ring(mtk, rdr); ++ if (ret) ++ return ret; ++ ++ writel((u32 __force)cdr->base_dma, mtk->base + EIP93_REG_PE_CDR_BASE); ++ writel((u32 __force)rdr->base_dma, mtk->base + EIP93_REG_PE_RDR_BASE); ++ ++ val = FIELD_PREP(EIP93_PE_RING_SIZE, EIP93_RING_NUM - 1); ++ writel(val, mtk->base + EIP93_REG_PE_RING_CONFIG); ++ ++ atomic_set(&mtk->ring->free, EIP93_RING_NUM - 1); ++ ++ return 0; ++} ++ ++static void eip93_cleanup(struct eip93_device *mtk) ++{ ++ tasklet_kill(&mtk->ring->done_task); ++ ++ /* Clear/ack all interrupts before disable all */ ++ eip93_irq_clear(mtk, EIP93_INT_ALL); ++ eip93_irq_disable(mtk, EIP93_INT_ALL); ++ ++ writel(0, mtk->base + EIP93_REG_PE_CLOCK_CTRL); ++ ++ eip93_desc_free(mtk); ++ ++ idr_destroy(&mtk->ring->crypto_async_idr); ++} ++ ++static int eip93_crypto_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct eip93_device *mtk; ++ u32 ver, algo_flags; ++ int ret; ++ ++ mtk = devm_kzalloc(dev, sizeof(*mtk), GFP_KERNEL); ++ if (!mtk) ++ return -ENOMEM; ++ ++ mtk->dev = dev; ++ platform_set_drvdata(pdev, mtk); ++ ++ mtk->base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(mtk->base)) ++ return PTR_ERR(mtk->base); ++ ++ mtk->irq = platform_get_irq(pdev, 0); ++ if (mtk->irq < 0) ++ return mtk->irq; ++ ++ ret = devm_request_threaded_irq(mtk->dev, mtk->irq, eip93_irq_handler, ++ NULL, IRQF_ONESHOT, ++ dev_name(mtk->dev), mtk); ++ ++ mtk->ring = devm_kcalloc(mtk->dev, 1, sizeof(*mtk->ring), GFP_KERNEL); ++ if (!mtk->ring) ++ return -ENOMEM; ++ ++ ret = eip93_desc_init(mtk); ++ ++ if (ret) ++ return ret; ++ ++ tasklet_init(&mtk->ring->done_task, eip93_done_task, (unsigned long)mtk); ++ ++ spin_lock_init(&mtk->ring->read_lock); ++ spin_lock_init(&mtk->ring->write_lock); ++ ++ spin_lock_init(&mtk->ring->idr_lock); ++ idr_init(&mtk->ring->crypto_async_idr); ++ ++ algo_flags = readl(mtk->base + EIP93_REG_PE_OPTION_1); ++ ++ eip93_initialize(mtk, algo_flags); ++ ++ /* Init finished, enable RDR interrupt */ ++ eip93_irq_enable(mtk, EIP93_INT_RDR_THRESH); ++ ++ ret = eip93_register_algs(mtk, algo_flags); ++ if (ret) { ++ eip93_cleanup(mtk); ++ return ret; ++ } ++ ++ ver = readl(mtk->base + EIP93_REG_PE_REVISION); ++ /* EIP_EIP_NO:MAJOR_HW_REV:MINOR_HW_REV:HW_PATCH,PE(ALGO_FLAGS) */ ++ dev_info(mtk->dev, "EIP%lu:%lx:%lx:%lx,PE(0x%x:0x%x)\n", ++ FIELD_GET(EIP93_PE_REVISION_EIP_NO, ver), ++ FIELD_GET(EIP93_PE_REVISION_MAJ_HW_REV, ver), ++ FIELD_GET(EIP93_PE_REVISION_MIN_HW_REV, ver), ++ FIELD_GET(EIP93_PE_REVISION_HW_PATCH, ver), ++ algo_flags, ++ readl(mtk->base + EIP93_REG_PE_OPTION_0)); ++ ++ return 0; ++} ++ ++static void eip93_crypto_remove(struct platform_device *pdev) ++{ ++ struct eip93_device *mtk = platform_get_drvdata(pdev); ++ ++ eip93_unregister_algs(ARRAY_SIZE(eip93_algs)); ++ eip93_cleanup(mtk); ++} ++ ++static const struct of_device_id eip93_crypto_of_match[] = { ++ { .compatible = "inside-secure,safexcel-eip93i", }, ++ { .compatible = "inside-secure,safexcel-eip93ie", }, ++ { .compatible = "inside-secure,safexcel-eip93is", }, ++ { .compatible = "inside-secure,safexcel-eip93ies", }, ++ /* IW not supported currently, missing AES-XCB-MAC/AES-CCM */ ++ /* { .compatible = "inside-secure,safexcel-eip93iw", }, */ ++ {} ++}; ++MODULE_DEVICE_TABLE(of, eip93_crypto_of_match); ++ ++static struct platform_driver eip93_crypto_driver = { ++ .probe = eip93_crypto_probe, ++ .remove_new = eip93_crypto_remove, ++ .driver = { ++ .name = "mtk-eip93", ++ .of_match_table = eip93_crypto_of_match, ++ }, ++}; ++module_platform_driver(eip93_crypto_driver); ++ ++MODULE_AUTHOR("Richard van Schagen "); ++MODULE_AUTHOR("Christian Marangi "); ++MODULE_DESCRIPTION("Mediatek EIP-93 crypto engine driver"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/crypto/inside-secure/eip93/eip93-main.h +@@ -0,0 +1,155 @@ ++/* SPDX-License-Identifier: GPL-2.0 ++ * ++ * Copyright (C) 2019 - 2021 ++ * ++ * Richard van Schagen ++ * Christian Marangi ++#include ++#include ++#include ++#include ++#include ++ ++#include "eip93-regs.h" ++ ++#define EIP93_RING_BUSY_DELAY 500 ++ ++#define EIP93_RING_NUM 512 ++#define EIP93_RING_BUSY 32 ++#define EIP93_CRA_PRIORITY 1500 ++ ++#define EIP93_RING_SA_STATE_ADDR(base, idx) ((base) + (idx)) ++#define EIP93_RING_SA_STATE_DMA(dma_base, idx) ((u32 __force)(dma_base) + \ ++ ((idx) * sizeof(struct sa_state))) ++ ++/* cipher algorithms */ ++#define EIP93_ALG_DES BIT(0) ++#define EIP93_ALG_3DES BIT(1) ++#define EIP93_ALG_AES BIT(2) ++#define EIP93_ALG_MASK GENMASK(2, 0) ++/* hash and hmac algorithms */ ++#define EIP93_HASH_MD5 BIT(3) ++#define EIP93_HASH_SHA1 BIT(4) ++#define EIP93_HASH_SHA224 BIT(5) ++#define EIP93_HASH_SHA256 BIT(6) ++#define EIP93_HASH_HMAC BIT(7) ++#define EIP93_HASH_MASK GENMASK(6, 3) ++/* cipher modes */ ++#define EIP93_MODE_CBC BIT(8) ++#define EIP93_MODE_ECB BIT(9) ++#define EIP93_MODE_CTR BIT(10) ++#define EIP93_MODE_RFC3686 BIT(11) ++#define EIP93_MODE_MASK GENMASK(10, 8) ++ ++/* cipher encryption/decryption operations */ ++#define EIP93_ENCRYPT BIT(12) ++#define EIP93_DECRYPT BIT(13) ++ ++#define EIP93_BUSY BIT(14) ++ ++/* descriptor flags */ ++#define EIP93_DESC_DMA_IV BIT(0) ++#define EIP93_DESC_IPSEC BIT(1) ++#define EIP93_DESC_FINISH BIT(2) ++#define EIP93_DESC_LAST BIT(3) ++#define EIP93_DESC_FAKE_HMAC BIT(4) ++#define EIP93_DESC_PRNG BIT(5) ++#define EIP93_DESC_HASH BIT(6) ++#define EIP93_DESC_AEAD BIT(7) ++#define EIP93_DESC_SKCIPHER BIT(8) ++#define EIP93_DESC_ASYNC BIT(9) ++ ++#define IS_DMA_IV(desc_flags) ((desc_flags) & EIP93_DESC_DMA_IV) ++ ++#define IS_DES(flags) ((flags) & EIP93_ALG_DES) ++#define IS_3DES(flags) ((flags) & EIP93_ALG_3DES) ++#define IS_AES(flags) ((flags) & EIP93_ALG_AES) ++ ++#define IS_HASH_MD5(flags) ((flags) & EIP93_HASH_MD5) ++#define IS_HASH_SHA1(flags) ((flags) & EIP93_HASH_SHA1) ++#define IS_HASH_SHA224(flags) ((flags) & EIP93_HASH_SHA224) ++#define IS_HASH_SHA256(flags) ((flags) & EIP93_HASH_SHA256) ++#define IS_HMAC(flags) ((flags) & EIP93_HASH_HMAC) ++ ++#define IS_CBC(mode) ((mode) & EIP93_MODE_CBC) ++#define IS_ECB(mode) ((mode) & EIP93_MODE_ECB) ++#define IS_CTR(mode) ((mode) & EIP93_MODE_CTR) ++#define IS_RFC3686(mode) ((mode) & EIP93_MODE_RFC3686) ++ ++#define IS_BUSY(flags) ((flags) & EIP93_BUSY) ++ ++#define IS_ENCRYPT(dir) ((dir) & EIP93_ENCRYPT) ++#define IS_DECRYPT(dir) ((dir) & EIP93_DECRYPT) ++ ++#define IS_CIPHER(flags) ((flags) & (EIP93_ALG_DES | \ ++ EIP93_ALG_3DES | \ ++ EIP93_ALG_AES)) ++ ++#define IS_HASH(flags) ((flags) & (EIP93_HASH_MD5 | \ ++ EIP93_HASH_SHA1 | \ ++ EIP93_HASH_SHA224 | \ ++ EIP93_HASH_SHA256)) ++ ++/** ++ * struct eip93_device - crypto engine device structure ++ */ ++struct eip93_device { ++ void __iomem *base; ++ struct device *dev; ++ struct clk *clk; ++ int irq; ++ struct eip93_ring *ring; ++}; ++ ++struct eip93_desc_ring { ++ void *base; ++ void *base_end; ++ dma_addr_t base_dma; ++ /* write and read pointers */ ++ void *read; ++ void *write; ++ /* descriptor element offset */ ++ u32 offset; ++}; ++ ++struct eip93_state_pool { ++ void *base; ++ dma_addr_t base_dma; ++}; ++ ++struct eip93_ring { ++ struct tasklet_struct done_task; ++ /* command/result rings */ ++ struct eip93_desc_ring cdr; ++ struct eip93_desc_ring rdr; ++ spinlock_t write_lock; ++ spinlock_t read_lock; ++ atomic_t free; ++ /* aync idr */ ++ spinlock_t idr_lock; ++ struct idr crypto_async_idr; ++}; ++ ++enum eip93_alg_type { ++ EIP93_ALG_TYPE_AEAD, ++ EIP93_ALG_TYPE_SKCIPHER, ++ EIP93_ALG_TYPE_HASH, ++}; ++ ++struct eip93_alg_template { ++ struct eip93_device *mtk; ++ enum eip93_alg_type type; ++ u32 flags; ++ union { ++ struct aead_alg aead; ++ struct skcipher_alg skcipher; ++ struct ahash_alg ahash; ++ } alg; ++}; ++ ++#endif /* _EIP93_MAIN_H_ */ +--- /dev/null ++++ b/drivers/crypto/inside-secure/eip93/eip93-regs.h +@@ -0,0 +1,335 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * Copyright (C) 2019 - 2021 ++ * ++ * Richard van Schagen ++ * Christian Marangi +Date: Tue, 28 Oct 2025 12:09:57 +0100 +Subject: [PATCH 04/10] dt-bindings: soc: Add bindings for Airoha SCU Serdes + lines + +The Airoha AN7581 SoC have can configure the SCU serdes lines for +multiple purpose. For example the Serdes for the USB1 port can be both +used for USB 3.0 operation or for Ethernet. Or the USB2 serdes can both +used for USB 3.0 operation or for PCIe. + +Add bindings to permit correct reference of the different ports in DT, +mostly to differenciate the different supported modes internally to the +drivers. + +Signed-off-by: Christian Marangi +--- + include/dt-bindings/soc/airoha,scu-ssr.h | 11 +++++++++++ + 1 file changed, 11 insertions(+) + create mode 100644 include/dt-bindings/soc/airoha,scu-ssr.h + +--- /dev/null ++++ b/include/dt-bindings/soc/airoha,scu-ssr.h +@@ -0,0 +1,11 @@ ++/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ ++ ++#ifndef __DT_BINDINGS_AIROHA_SCU_SSR_H ++#define __DT_BINDINGS_AIROHA_SCU_SSR_H ++ ++#define AIROHA_SCU_SERDES_WIFI1 0 ++#define AIROHA_SCU_SERDES_WIFI2 1 ++#define AIROHA_SCU_SERDES_USB1 2 ++#define AIROHA_SCU_SERDES_USB2 3 ++ ++#endif /* __DT_BINDINGS_AIROHA_SCU_SSR_H */ diff --git a/lede/target/linux/airoha/patches-6.12/220-05-dt-bindings-phy-Add-documentation-for-Airoha-AN7581-.patch b/lede/target/linux/airoha/patches-6.12/220-05-dt-bindings-phy-Add-documentation-for-Airoha-AN7581-.patch new file mode 100644 index 0000000000..3fc0ba7dc7 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/220-05-dt-bindings-phy-Add-documentation-for-Airoha-AN7581-.patch @@ -0,0 +1,141 @@ +From e0095e21dd9179250c304d6df2643e9a50d48edb Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 7 Feb 2025 13:25:28 +0100 +Subject: [PATCH 05/10] dt-bindings: phy: Add documentation for Airoha AN7581 + USB PHY + +Add documentation for Airoha AN7581 USB PHY that describe the USB PHY +for the USB controller. + +Airoha AN7581 SoC support a maximum of 2 USB port. The USB 2.0 mode is +always supported. The USB 3.0 mode is optional and depends on the Serdes +mode currently configured on the system for the USB port. + +If the airoha,serdes-port property is not declared, it's assumed USB 3.0 +mode is not supported, as the Serdes mode can't be validated. + +Signed-off-by: Christian Marangi +--- + .../bindings/phy/airoha,an7581-usb-phy.yaml | 83 +++++++++++++++++++ + MAINTAINERS | 7 ++ + .../dt-bindings/phy/airoha,an7581-usb-phy.h | 11 +++ + 3 files changed, 101 insertions(+) + create mode 100644 Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml + create mode 100644 include/dt-bindings/phy/airoha,an7581-usb-phy.h + +--- /dev/null ++++ b/Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml +@@ -0,0 +1,83 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/phy/airoha,an7581-usb-phy.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Airoha AN7581 SoC USB PHY ++ ++maintainers: ++ - Christian Marangi ++ ++description: > ++ The Airoha AN7581 SoC USB PHY describes the USB PHY for the USB controller. ++ ++ Airoha AN7581 SoC support a maximum of 2 USB port. The USB 2.0 mode is ++ always supported. The USB 3.0 mode is optional and depends on the Serdes ++ mode currently configured on the system for the USB port. ++ ++ If the airoha,serdes-port property is not declared, it's assumed USB 3.0 ++ mode is not supported, as the Serdes mode can't be validated. ++ ++properties: ++ compatible: ++ const: airoha,an7581-usb-phy ++ ++ reg: ++ maxItems: 1 ++ ++ ++ airoha,usb2-monitor-clk-sel: ++ description: Describe what oscillator across the available 4 ++ should be selected for USB 2.0 Slew Rate calibration. ++ $ref: /schemas/types.yaml#/definitions/uint32 ++ enum: [0, 1, 2, 3] ++ ++ airoha,serdes-port: ++ description: Describe what Serdes Port is attached to the USB 3.0 port. ++ $ref: /schemas/types.yaml#/definitions/uint32 ++ enum: [0, 1, 2, 3] ++ ++ airoha,scu: ++ description: Phandle to the SCU node for USB 3.0 Serdes mode validation. ++ $ref: /schemas/types.yaml#/definitions/phandle ++ ++ '#phy-cells': ++ const: 1 ++ ++required: ++ - compatible ++ - reg ++ - airoha,usb2-monitor-clk-sel ++ - '#phy-cells' ++ ++dependentRequired: ++ airoha,serdes-port: [ 'airoha,scu' ] ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ ++ phy@1fac0000 { ++ compatible = "airoha,an7581-usb-phy"; ++ reg = <0x1fac0000 0x10000>; ++ ++ airoha,usb2-monitor-clk-sel = ; ++ airoha,scu = <&scu>; ++ airoha,serdes-port = ; ++ ++ #phy-cells = <1>; ++ }; ++ ++ phy@1fae0000 { ++ compatible = "airoha,an7581-usb-phy"; ++ reg = <0x1fae0000 0x10000>; ++ ++ airoha,usb2-monitor-clk-sel = ; ++ ++ #phy-cells = <1>; ++ }; ++ +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -737,6 +737,13 @@ S: Maintained + F: Documentation/devicetree/bindings/spi/airoha,en7581-snand.yaml + F: drivers/spi/spi-airoha-snfi.c + ++AIROHA USB PHY DRIVER ++M: Christian Marangi ++L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) ++S: Maintained ++F: Documentation/devicetree/bindings/phy/airoha,an7581-usb-phy.yaml ++F: include/dt-bindings/phy/airoha,an7581-usb-phy.h ++ + AIRSPY MEDIA DRIVER + L: linux-media@vger.kernel.org + S: Orphan +--- /dev/null ++++ b/include/dt-bindings/phy/airoha,an7581-usb-phy.h +@@ -0,0 +1,11 @@ ++/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ ++ ++#ifndef _DT_BINDINGS_AIROHA_AN7581_USB_PHY_H_ ++#define _DT_BINDINGS_AIROHA_AN7581_USB_PHY_H_ ++ ++#define AIROHA_USB2_MONCLK_SEL0 0 ++#define AIROHA_USB2_MONCLK_SEL1 1 ++#define AIROHA_USB2_MONCLK_SEL2 2 ++#define AIROHA_USB2_MONCLK_SEL3 3 ++ ++#endif diff --git a/lede/target/linux/airoha/patches-6.12/220-06-phy-move-Airoha-PCIe-PHY-driver-to-dedicated-directo.patch b/lede/target/linux/airoha/patches-6.12/220-06-phy-move-Airoha-PCIe-PHY-driver-to-dedicated-directo.patch new file mode 100644 index 0000000000..e61de0441e --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/220-06-phy-move-Airoha-PCIe-PHY-driver-to-dedicated-directo.patch @@ -0,0 +1,1885 @@ +From 1bfe1cc581ffba2462580496507497840aa018aa Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 19 Mar 2025 15:23:50 +0100 +Subject: [PATCH 06/10] phy: move Airoha PCIe PHY driver to dedicated directory + +To keep the generic PHY directory tidy, move the PCIe PHY driver to a +dedicated directory. + +This is also in preparation for support of the Airoha USB PHY driver. + +Signed-off-by: Christian Marangi +--- + MAINTAINERS | 4 +- + drivers/phy/Kconfig | 11 +- + drivers/phy/Makefile | 5 +- + drivers/phy/airoha/Kconfig | 13 + + drivers/phy/airoha/Makefile | 3 + + drivers/phy/airoha/phy-airoha-pcie-regs.h | 494 ++++++++ + drivers/phy/airoha/phy-airoha-pcie.c | 1290 +++++++++++++++++++++ + 7 files changed, 1806 insertions(+), 14 deletions(-) + create mode 100644 drivers/phy/airoha/Kconfig + create mode 100644 drivers/phy/airoha/Makefile + create mode 100644 drivers/phy/airoha/phy-airoha-pcie-regs.h + create mode 100644 drivers/phy/airoha/phy-airoha-pcie.c + +# diff --git a/MAINTAINERS b/MAINTAINERS +# index 2468f4fea5b7..3f930a613658 100644 +# --- a/MAINTAINERS +# +++ b/MAINTAINERS +# @@ -733,8 +733,8 @@ M: Lorenzo Bianconi +# L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +# S: Maintained +# F: Documentation/devicetree/bindings/phy/airoha,en7581-pcie-phy.yaml +# -F: drivers/phy/phy-airoha-pcie-regs.h +# -F: drivers/phy/phy-airoha-pcie.c +# +F: drivers/phy/airoha/phy-airoha-pcie-regs.h +# +F: drivers/phy/airoha/phy-airoha-pcie.c + +# AIROHA SPI SNFI DRIVER +# M: Lorenzo Bianconi +--- a/drivers/phy/Kconfig ++++ b/drivers/phy/Kconfig +@@ -72,16 +72,7 @@ config PHY_CAN_TRANSCEIVER + functional modes using gpios and sets the attribute max link + rate, for CAN drivers. + +-config PHY_AIROHA_PCIE +- tristate "Airoha PCIe-PHY Driver" +- depends on ARCH_AIROHA || COMPILE_TEST +- depends on OF +- select GENERIC_PHY +- help +- Say Y here to add support for Airoha PCIe PHY driver. +- This driver create the basic PHY instance and provides initialize +- callback for PCIe GEN3 port. +- ++source "drivers/phy/airoha/Kconfig" + source "drivers/phy/allwinner/Kconfig" + source "drivers/phy/amlogic/Kconfig" + source "drivers/phy/broadcom/Kconfig" +--- a/drivers/phy/Makefile ++++ b/drivers/phy/Makefile +@@ -10,8 +10,8 @@ obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy + obj-$(CONFIG_PHY_XGENE) += phy-xgene.o + obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o + obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o +-obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o +-obj-y += allwinner/ \ ++obj-y += airoha/ \ ++ allwinner/ \ + amlogic/ \ + broadcom/ \ + cadence/ \ +--- /dev/null ++++ b/drivers/phy/airoha/Kconfig +@@ -0,0 +1,13 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++# ++# Phy drivers for Airoha devices ++# ++config PHY_AIROHA_PCIE ++ tristate "Airoha PCIe-PHY Driver" ++ depends on ARCH_AIROHA || COMPILE_TEST ++ depends on OF ++ select GENERIC_PHY ++ help ++ Say Y here to add support for Airoha PCIe PHY driver. ++ This driver create the basic PHY instance and provides initialize ++ callback for PCIe GEN3 port. +--- /dev/null ++++ b/drivers/phy/airoha/Makefile +@@ -0,0 +1,3 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++obj-$(CONFIG_PHY_AIROHA_PCIE) += phy-airoha-pcie.o +--- /dev/null ++++ b/drivers/phy/airoha/phy-airoha-pcie-regs.h +@@ -0,0 +1,494 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2024 AIROHA Inc ++ * Author: Lorenzo Bianconi ++ */ ++ ++#ifndef _PHY_AIROHA_PCIE_H ++#define _PHY_AIROHA_PCIE_H ++ ++/* CSR_2L */ ++#define REG_CSR_2L_CMN 0x0000 ++#define CSR_2L_PXP_CMN_LANE_EN BIT(0) ++#define CSR_2L_PXP_CMN_TRIM_MASK GENMASK(28, 24) ++ ++#define REG_CSR_2L_JCPLL_IB_EXT 0x0004 ++#define REG_CSR_2L_JCPLL_LPF_SHCK_EN BIT(8) ++#define CSR_2L_PXP_JCPLL_CHP_IBIAS GENMASK(21, 16) ++#define CSR_2L_PXP_JCPLL_CHP_IOFST GENMASK(29, 24) ++ ++#define REG_CSR_2L_JCPLL_LPF_BR 0x0008 ++#define CSR_2L_PXP_JCPLL_LPF_BR GENMASK(4, 0) ++#define CSR_2L_PXP_JCPLL_LPF_BC GENMASK(12, 8) ++#define CSR_2L_PXP_JCPLL_LPF_BP GENMASK(20, 16) ++#define CSR_2L_PXP_JCPLL_LPF_BWR GENMASK(28, 24) ++ ++#define REG_CSR_2L_JCPLL_LPF_BWC 0x000c ++#define CSR_2L_PXP_JCPLL_LPF_BWC GENMASK(4, 0) ++#define CSR_2L_PXP_JCPLL_KBAND_CODE GENMASK(23, 16) ++#define CSR_2L_PXP_JCPLL_KBAND_DIV GENMASK(26, 24) ++ ++#define REG_CSR_2L_JCPLL_KBAND_KFC 0x0010 ++#define CSR_2L_PXP_JCPLL_KBAND_KFC GENMASK(1, 0) ++#define CSR_2L_PXP_JCPLL_KBAND_KF GENMASK(9, 8) ++#define CSR_2L_PXP_JCPLL_KBAND_KS GENMASK(17, 16) ++#define CSR_2L_PXP_JCPLL_POSTDIV_EN BIT(24) ++ ++#define REG_CSR_2L_JCPLL_MMD_PREDIV_MODE 0x0014 ++#define CSR_2L_PXP_JCPLL_MMD_PREDIV_MODE GENMASK(1, 0) ++#define CSR_2L_PXP_JCPLL_POSTDIV_D2 BIT(16) ++#define CSR_2L_PXP_JCPLL_POSTDIV_D5 BIT(24) ++ ++#define CSR_2L_PXP_JCPLL_MONCK 0x0018 ++#define CSR_2L_PXP_JCPLL_REFIN_DIV GENMASK(25, 24) ++ ++#define REG_CSR_2L_JCPLL_RST_DLY 0x001c ++#define CSR_2L_PXP_JCPLL_RST_DLY GENMASK(2, 0) ++#define CSR_2L_PXP_JCPLL_RST BIT(8) ++#define CSR_2L_PXP_JCPLL_SDM_DI_EN BIT(16) ++#define CSR_2L_PXP_JCPLL_SDM_DI_LS GENMASK(25, 24) ++ ++#define REG_CSR_2L_JCPLL_SDM_IFM 0x0020 ++#define CSR_2L_PXP_JCPLL_SDM_IFM BIT(0) ++ ++#define REG_CSR_2L_JCPLL_SDM_HREN 0x0024 ++#define CSR_2L_PXP_JCPLL_SDM_HREN BIT(0) ++#define CSR_2L_PXP_JCPLL_TCL_AMP_EN BIT(8) ++#define CSR_2L_PXP_JCPLL_TCL_AMP_GAIN GENMASK(18, 16) ++#define CSR_2L_PXP_JCPLL_TCL_AMP_VREF GENMASK(28, 24) ++ ++#define REG_CSR_2L_JCPLL_TCL_CMP 0x0028 ++#define CSR_2L_PXP_JCPLL_TCL_LPF_EN BIT(16) ++#define CSR_2L_PXP_JCPLL_TCL_LPF_BW GENMASK(26, 24) ++ ++#define REG_CSR_2L_JCPLL_VCODIV 0x002c ++#define CSR_2L_PXP_JCPLL_VCO_CFIX GENMASK(9, 8) ++#define CSR_2L_PXP_JCPLL_VCO_HALFLSB_EN BIT(16) ++#define CSR_2L_PXP_JCPLL_VCO_SCAPWR GENMASK(26, 24) ++ ++#define REG_CSR_2L_JCPLL_VCO_TCLVAR 0x0030 ++#define CSR_2L_PXP_JCPLL_VCO_TCLVAR GENMASK(2, 0) ++ ++#define REG_CSR_2L_JCPLL_SSC 0x0038 ++#define CSR_2L_PXP_JCPLL_SSC_EN BIT(0) ++#define CSR_2L_PXP_JCPLL_SSC_PHASE_INI BIT(8) ++#define CSR_2L_PXP_JCPLL_SSC_TRI_EN BIT(16) ++ ++#define REG_CSR_2L_JCPLL_SSC_DELTA1 0x003c ++#define CSR_2L_PXP_JCPLL_SSC_DELTA1 GENMASK(15, 0) ++#define CSR_2L_PXP_JCPLL_SSC_DELTA GENMASK(31, 16) ++ ++#define REG_CSR_2L_JCPLL_SSC_PERIOD 0x0040 ++#define CSR_2L_PXP_JCPLL_SSC_PERIOD GENMASK(15, 0) ++ ++#define REG_CSR_2L_JCPLL_TCL_VTP_EN 0x004c ++#define CSR_2L_PXP_JCPLL_SPARE_LOW GENMASK(31, 24) ++ ++#define REG_CSR_2L_JCPLL_TCL_KBAND_VREF 0x0050 ++#define CSR_2L_PXP_JCPLL_TCL_KBAND_VREF GENMASK(4, 0) ++#define CSR_2L_PXP_JCPLL_VCO_KBAND_MEAS_EN BIT(24) ++ ++#define REG_CSR_2L_750M_SYS_CK 0x0054 ++#define CSR_2L_PXP_TXPLL_LPF_SHCK_EN BIT(16) ++#define CSR_2L_PXP_TXPLL_CHP_IBIAS GENMASK(29, 24) ++ ++#define REG_CSR_2L_TXPLL_CHP_IOFST 0x0058 ++#define CSR_2L_PXP_TXPLL_CHP_IOFST GENMASK(5, 0) ++#define CSR_2L_PXP_TXPLL_LPF_BR GENMASK(12, 8) ++#define CSR_2L_PXP_TXPLL_LPF_BC GENMASK(20, 16) ++#define CSR_2L_PXP_TXPLL_LPF_BP GENMASK(28, 24) ++ ++#define REG_CSR_2L_TXPLL_LPF_BWR 0x005c ++#define CSR_2L_PXP_TXPLL_LPF_BWR GENMASK(4, 0) ++#define CSR_2L_PXP_TXPLL_LPF_BWC GENMASK(12, 8) ++#define CSR_2L_PXP_TXPLL_KBAND_CODE GENMASK(31, 24) ++ ++#define REG_CSR_2L_TXPLL_KBAND_DIV 0x0060 ++#define CSR_2L_PXP_TXPLL_KBAND_DIV GENMASK(2, 0) ++#define CSR_2L_PXP_TXPLL_KBAND_KFC GENMASK(9, 8) ++#define CSR_2L_PXP_TXPLL_KBAND_KF GENMASK(17, 16) ++#define CSR_2L_PXP_txpll_KBAND_KS GENMASK(25, 24) ++ ++#define REG_CSR_2L_TXPLL_POSTDIV 0x0064 ++#define CSR_2L_PXP_TXPLL_POSTDIV_EN BIT(0) ++#define CSR_2L_PXP_TXPLL_MMD_PREDIV_MODE GENMASK(9, 8) ++#define CSR_2L_PXP_TXPLL_PHY_CK1_EN BIT(24) ++ ++#define REG_CSR_2L_TXPLL_PHY_CK2 0x0068 ++#define CSR_2L_PXP_TXPLL_REFIN_INTERNAL BIT(24) ++ ++#define REG_CSR_2L_TXPLL_REFIN_DIV 0x006c ++#define CSR_2L_PXP_TXPLL_REFIN_DIV GENMASK(1, 0) ++#define CSR_2L_PXP_TXPLL_RST_DLY GENMASK(10, 8) ++#define CSR_2L_PXP_TXPLL_PLL_RSTB BIT(16) ++ ++#define REG_CSR_2L_TXPLL_SDM_DI_LS 0x0070 ++#define CSR_2L_PXP_TXPLL_SDM_DI_LS GENMASK(1, 0) ++#define CSR_2L_PXP_TXPLL_SDM_IFM BIT(8) ++#define CSR_2L_PXP_TXPLL_SDM_ORD GENMASK(25, 24) ++ ++#define REG_CSR_2L_TXPLL_SDM_OUT 0x0074 ++#define CSR_2L_PXP_TXPLL_TCL_AMP_EN BIT(16) ++#define CSR_2L_PXP_TXPLL_TCL_AMP_GAIN GENMASK(26, 24) ++ ++#define REG_CSR_2L_TXPLL_TCL_AMP_VREF 0x0078 ++#define CSR_2L_PXP_TXPLL_TCL_AMP_VREF GENMASK(4, 0) ++#define CSR_2L_PXP_TXPLL_TCL_LPF_EN BIT(24) ++ ++#define REG_CSR_2L_TXPLL_TCL_LPF_BW 0x007c ++#define CSR_2L_PXP_TXPLL_TCL_LPF_BW GENMASK(2, 0) ++#define CSR_2L_PXP_TXPLL_VCO_CFIX GENMASK(17, 16) ++#define CSR_2L_PXP_TXPLL_VCO_HALFLSB_EN BIT(24) ++ ++#define REG_CSR_2L_TXPLL_VCO_SCAPWR 0x0080 ++#define CSR_2L_PXP_TXPLL_VCO_SCAPWR GENMASK(2, 0) ++ ++#define REG_CSR_2L_TXPLL_SSC 0x0084 ++#define CSR_2L_PXP_TXPLL_SSC_EN BIT(0) ++#define CSR_2L_PXP_TXPLL_SSC_PHASE_INI BIT(8) ++ ++#define REG_CSR_2L_TXPLL_SSC_DELTA1 0x0088 ++#define CSR_2L_PXP_TXPLL_SSC_DELTA1 GENMASK(15, 0) ++#define CSR_2L_PXP_TXPLL_SSC_DELTA GENMASK(31, 16) ++ ++#define REG_CSR_2L_TXPLL_SSC_PERIOD 0x008c ++#define CSR_2L_PXP_txpll_SSC_PERIOD GENMASK(15, 0) ++ ++#define REG_CSR_2L_TXPLL_VTP 0x0090 ++#define CSR_2L_PXP_TXPLL_VTP_EN BIT(0) ++ ++#define REG_CSR_2L_TXPLL_TCL_VTP 0x0098 ++#define CSR_2L_PXP_TXPLL_SPARE_L GENMASK(31, 24) ++ ++#define REG_CSR_2L_TXPLL_TCL_KBAND_VREF 0x009c ++#define CSR_2L_PXP_TXPLL_TCL_KBAND_VREF GENMASK(4, 0) ++#define CSR_2L_PXP_TXPLL_VCO_KBAND_MEAS_EN BIT(24) ++ ++#define REG_CSR_2L_TXPLL_POSTDIV_D256 0x00a0 ++#define CSR_2L_PXP_CLKTX0_AMP GENMASK(10, 8) ++#define CSR_2L_PXP_CLKTX0_OFFSET GENMASK(17, 16) ++#define CSR_2L_PXP_CLKTX0_SR GENMASK(25, 24) ++ ++#define REG_CSR_2L_CLKTX0_FORCE_OUT1 0x00a4 ++#define CSR_2L_PXP_CLKTX0_HZ BIT(8) ++#define CSR_2L_PXP_CLKTX0_IMP_SEL GENMASK(20, 16) ++#define CSR_2L_PXP_CLKTX1_AMP GENMASK(26, 24) ++ ++#define REG_CSR_2L_CLKTX1_OFFSET 0x00a8 ++#define CSR_2L_PXP_CLKTX1_OFFSET GENMASK(1, 0) ++#define CSR_2L_PXP_CLKTX1_SR GENMASK(9, 8) ++#define CSR_2L_PXP_CLKTX1_HZ BIT(24) ++ ++#define REG_CSR_2L_CLKTX1_IMP_SEL 0x00ac ++#define CSR_2L_PXP_CLKTX1_IMP_SEL GENMASK(4, 0) ++ ++#define REG_CSR_2L_PLL_CMN_RESERVE0 0x00b0 ++#define CSR_2L_PXP_PLL_RESERVE_MASK GENMASK(15, 0) ++ ++#define REG_CSR_2L_TX0_CKLDO 0x00cc ++#define CSR_2L_PXP_TX0_CKLDO_EN BIT(0) ++#define CSR_2L_PXP_TX0_DMEDGEGEN_EN BIT(24) ++ ++#define REG_CSR_2L_TX1_CKLDO 0x00e8 ++#define CSR_2L_PXP_TX1_CKLDO_EN BIT(0) ++#define CSR_2L_PXP_TX1_DMEDGEGEN_EN BIT(24) ++ ++#define REG_CSR_2L_TX1_MULTLANE 0x00ec ++#define CSR_2L_PXP_TX1_MULTLANE_EN BIT(0) ++ ++#define REG_CSR_2L_RX0_REV0 0x00fc ++#define CSR_2L_PXP_VOS_PNINV GENMASK(19, 18) ++#define CSR_2L_PXP_FE_GAIN_NORMAL_MODE GENMASK(22, 20) ++#define CSR_2L_PXP_FE_GAIN_TRAIN_MODE GENMASK(26, 24) ++ ++#define REG_CSR_2L_RX0_PHYCK_DIV 0x0100 ++#define CSR_2L_PXP_RX0_PHYCK_SEL GENMASK(9, 8) ++#define CSR_2L_PXP_RX0_PHYCK_RSTB BIT(16) ++#define CSR_2L_PXP_RX0_TDC_CK_SEL BIT(24) ++ ++#define REG_CSR_2L_CDR0_PD_PICAL_CKD8_INV 0x0104 ++#define CSR_2L_PXP_CDR0_PD_EDGE_DISABLE BIT(8) ++ ++#define REG_CSR_2L_CDR0_LPF_RATIO 0x0110 ++#define CSR_2L_PXP_CDR0_LPF_TOP_LIM GENMASK(26, 8) ++ ++#define REG_CSR_2L_CDR0_PR_INJ_MODE 0x011c ++#define CSR_2L_PXP_CDR0_INJ_FORCE_OFF BIT(24) ++ ++#define REG_CSR_2L_CDR0_PR_BETA_DAC 0x0120 ++#define CSR_2L_PXP_CDR0_PR_BETA_SEL GENMASK(19, 16) ++#define CSR_2L_PXP_CDR0_PR_KBAND_DIV GENMASK(26, 24) ++ ++#define REG_CSR_2L_CDR0_PR_VREG_IBAND 0x0124 ++#define CSR_2L_PXP_CDR0_PR_VREG_IBAND GENMASK(2, 0) ++#define CSR_2L_PXP_CDR0_PR_VREG_CKBUF GENMASK(10, 8) ++ ++#define REG_CSR_2L_CDR0_PR_CKREF_DIV 0x0128 ++#define CSR_2L_PXP_CDR0_PR_CKREF_DIV GENMASK(1, 0) ++ ++#define REG_CSR_2L_CDR0_PR_MONCK 0x012c ++#define CSR_2L_PXP_CDR0_PR_MONCK_ENABLE BIT(0) ++#define CSR_2L_PXP_CDR0_PR_RESERVE0 GENMASK(19, 16) ++ ++#define REG_CSR_2L_CDR0_PR_COR_HBW 0x0130 ++#define CSR_2L_PXP_CDR0_PR_LDO_FORCE_ON BIT(8) ++#define CSR_2L_PXP_CDR0_PR_CKREF_DIV1 GENMASK(17, 16) ++ ++#define REG_CSR_2L_CDR0_PR_MONPI 0x0134 ++#define CSR_2L_PXP_CDR0_PR_XFICK_EN BIT(8) ++ ++#define REG_CSR_2L_RX0_SIGDET_DCTEST 0x0140 ++#define CSR_2L_PXP_RX0_SIGDET_LPF_CTRL GENMASK(9, 8) ++#define CSR_2L_PXP_RX0_SIGDET_PEAK GENMASK(25, 24) ++ ++#define REG_CSR_2L_RX0_SIGDET_VTH_SEL 0x0144 ++#define CSR_2L_PXP_RX0_SIGDET_VTH_SEL GENMASK(4, 0) ++#define CSR_2L_PXP_RX0_FE_VB_EQ1_EN BIT(24) ++ ++#define REG_CSR_2L_PXP_RX0_FE_VB_EQ2 0x0148 ++#define CSR_2L_PXP_RX0_FE_VB_EQ2_EN BIT(0) ++#define CSR_2L_PXP_RX0_FE_VB_EQ3_EN BIT(8) ++#define CSR_2L_PXP_RX0_FE_VCM_GEN_PWDB BIT(16) ++ ++#define REG_CSR_2L_PXP_RX0_OSCAL_CTLE1IOS 0x0158 ++#define CSR_2L_PXP_RX0_PR_OSCAL_VGA1IOS GENMASK(29, 24) ++ ++#define REG_CSR_2L_PXP_RX0_OSCA_VGA1VOS 0x015c ++#define CSR_2L_PXP_RX0_PR_OSCAL_VGA1VOS GENMASK(5, 0) ++#define CSR_2L_PXP_RX0_PR_OSCAL_VGA2IOS GENMASK(13, 8) ++ ++#define REG_CSR_2L_RX1_REV0 0x01b4 ++ ++#define REG_CSR_2L_RX1_PHYCK_DIV 0x01b8 ++#define CSR_2L_PXP_RX1_PHYCK_SEL GENMASK(9, 8) ++#define CSR_2L_PXP_RX1_PHYCK_RSTB BIT(16) ++#define CSR_2L_PXP_RX1_TDC_CK_SEL BIT(24) ++ ++#define REG_CSR_2L_CDR1_PD_PICAL_CKD8_INV 0x01bc ++#define CSR_2L_PXP_CDR1_PD_EDGE_DISABLE BIT(8) ++ ++#define REG_CSR_2L_CDR1_PR_BETA_DAC 0x01d8 ++#define CSR_2L_PXP_CDR1_PR_BETA_SEL GENMASK(19, 16) ++#define CSR_2L_PXP_CDR1_PR_KBAND_DIV GENMASK(26, 24) ++ ++#define REG_CSR_2L_CDR1_PR_MONCK 0x01e4 ++#define CSR_2L_PXP_CDR1_PR_MONCK_ENABLE BIT(0) ++#define CSR_2L_PXP_CDR1_PR_RESERVE0 GENMASK(19, 16) ++ ++#define REG_CSR_2L_CDR1_LPF_RATIO 0x01c8 ++#define CSR_2L_PXP_CDR1_LPF_TOP_LIM GENMASK(26, 8) ++ ++#define REG_CSR_2L_CDR1_PR_INJ_MODE 0x01d4 ++#define CSR_2L_PXP_CDR1_INJ_FORCE_OFF BIT(24) ++ ++#define REG_CSR_2L_CDR1_PR_VREG_IBAND_VAL 0x01dc ++#define CSR_2L_PXP_CDR1_PR_VREG_IBAND GENMASK(2, 0) ++#define CSR_2L_PXP_CDR1_PR_VREG_CKBUF GENMASK(10, 8) ++ ++#define REG_CSR_2L_CDR1_PR_CKREF_DIV 0x01e0 ++#define CSR_2L_PXP_CDR1_PR_CKREF_DIV GENMASK(1, 0) ++ ++#define REG_CSR_2L_CDR1_PR_COR_HBW 0x01e8 ++#define CSR_2L_PXP_CDR1_PR_LDO_FORCE_ON BIT(8) ++#define CSR_2L_PXP_CDR1_PR_CKREF_DIV1 GENMASK(17, 16) ++ ++#define REG_CSR_2L_CDR1_PR_MONPI 0x01ec ++#define CSR_2L_PXP_CDR1_PR_XFICK_EN BIT(8) ++ ++#define REG_CSR_2L_RX1_DAC_RANGE_EYE 0x01f4 ++#define CSR_2L_PXP_RX1_SIGDET_LPF_CTRL GENMASK(25, 24) ++ ++#define REG_CSR_2L_RX1_SIGDET_NOVTH 0x01f8 ++#define CSR_2L_PXP_RX1_SIGDET_PEAK GENMASK(9, 8) ++#define CSR_2L_PXP_RX1_SIGDET_VTH_SEL GENMASK(20, 16) ++ ++#define REG_CSR_2L_RX1_FE_VB_EQ1 0x0200 ++#define CSR_2L_PXP_RX1_FE_VB_EQ1_EN BIT(0) ++#define CSR_2L_PXP_RX1_FE_VB_EQ2_EN BIT(8) ++#define CSR_2L_PXP_RX1_FE_VB_EQ3_EN BIT(16) ++#define CSR_2L_PXP_RX1_FE_VCM_GEN_PWDB BIT(24) ++ ++#define REG_CSR_2L_RX1_OSCAL_VGA1IOS 0x0214 ++#define CSR_2L_PXP_RX1_PR_OSCAL_VGA1IOS GENMASK(5, 0) ++#define CSR_2L_PXP_RX1_PR_OSCAL_VGA1VOS GENMASK(13, 8) ++#define CSR_2L_PXP_RX1_PR_OSCAL_VGA2IOS GENMASK(21, 16) ++ ++/* PMA */ ++#define REG_PCIE_PMA_SS_LCPLL_PWCTL_SETTING_1 0x0004 ++#define PCIE_LCPLL_MAN_PWDB BIT(0) ++ ++#define REG_PCIE_PMA_SEQUENCE_DISB_CTRL1 0x010c ++#define PCIE_DISB_RX_SDCAL_EN BIT(0) ++ ++#define REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1 0x0114 ++#define PCIE_FORCE_RX_SDCAL_EN BIT(0) ++ ++#define REG_PCIE_PMA_SS_RX_FREQ_DET1 0x014c ++#define PCIE_PLL_FT_LOCK_CYCLECNT GENMASK(15, 0) ++#define PCIE_PLL_FT_UNLOCK_CYCLECNT GENMASK(31, 16) ++ ++#define REG_PCIE_PMA_SS_RX_FREQ_DET2 0x0150 ++#define PCIE_LOCK_TARGET_BEG GENMASK(15, 0) ++#define PCIE_LOCK_TARGET_END GENMASK(31, 16) ++ ++#define REG_PCIE_PMA_SS_RX_FREQ_DET3 0x0154 ++#define PCIE_UNLOCK_TARGET_BEG GENMASK(15, 0) ++#define PCIE_UNLOCK_TARGET_END GENMASK(31, 16) ++ ++#define REG_PCIE_PMA_SS_RX_FREQ_DET4 0x0158 ++#define PCIE_FREQLOCK_DET_EN GENMASK(2, 0) ++#define PCIE_LOCK_LOCKTH GENMASK(11, 8) ++#define PCIE_UNLOCK_LOCKTH GENMASK(15, 12) ++ ++#define REG_PCIE_PMA_SS_RX_CAL1 0x0160 ++#define REG_PCIE_PMA_SS_RX_CAL2 0x0164 ++#define PCIE_CAL_OUT_OS GENMASK(11, 8) ++ ++#define REG_PCIE_PMA_SS_RX_SIGDET0 0x0168 ++#define PCIE_SIGDET_WIN_NONVLD_TIMES GENMASK(28, 24) ++ ++#define REG_PCIE_PMA_TX_RESET 0x0260 ++#define PCIE_TX_TOP_RST BIT(0) ++#define PCIE_TX_CAL_RST BIT(8) ++ ++#define REG_PCIE_PMA_RX_FORCE_MODE0 0x0294 ++#define PCIE_FORCE_DA_XPON_RX_FE_GAIN_CTRL GENMASK(1, 0) ++ ++#define REG_PCIE_PMA_SS_DA_XPON_PWDB0 0x034c ++#define PCIE_DA_XPON_CDR_PR_PWDB BIT(8) ++ ++#define REG_PCIE_PMA_SW_RESET 0x0460 ++#define PCIE_SW_RX_FIFO_RST BIT(0) ++#define PCIE_SW_RX_RST BIT(1) ++#define PCIE_SW_TX_RST BIT(2) ++#define PCIE_SW_PMA_RST BIT(3) ++#define PCIE_SW_ALLPCS_RST BIT(4) ++#define PCIE_SW_REF_RST BIT(5) ++#define PCIE_SW_TX_FIFO_RST BIT(6) ++#define PCIE_SW_XFI_TXPCS_RST BIT(7) ++#define PCIE_SW_XFI_RXPCS_RST BIT(8) ++#define PCIE_SW_XFI_RXPCS_BIST_RST BIT(9) ++#define PCIE_SW_HSG_TXPCS_RST BIT(10) ++#define PCIE_SW_HSG_RXPCS_RST BIT(11) ++#define PCIE_PMA_SW_RST (PCIE_SW_RX_FIFO_RST | \ ++ PCIE_SW_RX_RST | \ ++ PCIE_SW_TX_RST | \ ++ PCIE_SW_PMA_RST | \ ++ PCIE_SW_ALLPCS_RST | \ ++ PCIE_SW_REF_RST | \ ++ PCIE_SW_TX_FIFO_RST | \ ++ PCIE_SW_XFI_TXPCS_RST | \ ++ PCIE_SW_XFI_RXPCS_RST | \ ++ PCIE_SW_XFI_RXPCS_BIST_RST | \ ++ PCIE_SW_HSG_TXPCS_RST | \ ++ PCIE_SW_HSG_RXPCS_RST) ++ ++#define REG_PCIE_PMA_RO_RX_FREQDET 0x0530 ++#define PCIE_RO_FBCK_LOCK BIT(0) ++#define PCIE_RO_FL_OUT GENMASK(31, 16) ++ ++#define REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC 0x0794 ++#define PCIE_FORCE_DA_PXP_CDR_PR_IDAC GENMASK(10, 0) ++#define PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC BIT(16) ++#define PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW BIT(24) ++ ++#define REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_SDM_PCW 0x0798 ++#define PCIE_FORCE_DA_PXP_TXPLL_SDM_PCW GENMASK(30, 0) ++ ++#define REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_VOS 0x079c ++#define PCIE_FORCE_SEL_DA_PXP_JCPLL_SDM_PCW BIT(16) ++ ++#define REG_PCIE_PMA_FORCE_DA_PXP_JCPLL_SDM_PCW 0x0800 ++#define PCIE_FORCE_DA_PXP_JCPLL_SDM_PCW GENMASK(30, 0) ++ ++#define REG_PCIE_PMA_FORCE_DA_PXP_CDR_PD_PWDB 0x081c ++#define PCIE_FORCE_DA_PXP_CDR_PD_PWDB BIT(0) ++#define PCIE_FORCE_SEL_DA_PXP_CDR_PD_PWDB BIT(8) ++ ++#define REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C 0x0820 ++#define PCIE_FORCE_DA_PXP_CDR_PR_LPF_C_EN BIT(0) ++#define PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN BIT(8) ++#define PCIE_FORCE_DA_PXP_CDR_PR_LPF_R_EN BIT(16) ++#define PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN BIT(24) ++ ++#define REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB 0x0824 ++#define PCIE_FORCE_DA_PXP_CDR_PR_PWDB BIT(16) ++#define PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB BIT(24) ++ ++#define REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT 0x0828 ++#define PCIE_FORCE_DA_PXP_JCPLL_CKOUT_EN BIT(0) ++#define PCIE_FORCE_SEL_DA_PXP_JCPLL_CKOUT_EN BIT(8) ++#define PCIE_FORCE_DA_PXP_JCPLL_EN BIT(16) ++#define PCIE_FORCE_SEL_DA_PXP_JCPLL_EN BIT(24) ++ ++#define REG_PCIE_PMA_FORCE_DA_PXP_RX_SCAN_RST 0x0084c ++#define PCIE_FORCE_DA_PXP_RX_SIGDET_PWDB BIT(16) ++#define PCIE_FORCE_SEL_DA_PXP_RX_SIGDET_PWDB BIT(24) ++ ++#define REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT 0x0854 ++#define PCIE_FORCE_DA_PXP_TXPLL_CKOUT_EN BIT(0) ++#define PCIE_FORCE_SEL_DA_PXP_TXPLL_CKOUT_EN BIT(8) ++#define PCIE_FORCE_DA_PXP_TXPLL_EN BIT(16) ++#define PCIE_FORCE_SEL_DA_PXP_TXPLL_EN BIT(24) ++ ++#define REG_PCIE_PMA_SCAN_MODE 0x0884 ++#define PCIE_FORCE_DA_PXP_JCPLL_KBAND_LOAD_EN BIT(0) ++#define PCIE_FORCE_SEL_DA_PXP_JCPLL_KBAND_LOAD_EN BIT(8) ++ ++#define REG_PCIE_PMA_DIG_RESERVE_13 0x08bc ++#define PCIE_FLL_IDAC_PCIEG1 GENMASK(10, 0) ++#define PCIE_FLL_IDAC_PCIEG2 GENMASK(26, 16) ++ ++#define REG_PCIE_PMA_DIG_RESERVE_14 0x08c0 ++#define PCIE_FLL_IDAC_PCIEG3 GENMASK(10, 0) ++#define PCIE_FLL_LOAD_EN BIT(16) ++ ++#define REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL 0x088c ++#define PCIE_FORCE_DA_PXP_RX_FE_GAIN_CTRL GENMASK(1, 0) ++#define PCIE_FORCE_SEL_DA_PXP_RX_FE_GAIN_CTRL BIT(8) ++ ++#define REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_PWDB 0x0894 ++#define PCIE_FORCE_DA_PXP_RX_FE_PWDB BIT(0) ++#define PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB BIT(8) ++ ++#define REG_PCIE_PMA_DIG_RESERVE_12 0x08b8 ++#define PCIE_FORCE_PMA_RX_SPEED GENMASK(7, 4) ++#define PCIE_FORCE_SEL_PMA_RX_SPEED BIT(7) ++ ++#define REG_PCIE_PMA_DIG_RESERVE_17 0x08e0 ++ ++#define REG_PCIE_PMA_DIG_RESERVE_18 0x08e4 ++#define PCIE_PXP_RX_VTH_SEL_PCIE_G1 GENMASK(4, 0) ++#define PCIE_PXP_RX_VTH_SEL_PCIE_G2 GENMASK(12, 8) ++#define PCIE_PXP_RX_VTH_SEL_PCIE_G3 GENMASK(20, 16) ++ ++#define REG_PCIE_PMA_DIG_RESERVE_19 0x08e8 ++#define PCIE_PCP_RX_REV0_PCIE_GEN1 GENMASK(31, 16) ++ ++#define REG_PCIE_PMA_DIG_RESERVE_20 0x08ec ++#define PCIE_PCP_RX_REV0_PCIE_GEN2 GENMASK(15, 0) ++#define PCIE_PCP_RX_REV0_PCIE_GEN3 GENMASK(31, 16) ++ ++#define REG_PCIE_PMA_DIG_RESERVE_21 0x08f0 ++#define REG_PCIE_PMA_DIG_RESERVE_22 0x08f4 ++#define REG_PCIE_PMA_DIG_RESERVE_27 0x0908 ++#define REG_PCIE_PMA_DIG_RESERVE_30 0x0914 ++ ++/* DTIME */ ++#define REG_PCIE_PEXTP_DIG_GLB44 0x00 ++#define PCIE_XTP_RXDET_VCM_OFF_STB_T_SEL GENMASK(7, 0) ++#define PCIE_XTP_RXDET_EN_STB_T_SEL GENMASK(15, 8) ++#define PCIE_XTP_RXDET_FINISH_STB_T_SEL GENMASK(23, 16) ++#define PCIE_XTP_TXPD_TX_DATA_EN_DLY GENMASK(27, 24) ++#define PCIE_XTP_TXPD_RXDET_DONE_CDT BIT(28) ++#define PCIE_XTP_RXDET_LATCH_STB_T_SEL GENMASK(31, 29) ++ ++/* RX AEQ */ ++#define REG_PCIE_PEXTP_DIG_LN_RX30_P0 0x0000 ++#define PCIE_XTP_LN_RX_PDOWN_L1P2_EXIT_WAIT GENMASK(7, 0) ++#define PCIE_XTP_LN_RX_PDOWN_T2RLB_DIG_EN BIT(8) ++#define PCIE_XTP_LN_RX_PDOWN_E0_AEQEN_WAIT GENMASK(31, 16) ++ ++#define REG_PCIE_PEXTP_DIG_LN_RX30_P1 0x0100 ++ ++#endif /* _PHY_AIROHA_PCIE_H */ +--- /dev/null ++++ b/drivers/phy/airoha/phy-airoha-pcie.c +@@ -0,0 +1,1290 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * Copyright (c) 2024 AIROHA Inc ++ * Author: Lorenzo Bianconi ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "phy-airoha-pcie-regs.h" ++ ++#define LEQ_LEN_CTRL_MAX_VAL 7 ++#define FREQ_LOCK_MAX_ATTEMPT 10 ++ ++/* PCIe-PHY initialization time in ms needed by the hw to complete */ ++#define PHY_HW_INIT_TIME_MS 30 ++ ++enum airoha_pcie_port_gen { ++ PCIE_PORT_GEN1 = 1, ++ PCIE_PORT_GEN2, ++ PCIE_PORT_GEN3, ++}; ++ ++/** ++ * struct airoha_pcie_phy - PCIe phy driver main structure ++ * @dev: pointer to device ++ * @phy: pointer to generic phy ++ * @csr_2l: Analogic lane IO mapped register base address ++ * @pma0: IO mapped register base address of PMA0-PCIe ++ * @pma1: IO mapped register base address of PMA1-PCIe ++ * @p0_xr_dtime: IO mapped register base address of port0 Tx-Rx detection time ++ * @p1_xr_dtime: IO mapped register base address of port1 Tx-Rx detection time ++ * @rx_aeq: IO mapped register base address of Rx AEQ training ++ */ ++struct airoha_pcie_phy { ++ struct device *dev; ++ struct phy *phy; ++ void __iomem *csr_2l; ++ void __iomem *pma0; ++ void __iomem *pma1; ++ void __iomem *p0_xr_dtime; ++ void __iomem *p1_xr_dtime; ++ void __iomem *rx_aeq; ++}; ++ ++static void airoha_phy_clear_bits(void __iomem *reg, u32 mask) ++{ ++ u32 val = readl(reg) & ~mask; ++ ++ writel(val, reg); ++} ++ ++static void airoha_phy_set_bits(void __iomem *reg, u32 mask) ++{ ++ u32 val = readl(reg) | mask; ++ ++ writel(val, reg); ++} ++ ++static void airoha_phy_update_bits(void __iomem *reg, u32 mask, u32 val) ++{ ++ u32 tmp = readl(reg); ++ ++ tmp &= ~mask; ++ tmp |= val & mask; ++ writel(tmp, reg); ++} ++ ++#define airoha_phy_update_field(reg, mask, val) \ ++ do { \ ++ BUILD_BUG_ON_MSG(!__builtin_constant_p((mask)), \ ++ "mask is not constant"); \ ++ airoha_phy_update_bits((reg), (mask), \ ++ FIELD_PREP((mask), (val))); \ ++ } while (0) ++ ++#define airoha_phy_csr_2l_clear_bits(pcie_phy, reg, mask) \ ++ airoha_phy_clear_bits((pcie_phy)->csr_2l + (reg), (mask)) ++#define airoha_phy_csr_2l_set_bits(pcie_phy, reg, mask) \ ++ airoha_phy_set_bits((pcie_phy)->csr_2l + (reg), (mask)) ++#define airoha_phy_csr_2l_update_field(pcie_phy, reg, mask, val) \ ++ airoha_phy_update_field((pcie_phy)->csr_2l + (reg), (mask), (val)) ++#define airoha_phy_pma0_clear_bits(pcie_phy, reg, mask) \ ++ airoha_phy_clear_bits((pcie_phy)->pma0 + (reg), (mask)) ++#define airoha_phy_pma1_clear_bits(pcie_phy, reg, mask) \ ++ airoha_phy_clear_bits((pcie_phy)->pma1 + (reg), (mask)) ++#define airoha_phy_pma0_set_bits(pcie_phy, reg, mask) \ ++ airoha_phy_set_bits((pcie_phy)->pma0 + (reg), (mask)) ++#define airoha_phy_pma1_set_bits(pcie_phy, reg, mask) \ ++ airoha_phy_set_bits((pcie_phy)->pma1 + (reg), (mask)) ++#define airoha_phy_pma0_update_field(pcie_phy, reg, mask, val) \ ++ airoha_phy_update_field((pcie_phy)->pma0 + (reg), (mask), (val)) ++#define airoha_phy_pma1_update_field(pcie_phy, reg, mask, val) \ ++ airoha_phy_update_field((pcie_phy)->pma1 + (reg), (mask), (val)) ++ ++static void ++airoha_phy_init_lane0_rx_fw_pre_calib(struct airoha_pcie_phy *pcie_phy, ++ enum airoha_pcie_port_gen gen) ++{ ++ u32 fl_out_target = gen == PCIE_PORT_GEN3 ? 41600 : 41941; ++ u32 lock_cyclecnt = gen == PCIE_PORT_GEN3 ? 26000 : 32767; ++ u32 pr_idac, val, cdr_pr_idac_tmp = 0; ++ int i; ++ ++ airoha_phy_pma0_set_bits(pcie_phy, ++ REG_PCIE_PMA_SS_LCPLL_PWCTL_SETTING_1, ++ PCIE_LCPLL_MAN_PWDB); ++ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET2, ++ PCIE_LOCK_TARGET_BEG, ++ fl_out_target - 100); ++ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET2, ++ PCIE_LOCK_TARGET_END, ++ fl_out_target + 100); ++ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET1, ++ PCIE_PLL_FT_LOCK_CYCLECNT, lock_cyclecnt); ++ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET4, ++ PCIE_LOCK_LOCKTH, 0x3); ++ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET3, ++ PCIE_UNLOCK_TARGET_BEG, ++ fl_out_target - 100); ++ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET3, ++ PCIE_UNLOCK_TARGET_END, ++ fl_out_target + 100); ++ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET1, ++ PCIE_PLL_FT_UNLOCK_CYCLECNT, ++ lock_cyclecnt); ++ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET4, ++ PCIE_UNLOCK_LOCKTH, 0x3); ++ ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR0_PR_INJ_MODE, ++ CSR_2L_PXP_CDR0_INJ_FORCE_OFF); ++ ++ airoha_phy_pma0_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C, ++ PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN); ++ airoha_phy_pma0_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C, ++ PCIE_FORCE_DA_PXP_CDR_PR_LPF_R_EN); ++ airoha_phy_pma0_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C, ++ PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN); ++ airoha_phy_pma0_clear_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C, ++ PCIE_FORCE_DA_PXP_CDR_PR_LPF_C_EN); ++ airoha_phy_pma0_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC, ++ PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC); ++ ++ airoha_phy_pma0_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB, ++ PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB); ++ airoha_phy_pma0_clear_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB, ++ PCIE_FORCE_DA_PXP_CDR_PR_PWDB); ++ airoha_phy_pma0_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB, ++ PCIE_FORCE_DA_PXP_CDR_PR_PWDB); ++ ++ for (i = 0; i < LEQ_LEN_CTRL_MAX_VAL; i++) { ++ airoha_phy_pma0_update_field(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC, ++ PCIE_FORCE_DA_PXP_CDR_PR_IDAC, i << 8); ++ airoha_phy_pma0_clear_bits(pcie_phy, ++ REG_PCIE_PMA_SS_RX_FREQ_DET4, ++ PCIE_FREQLOCK_DET_EN); ++ airoha_phy_pma0_update_field(pcie_phy, ++ REG_PCIE_PMA_SS_RX_FREQ_DET4, ++ PCIE_FREQLOCK_DET_EN, 0x3); ++ ++ usleep_range(10000, 15000); ++ ++ val = FIELD_GET(PCIE_RO_FL_OUT, ++ readl(pcie_phy->pma0 + ++ REG_PCIE_PMA_RO_RX_FREQDET)); ++ if (val > fl_out_target) ++ cdr_pr_idac_tmp = i << 8; ++ } ++ ++ for (i = LEQ_LEN_CTRL_MAX_VAL; i >= 0; i--) { ++ pr_idac = cdr_pr_idac_tmp | (0x1 << i); ++ airoha_phy_pma0_update_field(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC, ++ PCIE_FORCE_DA_PXP_CDR_PR_IDAC, pr_idac); ++ airoha_phy_pma0_clear_bits(pcie_phy, ++ REG_PCIE_PMA_SS_RX_FREQ_DET4, ++ PCIE_FREQLOCK_DET_EN); ++ airoha_phy_pma0_update_field(pcie_phy, ++ REG_PCIE_PMA_SS_RX_FREQ_DET4, ++ PCIE_FREQLOCK_DET_EN, 0x3); ++ ++ usleep_range(10000, 15000); ++ ++ val = FIELD_GET(PCIE_RO_FL_OUT, ++ readl(pcie_phy->pma0 + ++ REG_PCIE_PMA_RO_RX_FREQDET)); ++ if (val < fl_out_target) ++ pr_idac &= ~(0x1 << i); ++ ++ cdr_pr_idac_tmp = pr_idac; ++ } ++ ++ airoha_phy_pma0_update_field(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC, ++ PCIE_FORCE_DA_PXP_CDR_PR_IDAC, ++ cdr_pr_idac_tmp); ++ ++ for (i = 0; i < FREQ_LOCK_MAX_ATTEMPT; i++) { ++ u32 val; ++ ++ airoha_phy_pma0_clear_bits(pcie_phy, ++ REG_PCIE_PMA_SS_RX_FREQ_DET4, ++ PCIE_FREQLOCK_DET_EN); ++ airoha_phy_pma0_update_field(pcie_phy, ++ REG_PCIE_PMA_SS_RX_FREQ_DET4, ++ PCIE_FREQLOCK_DET_EN, 0x3); ++ ++ usleep_range(10000, 15000); ++ ++ val = readl(pcie_phy->pma0 + REG_PCIE_PMA_RO_RX_FREQDET); ++ if (val & PCIE_RO_FBCK_LOCK) ++ break; ++ } ++ ++ /* turn off force mode and update band values */ ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR0_PR_INJ_MODE, ++ CSR_2L_PXP_CDR0_INJ_FORCE_OFF); ++ ++ airoha_phy_pma0_clear_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C, ++ PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN); ++ airoha_phy_pma0_clear_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C, ++ PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN); ++ airoha_phy_pma0_clear_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB, ++ PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB); ++ airoha_phy_pma0_clear_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC, ++ PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC); ++ if (gen == PCIE_PORT_GEN3) { ++ airoha_phy_pma0_update_field(pcie_phy, ++ REG_PCIE_PMA_DIG_RESERVE_14, ++ PCIE_FLL_IDAC_PCIEG3, ++ cdr_pr_idac_tmp); ++ } else { ++ airoha_phy_pma0_update_field(pcie_phy, ++ REG_PCIE_PMA_DIG_RESERVE_13, ++ PCIE_FLL_IDAC_PCIEG1, ++ cdr_pr_idac_tmp); ++ airoha_phy_pma0_update_field(pcie_phy, ++ REG_PCIE_PMA_DIG_RESERVE_13, ++ PCIE_FLL_IDAC_PCIEG2, ++ cdr_pr_idac_tmp); ++ } ++} ++ ++static void ++airoha_phy_init_lane1_rx_fw_pre_calib(struct airoha_pcie_phy *pcie_phy, ++ enum airoha_pcie_port_gen gen) ++{ ++ u32 fl_out_target = gen == PCIE_PORT_GEN3 ? 41600 : 41941; ++ u32 lock_cyclecnt = gen == PCIE_PORT_GEN3 ? 26000 : 32767; ++ u32 pr_idac, val, cdr_pr_idac_tmp = 0; ++ int i; ++ ++ airoha_phy_pma1_set_bits(pcie_phy, ++ REG_PCIE_PMA_SS_LCPLL_PWCTL_SETTING_1, ++ PCIE_LCPLL_MAN_PWDB); ++ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET2, ++ PCIE_LOCK_TARGET_BEG, ++ fl_out_target - 100); ++ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET2, ++ PCIE_LOCK_TARGET_END, ++ fl_out_target + 100); ++ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET1, ++ PCIE_PLL_FT_LOCK_CYCLECNT, lock_cyclecnt); ++ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET4, ++ PCIE_LOCK_LOCKTH, 0x3); ++ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET3, ++ PCIE_UNLOCK_TARGET_BEG, ++ fl_out_target - 100); ++ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET3, ++ PCIE_UNLOCK_TARGET_END, ++ fl_out_target + 100); ++ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET1, ++ PCIE_PLL_FT_UNLOCK_CYCLECNT, ++ lock_cyclecnt); ++ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_FREQ_DET4, ++ PCIE_UNLOCK_LOCKTH, 0x3); ++ ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR1_PR_INJ_MODE, ++ CSR_2L_PXP_CDR1_INJ_FORCE_OFF); ++ ++ airoha_phy_pma1_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C, ++ PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN); ++ airoha_phy_pma1_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C, ++ PCIE_FORCE_DA_PXP_CDR_PR_LPF_R_EN); ++ airoha_phy_pma1_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C, ++ PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN); ++ airoha_phy_pma1_clear_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C, ++ PCIE_FORCE_DA_PXP_CDR_PR_LPF_C_EN); ++ airoha_phy_pma1_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC, ++ PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC); ++ airoha_phy_pma1_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB, ++ PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB); ++ airoha_phy_pma1_clear_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB, ++ PCIE_FORCE_DA_PXP_CDR_PR_PWDB); ++ airoha_phy_pma1_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB, ++ PCIE_FORCE_DA_PXP_CDR_PR_PWDB); ++ ++ for (i = 0; i < LEQ_LEN_CTRL_MAX_VAL; i++) { ++ airoha_phy_pma1_update_field(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC, ++ PCIE_FORCE_DA_PXP_CDR_PR_IDAC, i << 8); ++ airoha_phy_pma1_clear_bits(pcie_phy, ++ REG_PCIE_PMA_SS_RX_FREQ_DET4, ++ PCIE_FREQLOCK_DET_EN); ++ airoha_phy_pma1_update_field(pcie_phy, ++ REG_PCIE_PMA_SS_RX_FREQ_DET4, ++ PCIE_FREQLOCK_DET_EN, 0x3); ++ ++ usleep_range(10000, 15000); ++ ++ val = FIELD_GET(PCIE_RO_FL_OUT, ++ readl(pcie_phy->pma1 + ++ REG_PCIE_PMA_RO_RX_FREQDET)); ++ if (val > fl_out_target) ++ cdr_pr_idac_tmp = i << 8; ++ } ++ ++ for (i = LEQ_LEN_CTRL_MAX_VAL; i >= 0; i--) { ++ pr_idac = cdr_pr_idac_tmp | (0x1 << i); ++ airoha_phy_pma1_update_field(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC, ++ PCIE_FORCE_DA_PXP_CDR_PR_IDAC, pr_idac); ++ airoha_phy_pma1_clear_bits(pcie_phy, ++ REG_PCIE_PMA_SS_RX_FREQ_DET4, ++ PCIE_FREQLOCK_DET_EN); ++ airoha_phy_pma1_update_field(pcie_phy, ++ REG_PCIE_PMA_SS_RX_FREQ_DET4, ++ PCIE_FREQLOCK_DET_EN, 0x3); ++ ++ usleep_range(10000, 15000); ++ ++ val = FIELD_GET(PCIE_RO_FL_OUT, ++ readl(pcie_phy->pma1 + ++ REG_PCIE_PMA_RO_RX_FREQDET)); ++ if (val < fl_out_target) ++ pr_idac &= ~(0x1 << i); ++ ++ cdr_pr_idac_tmp = pr_idac; ++ } ++ ++ airoha_phy_pma1_update_field(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC, ++ PCIE_FORCE_DA_PXP_CDR_PR_IDAC, ++ cdr_pr_idac_tmp); ++ ++ for (i = 0; i < FREQ_LOCK_MAX_ATTEMPT; i++) { ++ u32 val; ++ ++ airoha_phy_pma1_clear_bits(pcie_phy, ++ REG_PCIE_PMA_SS_RX_FREQ_DET4, ++ PCIE_FREQLOCK_DET_EN); ++ airoha_phy_pma1_update_field(pcie_phy, ++ REG_PCIE_PMA_SS_RX_FREQ_DET4, ++ PCIE_FREQLOCK_DET_EN, 0x3); ++ ++ usleep_range(10000, 15000); ++ ++ val = readl(pcie_phy->pma1 + REG_PCIE_PMA_RO_RX_FREQDET); ++ if (val & PCIE_RO_FBCK_LOCK) ++ break; ++ } ++ ++ /* turn off force mode and update band values */ ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR1_PR_INJ_MODE, ++ CSR_2L_PXP_CDR1_INJ_FORCE_OFF); ++ ++ airoha_phy_pma1_clear_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C, ++ PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_R_EN); ++ airoha_phy_pma1_clear_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_LPF_C, ++ PCIE_FORCE_SEL_DA_PXP_CDR_PR_LPF_C_EN); ++ airoha_phy_pma1_clear_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_PIEYE_PWDB, ++ PCIE_FORCE_SEL_DA_PXP_CDR_PR_PWDB); ++ airoha_phy_pma1_clear_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC, ++ PCIE_FORCE_SEL_DA_PXP_CDR_PR_IDAC); ++ if (gen == PCIE_PORT_GEN3) { ++ airoha_phy_pma1_update_field(pcie_phy, ++ REG_PCIE_PMA_DIG_RESERVE_14, ++ PCIE_FLL_IDAC_PCIEG3, ++ cdr_pr_idac_tmp); ++ } else { ++ airoha_phy_pma1_update_field(pcie_phy, ++ REG_PCIE_PMA_DIG_RESERVE_13, ++ PCIE_FLL_IDAC_PCIEG1, ++ cdr_pr_idac_tmp); ++ airoha_phy_pma1_update_field(pcie_phy, ++ REG_PCIE_PMA_DIG_RESERVE_13, ++ PCIE_FLL_IDAC_PCIEG2, ++ cdr_pr_idac_tmp); ++ } ++} ++ ++static void airoha_pcie_phy_init_default(struct airoha_pcie_phy *pcie_phy) ++{ ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CMN, ++ CSR_2L_PXP_CMN_TRIM_MASK, 0x10); ++ writel(0xcccbcccb, pcie_phy->pma0 + REG_PCIE_PMA_DIG_RESERVE_21); ++ writel(0xcccb, pcie_phy->pma0 + REG_PCIE_PMA_DIG_RESERVE_22); ++ writel(0xcccbcccb, pcie_phy->pma1 + REG_PCIE_PMA_DIG_RESERVE_21); ++ writel(0xcccb, pcie_phy->pma1 + REG_PCIE_PMA_DIG_RESERVE_22); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CMN, ++ CSR_2L_PXP_CMN_LANE_EN); ++} ++ ++static void airoha_pcie_phy_init_clk_out(struct airoha_pcie_phy *pcie_phy) ++{ ++ airoha_phy_csr_2l_update_field(pcie_phy, ++ REG_CSR_2L_TXPLL_POSTDIV_D256, ++ CSR_2L_PXP_CLKTX0_AMP, 0x5); ++ airoha_phy_csr_2l_update_field(pcie_phy, ++ REG_CSR_2L_CLKTX0_FORCE_OUT1, ++ CSR_2L_PXP_CLKTX1_AMP, 0x5); ++ airoha_phy_csr_2l_update_field(pcie_phy, ++ REG_CSR_2L_TXPLL_POSTDIV_D256, ++ CSR_2L_PXP_CLKTX0_OFFSET, 0x2); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CLKTX1_OFFSET, ++ CSR_2L_PXP_CLKTX1_OFFSET, 0x2); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CLKTX0_FORCE_OUT1, ++ CSR_2L_PXP_CLKTX0_HZ); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CLKTX1_OFFSET, ++ CSR_2L_PXP_CLKTX1_HZ); ++ airoha_phy_csr_2l_update_field(pcie_phy, ++ REG_CSR_2L_CLKTX0_FORCE_OUT1, ++ CSR_2L_PXP_CLKTX0_IMP_SEL, 0x12); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CLKTX1_IMP_SEL, ++ CSR_2L_PXP_CLKTX1_IMP_SEL, 0x12); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_POSTDIV_D256, ++ CSR_2L_PXP_CLKTX0_SR); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CLKTX1_OFFSET, ++ CSR_2L_PXP_CLKTX1_SR); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_PLL_CMN_RESERVE0, ++ CSR_2L_PXP_PLL_RESERVE_MASK, 0xd0d); ++} ++ ++static void airoha_pcie_phy_init_csr_2l(struct airoha_pcie_phy *pcie_phy) ++{ ++ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_SW_RESET, ++ PCIE_SW_XFI_RXPCS_RST | PCIE_SW_REF_RST | ++ PCIE_SW_RX_RST); ++ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_SW_RESET, ++ PCIE_SW_XFI_RXPCS_RST | PCIE_SW_REF_RST | ++ PCIE_SW_RX_RST); ++ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_TX_RESET, ++ PCIE_TX_TOP_RST | PCIE_TX_CAL_RST); ++ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_TX_RESET, ++ PCIE_TX_TOP_RST | PCIE_TX_CAL_RST); ++} ++ ++static void airoha_pcie_phy_init_rx(struct airoha_pcie_phy *pcie_phy) ++{ ++ writel(0x2a00090b, pcie_phy->pma0 + REG_PCIE_PMA_DIG_RESERVE_17); ++ writel(0x2a00090b, pcie_phy->pma1 + REG_PCIE_PMA_DIG_RESERVE_17); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR0_PR_MONPI, ++ CSR_2L_PXP_CDR0_PR_XFICK_EN); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR1_PR_MONPI, ++ CSR_2L_PXP_CDR1_PR_XFICK_EN); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, ++ REG_CSR_2L_CDR0_PD_PICAL_CKD8_INV, ++ CSR_2L_PXP_CDR0_PD_EDGE_DISABLE); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, ++ REG_CSR_2L_CDR1_PD_PICAL_CKD8_INV, ++ CSR_2L_PXP_CDR1_PD_EDGE_DISABLE); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_PHYCK_DIV, ++ CSR_2L_PXP_RX0_PHYCK_SEL, 0x1); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_PHYCK_DIV, ++ CSR_2L_PXP_RX1_PHYCK_SEL, 0x1); ++} ++ ++static void airoha_pcie_phy_init_jcpll(struct airoha_pcie_phy *pcie_phy) ++{ ++ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT, ++ PCIE_FORCE_SEL_DA_PXP_JCPLL_EN); ++ airoha_phy_pma0_clear_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT, ++ PCIE_FORCE_DA_PXP_JCPLL_EN); ++ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT, ++ PCIE_FORCE_SEL_DA_PXP_JCPLL_EN); ++ airoha_phy_pma1_clear_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT, ++ PCIE_FORCE_DA_PXP_JCPLL_EN); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_TCL_VTP_EN, ++ CSR_2L_PXP_JCPLL_SPARE_LOW, 0x20); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY, ++ CSR_2L_PXP_JCPLL_RST); ++ writel(0x0, pcie_phy->csr_2l + REG_CSR_2L_JCPLL_SSC_DELTA1); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC_PERIOD, ++ CSR_2L_PXP_JCPLL_SSC_PERIOD); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC, ++ CSR_2L_PXP_JCPLL_SSC_PHASE_INI); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC, ++ CSR_2L_PXP_JCPLL_SSC_TRI_EN); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BR, ++ CSR_2L_PXP_JCPLL_LPF_BR, 0xa); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BR, ++ CSR_2L_PXP_JCPLL_LPF_BP, 0xc); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BR, ++ CSR_2L_PXP_JCPLL_LPF_BC, 0x1f); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BWC, ++ CSR_2L_PXP_JCPLL_LPF_BWC, 0x1e); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BR, ++ CSR_2L_PXP_JCPLL_LPF_BWR, 0xa); ++ airoha_phy_csr_2l_update_field(pcie_phy, ++ REG_CSR_2L_JCPLL_MMD_PREDIV_MODE, ++ CSR_2L_PXP_JCPLL_MMD_PREDIV_MODE, ++ 0x1); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, CSR_2L_PXP_JCPLL_MONCK, ++ CSR_2L_PXP_JCPLL_REFIN_DIV); ++ ++ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_VOS, ++ PCIE_FORCE_SEL_DA_PXP_JCPLL_SDM_PCW); ++ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_VOS, ++ PCIE_FORCE_SEL_DA_PXP_JCPLL_SDM_PCW); ++ airoha_phy_pma0_update_field(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_JCPLL_SDM_PCW, ++ PCIE_FORCE_DA_PXP_JCPLL_SDM_PCW, ++ 0x50000000); ++ airoha_phy_pma1_update_field(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_JCPLL_SDM_PCW, ++ PCIE_FORCE_DA_PXP_JCPLL_SDM_PCW, ++ 0x50000000); ++ ++ airoha_phy_csr_2l_set_bits(pcie_phy, ++ REG_CSR_2L_JCPLL_MMD_PREDIV_MODE, ++ CSR_2L_PXP_JCPLL_POSTDIV_D5); ++ airoha_phy_csr_2l_set_bits(pcie_phy, ++ REG_CSR_2L_JCPLL_MMD_PREDIV_MODE, ++ CSR_2L_PXP_JCPLL_POSTDIV_D2); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY, ++ CSR_2L_PXP_JCPLL_RST_DLY, 0x4); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY, ++ CSR_2L_PXP_JCPLL_SDM_DI_LS); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_TCL_KBAND_VREF, ++ CSR_2L_PXP_JCPLL_VCO_KBAND_MEAS_EN); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_IB_EXT, ++ CSR_2L_PXP_JCPLL_CHP_IOFST); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_IB_EXT, ++ CSR_2L_PXP_JCPLL_CHP_IBIAS, 0xc); ++ airoha_phy_csr_2l_update_field(pcie_phy, ++ REG_CSR_2L_JCPLL_MMD_PREDIV_MODE, ++ CSR_2L_PXP_JCPLL_MMD_PREDIV_MODE, ++ 0x1); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_VCODIV, ++ CSR_2L_PXP_JCPLL_VCO_HALFLSB_EN); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_VCODIV, ++ CSR_2L_PXP_JCPLL_VCO_CFIX, 0x1); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_VCODIV, ++ CSR_2L_PXP_JCPLL_VCO_SCAPWR, 0x4); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_IB_EXT, ++ REG_CSR_2L_JCPLL_LPF_SHCK_EN); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_KBAND_KFC, ++ CSR_2L_PXP_JCPLL_POSTDIV_EN); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_KBAND_KFC, ++ CSR_2L_PXP_JCPLL_KBAND_KFC); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_KBAND_KFC, ++ CSR_2L_PXP_JCPLL_KBAND_KF, 0x3); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_KBAND_KFC, ++ CSR_2L_PXP_JCPLL_KBAND_KS); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BWC, ++ CSR_2L_PXP_JCPLL_KBAND_DIV, 0x1); ++ ++ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_SCAN_MODE, ++ PCIE_FORCE_SEL_DA_PXP_JCPLL_KBAND_LOAD_EN); ++ airoha_phy_pma0_clear_bits(pcie_phy, REG_PCIE_PMA_SCAN_MODE, ++ PCIE_FORCE_DA_PXP_JCPLL_KBAND_LOAD_EN); ++ ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_LPF_BWC, ++ CSR_2L_PXP_JCPLL_KBAND_CODE, 0xe4); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN, ++ CSR_2L_PXP_JCPLL_TCL_AMP_EN); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_TCL_CMP, ++ CSR_2L_PXP_JCPLL_TCL_LPF_EN); ++ airoha_phy_csr_2l_update_field(pcie_phy, ++ REG_CSR_2L_JCPLL_TCL_KBAND_VREF, ++ CSR_2L_PXP_JCPLL_TCL_KBAND_VREF, 0xf); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN, ++ CSR_2L_PXP_JCPLL_TCL_AMP_GAIN, 0x1); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN, ++ CSR_2L_PXP_JCPLL_TCL_AMP_VREF, 0x5); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_TCL_CMP, ++ CSR_2L_PXP_JCPLL_TCL_LPF_BW, 0x1); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_VCO_TCLVAR, ++ CSR_2L_PXP_JCPLL_VCO_TCLVAR, 0x3); ++ ++ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT, ++ PCIE_FORCE_SEL_DA_PXP_JCPLL_CKOUT_EN); ++ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT, ++ PCIE_FORCE_DA_PXP_JCPLL_CKOUT_EN); ++ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT, ++ PCIE_FORCE_SEL_DA_PXP_JCPLL_CKOUT_EN); ++ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT, ++ PCIE_FORCE_DA_PXP_JCPLL_CKOUT_EN); ++ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT, ++ PCIE_FORCE_SEL_DA_PXP_JCPLL_EN); ++ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT, ++ PCIE_FORCE_DA_PXP_JCPLL_EN); ++ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT, ++ PCIE_FORCE_SEL_DA_PXP_JCPLL_EN); ++ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_PXP_JCPLL_CKOUT, ++ PCIE_FORCE_DA_PXP_JCPLL_EN); ++} ++ ++static void airoha_pcie_phy_txpll(struct airoha_pcie_phy *pcie_phy) ++{ ++ airoha_phy_pma0_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT, ++ PCIE_FORCE_SEL_DA_PXP_TXPLL_EN); ++ airoha_phy_pma0_clear_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT, ++ PCIE_FORCE_DA_PXP_TXPLL_EN); ++ airoha_phy_pma1_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT, ++ PCIE_FORCE_SEL_DA_PXP_TXPLL_EN); ++ airoha_phy_pma1_clear_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT, ++ PCIE_FORCE_DA_PXP_TXPLL_EN); ++ ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_REFIN_DIV, ++ CSR_2L_PXP_TXPLL_PLL_RSTB); ++ writel(0x0, pcie_phy->csr_2l + REG_CSR_2L_TXPLL_SSC_DELTA1); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SSC_PERIOD, ++ CSR_2L_PXP_txpll_SSC_PERIOD); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_CHP_IOFST, ++ CSR_2L_PXP_TXPLL_CHP_IOFST, 0x1); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_750M_SYS_CK, ++ CSR_2L_PXP_TXPLL_CHP_IBIAS, 0x2d); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_REFIN_DIV, ++ CSR_2L_PXP_TXPLL_REFIN_DIV); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_TCL_LPF_BW, ++ CSR_2L_PXP_TXPLL_VCO_CFIX, 0x3); ++ ++ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC, ++ PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW); ++ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC, ++ PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW); ++ airoha_phy_pma0_update_field(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_SDM_PCW, ++ PCIE_FORCE_DA_PXP_TXPLL_SDM_PCW, ++ 0xc800000); ++ airoha_phy_pma1_update_field(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_SDM_PCW, ++ PCIE_FORCE_DA_PXP_TXPLL_SDM_PCW, ++ 0xc800000); ++ ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SDM_DI_LS, ++ CSR_2L_PXP_TXPLL_SDM_IFM); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SSC, ++ CSR_2L_PXP_TXPLL_SSC_PHASE_INI); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_REFIN_DIV, ++ CSR_2L_PXP_TXPLL_RST_DLY, 0x4); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SDM_DI_LS, ++ CSR_2L_PXP_TXPLL_SDM_DI_LS); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_SDM_DI_LS, ++ CSR_2L_PXP_TXPLL_SDM_ORD, 0x3); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_TCL_KBAND_VREF, ++ CSR_2L_PXP_TXPLL_VCO_KBAND_MEAS_EN); ++ writel(0x0, pcie_phy->csr_2l + REG_CSR_2L_TXPLL_SSC_DELTA1); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_CHP_IOFST, ++ CSR_2L_PXP_TXPLL_LPF_BP, 0x1); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_CHP_IOFST, ++ CSR_2L_PXP_TXPLL_LPF_BC, 0x18); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_CHP_IOFST, ++ CSR_2L_PXP_TXPLL_LPF_BR, 0x5); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_CHP_IOFST, ++ CSR_2L_PXP_TXPLL_CHP_IOFST, 0x1); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_750M_SYS_CK, ++ CSR_2L_PXP_TXPLL_CHP_IBIAS, 0x2d); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_TCL_VTP, ++ CSR_2L_PXP_TXPLL_SPARE_L, 0x1); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_LPF_BWR, ++ CSR_2L_PXP_TXPLL_LPF_BWC); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_POSTDIV, ++ CSR_2L_PXP_TXPLL_MMD_PREDIV_MODE); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_REFIN_DIV, ++ CSR_2L_PXP_TXPLL_REFIN_DIV); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_TCL_LPF_BW, ++ CSR_2L_PXP_TXPLL_VCO_HALFLSB_EN); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_VCO_SCAPWR, ++ CSR_2L_PXP_TXPLL_VCO_SCAPWR, 0x7); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_TCL_LPF_BW, ++ CSR_2L_PXP_TXPLL_VCO_CFIX, 0x3); ++ ++ airoha_phy_pma0_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC, ++ PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW); ++ airoha_phy_pma1_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PR_IDAC, ++ PCIE_FORCE_SEL_DA_PXP_TXPLL_SDM_PCW); ++ ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SSC, ++ CSR_2L_PXP_TXPLL_SSC_PHASE_INI); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_LPF_BWR, ++ CSR_2L_PXP_TXPLL_LPF_BWR); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_PHY_CK2, ++ CSR_2L_PXP_TXPLL_REFIN_INTERNAL); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_TCL_KBAND_VREF, ++ CSR_2L_PXP_TXPLL_VCO_KBAND_MEAS_EN); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_VTP, ++ CSR_2L_PXP_TXPLL_VTP_EN); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_POSTDIV, ++ CSR_2L_PXP_TXPLL_PHY_CK1_EN); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_PHY_CK2, ++ CSR_2L_PXP_TXPLL_REFIN_INTERNAL); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_SSC, ++ CSR_2L_PXP_TXPLL_SSC_EN); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_750M_SYS_CK, ++ CSR_2L_PXP_TXPLL_LPF_SHCK_EN); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_POSTDIV, ++ CSR_2L_PXP_TXPLL_POSTDIV_EN); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TXPLL_KBAND_DIV, ++ CSR_2L_PXP_TXPLL_KBAND_KFC); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_KBAND_DIV, ++ CSR_2L_PXP_TXPLL_KBAND_KF, 0x3); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_KBAND_DIV, ++ CSR_2L_PXP_txpll_KBAND_KS, 0x1); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_KBAND_DIV, ++ CSR_2L_PXP_TXPLL_KBAND_DIV, 0x4); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_LPF_BWR, ++ CSR_2L_PXP_TXPLL_KBAND_CODE, 0xe4); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_SDM_OUT, ++ CSR_2L_PXP_TXPLL_TCL_AMP_EN); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TXPLL_TCL_AMP_VREF, ++ CSR_2L_PXP_TXPLL_TCL_LPF_EN); ++ airoha_phy_csr_2l_update_field(pcie_phy, ++ REG_CSR_2L_TXPLL_TCL_KBAND_VREF, ++ CSR_2L_PXP_TXPLL_TCL_KBAND_VREF, 0xf); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_SDM_OUT, ++ CSR_2L_PXP_TXPLL_TCL_AMP_GAIN, 0x3); ++ airoha_phy_csr_2l_update_field(pcie_phy, ++ REG_CSR_2L_TXPLL_TCL_AMP_VREF, ++ CSR_2L_PXP_TXPLL_TCL_AMP_VREF, 0xb); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_TXPLL_TCL_LPF_BW, ++ CSR_2L_PXP_TXPLL_TCL_LPF_BW, 0x3); ++ ++ airoha_phy_pma0_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT, ++ PCIE_FORCE_SEL_DA_PXP_TXPLL_CKOUT_EN); ++ airoha_phy_pma0_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT, ++ PCIE_FORCE_DA_PXP_TXPLL_CKOUT_EN); ++ airoha_phy_pma1_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT, ++ PCIE_FORCE_SEL_DA_PXP_TXPLL_CKOUT_EN); ++ airoha_phy_pma1_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT, ++ PCIE_FORCE_DA_PXP_TXPLL_CKOUT_EN); ++ airoha_phy_pma0_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT, ++ PCIE_FORCE_SEL_DA_PXP_TXPLL_EN); ++ airoha_phy_pma0_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT, ++ PCIE_FORCE_DA_PXP_TXPLL_EN); ++ airoha_phy_pma1_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT, ++ PCIE_FORCE_SEL_DA_PXP_TXPLL_EN); ++ airoha_phy_pma1_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_TXPLL_CKOUT, ++ PCIE_FORCE_DA_PXP_TXPLL_EN); ++} ++ ++static void airoha_pcie_phy_init_ssc_jcpll(struct airoha_pcie_phy *pcie_phy) ++{ ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_SSC_DELTA1, ++ CSR_2L_PXP_JCPLL_SSC_DELTA1, 0x106); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_SSC_DELTA1, ++ CSR_2L_PXP_JCPLL_SSC_DELTA, 0x106); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_JCPLL_SSC_PERIOD, ++ CSR_2L_PXP_JCPLL_SSC_PERIOD, 0x31b); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC, ++ CSR_2L_PXP_JCPLL_SSC_PHASE_INI); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC, ++ CSR_2L_PXP_JCPLL_SSC_EN); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_IFM, ++ CSR_2L_PXP_JCPLL_SDM_IFM); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN, ++ CSR_2L_PXP_JCPLL_SDM_HREN); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY, ++ CSR_2L_PXP_JCPLL_SDM_DI_EN); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC, ++ CSR_2L_PXP_JCPLL_SSC_TRI_EN); ++} ++ ++static void ++airoha_pcie_phy_set_rxlan0_signal_detect(struct airoha_pcie_phy *pcie_phy) ++{ ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR0_PR_COR_HBW, ++ CSR_2L_PXP_CDR0_PR_LDO_FORCE_ON); ++ ++ usleep_range(100, 200); ++ ++ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_19, ++ PCIE_PCP_RX_REV0_PCIE_GEN1, 0x18b0); ++ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_20, ++ PCIE_PCP_RX_REV0_PCIE_GEN2, 0x18b0); ++ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_20, ++ PCIE_PCP_RX_REV0_PCIE_GEN3, 0x1030); ++ ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_SIGDET_DCTEST, ++ CSR_2L_PXP_RX0_SIGDET_PEAK, 0x2); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_SIGDET_VTH_SEL, ++ CSR_2L_PXP_RX0_SIGDET_VTH_SEL, 0x5); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_REV0, ++ CSR_2L_PXP_VOS_PNINV, 0x2); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_SIGDET_DCTEST, ++ CSR_2L_PXP_RX0_SIGDET_LPF_CTRL, 0x1); ++ ++ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_CAL2, ++ PCIE_CAL_OUT_OS, 0x0); ++ ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_PXP_RX0_FE_VB_EQ2, ++ CSR_2L_PXP_RX0_FE_VCM_GEN_PWDB); ++ ++ airoha_phy_pma0_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL, ++ PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB); ++ airoha_phy_pma0_update_field(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL, ++ PCIE_FORCE_DA_PXP_RX_FE_GAIN_CTRL, 0x3); ++ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_RX_FORCE_MODE0, ++ PCIE_FORCE_DA_XPON_RX_FE_GAIN_CTRL, 0x1); ++ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_SIGDET0, ++ PCIE_SIGDET_WIN_NONVLD_TIMES, 0x3); ++ airoha_phy_pma0_clear_bits(pcie_phy, REG_PCIE_PMA_SEQUENCE_DISB_CTRL1, ++ PCIE_DISB_RX_SDCAL_EN); ++ ++ airoha_phy_pma0_set_bits(pcie_phy, ++ REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1, ++ PCIE_FORCE_RX_SDCAL_EN); ++ usleep_range(150, 200); ++ airoha_phy_pma0_clear_bits(pcie_phy, ++ REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1, ++ PCIE_FORCE_RX_SDCAL_EN); ++} ++ ++static void ++airoha_pcie_phy_set_rxlan1_signal_detect(struct airoha_pcie_phy *pcie_phy) ++{ ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_CDR1_PR_COR_HBW, ++ CSR_2L_PXP_CDR1_PR_LDO_FORCE_ON); ++ ++ usleep_range(100, 200); ++ ++ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_19, ++ PCIE_PCP_RX_REV0_PCIE_GEN1, 0x18b0); ++ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_20, ++ PCIE_PCP_RX_REV0_PCIE_GEN2, 0x18b0); ++ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_20, ++ PCIE_PCP_RX_REV0_PCIE_GEN3, 0x1030); ++ ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_SIGDET_NOVTH, ++ CSR_2L_PXP_RX1_SIGDET_PEAK, 0x2); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_SIGDET_NOVTH, ++ CSR_2L_PXP_RX1_SIGDET_VTH_SEL, 0x5); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_REV0, ++ CSR_2L_PXP_VOS_PNINV, 0x2); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_DAC_RANGE_EYE, ++ CSR_2L_PXP_RX1_SIGDET_LPF_CTRL, 0x1); ++ ++ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_CAL2, ++ PCIE_CAL_OUT_OS, 0x0); ++ ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_RX1_FE_VB_EQ1, ++ CSR_2L_PXP_RX1_FE_VCM_GEN_PWDB); ++ ++ airoha_phy_pma1_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL, ++ PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB); ++ airoha_phy_pma1_update_field(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_GAIN_CTRL, ++ PCIE_FORCE_DA_PXP_RX_FE_GAIN_CTRL, 0x3); ++ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_RX_FORCE_MODE0, ++ PCIE_FORCE_DA_XPON_RX_FE_GAIN_CTRL, 0x1); ++ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_SS_RX_SIGDET0, ++ PCIE_SIGDET_WIN_NONVLD_TIMES, 0x3); ++ airoha_phy_pma1_clear_bits(pcie_phy, REG_PCIE_PMA_SEQUENCE_DISB_CTRL1, ++ PCIE_DISB_RX_SDCAL_EN); ++ ++ airoha_phy_pma1_set_bits(pcie_phy, ++ REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1, ++ PCIE_FORCE_RX_SDCAL_EN); ++ usleep_range(150, 200); ++ airoha_phy_pma1_clear_bits(pcie_phy, ++ REG_PCIE_PMA_CTRL_SEQUENCE_FORCE_CTRL1, ++ PCIE_FORCE_RX_SDCAL_EN); ++} ++ ++static void airoha_pcie_phy_set_rxflow(struct airoha_pcie_phy *pcie_phy) ++{ ++ airoha_phy_pma0_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_RX_SCAN_RST, ++ PCIE_FORCE_DA_PXP_RX_SIGDET_PWDB | ++ PCIE_FORCE_SEL_DA_PXP_RX_SIGDET_PWDB); ++ airoha_phy_pma1_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_RX_SCAN_RST, ++ PCIE_FORCE_DA_PXP_RX_SIGDET_PWDB | ++ PCIE_FORCE_SEL_DA_PXP_RX_SIGDET_PWDB); ++ ++ airoha_phy_pma0_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PD_PWDB, ++ PCIE_FORCE_DA_PXP_CDR_PD_PWDB | ++ PCIE_FORCE_SEL_DA_PXP_CDR_PD_PWDB); ++ airoha_phy_pma0_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_PWDB, ++ PCIE_FORCE_DA_PXP_RX_FE_PWDB | ++ PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB); ++ airoha_phy_pma1_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_CDR_PD_PWDB, ++ PCIE_FORCE_DA_PXP_CDR_PD_PWDB | ++ PCIE_FORCE_SEL_DA_PXP_CDR_PD_PWDB); ++ airoha_phy_pma1_set_bits(pcie_phy, ++ REG_PCIE_PMA_FORCE_DA_PXP_RX_FE_PWDB, ++ PCIE_FORCE_DA_PXP_RX_FE_PWDB | ++ PCIE_FORCE_SEL_DA_PXP_RX_FE_PWDB); ++ ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_RX0_PHYCK_DIV, ++ CSR_2L_PXP_RX0_PHYCK_RSTB | ++ CSR_2L_PXP_RX0_TDC_CK_SEL); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_RX1_PHYCK_DIV, ++ CSR_2L_PXP_RX1_PHYCK_RSTB | ++ CSR_2L_PXP_RX1_TDC_CK_SEL); ++ ++ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_SW_RESET, ++ PCIE_SW_RX_FIFO_RST | PCIE_SW_TX_RST | ++ PCIE_SW_PMA_RST | PCIE_SW_ALLPCS_RST | ++ PCIE_SW_TX_FIFO_RST); ++ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_SW_RESET, ++ PCIE_SW_RX_FIFO_RST | PCIE_SW_TX_RST | ++ PCIE_SW_PMA_RST | PCIE_SW_ALLPCS_RST | ++ PCIE_SW_TX_FIFO_RST); ++ ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_PXP_RX0_FE_VB_EQ2, ++ CSR_2L_PXP_RX0_FE_VB_EQ2_EN | ++ CSR_2L_PXP_RX0_FE_VB_EQ3_EN); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_RX0_SIGDET_VTH_SEL, ++ CSR_2L_PXP_RX0_FE_VB_EQ1_EN); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_RX1_FE_VB_EQ1, ++ CSR_2L_PXP_RX1_FE_VB_EQ1_EN | ++ CSR_2L_PXP_RX1_FE_VB_EQ2_EN | ++ CSR_2L_PXP_RX1_FE_VB_EQ3_EN); ++ ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_REV0, ++ CSR_2L_PXP_FE_GAIN_NORMAL_MODE, 0x4); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX0_REV0, ++ CSR_2L_PXP_FE_GAIN_TRAIN_MODE, 0x4); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_REV0, ++ CSR_2L_PXP_FE_GAIN_NORMAL_MODE, 0x4); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_REV0, ++ CSR_2L_PXP_FE_GAIN_TRAIN_MODE, 0x4); ++} ++ ++static void airoha_pcie_phy_set_pr(struct airoha_pcie_phy *pcie_phy) ++{ ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_PR_VREG_IBAND, ++ CSR_2L_PXP_CDR0_PR_VREG_IBAND, 0x5); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_PR_VREG_IBAND, ++ CSR_2L_PXP_CDR0_PR_VREG_CKBUF, 0x5); ++ ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR0_PR_CKREF_DIV, ++ CSR_2L_PXP_CDR0_PR_CKREF_DIV); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR0_PR_COR_HBW, ++ CSR_2L_PXP_CDR0_PR_CKREF_DIV1); ++ ++ airoha_phy_csr_2l_update_field(pcie_phy, ++ REG_CSR_2L_CDR1_PR_VREG_IBAND_VAL, ++ CSR_2L_PXP_CDR1_PR_VREG_IBAND, 0x5); ++ airoha_phy_csr_2l_update_field(pcie_phy, ++ REG_CSR_2L_CDR1_PR_VREG_IBAND_VAL, ++ CSR_2L_PXP_CDR1_PR_VREG_CKBUF, 0x5); ++ ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR1_PR_CKREF_DIV, ++ CSR_2L_PXP_CDR1_PR_CKREF_DIV); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR1_PR_COR_HBW, ++ CSR_2L_PXP_CDR1_PR_CKREF_DIV1); ++ ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_LPF_RATIO, ++ CSR_2L_PXP_CDR0_LPF_TOP_LIM, 0x20000); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR1_LPF_RATIO, ++ CSR_2L_PXP_CDR1_LPF_TOP_LIM, 0x20000); ++ ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_PR_BETA_DAC, ++ CSR_2L_PXP_CDR0_PR_BETA_SEL, 0x2); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR1_PR_BETA_DAC, ++ CSR_2L_PXP_CDR1_PR_BETA_SEL, 0x2); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_PR_BETA_DAC, ++ CSR_2L_PXP_CDR0_PR_KBAND_DIV, 0x4); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR1_PR_BETA_DAC, ++ CSR_2L_PXP_CDR1_PR_KBAND_DIV, 0x4); ++} ++ ++static void airoha_pcie_phy_set_txflow(struct airoha_pcie_phy *pcie_phy) ++{ ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TX0_CKLDO, ++ CSR_2L_PXP_TX0_CKLDO_EN); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TX1_CKLDO, ++ CSR_2L_PXP_TX1_CKLDO_EN); ++ ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TX0_CKLDO, ++ CSR_2L_PXP_TX0_DMEDGEGEN_EN); ++ airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_TX1_CKLDO, ++ CSR_2L_PXP_TX1_DMEDGEGEN_EN); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_TX1_MULTLANE, ++ CSR_2L_PXP_TX1_MULTLANE_EN); ++} ++ ++static void airoha_pcie_phy_set_rx_mode(struct airoha_pcie_phy *pcie_phy) ++{ ++ writel(0x804000, pcie_phy->pma0 + REG_PCIE_PMA_DIG_RESERVE_27); ++ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18, ++ PCIE_PXP_RX_VTH_SEL_PCIE_G1, 0x5); ++ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18, ++ PCIE_PXP_RX_VTH_SEL_PCIE_G2, 0x5); ++ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18, ++ PCIE_PXP_RX_VTH_SEL_PCIE_G3, 0x5); ++ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_30, ++ 0x77700); ++ ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR0_PR_MONCK, ++ CSR_2L_PXP_CDR0_PR_MONCK_ENABLE); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR0_PR_MONCK, ++ CSR_2L_PXP_CDR0_PR_RESERVE0, 0x2); ++ airoha_phy_csr_2l_update_field(pcie_phy, ++ REG_CSR_2L_PXP_RX0_OSCAL_CTLE1IOS, ++ CSR_2L_PXP_RX0_PR_OSCAL_VGA1IOS, 0x19); ++ airoha_phy_csr_2l_update_field(pcie_phy, ++ REG_CSR_2L_PXP_RX0_OSCA_VGA1VOS, ++ CSR_2L_PXP_RX0_PR_OSCAL_VGA1VOS, 0x19); ++ airoha_phy_csr_2l_update_field(pcie_phy, ++ REG_CSR_2L_PXP_RX0_OSCA_VGA1VOS, ++ CSR_2L_PXP_RX0_PR_OSCAL_VGA2IOS, 0x14); ++ ++ writel(0x804000, pcie_phy->pma1 + REG_PCIE_PMA_DIG_RESERVE_27); ++ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18, ++ PCIE_PXP_RX_VTH_SEL_PCIE_G1, 0x5); ++ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18, ++ PCIE_PXP_RX_VTH_SEL_PCIE_G2, 0x5); ++ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_18, ++ PCIE_PXP_RX_VTH_SEL_PCIE_G3, 0x5); ++ ++ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_30, ++ 0x77700); ++ ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CDR1_PR_MONCK, ++ CSR_2L_PXP_CDR1_PR_MONCK_ENABLE); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_CDR1_PR_MONCK, ++ CSR_2L_PXP_CDR1_PR_RESERVE0, 0x2); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_OSCAL_VGA1IOS, ++ CSR_2L_PXP_RX1_PR_OSCAL_VGA1IOS, 0x19); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_OSCAL_VGA1IOS, ++ CSR_2L_PXP_RX1_PR_OSCAL_VGA1VOS, 0x19); ++ airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_RX1_OSCAL_VGA1IOS, ++ CSR_2L_PXP_RX1_PR_OSCAL_VGA2IOS, 0x14); ++} ++ ++static void airoha_pcie_phy_load_kflow(struct airoha_pcie_phy *pcie_phy) ++{ ++ airoha_phy_pma0_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_12, ++ PCIE_FORCE_PMA_RX_SPEED, 0xa); ++ airoha_phy_pma1_update_field(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_12, ++ PCIE_FORCE_PMA_RX_SPEED, 0xa); ++ airoha_phy_init_lane0_rx_fw_pre_calib(pcie_phy, PCIE_PORT_GEN3); ++ airoha_phy_init_lane1_rx_fw_pre_calib(pcie_phy, PCIE_PORT_GEN3); ++ ++ airoha_phy_pma0_clear_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_12, ++ PCIE_FORCE_PMA_RX_SPEED); ++ airoha_phy_pma1_clear_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_12, ++ PCIE_FORCE_PMA_RX_SPEED); ++ usleep_range(100, 200); ++ ++ airoha_phy_init_lane0_rx_fw_pre_calib(pcie_phy, PCIE_PORT_GEN2); ++ airoha_phy_init_lane1_rx_fw_pre_calib(pcie_phy, PCIE_PORT_GEN2); ++} ++ ++/** ++ * airoha_pcie_phy_init() - Initialize the phy ++ * @phy: the phy to be initialized ++ * ++ * Initialize the phy registers. ++ * The hardware settings will be reset during suspend, it should be ++ * reinitialized when the consumer calls phy_init() again on resume. ++ */ ++static int airoha_pcie_phy_init(struct phy *phy) ++{ ++ struct airoha_pcie_phy *pcie_phy = phy_get_drvdata(phy); ++ u32 val; ++ ++ /* Setup Tx-Rx detection time */ ++ val = FIELD_PREP(PCIE_XTP_RXDET_VCM_OFF_STB_T_SEL, 0x33) | ++ FIELD_PREP(PCIE_XTP_RXDET_EN_STB_T_SEL, 0x1) | ++ FIELD_PREP(PCIE_XTP_RXDET_FINISH_STB_T_SEL, 0x2) | ++ FIELD_PREP(PCIE_XTP_TXPD_TX_DATA_EN_DLY, 0x3) | ++ FIELD_PREP(PCIE_XTP_RXDET_LATCH_STB_T_SEL, 0x1); ++ writel(val, pcie_phy->p0_xr_dtime + REG_PCIE_PEXTP_DIG_GLB44); ++ writel(val, pcie_phy->p1_xr_dtime + REG_PCIE_PEXTP_DIG_GLB44); ++ /* Setup Rx AEQ training time */ ++ val = FIELD_PREP(PCIE_XTP_LN_RX_PDOWN_L1P2_EXIT_WAIT, 0x32) | ++ FIELD_PREP(PCIE_XTP_LN_RX_PDOWN_E0_AEQEN_WAIT, 0x5050); ++ writel(val, pcie_phy->rx_aeq + REG_PCIE_PEXTP_DIG_LN_RX30_P0); ++ writel(val, pcie_phy->rx_aeq + REG_PCIE_PEXTP_DIG_LN_RX30_P1); ++ ++ /* enable load FLL-K flow */ ++ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_14, ++ PCIE_FLL_LOAD_EN); ++ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_14, ++ PCIE_FLL_LOAD_EN); ++ ++ airoha_pcie_phy_init_default(pcie_phy); ++ airoha_pcie_phy_init_clk_out(pcie_phy); ++ airoha_pcie_phy_init_csr_2l(pcie_phy); ++ ++ usleep_range(100, 200); ++ ++ airoha_pcie_phy_init_rx(pcie_phy); ++ /* phase 1, no ssc for K TXPLL */ ++ airoha_pcie_phy_init_jcpll(pcie_phy); ++ ++ usleep_range(500, 600); ++ ++ /* TX PLL settings */ ++ airoha_pcie_phy_txpll(pcie_phy); ++ ++ usleep_range(200, 300); ++ ++ /* SSC JCPLL setting */ ++ airoha_pcie_phy_init_ssc_jcpll(pcie_phy); ++ ++ usleep_range(100, 200); ++ ++ /* Rx lan0 signal detect */ ++ airoha_pcie_phy_set_rxlan0_signal_detect(pcie_phy); ++ /* Rx lan1 signal detect */ ++ airoha_pcie_phy_set_rxlan1_signal_detect(pcie_phy); ++ /* RX FLOW */ ++ airoha_pcie_phy_set_rxflow(pcie_phy); ++ ++ usleep_range(100, 200); ++ ++ airoha_pcie_phy_set_pr(pcie_phy); ++ /* TX FLOW */ ++ airoha_pcie_phy_set_txflow(pcie_phy); ++ ++ usleep_range(100, 200); ++ /* RX mode setting */ ++ airoha_pcie_phy_set_rx_mode(pcie_phy); ++ /* Load K-Flow */ ++ airoha_pcie_phy_load_kflow(pcie_phy); ++ airoha_phy_pma0_clear_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0, ++ PCIE_DA_XPON_CDR_PR_PWDB); ++ airoha_phy_pma1_clear_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0, ++ PCIE_DA_XPON_CDR_PR_PWDB); ++ ++ usleep_range(100, 200); ++ ++ airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0, ++ PCIE_DA_XPON_CDR_PR_PWDB); ++ airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0, ++ PCIE_DA_XPON_CDR_PR_PWDB); ++ ++ /* Wait for the PCIe PHY to complete initialization before returning */ ++ msleep(PHY_HW_INIT_TIME_MS); ++ ++ return 0; ++} ++ ++static int airoha_pcie_phy_exit(struct phy *phy) ++{ ++ struct airoha_pcie_phy *pcie_phy = phy_get_drvdata(phy); ++ ++ airoha_phy_pma0_clear_bits(pcie_phy, REG_PCIE_PMA_SW_RESET, ++ PCIE_PMA_SW_RST); ++ airoha_phy_pma1_clear_bits(pcie_phy, REG_PCIE_PMA_SW_RESET, ++ PCIE_PMA_SW_RST); ++ airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC, ++ CSR_2L_PXP_JCPLL_SSC_PHASE_INI | ++ CSR_2L_PXP_JCPLL_SSC_TRI_EN | ++ CSR_2L_PXP_JCPLL_SSC_EN); ++ ++ return 0; ++} ++ ++static const struct phy_ops airoha_pcie_phy_ops = { ++ .init = airoha_pcie_phy_init, ++ .exit = airoha_pcie_phy_exit, ++ .owner = THIS_MODULE, ++}; ++ ++static int airoha_pcie_phy_probe(struct platform_device *pdev) ++{ ++ struct airoha_pcie_phy *pcie_phy; ++ struct device *dev = &pdev->dev; ++ struct phy_provider *provider; ++ ++ pcie_phy = devm_kzalloc(dev, sizeof(*pcie_phy), GFP_KERNEL); ++ if (!pcie_phy) ++ return -ENOMEM; ++ ++ pcie_phy->csr_2l = devm_platform_ioremap_resource_byname(pdev, "csr-2l"); ++ if (IS_ERR(pcie_phy->csr_2l)) ++ return dev_err_probe(dev, PTR_ERR(pcie_phy->csr_2l), ++ "Failed to map phy-csr-2l base\n"); ++ ++ pcie_phy->pma0 = devm_platform_ioremap_resource_byname(pdev, "pma0"); ++ if (IS_ERR(pcie_phy->pma0)) ++ return dev_err_probe(dev, PTR_ERR(pcie_phy->pma0), ++ "Failed to map phy-pma0 base\n"); ++ ++ pcie_phy->pma1 = devm_platform_ioremap_resource_byname(pdev, "pma1"); ++ if (IS_ERR(pcie_phy->pma1)) ++ return dev_err_probe(dev, PTR_ERR(pcie_phy->pma1), ++ "Failed to map phy-pma1 base\n"); ++ ++ pcie_phy->phy = devm_phy_create(dev, dev->of_node, &airoha_pcie_phy_ops); ++ if (IS_ERR(pcie_phy->phy)) ++ return dev_err_probe(dev, PTR_ERR(pcie_phy->phy), ++ "Failed to create PCIe phy\n"); ++ ++ pcie_phy->p0_xr_dtime = ++ devm_platform_ioremap_resource_byname(pdev, "p0-xr-dtime"); ++ if (IS_ERR(pcie_phy->p0_xr_dtime)) ++ return dev_err_probe(dev, PTR_ERR(pcie_phy->p0_xr_dtime), ++ "Failed to map P0 Tx-Rx dtime base\n"); ++ ++ pcie_phy->p1_xr_dtime = ++ devm_platform_ioremap_resource_byname(pdev, "p1-xr-dtime"); ++ if (IS_ERR(pcie_phy->p1_xr_dtime)) ++ return dev_err_probe(dev, PTR_ERR(pcie_phy->p1_xr_dtime), ++ "Failed to map P1 Tx-Rx dtime base\n"); ++ ++ pcie_phy->rx_aeq = devm_platform_ioremap_resource_byname(pdev, "rx-aeq"); ++ if (IS_ERR(pcie_phy->rx_aeq)) ++ return dev_err_probe(dev, PTR_ERR(pcie_phy->rx_aeq), ++ "Failed to map Rx AEQ base\n"); ++ ++ pcie_phy->dev = dev; ++ phy_set_drvdata(pcie_phy->phy, pcie_phy); ++ ++ provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ if (IS_ERR(provider)) ++ return dev_err_probe(dev, PTR_ERR(provider), ++ "PCIe phy probe failed\n"); ++ ++ return 0; ++} ++ ++static const struct of_device_id airoha_pcie_phy_of_match[] = { ++ { .compatible = "airoha,en7581-pcie-phy" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, airoha_pcie_phy_of_match); ++ ++static struct platform_driver airoha_pcie_phy_driver = { ++ .probe = airoha_pcie_phy_probe, ++ .driver = { ++ .name = "airoha-pcie-phy", ++ .of_match_table = airoha_pcie_phy_of_match, ++ }, ++}; ++module_platform_driver(airoha_pcie_phy_driver); ++ ++MODULE_DESCRIPTION("Airoha PCIe PHY driver"); ++MODULE_AUTHOR("Lorenzo Bianconi "); ++MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/airoha/patches-6.12/220-07-phy-airoha-Add-support-for-Airoha-AN7581-USB-PHY.patch b/lede/target/linux/airoha/patches-6.12/220-07-phy-airoha-Add-support-for-Airoha-AN7581-USB-PHY.patch new file mode 100644 index 0000000000..bf106fa544 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/220-07-phy-airoha-Add-support-for-Airoha-AN7581-USB-PHY.patch @@ -0,0 +1,667 @@ +From fadd22890b239e5a251dbe47367cfbeb1ea105f7 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 7 Feb 2025 13:28:40 +0100 +Subject: [PATCH 07/10] phy: airoha: Add support for Airoha AN7581 USB PHY + +Add support for Airoha AN7581 USB PHY driver. AN7581 supports up to 2 +USB port with USB 2.0 mode always supported and USB 3.0 mode available +only if the Serdes port is correctly configured for USB 3.0. + +The second USB port on the SoC can be both used for USB 3.0 operation or +PCIe. (toggled by the SCU SSR register and configured by the USB PHY +driver) + +If the USB 3.0 mode is not configured, the modes needs to be also +disabled in the xHCI node or the driver will report unsable clock and +fail probe. + +Also USB 3.0 PHY instance are provided only if the airoha,serdes-port +and airoha,scu property is defined in DT, if it's not then USB 3.0 PHY +is assumed not supported. + +For USB 2.0 Slew Rate calibration, airoha,usb2-monitor-clk-sel is +mandatory and is used to select the monitor clock for calibration. + +Normally it's 1 for USB port 1 and 2 for USB port 2. + +Signed-off-by: Christian Marangi +--- + MAINTAINERS | 1 + + drivers/phy/airoha/Kconfig | 10 + + drivers/phy/airoha/Makefile | 1 + + drivers/phy/airoha/phy-airoha-usb.c | 597 ++++++++++++++++++++++++++++ + 4 files changed, 609 insertions(+) + create mode 100644 drivers/phy/airoha/phy-airoha-usb.c + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -742,6 +742,7 @@ M: Christian Marangi ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* SCU */ ++#define AIROHA_SCU_SSTR 0x9c ++#define AIROHA_SCU_SSTR_USB_PCIE_SEL BIT(3) ++#define AIROHA_SCU_SSTR_USB_PCIE_SEL_PCIE FIELD_PREP_CONST(AIROHA_SCU_SSTR_USB_PCIE_SEL, 0x0) ++#define AIROHA_SCU_SSTR_USB_PCIE_SEL_USB FIELD_PREP_CONST(AIROHA_SCU_SSTR_USB_PCIE_SEL, 0x1) ++ ++/* U2PHY */ ++#define AIROHA_USB_PHY_FMCR0 0x100 ++#define AIROHA_USB_PHY_MONCLK_SEL GENMASK(27, 26) ++#define AIROHA_USB_PHY_MONCLK_SEL0 FIELD_PREP_CONST(AIROHA_USB_PHY_MONCLK_SEL, 0x0) ++#define AIROHA_USB_PHY_MONCLK_SEL1 FIELD_PREP_CONST(AIROHA_USB_PHY_MONCLK_SEL, 0x1) ++#define AIROHA_USB_PHY_MONCLK_SEL2 FIELD_PREP_CONST(AIROHA_USB_PHY_MONCLK_SEL, 0x2) ++#define AIROHA_USB_PHY_MONCLK_SEL3 FIELD_PREP_CONST(AIROHA_USB_PHY_MONCLK_SEL, 0x3) ++#define AIROHA_USB_PHY_FREQDET_EN BIT(24) ++#define AIROHA_USB_PHY_CYCLECNT GENMASK(23, 0) ++#define AIROHA_USB_PHY_FMMONR0 0x10c ++#define AIROHA_USB_PHY_USB_FM_OUT GENMASK(31, 0) ++#define AIROHA_USB_PHY_FMMONR1 0x110 ++#define AIROHA_USB_PHY_FRCK_EN BIT(8) ++ ++#define AIROHA_USB_PHY_USBPHYACR4 0x310 ++#define AIROHA_USB_PHY_USB20_FS_CR GENMASK(10, 8) ++#define AIROHA_USB_PHY_USB20_FS_CR_MAX FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_CR, 0x0) ++#define AIROHA_USB_PHY_USB20_FS_CR_NORMAL FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_CR, 0x2) ++#define AIROHA_USB_PHY_USB20_FS_CR_SMALLER FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_CR, 0x4) ++#define AIROHA_USB_PHY_USB20_FS_CR_MIN FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_CR, 0x6) ++#define AIROHA_USB_PHY_USB20_FS_SR GENMASK(2, 0) ++#define AIROHA_USB_PHY_USB20_FS_SR_MAX FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_SR, 0x0) ++#define AIROHA_USB_PHY_USB20_FS_SR_NORMAL FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_SR, 0x2) ++#define AIROHA_USB_PHY_USB20_FS_SR_SMALLER FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_SR, 0x4) ++#define AIROHA_USB_PHY_USB20_FS_SR_MIN FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_FS_SR, 0x6) ++#define AIROHA_USB_PHY_USBPHYACR5 0x314 ++#define AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN BIT(15) ++#define AIROHA_USB_PHY_USB20_HSTX_SRCTRL GENMASK(14, 12) ++#define AIROHA_USB_PHY_USBPHYACR6 0x318 ++#define AIROHA_USB_PHY_USB20_BC11_SW_EN BIT(23) ++#define AIROHA_USB_PHY_USB20_DISCTH GENMASK(7, 4) ++#define AIROHA_USB_PHY_USB20_DISCTH_400 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x0) ++#define AIROHA_USB_PHY_USB20_DISCTH_420 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x1) ++#define AIROHA_USB_PHY_USB20_DISCTH_440 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x2) ++#define AIROHA_USB_PHY_USB20_DISCTH_460 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x3) ++#define AIROHA_USB_PHY_USB20_DISCTH_480 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x4) ++#define AIROHA_USB_PHY_USB20_DISCTH_500 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x5) ++#define AIROHA_USB_PHY_USB20_DISCTH_520 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x6) ++#define AIROHA_USB_PHY_USB20_DISCTH_540 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x7) ++#define AIROHA_USB_PHY_USB20_DISCTH_560 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x8) ++#define AIROHA_USB_PHY_USB20_DISCTH_580 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0x9) ++#define AIROHA_USB_PHY_USB20_DISCTH_600 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xa) ++#define AIROHA_USB_PHY_USB20_DISCTH_620 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xb) ++#define AIROHA_USB_PHY_USB20_DISCTH_640 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xc) ++#define AIROHA_USB_PHY_USB20_DISCTH_660 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xd) ++#define AIROHA_USB_PHY_USB20_DISCTH_680 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xe) ++#define AIROHA_USB_PHY_USB20_DISCTH_700 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_DISCTH, 0xf) ++#define AIROHA_USB_PHY_USB20_SQTH GENMASK(3, 0) ++#define AIROHA_USB_PHY_USB20_SQTH_85 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x0) ++#define AIROHA_USB_PHY_USB20_SQTH_90 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x1) ++#define AIROHA_USB_PHY_USB20_SQTH_95 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x2) ++#define AIROHA_USB_PHY_USB20_SQTH_100 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x3) ++#define AIROHA_USB_PHY_USB20_SQTH_105 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x4) ++#define AIROHA_USB_PHY_USB20_SQTH_110 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x5) ++#define AIROHA_USB_PHY_USB20_SQTH_115 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x6) ++#define AIROHA_USB_PHY_USB20_SQTH_120 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x7) ++#define AIROHA_USB_PHY_USB20_SQTH_125 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x8) ++#define AIROHA_USB_PHY_USB20_SQTH_130 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0x9) ++#define AIROHA_USB_PHY_USB20_SQTH_135 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xa) ++#define AIROHA_USB_PHY_USB20_SQTH_140 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xb) ++#define AIROHA_USB_PHY_USB20_SQTH_145 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xc) ++#define AIROHA_USB_PHY_USB20_SQTH_150 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xd) ++#define AIROHA_USB_PHY_USB20_SQTH_155 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xe) ++#define AIROHA_USB_PHY_USB20_SQTH_160 FIELD_PREP_CONST(AIROHA_USB_PHY_USB20_SQTH, 0xf) ++ ++#define AIROHA_USB_PHY_U2PHYDTM1 0x36c ++#define AIROHA_USB_PHY_FORCE_IDDIG BIT(9) ++#define AIROHA_USB_PHY_IDDIG BIT(1) ++ ++#define AIROHA_USB_PHY_GPIO_CTLD 0x80c ++#define AIROHA_USB_PHY_C60802_GPIO_CTLD GENMASK(31, 0) ++#define AIROHA_USB_PHY_SSUSB_IP_SW_RST BIT(31) ++#define AIROHA_USB_PHY_MCU_BUS_CK_GATE_EN BIT(30) ++#define AIROHA_USB_PHY_FORCE_SSUSB_IP_SW_RST BIT(29) ++#define AIROHA_USB_PHY_SSUSB_SW_RST BIT(28) ++ ++#define AIROHA_USB_PHY_U3_PHYA_REG0 0xb00 ++#define AIROHA_USB_PHY_SSUSB_BG_DIV GENMASK(29, 28) ++#define AIROHA_USB_PHY_SSUSB_BG_DIV_2 FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_BG_DIV, 0x0) ++#define AIROHA_USB_PHY_SSUSB_BG_DIV_4 FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_BG_DIV, 0x1) ++#define AIROHA_USB_PHY_SSUSB_BG_DIV_8 FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_BG_DIV, 0x2) ++#define AIROHA_USB_PHY_SSUSB_BG_DIV_16 FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_BG_DIV, 0x3) ++#define AIROHA_USB_PHY_U3_PHYA_REG1 0xb04 ++#define AIROHA_USB_PHY_SSUSB_XTAL_TOP_RESERVE GENMASK(25, 10) ++#define AIROHA_USB_PHY_U3_PHYA_REG6 0xb18 ++#define AIROHA_USB_PHY_SSUSB_CDR_RESERVE GENMASK(31, 24) ++#define AIROHA_USB_PHY_U3_PHYA_REG8 0xb20 ++#define AIROHA_USB_PHY_SSUSB_CDR_RST_DLY GENMASK(7, 6) ++#define AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_32 FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, 0x0) ++#define AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_64 FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, 0x1) ++#define AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_128 FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, 0x2) ++#define AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_216 FIELD_PREP_CONST(AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, 0x3) ++ ++#define AIROHA_USB_PHY_U3_PHYA_DA_REG19 0xc38 ++#define AIROHA_USB_PHY_SSUSB_PLL_SSC_DELTA1_U3 GENMASK(15, 0) ++ ++#define AIROHA_USB_PHY_U2_FM_DET_CYCLE_CNT 1024 ++#define AIROHA_USB_PHY_REF_CK 20 ++#define AIROHA_USB_PHY_U2_SR_COEF 28 ++#define AIROHA_USB_PHY_U2_SR_COEF_DIVISOR 1000 ++ ++#define AIROHA_USB_PHY_DEFAULT_SR_CALIBRATION 0x5 ++#define AIROHA_USB_PHY_FREQDET_SLEEP 1000 /* 1ms */ ++#define AIROHA_USB_PHY_FREQDET_TIMEOUT (AIROHA_USB_PHY_FREQDET_SLEEP * 10) ++ ++struct airoha_usb_phy_instance { ++ struct phy *phy; ++ u32 type; ++}; ++ ++enum airoha_usb_phy_instance_type { ++ AIROHA_PHY_USB2, ++ AIROHA_PHY_USB3, ++ ++ AIROHA_PHY_USB_MAX, ++}; ++ ++struct airoha_usb_phy_priv { ++ struct device *dev; ++ struct regmap *regmap; ++ struct regmap *scu; ++ ++ unsigned int monclk_sel; ++ unsigned int serdes_port; ++ ++ struct airoha_usb_phy_instance *phys[AIROHA_PHY_USB_MAX]; ++}; ++ ++static void airoha_usb_phy_u2_slew_rate_calibration(struct airoha_usb_phy_priv *priv) ++{ ++ u32 fm_out; ++ u32 srctrl; ++ ++ /* Enable HS TX SR calibration */ ++ regmap_set_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5, ++ AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN); ++ ++ usleep_range(1000, 1500); ++ ++ /* Enable Free run clock */ ++ regmap_set_bits(priv->regmap, AIROHA_USB_PHY_FMMONR1, ++ AIROHA_USB_PHY_FRCK_EN); ++ ++ /* Select Monitor Clock */ ++ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_FMCR0, ++ AIROHA_USB_PHY_MONCLK_SEL, ++ FIELD_PREP(AIROHA_USB_PHY_MONCLK_SEL, ++ priv->monclk_sel)); ++ ++ /* Set cyclecnt */ ++ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_FMCR0, ++ AIROHA_USB_PHY_CYCLECNT, ++ FIELD_PREP(AIROHA_USB_PHY_CYCLECNT, ++ AIROHA_USB_PHY_U2_FM_DET_CYCLE_CNT)); ++ ++ /* Enable Frequency meter */ ++ regmap_set_bits(priv->regmap, AIROHA_USB_PHY_FMCR0, ++ AIROHA_USB_PHY_FREQDET_EN); ++ ++ /* Timeout can happen and we will apply workaround at the end */ ++ regmap_read_poll_timeout(priv->regmap, AIROHA_USB_PHY_FMMONR0, fm_out, ++ fm_out, AIROHA_USB_PHY_FREQDET_SLEEP, ++ AIROHA_USB_PHY_FREQDET_TIMEOUT); ++ ++ /* Disable Frequency meter */ ++ regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_FMCR0, ++ AIROHA_USB_PHY_FREQDET_EN); ++ ++ /* Disable Free run clock */ ++ regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_FMMONR1, ++ AIROHA_USB_PHY_FRCK_EN); ++ ++ /* Disable HS TX SR calibration */ ++ regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5, ++ AIROHA_USB_PHY_USB20_HSTX_SRCAL_EN); ++ ++ usleep_range(1000, 1500); ++ ++ /* Frequency was not detected, use default SR calibration value */ ++ if (!fm_out) { ++ srctrl = AIROHA_USB_PHY_DEFAULT_SR_CALIBRATION; ++ dev_err(priv->dev, "Frequency not detected, using default SR calibration.\n"); ++ } else { ++ /* (1024 / FM_OUT) * REF_CK * U2_SR_COEF (round to the nearest digits) */ ++ srctrl = AIROHA_USB_PHY_REF_CK * AIROHA_USB_PHY_U2_SR_COEF; ++ srctrl = (srctrl * AIROHA_USB_PHY_U2_FM_DET_CYCLE_CNT) / fm_out; ++ srctrl = DIV_ROUND_CLOSEST(srctrl, AIROHA_USB_PHY_U2_SR_COEF_DIVISOR); ++ dev_dbg(priv->dev, "SR calibration applied: %x\n", srctrl); ++ } ++ ++ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR5, ++ AIROHA_USB_PHY_USB20_HSTX_SRCTRL, ++ FIELD_PREP(AIROHA_USB_PHY_USB20_HSTX_SRCTRL, srctrl)); ++} ++ ++static void airoha_usb_phy_u2_init(struct airoha_usb_phy_priv *priv) ++{ ++ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR4, ++ AIROHA_USB_PHY_USB20_FS_CR, ++ AIROHA_USB_PHY_USB20_FS_CR_MIN); ++ ++ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR4, ++ AIROHA_USB_PHY_USB20_FS_SR, ++ AIROHA_USB_PHY_USB20_FS_SR_NORMAL); ++ ++ /* FIXME: evaluate if needed */ ++ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6, ++ AIROHA_USB_PHY_USB20_SQTH, ++ AIROHA_USB_PHY_USB20_SQTH_130); ++ ++ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6, ++ AIROHA_USB_PHY_USB20_DISCTH, ++ AIROHA_USB_PHY_USB20_DISCTH_600); ++ ++ /* Enable the USB port and then disable after calibration */ ++ regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6, ++ AIROHA_USB_PHY_USB20_BC11_SW_EN); ++ ++ airoha_usb_phy_u2_slew_rate_calibration(priv); ++ ++ regmap_set_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6, ++ AIROHA_USB_PHY_USB20_BC11_SW_EN); ++ ++ usleep_range(1000, 1500); ++} ++ ++/* ++ * USB 3.0 mode can only work if USB serdes is correctly set. ++ * This is validated in xLate function. ++ */ ++static void airoha_usb_phy_u3_init(struct airoha_usb_phy_priv *priv) ++{ ++ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG8, ++ AIROHA_USB_PHY_SSUSB_CDR_RST_DLY, ++ AIROHA_USB_PHY_SSUSB_CDR_RST_DLY_32); ++ ++ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG6, ++ AIROHA_USB_PHY_SSUSB_CDR_RESERVE, ++ FIELD_PREP(AIROHA_USB_PHY_SSUSB_CDR_RESERVE, 0xe)); ++ ++ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG0, ++ AIROHA_USB_PHY_SSUSB_BG_DIV, ++ AIROHA_USB_PHY_SSUSB_BG_DIV_4); ++ ++ regmap_set_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_REG1, ++ FIELD_PREP(AIROHA_USB_PHY_SSUSB_XTAL_TOP_RESERVE, 0x600)); ++ ++ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U3_PHYA_DA_REG19, ++ AIROHA_USB_PHY_SSUSB_PLL_SSC_DELTA1_U3, ++ FIELD_PREP(AIROHA_USB_PHY_SSUSB_PLL_SSC_DELTA1_U3, 0x43)); ++} ++ ++static int airoha_usb_phy_init(struct phy *phy) ++{ ++ struct airoha_usb_phy_instance *instance = phy_get_drvdata(phy); ++ struct airoha_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent); ++ ++ switch (instance->type) { ++ case PHY_TYPE_USB2: ++ airoha_usb_phy_u2_init(priv); ++ break; ++ case PHY_TYPE_USB3: ++ if (phy_get_mode(phy) == PHY_MODE_PCIE) ++ return 0; ++ ++ airoha_usb_phy_u3_init(priv); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int airoha_usb_phy_u2_power_on(struct airoha_usb_phy_priv *priv) ++{ ++ regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6, ++ AIROHA_USB_PHY_USB20_BC11_SW_EN); ++ ++ usleep_range(1000, 1500); ++ ++ return 0; ++} ++ ++static int airoha_usb_phy_u3_power_on(struct airoha_usb_phy_priv *priv) ++{ ++ regmap_clear_bits(priv->regmap, AIROHA_USB_PHY_GPIO_CTLD, ++ AIROHA_USB_PHY_SSUSB_IP_SW_RST | ++ AIROHA_USB_PHY_MCU_BUS_CK_GATE_EN | ++ AIROHA_USB_PHY_FORCE_SSUSB_IP_SW_RST | ++ AIROHA_USB_PHY_SSUSB_SW_RST); ++ ++ usleep_range(1000, 1500); ++ ++ return 0; ++} ++ ++static int airoha_usb_phy_power_on(struct phy *phy) ++{ ++ struct airoha_usb_phy_instance *instance = phy_get_drvdata(phy); ++ struct airoha_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent); ++ ++ switch (instance->type) { ++ case PHY_TYPE_USB2: ++ airoha_usb_phy_u2_power_on(priv); ++ break; ++ case PHY_TYPE_USB3: ++ if (phy_get_mode(phy) == PHY_MODE_PCIE) ++ return 0; ++ ++ airoha_usb_phy_u3_power_on(priv); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int airoha_usb_phy_u2_power_off(struct airoha_usb_phy_priv *priv) ++{ ++ regmap_set_bits(priv->regmap, AIROHA_USB_PHY_USBPHYACR6, ++ AIROHA_USB_PHY_USB20_BC11_SW_EN); ++ ++ usleep_range(1000, 1500); ++ ++ return 0; ++} ++ ++static int airoha_usb_phy_u3_power_off(struct airoha_usb_phy_priv *priv) ++{ ++ regmap_set_bits(priv->regmap, AIROHA_USB_PHY_GPIO_CTLD, ++ AIROHA_USB_PHY_SSUSB_IP_SW_RST | ++ AIROHA_USB_PHY_FORCE_SSUSB_IP_SW_RST); ++ ++ usleep_range(1000, 1500); ++ ++ return 0; ++} ++ ++static int airoha_usb_phy_power_off(struct phy *phy) ++{ ++ struct airoha_usb_phy_instance *instance = phy_get_drvdata(phy); ++ struct airoha_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent); ++ ++ switch (instance->type) { ++ case PHY_TYPE_USB2: ++ airoha_usb_phy_u2_power_off(priv); ++ break; ++ case PHY_TYPE_USB3: ++ if (phy_get_mode(phy) == PHY_MODE_PCIE) ++ return 0; ++ ++ airoha_usb_phy_u3_power_off(priv); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int airoha_usb_phy_u2_set_mode(struct airoha_usb_phy_priv *priv, ++ enum phy_mode mode) ++{ ++ u32 val; ++ ++ /* ++ * For Device and Host mode, enable force IDDIG. ++ * For Device set IDDIG, for Host clear IDDIG. ++ * For OTG disable force and clear IDDIG bit while at it. ++ */ ++ switch (mode) { ++ case PHY_MODE_USB_DEVICE: ++ val = AIROHA_USB_PHY_IDDIG; ++ break; ++ case PHY_MODE_USB_HOST: ++ val = AIROHA_USB_PHY_FORCE_IDDIG | ++ AIROHA_USB_PHY_FORCE_IDDIG; ++ break; ++ case PHY_MODE_USB_OTG: ++ val = 0; ++ break; ++ default: ++ return 0; ++ } ++ ++ regmap_update_bits(priv->regmap, AIROHA_USB_PHY_U2PHYDTM1, ++ AIROHA_USB_PHY_FORCE_IDDIG | ++ AIROHA_USB_PHY_IDDIG, val); ++ ++ return 0; ++} ++ ++static int airoha_usb_phy_u3_set_mode(struct airoha_usb_phy_priv *priv, ++ enum phy_mode mode) ++{ ++ u32 sel; ++ ++ /* Only USB2 supports PCIe mode */ ++ if (mode == PHY_MODE_PCIE && ++ priv->serdes_port != AIROHA_SCU_SERDES_USB2) ++ return -EINVAL; ++ ++ if (mode == PHY_MODE_PCIE) ++ sel = AIROHA_SCU_SSTR_USB_PCIE_SEL_PCIE; ++ else ++ sel = AIROHA_SCU_SSTR_USB_PCIE_SEL_USB; ++ ++ regmap_update_bits(priv->scu, AIROHA_SCU_SSTR, ++ AIROHA_SCU_SSTR_USB_PCIE_SEL, sel); ++ ++ return 0; ++} ++ ++static int airoha_usb_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode) ++{ ++ struct airoha_usb_phy_instance *instance = phy_get_drvdata(phy); ++ struct airoha_usb_phy_priv *priv = dev_get_drvdata(phy->dev.parent); ++ ++ switch (instance->type) { ++ case PHY_TYPE_USB2: ++ return airoha_usb_phy_u2_set_mode(priv, mode); ++ case PHY_TYPE_USB3: ++ return airoha_usb_phy_u3_set_mode(priv, mode); ++ default: ++ return 0; ++ } ++} ++ ++static struct phy *airoha_usb_phy_xlate(struct device *dev, ++ const struct of_phandle_args *args) ++{ ++ struct airoha_usb_phy_priv *priv = dev_get_drvdata(dev); ++ struct airoha_usb_phy_instance *instance = NULL; ++ unsigned int index, phy_type; ++ ++ if (args->args_count != 1) { ++ dev_err(dev, "invalid number of cells in 'phy' property\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ phy_type = args->args[0]; ++ if (!(phy_type == PHY_TYPE_USB2 || phy_type == PHY_TYPE_USB3)) { ++ dev_err(dev, "unsupported device type: %d\n", phy_type); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ for (index = 0; index < AIROHA_PHY_USB_MAX; index++) ++ if (priv->phys[index] && ++ phy_type == priv->phys[index]->type) { ++ instance = priv->phys[index]; ++ break; ++ } ++ ++ if (!instance) { ++ dev_err(dev, "failed to find appropriate phy\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ return instance->phy; ++} ++ ++static const struct phy_ops airoha_phy = { ++ .init = airoha_usb_phy_init, ++ .power_on = airoha_usb_phy_power_on, ++ .power_off = airoha_usb_phy_power_off, ++ .set_mode = airoha_usb_phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct regmap_config airoha_usb_phy_regmap_config = { ++ .reg_bits = 32, ++ .val_bits = 32, ++ .reg_stride = 4, ++}; ++ ++static int airoha_usb_phy_probe(struct platform_device *pdev) ++{ ++ struct phy_provider *phy_provider; ++ struct airoha_usb_phy_priv *priv; ++ struct device *dev = &pdev->dev; ++ unsigned int index; ++ void *base; ++ int ret; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->dev = dev; ++ ++ ret = of_property_read_u32(dev->of_node, "airoha,usb2-monitor-clk-sel", ++ &priv->monclk_sel); ++ if (ret) ++ return dev_err_probe(dev, ret, "Monitor clock selection is mandatory for USB PHY calibration.\n"); ++ ++ if (priv->monclk_sel > 3) ++ return dev_err_probe(dev, -EINVAL, "only 4 Monitor clock are selectable on the SoC.\n"); ++ ++ base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ priv->regmap = devm_regmap_init_mmio(dev, base, &airoha_usb_phy_regmap_config); ++ if (IS_ERR(priv->regmap)) ++ return PTR_ERR(priv->regmap); ++ ++ platform_set_drvdata(pdev, priv); ++ ++ for (index = 0; index < AIROHA_PHY_USB_MAX; index++) { ++ enum airoha_usb_phy_instance_type phy_type; ++ struct airoha_usb_phy_instance *instance; ++ ++ switch (index) { ++ case AIROHA_PHY_USB2: ++ phy_type = PHY_TYPE_USB2; ++ break; ++ case AIROHA_PHY_USB3: ++ phy_type = PHY_TYPE_USB3; ++ break; ++ } ++ ++ /* Skip registering USB3 instance if not supported */ ++ if (phy_type == PHY_TYPE_USB3) { ++ ret = of_property_read_u32(dev->of_node, "airoha,serdes-port", ++ &priv->serdes_port); ++ if (ret) ++ continue; ++ ++ /* With Serdes Port property, SCU is required */ ++ priv->scu = syscon_regmap_lookup_by_phandle(dev->of_node, ++ "airoha,scu"); ++ if (IS_ERR(priv->scu)) ++ return dev_err_probe(dev, PTR_ERR(priv->scu), "failed to get SCU syscon.\n"); ++ } ++ ++ instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL); ++ if (!instance) ++ return -ENOMEM; ++ ++ instance->type = phy_type; ++ priv->phys[index] = instance; ++ ++ instance->phy = devm_phy_create(dev, NULL, &airoha_phy); ++ if (IS_ERR(instance->phy)) ++ return dev_err_probe(dev, PTR_ERR(instance->phy), "failed to create phy\n"); ++ ++ phy_set_drvdata(instance->phy, instance); ++ } ++ ++ phy_provider = devm_of_phy_provider_register(&pdev->dev, airoha_usb_phy_xlate); ++ ++ return PTR_ERR_OR_ZERO(phy_provider); ++} ++ ++static const struct of_device_id airoha_phy_id_table[] = { ++ { .compatible = "airoha,an7581-usb-phy" }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, airoha_phy_id_table); ++ ++static struct platform_driver airoha_usb_driver = { ++ .probe = airoha_usb_phy_probe, ++ .driver = { ++ .name = "airoha-usb-phy", ++ .of_match_table = airoha_phy_id_table, ++ }, ++}; ++ ++module_platform_driver(airoha_usb_driver); ++ ++MODULE_AUTHOR("Christian Marangi "); ++MODULE_LICENSE("GPL"); ++MODULE_DESCRIPTION("Airoha USB PHY driver"); diff --git a/lede/target/linux/airoha/patches-6.12/220-08-usb-host-add-ARCH_AIROHA-in-XHCI-MTK-dependency.patch b/lede/target/linux/airoha/patches-6.12/220-08-usb-host-add-ARCH_AIROHA-in-XHCI-MTK-dependency.patch new file mode 100644 index 0000000000..3756f7643a --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/220-08-usb-host-add-ARCH_AIROHA-in-XHCI-MTK-dependency.patch @@ -0,0 +1,25 @@ +From 3d3a406dea89b789dfb550bd05d0eba5ae926755 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 7 Feb 2025 14:17:06 +0100 +Subject: [PATCH 08/10] usb: host: add ARCH_AIROHA in XHCI MTK dependency + +Airoha SoC use the same register map a logic of the Mediatek xHCI +driver, hence add it to the dependency list to permit compilation also +on this ARCH. + +Signed-off-by: Christian Marangi +--- + drivers/usb/host/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -71,7 +71,7 @@ config USB_XHCI_HISTB + config USB_XHCI_MTK + tristate "xHCI support for MediaTek SoCs" + select MFD_SYSCON +- depends on (MIPS && SOC_MT7621) || ARCH_MEDIATEK || COMPILE_TEST ++ depends on (MIPS && SOC_MT7621) || ARCH_MEDIATEK || ARCH_AIROHA || COMPILE_TEST + help + Say 'Y' to enable the support for the xHCI host controller + found in MediaTek SoCs. diff --git a/lede/target/linux/airoha/patches-6.12/220-10-PCI-mediatek-gen3-set-PHY-mode-for-Airoha-EN7581.patch b/lede/target/linux/airoha/patches-6.12/220-10-PCI-mediatek-gen3-set-PHY-mode-for-Airoha-EN7581.patch new file mode 100644 index 0000000000..19d168db64 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/220-10-PCI-mediatek-gen3-set-PHY-mode-for-Airoha-EN7581.patch @@ -0,0 +1,34 @@ +From 112c6ea7ac356dab16e11084f2183e653a289e91 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 28 Oct 2025 12:35:41 +0100 +Subject: [PATCH 10/10] PCI: mediatek-gen3: set PHY mode for Airoha EN7581 + +For the Airoha EN7581 SoC, the 3rd PCIe line is attached to a special +PHY that can be both used for USB 3.0 operation or PCIe. + +Configure the PHY for PCIe operation before init it to correctly +configure the SCU Serdes register. + +This permits correct functionality and enumeration of PCIe devices on +the 3rd PCIe line present on the SoC. + +Signed-off-by: Christian Marangi +--- + drivers/pci/controller/pcie-mediatek-gen3.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/pci/controller/pcie-mediatek-gen3.c ++++ b/drivers/pci/controller/pcie-mediatek-gen3.c +@@ -925,6 +925,12 @@ static int mtk_pcie_en7581_power_up(stru + size = lower_32_bits(resource_size(entry->res)); + regmap_write(pbus_regmap, args[1], GENMASK(31, __fls(size))); + ++ err = phy_set_mode(pcie->phy, PHY_MODE_PCIE); ++ if (err) { ++ dev_err(dev, "failed to set PHY mode\n"); ++ return err; ++ } ++ + /* + * Unlike the other MediaTek Gen3 controllers, the Airoha EN7581 + * requires PHY initialization and power-on before PHY reset deassert. diff --git a/lede/target/linux/airoha/patches-6.12/401-02-net-dsa-mt7530-Add-AN7583-support.patch b/lede/target/linux/airoha/patches-6.12/401-02-net-dsa-mt7530-Add-AN7583-support.patch new file mode 100644 index 0000000000..0d72a59ad9 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/401-02-net-dsa-mt7530-Add-AN7583-support.patch @@ -0,0 +1,140 @@ +From 7e112e51d48db09739dd73c90411fc8a5635747f Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 22 May 2025 15:13:10 +0200 +Subject: [PATCH 2/3] net: dsa: mt7530: Add AN7583 support + +Add Airoha AN7583 Switch support. This is based on Airoha EN7581 that is +based on Mediatek MT7988 Switch. + +Airoha AN7583 require additional tweak to the GEPHY_CONN_CFG register to +make the internal PHY work. + +Signed-off-by: Christian Marangi +--- + drivers/net/dsa/mt7530-mmio.c | 1 + + drivers/net/dsa/mt7530.c | 24 ++++++++++++++++++++++-- + drivers/net/dsa/mt7530.h | 18 ++++++++++++++---- + 3 files changed, 37 insertions(+), 6 deletions(-) + +--- a/drivers/net/dsa/mt7530-mmio.c ++++ b/drivers/net/dsa/mt7530-mmio.c +@@ -11,6 +11,7 @@ + #include "mt7530.h" + + static const struct of_device_id mt7988_of_match[] = { ++ { .compatible = "airoha,an7583-switch", .data = &mt753x_table[ID_AN7583], }, + { .compatible = "airoha,en7581-switch", .data = &mt753x_table[ID_EN7581], }, + { .compatible = "mediatek,mt7988-switch", .data = &mt753x_table[ID_MT7988], }, + { /* sentinel */ }, +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1153,7 +1153,7 @@ mt753x_cpu_port_enable(struct dsa_switch + * is affine to the inbound user port. + */ + if (priv->id == ID_MT7531 || priv->id == ID_MT7988 || +- priv->id == ID_EN7581) ++ priv->id == ID_EN7581 || priv->id == ID_AN7583) + mt7530_set(priv, MT7531_CFC, MT7531_CPU_PMAP(BIT(port))); + + /* CPU port gets connected to all user ports of +@@ -2589,7 +2589,7 @@ mt7531_setup_common(struct dsa_switch *d + mt7530_set(priv, MT753X_AGC, LOCAL_EN); + + /* Enable Special Tag for rx frames */ +- if (priv->id == ID_EN7581) ++ if (priv->id == ID_EN7581 || priv->id == ID_AN7583) + mt7530_write(priv, MT753X_CPORT_SPTAG_CFG, + CPORT_SW2FE_STAG_EN | CPORT_FE2SW_STAG_EN); + +@@ -3157,6 +3157,16 @@ static int mt7988_setup(struct dsa_switc + reset_control_deassert(priv->rstc); + usleep_range(20, 50); + ++ /* AN7583 require additional tweak to CONN_CFG */ ++ if (priv->id == ID_AN7583) ++ mt7530_rmw(priv, AN7583_GEPHY_CONN_CFG, ++ AN7583_CSR_DPHY_CKIN_SEL | ++ AN7583_CSR_PHY_CORE_REG_CLK_SEL | ++ AN7583_CSR_ETHER_AFE_PWD, ++ AN7583_CSR_DPHY_CKIN_SEL | ++ AN7583_CSR_PHY_CORE_REG_CLK_SEL | ++ FIELD_PREP(AN7583_CSR_ETHER_AFE_PWD, 0)); ++ + /* Reset the switch PHYs */ + mt7530_write(priv, MT7530_SYS_CTRL, SYS_CTRL_PHY_RST); + +@@ -3253,6 +3263,16 @@ const struct mt753x_info mt753x_table[] + .pcs_ops = &mt7530_pcs_ops, + .sw_setup = mt7988_setup, + .phy_read_c22 = mt7531_ind_c22_phy_read, ++ .phy_write_c22 = mt7531_ind_c22_phy_write, ++ .phy_read_c45 = mt7531_ind_c45_phy_read, ++ .phy_write_c45 = mt7531_ind_c45_phy_write, ++ .mac_port_get_caps = en7581_mac_port_get_caps, ++ }, ++ [ID_AN7583] = { ++ .id = ID_AN7583, ++ .pcs_ops = &mt7530_pcs_ops, ++ .sw_setup = mt7988_setup, ++ .phy_read_c22 = mt7531_ind_c22_phy_read, + .phy_write_c22 = mt7531_ind_c22_phy_write, + .phy_read_c45 = mt7531_ind_c45_phy_read, + .phy_write_c45 = mt7531_ind_c45_phy_write, +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -20,6 +20,7 @@ enum mt753x_id { + ID_MT7531 = 2, + ID_MT7988 = 3, + ID_EN7581 = 4, ++ ID_AN7583 = 5, + }; + + #define NUM_TRGMII_CTRL 5 +@@ -66,7 +67,8 @@ enum mt753x_id { + + #define MT753X_MIRROR_REG(id) ((id == ID_MT7531 || \ + id == ID_MT7988 || \ +- id == ID_EN7581) ? \ ++ id == ID_EN7581 || \ ++ id == ID_AN7583) ? \ + MT7531_CFC : MT753X_MFC) + + #define MT753X_MIRROR_EN(id) ((id == ID_MT7531 || \ +@@ -76,19 +78,22 @@ enum mt753x_id { + + #define MT753X_MIRROR_PORT_MASK(id) ((id == ID_MT7531 || \ + id == ID_MT7988 || \ +- id == ID_EN7581) ? \ ++ id == ID_EN7581 || \ ++ id == ID_AN7583) ? \ + MT7531_MIRROR_PORT_MASK : \ + MT7530_MIRROR_PORT_MASK) + + #define MT753X_MIRROR_PORT_GET(id, val) ((id == ID_MT7531 || \ + id == ID_MT7988 || \ +- id == ID_EN7581) ? \ ++ id == ID_EN7581 || \ ++ id == ID_AN7583) ? \ + MT7531_MIRROR_PORT_GET(val) : \ + MT7530_MIRROR_PORT_GET(val)) + + #define MT753X_MIRROR_PORT_SET(id, val) ((id == ID_MT7531 || \ + id == ID_MT7988 || \ +- id == ID_EN7581) ? \ ++ id == ID_EN7581 || \ ++ id == ID_AN7583) ? \ + MT7531_MIRROR_PORT_SET(val) : \ + MT7530_MIRROR_PORT_SET(val)) + +@@ -619,6 +624,11 @@ enum mt7531_xtal_fsel { + #define CPORT_SW2FE_STAG_EN BIT(1) + #define CPORT_FE2SW_STAG_EN BIT(0) + ++#define AN7583_GEPHY_CONN_CFG 0x7c14 ++#define AN7583_CSR_DPHY_CKIN_SEL BIT(31) ++#define AN7583_CSR_PHY_CORE_REG_CLK_SEL BIT(30) ++#define AN7583_CSR_ETHER_AFE_PWD GENMASK(28, 24) ++ + /* Registers for LED GPIO control (MT7530 only) + * All registers follow this pattern: + * [ 2: 0] port 0 diff --git a/lede/target/linux/airoha/patches-6.12/402-01-thermal-airoha-convert-to-regmap-API.patch b/lede/target/linux/airoha/patches-6.12/402-01-thermal-airoha-convert-to-regmap-API.patch new file mode 100644 index 0000000000..9414bef9cb --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/402-01-thermal-airoha-convert-to-regmap-API.patch @@ -0,0 +1,194 @@ +From 7d55e75edc87022a4c1820588f70a80cebb13c5f Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 23 May 2025 19:34:54 +0200 +Subject: [PATCH 1/5] thermal: airoha: convert to regmap API + +In preparation for support of Airoha AN7583, convert the driver to +regmap API. This is needed as Airoha AN7583 will be based on syscon +regmap. + +Signed-off-by: Christian Marangi +--- + drivers/thermal/airoha_thermal.c | 72 +++++++++++++++++++------------- + 1 file changed, 42 insertions(+), 30 deletions(-) + +--- a/drivers/thermal/airoha_thermal.c ++++ b/drivers/thermal/airoha_thermal.c +@@ -194,7 +194,7 @@ + #define AIROHA_MAX_SAMPLES 6 + + struct airoha_thermal_priv { +- void __iomem *base; ++ struct regmap *map; + struct regmap *chip_scu; + struct resource scu_adc_res; + +@@ -265,8 +265,8 @@ static int airoha_thermal_set_trips(stru + RAW_TO_TEMP(priv, FIELD_MAX(EN7581_DOUT_TADC_MASK))); + + /* We offset the high temp of 1°C to trigger correct event */ +- writel(TEMP_TO_RAW(priv, high) >> 4, +- priv->base + EN7581_TEMPOFFSETH); ++ regmap_write(priv->map, EN7581_TEMPOFFSETH, ++ TEMP_TO_RAW(priv, high) >> 4); + + enable_monitor = true; + } +@@ -277,15 +277,15 @@ static int airoha_thermal_set_trips(stru + RAW_TO_TEMP(priv, FIELD_MAX(EN7581_DOUT_TADC_MASK))); + + /* We offset the low temp of 1°C to trigger correct event */ +- writel(TEMP_TO_RAW(priv, low) >> 4, +- priv->base + EN7581_TEMPOFFSETL); ++ regmap_write(priv->map, EN7581_TEMPOFFSETL, ++ TEMP_TO_RAW(priv, high) >> 4); + + enable_monitor = true; + } + + /* Enable sensor 0 monitor after trip are set */ + if (enable_monitor) +- writel(EN7581_SENSE0_EN, priv->base + EN7581_TEMPMONCTL0); ++ regmap_write(priv->map, EN7581_TEMPMONCTL0, EN7581_SENSE0_EN); + + return 0; + } +@@ -302,7 +302,7 @@ static irqreturn_t airoha_thermal_irq(in + bool update = false; + u32 status; + +- status = readl(priv->base + EN7581_TEMPMONINTSTS); ++ regmap_read(priv->map, EN7581_TEMPMONINTSTS, &status); + switch (status & (EN7581_HOFSINTSTS0 | EN7581_LOFSINTSTS0)) { + case EN7581_HOFSINTSTS0: + event = THERMAL_TRIP_VIOLATED; +@@ -318,7 +318,7 @@ static irqreturn_t airoha_thermal_irq(in + } + + /* Reset Interrupt */ +- writel(status, priv->base + EN7581_TEMPMONINTSTS); ++ regmap_write(priv->map, EN7581_TEMPMONINTSTS, status); + + if (update) + thermal_zone_device_update(priv->tz, event); +@@ -336,11 +336,11 @@ static void airoha_thermal_setup_adc_val + /* sleep 10 ms for ADC to enable */ + usleep_range(10 * USEC_PER_MSEC, 11 * USEC_PER_MSEC); + +- efuse_calib_info = readl(priv->base + EN7581_EFUSE_TEMP_OFFSET_REG); ++ regmap_read(priv->map, EN7581_EFUSE_TEMP_OFFSET_REG, &efuse_calib_info); + if (efuse_calib_info) { + priv->default_offset = FIELD_GET(EN7581_EFUSE_TEMP_OFFSET, efuse_calib_info); + /* Different slope are applied if the sensor is used for CPU or for package */ +- cpu_sensor = readl(priv->base + EN7581_EFUSE_TEMP_CPU_SENSOR_REG); ++ regmap_read(priv->map, EN7581_EFUSE_TEMP_CPU_SENSOR_REG, &cpu_sensor); + if (cpu_sensor) { + priv->default_slope = EN7581_SLOPE_X100_DIO_DEFAULT; + priv->init_temp = EN7581_INIT_TEMP_FTK_X10; +@@ -359,8 +359,8 @@ static void airoha_thermal_setup_adc_val + static void airoha_thermal_setup_monitor(struct airoha_thermal_priv *priv) + { + /* Set measure mode */ +- writel(FIELD_PREP(EN7581_MSRCTL0, EN7581_MSRCTL_6SAMPLE_MAX_MIX_AVG4), +- priv->base + EN7581_TEMPMSRCTL0); ++ regmap_write(priv->map, EN7581_TEMPMSRCTL0, ++ FIELD_PREP(EN7581_MSRCTL0, EN7581_MSRCTL_6SAMPLE_MAX_MIX_AVG4)); + + /* + * Configure ADC valid reading addr +@@ -375,15 +375,15 @@ static void airoha_thermal_setup_monitor + * We set valid instead of volt as we don't enable valid/volt + * split reading and AHB read valid addr in such case. + */ +- writel(priv->scu_adc_res.start + EN7581_DOUT_TADC, +- priv->base + EN7581_TEMPADCVALIDADDR); ++ regmap_write(priv->map, EN7581_TEMPADCVALIDADDR, ++ priv->scu_adc_res.start + EN7581_DOUT_TADC); + + /* + * Configure valid bit on a fake value of bit 16. The ADC outputs + * max of 2 bytes for voltage. + */ +- writel(FIELD_PREP(EN7581_ADV_RD_VALID_POS, 16), +- priv->base + EN7581_TEMPADCVALIDMASK); ++ regmap_write(priv->map, EN7581_TEMPADCVALIDMASK, ++ FIELD_PREP(EN7581_ADV_RD_VALID_POS, 16)); + + /* + * AHB supports max 12 bytes for ADC voltage. Shift the read +@@ -391,40 +391,52 @@ static void airoha_thermal_setup_monitor + * in the order of half a °C and is acceptable in the context + * of triggering interrupt in critical condition. + */ +- writel(FIELD_PREP(EN7581_ADC_VOLTAGE_SHIFT, 4), +- priv->base + EN7581_TEMPADCVOLTAGESHIFT); ++ regmap_write(priv->map, EN7581_TEMPADCVOLTAGESHIFT, ++ FIELD_PREP(EN7581_ADC_VOLTAGE_SHIFT, 4)); + + /* BUS clock is 300MHz counting unit is 3 * 68.64 * 256 = 52.715us */ +- writel(FIELD_PREP(EN7581_PERIOD_UNIT, 3), +- priv->base + EN7581_TEMPMONCTL1); ++ regmap_write(priv->map, EN7581_TEMPMONCTL1, ++ FIELD_PREP(EN7581_PERIOD_UNIT, 3)); + + /* + * filt interval is 1 * 52.715us = 52.715us, + * sen interval is 379 * 52.715us = 19.97ms + */ +- writel(FIELD_PREP(EN7581_FILT_INTERVAL, 1) | +- FIELD_PREP(EN7581_FILT_INTERVAL, 379), +- priv->base + EN7581_TEMPMONCTL2); ++ regmap_write(priv->map, EN7581_TEMPMONCTL2, ++ FIELD_PREP(EN7581_FILT_INTERVAL, 1) | ++ FIELD_PREP(EN7581_FILT_INTERVAL, 379)); + + /* AHB poll is set to 146 * 68.64 = 10.02us */ +- writel(FIELD_PREP(EN7581_ADC_POLL_INTVL, 146), +- priv->base + EN7581_TEMPAHBPOLL); ++ regmap_write(priv->map, EN7581_TEMPAHBPOLL, ++ FIELD_PREP(EN7581_ADC_POLL_INTVL, 146)); + } + ++static const struct regmap_config airoha_thermal_regmap_config = { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++}; ++ + static int airoha_thermal_probe(struct platform_device *pdev) + { + struct airoha_thermal_priv *priv; + struct device_node *chip_scu_np; + struct device *dev = &pdev->dev; ++ void __iomem *base; + int irq, ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + +- priv->base = devm_platform_ioremap_resource(pdev, 0); +- if (IS_ERR(priv->base)) +- return PTR_ERR(priv->base); ++ base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ priv->map = devm_regmap_init_mmio(dev, base, ++ &airoha_thermal_regmap_config); ++ if (IS_ERR(priv->map)) ++ return PTR_ERR(priv->map); + + chip_scu_np = of_parse_phandle(dev->of_node, "airoha,chip-scu", 0); + if (!chip_scu_np) +@@ -462,8 +474,8 @@ static int airoha_thermal_probe(struct p + platform_set_drvdata(pdev, priv); + + /* Enable LOW and HIGH interrupt */ +- writel(EN7581_HOFSINTEN0 | EN7581_LOFSINTEN0, +- priv->base + EN7581_TEMPMONINT); ++ regmap_write(priv->map, EN7581_TEMPMONINT, ++ EN7581_HOFSINTEN0 | EN7581_LOFSINTEN0); + + return 0; + } diff --git a/lede/target/linux/airoha/patches-6.12/402-02-thermal-drivers-airoha-Generalize-probe-function.patch b/lede/target/linux/airoha/patches-6.12/402-02-thermal-drivers-airoha-Generalize-probe-function.patch new file mode 100644 index 0000000000..b306b2308b --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/402-02-thermal-drivers-airoha-Generalize-probe-function.patch @@ -0,0 +1,226 @@ +From 6c0f01b16687dc582f0470a5d5b20084fb3a290f Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 23 May 2025 19:48:32 +0200 +Subject: [PATCH 2/5] thermal/drivers: airoha: Generalize probe function + +In preparation for support of Airoha AN7583, generalize the probe +function to address for the 2 SoC differece. + +Implement a match_data struct where it's possible to define a more +specific probe and post_probe function and specific thermal ops and +pllrg protect value. + +Signed-off-by: Christian Marangi +--- + drivers/thermal/airoha_thermal.c | 102 +++++++++++++++++++++++-------- + 1 file changed, 75 insertions(+), 27 deletions(-) + +--- a/drivers/thermal/airoha_thermal.c ++++ b/drivers/thermal/airoha_thermal.c +@@ -198,12 +198,23 @@ struct airoha_thermal_priv { + struct regmap *chip_scu; + struct resource scu_adc_res; + ++ u32 pllrg_protect; ++ + struct thermal_zone_device *tz; + int init_temp; + int default_slope; + int default_offset; + }; + ++struct airoha_thermal_soc_data { ++ u32 pllrg_protect; ++ ++ const struct thermal_zone_device_ops *thdev_ops; ++ int (*probe)(struct platform_device *pdev, ++ struct airoha_thermal_priv *priv); ++ int (*post_probe)(struct platform_device *pdev); ++}; ++ + static int airoha_get_thermal_ADC(struct airoha_thermal_priv *priv) + { + u32 val; +@@ -220,7 +231,8 @@ static void airoha_init_thermal_ADC_mode + regmap_read(priv->chip_scu, EN7581_PLLRG_PROTECT, &pllrg); + + /* Give access to thermal regs */ +- regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT, EN7581_SCU_THERMAL_PROTECT_KEY); ++ regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT, ++ priv->pllrg_protect); + adc_mux = FIELD_PREP(EN7581_MUX_TADC, EN7581_SCU_THERMAL_MUX_DIODE1); + regmap_write(priv->chip_scu, EN7581_PWD_TADC, adc_mux); + +@@ -228,7 +240,7 @@ static void airoha_init_thermal_ADC_mode + regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT, pllrg); + } + +-static int airoha_thermal_get_temp(struct thermal_zone_device *tz, int *temp) ++static int en7581_thermal_get_temp(struct thermal_zone_device *tz, int *temp) + { + struct airoha_thermal_priv *priv = thermal_zone_device_priv(tz); + int min_value, max_value, avg_value, value; +@@ -253,7 +265,7 @@ static int airoha_thermal_get_temp(struc + return 0; + } + +-static int airoha_thermal_set_trips(struct thermal_zone_device *tz, int low, ++static int en7581_thermal_set_trips(struct thermal_zone_device *tz, int low, + int high) + { + struct airoha_thermal_priv *priv = thermal_zone_device_priv(tz); +@@ -290,12 +302,12 @@ static int airoha_thermal_set_trips(stru + return 0; + } + +-static const struct thermal_zone_device_ops thdev_ops = { +- .get_temp = airoha_thermal_get_temp, +- .set_trips = airoha_thermal_set_trips, ++static const struct thermal_zone_device_ops en7581_thdev_ops = { ++ .get_temp = en7581_thermal_get_temp, ++ .set_trips = en7581_thermal_set_trips, + }; + +-static irqreturn_t airoha_thermal_irq(int irq, void *data) ++static irqreturn_t en7581_thermal_irq(int irq, void *data) + { + struct airoha_thermal_priv *priv = data; + enum thermal_notify_event event; +@@ -326,7 +338,7 @@ static irqreturn_t airoha_thermal_irq(in + return IRQ_HANDLED; + } + +-static void airoha_thermal_setup_adc_val(struct device *dev, ++static void en7581_thermal_setup_adc_val(struct device *dev, + struct airoha_thermal_priv *priv) + { + u32 efuse_calib_info, cpu_sensor; +@@ -356,7 +368,7 @@ static void airoha_thermal_setup_adc_val + } + } + +-static void airoha_thermal_setup_monitor(struct airoha_thermal_priv *priv) ++static void en7581_thermal_setup_monitor(struct airoha_thermal_priv *priv) + { + /* Set measure mode */ + regmap_write(priv->map, EN7581_TEMPMSRCTL0, +@@ -411,30 +423,26 @@ static void airoha_thermal_setup_monitor + FIELD_PREP(EN7581_ADC_POLL_INTVL, 146)); + } + +-static const struct regmap_config airoha_thermal_regmap_config = { ++static const struct regmap_config en7581_thermal_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + }; + +-static int airoha_thermal_probe(struct platform_device *pdev) ++static int en7581_thermal_probe(struct platform_device *pdev, ++ struct airoha_thermal_priv *priv) + { +- struct airoha_thermal_priv *priv; + struct device_node *chip_scu_np; + struct device *dev = &pdev->dev; + void __iomem *base; + int irq, ret; + +- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; +- + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + priv->map = devm_regmap_init_mmio(dev, base, +- &airoha_thermal_regmap_config); ++ &en7581_thermal_regmap_config); + if (IS_ERR(priv->map)) + return PTR_ERR(priv->map); + +@@ -454,18 +462,55 @@ static int airoha_thermal_probe(struct p + return irq; + + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, +- airoha_thermal_irq, IRQF_ONESHOT, ++ en7581_thermal_irq, IRQF_ONESHOT, + pdev->name, priv); + if (ret) { + dev_err(dev, "Can't get interrupt working.\n"); + return ret; + } + +- airoha_thermal_setup_monitor(priv); +- airoha_thermal_setup_adc_val(dev, priv); ++ en7581_thermal_setup_monitor(priv); ++ en7581_thermal_setup_adc_val(dev, priv); ++ ++ return 0; ++} ++ ++static int en7581_thermal_post_probe(struct platform_device *pdev) ++{ ++ struct airoha_thermal_priv *priv = platform_get_drvdata(pdev); ++ ++ /* Enable LOW and HIGH interrupt (if supported) */ ++ regmap_write(priv->map, EN7581_TEMPMONINT, ++ EN7581_HOFSINTEN0 | EN7581_LOFSINTEN0); ++ ++ return 0; ++} ++ ++static int airoha_thermal_probe(struct platform_device *pdev) ++{ ++ const struct airoha_thermal_soc_data *soc_data; ++ struct airoha_thermal_priv *priv; ++ struct device *dev = &pdev->dev; ++ int ret; ++ ++ soc_data = device_get_match_data(dev); ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->pllrg_protect = soc_data->pllrg_protect; ++ ++ if (!soc_data->probe) ++ return -EINVAL; ++ ++ ret = soc_data->probe(pdev, priv); ++ if (ret) ++ return ret; + + /* register of thermal sensor and get info from DT */ +- priv->tz = devm_thermal_of_zone_register(dev, 0, priv, &thdev_ops); ++ priv->tz = devm_thermal_of_zone_register(dev, 0, priv, ++ soc_data->thdev_ops); + if (IS_ERR(priv->tz)) { + dev_err(dev, "register thermal zone sensor failed\n"); + return PTR_ERR(priv->tz); +@@ -473,15 +518,18 @@ static int airoha_thermal_probe(struct p + + platform_set_drvdata(pdev, priv); + +- /* Enable LOW and HIGH interrupt */ +- regmap_write(priv->map, EN7581_TEMPMONINT, +- EN7581_HOFSINTEN0 | EN7581_LOFSINTEN0); +- +- return 0; ++ return soc_data->post_probe ? soc_data->post_probe(pdev) : 0; + } + ++static const struct airoha_thermal_soc_data en7581_data = { ++ .pllrg_protect = EN7581_SCU_THERMAL_PROTECT_KEY, ++ .thdev_ops = &en7581_thdev_ops, ++ .probe = &en7581_thermal_probe, ++ .post_probe = &en7581_thermal_post_probe, ++}; ++ + static const struct of_device_id airoha_thermal_match[] = { +- { .compatible = "airoha,en7581-thermal" }, ++ { .compatible = "airoha,en7581-thermal", .data = &en7581_data }, + {}, + }; + MODULE_DEVICE_TABLE(of, airoha_thermal_match); diff --git a/lede/target/linux/airoha/patches-6.12/402-03-thermal-drivers-airoha-generalize-get_thermal_ADC-an.patch b/lede/target/linux/airoha/patches-6.12/402-03-thermal-drivers-airoha-generalize-get_thermal_ADC-an.patch new file mode 100644 index 0000000000..5f6ae2c08a --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/402-03-thermal-drivers-airoha-generalize-get_thermal_ADC-an.patch @@ -0,0 +1,129 @@ +From 1e623852d07759c3c076505193bd7f0bd3486774 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 23 May 2025 19:54:53 +0200 +Subject: [PATCH 3/5] thermal/drivers: airoha: generalize get_thermal_ADC and + set_mux function + +In preparation for support of Airoha AN7583, generalize +get_thermal_ADC() and set_thermal_mux() with the use of reg_field API. + +This is to account the same logic between the current supported SoC and +the new one but with different register address. + +While at it also further improve some comments and move sleep inside the +set_thermal_mux function. + +Signed-off-by: Christian Marangi +--- + drivers/thermal/airoha_thermal.c | 54 +++++++++++++++++++++++++------- + 1 file changed, 42 insertions(+), 12 deletions(-) + +--- a/drivers/thermal/airoha_thermal.c ++++ b/drivers/thermal/airoha_thermal.c +@@ -193,9 +193,18 @@ + + #define AIROHA_MAX_SAMPLES 6 + ++enum airoha_thermal_chip_scu_field { ++ AIROHA_THERMAL_DOUT_TADC, ++ AIROHA_THERMAL_MUX_TADC, ++ ++ /* keep last */ ++ AIROHA_THERMAL_FIELD_MAX, ++}; ++ + struct airoha_thermal_priv { + struct regmap *map; + struct regmap *chip_scu; ++ struct regmap_field *chip_scu_fields[AIROHA_THERMAL_FIELD_MAX]; + struct resource scu_adc_res; + + u32 pllrg_protect; +@@ -219,22 +228,29 @@ static int airoha_get_thermal_ADC(struct + { + u32 val; + +- regmap_read(priv->chip_scu, EN7581_DOUT_TADC, &val); +- return FIELD_GET(EN7581_DOUT_TADC_MASK, val); ++ regmap_field_read(priv->chip_scu_fields[AIROHA_THERMAL_DOUT_TADC], ++ &val); ++ return val; + } + +-static void airoha_init_thermal_ADC_mode(struct airoha_thermal_priv *priv) ++static void airoha_set_thermal_mux(struct airoha_thermal_priv *priv, ++ int tdac_idx) + { +- u32 adc_mux, pllrg; ++ u32 pllrg; + + /* Save PLLRG current value */ + regmap_read(priv->chip_scu, EN7581_PLLRG_PROTECT, &pllrg); + +- /* Give access to thermal regs */ ++ /* Give access to Thermal regs */ + regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT, + priv->pllrg_protect); +- adc_mux = FIELD_PREP(EN7581_MUX_TADC, EN7581_SCU_THERMAL_MUX_DIODE1); +- regmap_write(priv->chip_scu, EN7581_PWD_TADC, adc_mux); ++ ++ /* Configure Thermal ADC mux to tdac_idx */ ++ regmap_field_write(priv->chip_scu_fields[AIROHA_THERMAL_MUX_TADC], ++ tdac_idx); ++ ++ /* Sleep 10 ms for Thermal ADC to enable */ ++ usleep_range(10 * USEC_PER_MSEC, 11 * USEC_PER_MSEC); + + /* Restore PLLRG value on exit */ + regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT, pllrg); +@@ -343,10 +359,8 @@ static void en7581_thermal_setup_adc_val + { + u32 efuse_calib_info, cpu_sensor; + +- /* Setup thermal sensor to ADC mode and setup the mux to DIODE1 */ +- airoha_init_thermal_ADC_mode(priv); +- /* sleep 10 ms for ADC to enable */ +- usleep_range(10 * USEC_PER_MSEC, 11 * USEC_PER_MSEC); ++ /* Setup Thermal Sensor to ADC mode and setup the mux to DIODE1 */ ++ airoha_set_thermal_mux(priv, EN7581_SCU_THERMAL_MUX_DIODE1); + + regmap_read(priv->map, EN7581_EFUSE_TEMP_OFFSET_REG, &efuse_calib_info); + if (efuse_calib_info) { +@@ -429,13 +443,18 @@ static const struct regmap_config en7581 + .val_bits = 32, + }; + ++static const struct reg_field en7581_chip_scu_fields[AIROHA_THERMAL_FIELD_MAX] = { ++ [AIROHA_THERMAL_DOUT_TADC] = REG_FIELD(EN7581_DOUT_TADC, 0, 15), ++ [AIROHA_THERMAL_MUX_TADC] = REG_FIELD(EN7581_PWD_TADC, 1, 3), ++}; ++ + static int en7581_thermal_probe(struct platform_device *pdev, + struct airoha_thermal_priv *priv) + { + struct device_node *chip_scu_np; + struct device *dev = &pdev->dev; + void __iomem *base; +- int irq, ret; ++ int i, irq, ret; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) +@@ -454,6 +473,17 @@ static int en7581_thermal_probe(struct p + if (IS_ERR(priv->chip_scu)) + return PTR_ERR(priv->chip_scu); + ++ for (i = 0; i < AIROHA_THERMAL_FIELD_MAX; i++) { ++ struct regmap_field *field; ++ ++ field = devm_regmap_field_alloc(dev, priv->chip_scu, ++ en7581_chip_scu_fields[i]); ++ if (IS_ERR(field)) ++ return PTR_ERR(field); ++ ++ priv->chip_scu_fields[i] = field; ++ } ++ + of_address_to_resource(chip_scu_np, 0, &priv->scu_adc_res); + of_node_put(chip_scu_np); + diff --git a/lede/target/linux/airoha/patches-6.12/402-05-thermal-drivers-airoha-Add-support-for-AN7583.patch b/lede/target/linux/airoha/patches-6.12/402-05-thermal-drivers-airoha-Add-support-for-AN7583.patch new file mode 100644 index 0000000000..51332350ef --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/402-05-thermal-drivers-airoha-Add-support-for-AN7583.patch @@ -0,0 +1,277 @@ +From 5891a9e5fbdf9a305b5f81e2625455efb2a886f0 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 23 May 2025 19:59:20 +0200 +Subject: [PATCH 5/5] thermal/drivers: airoha: Add support for AN7583 + +Add support for Airoha AN7583 Thermal driver. This apply similar logic +on how to read the temperature but totally drop support for the +PTP_THERMAL subsystem. PTP_THERMAL subsystem was a way to trigger trip +point from hardware by configuring how to read the temperature +internally. + +This subsystem has been totally removed from Airoha AN7583 permitting +only to read the temperature. + +The SoC support up to 3 sensor but the original driver always read the +BGA sensor hence it's currently implemented reading only this specific +sensor. Reference and values for the other 2 sensor are defined for +further implementation if confirmed working. + +set_thermal_mux() is extended to also address muxing the sensor as +AN7583 use a different way to read the temperature from 3 different +diode. The EN7581 code is updated to account for these changes. + +Signed-off-by: Christian Marangi +--- + drivers/thermal/airoha_thermal.c | 158 ++++++++++++++++++++++++++++++- + 1 file changed, 154 insertions(+), 4 deletions(-) + +--- a/drivers/thermal/airoha_thermal.c ++++ b/drivers/thermal/airoha_thermal.c +@@ -18,6 +18,12 @@ + #define EN7581_DOUT_TADC 0x2f8 + #define EN7581_DOUT_TADC_MASK GENMASK(15, 0) + ++#define AN7583_MUX_SENSOR 0x2a0 ++#define AN7583_LOAD_ADJ GENMASK(3, 2) ++#define AN7583_MUX_TADC 0x2e4 ++#define AN7583_MUX_TADC_MASK GENMASK(3, 1) ++#define AN7583_DOUT_TADC 0x2f0 ++ + /* PTP_THERMAL regs */ + #define EN7581_TEMPMONCTL0 0x800 + #define EN7581_SENSE3_EN BIT(3) +@@ -181,6 +187,11 @@ + #define EN7581_SCU_THERMAL_PROTECT_KEY 0x12 + #define EN7581_SCU_THERMAL_MUX_DIODE1 0x7 + ++#define AN7583_SCU_THERMAL_PROTECT_KEY 0x80 ++#define AN7583_NUM_SENSOR 3 ++ ++#define AIROHA_THERMAL_NO_MUX_SENSOR -1 ++ + /* Convert temp to raw value as read from ADC ((((temp / 100) - init) * slope) / 1000) + offset */ + #define TEMP_TO_RAW(priv, temp) ((((((temp) / 100) - (priv)->init_temp) * \ + (priv)->default_slope) / 1000) + \ +@@ -193,8 +204,39 @@ + + #define AIROHA_MAX_SAMPLES 6 + ++/* ++ * AN7583 supports all these ADC mux but the original driver ++ * always checked temp with the AN7583_BGP_TEMP_SENSOR. ++ * Assume using the other sensor temperature is invalid and ++ * always read from AN7583_BGP_TEMP_SENSOR. ++ * ++ * On top of this it's defined that AN7583 supports 3 ++ * sensor: AN7583_BGP_TEMP_SENSOR, AN7583_GBE_TEMP_SENSOR, ++ * AN7583_CPU_TEMP_SENSOR. ++ * ++ * Provide the ADC mux for reference. ++ */ ++enum an7583_thermal_adc_mux { ++ AN7583_BGP_TEMP_SENSOR, ++ AN7583_PAD_AVS, ++ AN7583_CORE_POWER, ++ AN7583_AVSDAC_OUT, ++ AN7583_VCM, ++ AN7583_GBE_TEMP_SENSOR, ++ AN7583_CPU_TEMP_SENSOR, ++ ++ AN7583_ADC_MUX_MAX, ++}; ++ ++enum an7583_thermal_diode_mux { ++ AN7583_D0_TADC, ++ AN7583_ZERO_TADC, ++ AN7583_D1_TADC, ++}; ++ + enum airoha_thermal_chip_scu_field { + AIROHA_THERMAL_DOUT_TADC, ++ AIROHA_THERMAL_MUX_SENSOR, + AIROHA_THERMAL_MUX_TADC, + + /* keep last */ +@@ -208,6 +250,7 @@ struct airoha_thermal_priv { + struct resource scu_adc_res; + + u32 pllrg_protect; ++ int current_adc; + + struct thermal_zone_device *tz; + int init_temp; +@@ -224,6 +267,24 @@ struct airoha_thermal_soc_data { + int (*post_probe)(struct platform_device *pdev); + }; + ++static const unsigned int an7583_thermal_coeff[AN7583_ADC_MUX_MAX] = { ++ [AN7583_BGP_TEMP_SENSOR] = 973, ++ [AN7583_GBE_TEMP_SENSOR] = 995, ++ [AN7583_CPU_TEMP_SENSOR] = 1035, ++}; ++ ++static const unsigned int an7583_thermal_slope[AN7583_ADC_MUX_MAX] = { ++ [AN7583_BGP_TEMP_SENSOR] = 7440, ++ [AN7583_GBE_TEMP_SENSOR] = 7620, ++ [AN7583_CPU_TEMP_SENSOR] = 8390, ++}; ++ ++static const unsigned int an7583_thermal_offset[AN7583_ADC_MUX_MAX] = { ++ [AN7583_BGP_TEMP_SENSOR] = 294, ++ [AN7583_GBE_TEMP_SENSOR] = 298, ++ [AN7583_CPU_TEMP_SENSOR] = 344, ++}; ++ + static int airoha_get_thermal_ADC(struct airoha_thermal_priv *priv) + { + u32 val; +@@ -234,7 +295,7 @@ static int airoha_get_thermal_ADC(struct + } + + static void airoha_set_thermal_mux(struct airoha_thermal_priv *priv, +- int tdac_idx) ++ int tdac_idx, int sensor_idx) + { + u32 pllrg; + +@@ -245,9 +306,20 @@ static void airoha_set_thermal_mux(struc + regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT, + priv->pllrg_protect); + ++ /* ++ * Configure Thermal Sensor mux to sensor_idx. ++ * (if not supported, sensor_idx is AIROHA_THERMAL_NO_MUX_SENSOR) ++ */ ++ if (sensor_idx != AIROHA_THERMAL_NO_MUX_SENSOR) ++ regmap_field_write(priv->chip_scu_fields[AIROHA_THERMAL_MUX_SENSOR], ++ sensor_idx); ++ + /* Configure Thermal ADC mux to tdac_idx */ +- regmap_field_write(priv->chip_scu_fields[AIROHA_THERMAL_MUX_TADC], +- tdac_idx); ++ if (priv->current_adc != tdac_idx) { ++ regmap_field_write(priv->chip_scu_fields[AIROHA_THERMAL_MUX_TADC], ++ tdac_idx); ++ priv->current_adc = tdac_idx; ++ } + + /* Sleep 10 ms for Thermal ADC to enable */ + usleep_range(10 * USEC_PER_MSEC, 11 * USEC_PER_MSEC); +@@ -360,7 +432,8 @@ static void en7581_thermal_setup_adc_val + u32 efuse_calib_info, cpu_sensor; + + /* Setup Thermal Sensor to ADC mode and setup the mux to DIODE1 */ +- airoha_set_thermal_mux(priv, EN7581_SCU_THERMAL_MUX_DIODE1); ++ airoha_set_thermal_mux(priv, EN7581_SCU_THERMAL_MUX_DIODE1, ++ AIROHA_THERMAL_NO_MUX_SENSOR); + + regmap_read(priv->map, EN7581_EFUSE_TEMP_OFFSET_REG, &efuse_calib_info); + if (efuse_calib_info) { +@@ -476,6 +549,10 @@ static int en7581_thermal_probe(struct p + for (i = 0; i < AIROHA_THERMAL_FIELD_MAX; i++) { + struct regmap_field *field; + ++ /* Skip registering MUX_SENSOR field as not supported */ ++ if (i == AIROHA_THERMAL_MUX_SENSOR) ++ continue; ++ + field = devm_regmap_field_alloc(dev, priv->chip_scu, + en7581_chip_scu_fields[i]); + if (IS_ERR(field)) +@@ -516,6 +593,71 @@ static int en7581_thermal_post_probe(str + return 0; + } + ++static int an7583_thermal_get_temp(struct thermal_zone_device *tz, int *temp) ++{ ++ struct airoha_thermal_priv *priv = thermal_zone_device_priv(tz); ++ int sensor_idx; ++ int delta_diode, delta_gain; ++ int coeff, slope, offset; ++ ++ int diode_zero, diode_d0, diode_d1; ++ ++ /* Always read sensor AN7583_BGP_TEMP_SENSOR */ ++ sensor_idx = AN7583_BGP_TEMP_SENSOR; ++ ++ coeff = an7583_thermal_coeff[sensor_idx]; ++ slope = an7583_thermal_slope[sensor_idx]; ++ offset = an7583_thermal_offset[sensor_idx]; ++ ++ airoha_set_thermal_mux(priv, sensor_idx, AN7583_ZERO_TADC); ++ diode_zero = airoha_get_thermal_ADC(priv); ++ airoha_set_thermal_mux(priv, sensor_idx, AN7583_D0_TADC); ++ diode_d0 = airoha_get_thermal_ADC(priv); ++ airoha_set_thermal_mux(priv, sensor_idx, AN7583_D1_TADC); ++ diode_d1 = airoha_get_thermal_ADC(priv); ++ ++ delta_diode = diode_d1 - diode_d0; ++ delta_gain = (delta_diode * coeff) / 100 + (diode_zero - diode_d1); ++ *temp = (slope * delta_diode * 10) / delta_gain - offset * 10; ++ *temp *= 100; ++ ++ return 0; ++} ++ ++static const struct thermal_zone_device_ops an7583_tz_ops = { ++ .get_temp = an7583_thermal_get_temp, ++}; ++ ++static const struct reg_field an7583_chip_scu_fields[AIROHA_THERMAL_FIELD_MAX] = { ++ [AIROHA_THERMAL_DOUT_TADC] = REG_FIELD(AN7583_DOUT_TADC, 0, 31), ++ [AIROHA_THERMAL_MUX_TADC] = REG_FIELD(AN7583_MUX_TADC, 1, 3), ++ [AIROHA_THERMAL_MUX_SENSOR] = REG_FIELD(AN7583_MUX_SENSOR, 2, 3), ++}; ++ ++static int an7583_thermal_probe(struct platform_device *pdev, ++ struct airoha_thermal_priv *priv) ++{ ++ struct device *dev = &pdev->dev; ++ int i; ++ ++ priv->chip_scu = device_node_to_regmap(dev->parent->of_node); ++ if (IS_ERR(priv->map)) ++ return PTR_ERR(priv->map); ++ ++ for (i = 0; i < AIROHA_THERMAL_FIELD_MAX; i++) { ++ struct regmap_field *field; ++ ++ field = devm_regmap_field_alloc(dev, priv->chip_scu, ++ an7583_chip_scu_fields[i]); ++ if (IS_ERR(field)) ++ return PTR_ERR(field); ++ ++ priv->chip_scu_fields[i] = field; ++ } ++ ++ return 0; ++} ++ + static int airoha_thermal_probe(struct platform_device *pdev) + { + const struct airoha_thermal_soc_data *soc_data; +@@ -530,6 +672,7 @@ static int airoha_thermal_probe(struct p + return -ENOMEM; + + priv->pllrg_protect = soc_data->pllrg_protect; ++ priv->current_adc = -1; + + if (!soc_data->probe) + return -EINVAL; +@@ -558,8 +701,15 @@ static const struct airoha_thermal_soc_d + .post_probe = &en7581_thermal_post_probe, + }; + ++static const struct airoha_thermal_soc_data an7583_data = { ++ .pllrg_protect = AN7583_SCU_THERMAL_PROTECT_KEY, ++ .thdev_ops = &an7583_tz_ops, ++ .probe = &an7583_thermal_probe, ++}; ++ + static const struct of_device_id airoha_thermal_match[] = { + { .compatible = "airoha,en7581-thermal", .data = &en7581_data }, ++ { .compatible = "airoha,an7583-thermal", .data = &an7583_data }, + {}, + }; + MODULE_DEVICE_TABLE(of, airoha_thermal_match); diff --git a/lede/target/linux/airoha/patches-6.12/403-cpufreq-airoha-Add-support-for-AN7583-SoC.patch b/lede/target/linux/airoha/patches-6.12/403-cpufreq-airoha-Add-support-for-AN7583-SoC.patch new file mode 100644 index 0000000000..3c076b4173 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/403-cpufreq-airoha-Add-support-for-AN7583-SoC.patch @@ -0,0 +1,35 @@ +From 8a38220c6bf6d79ecb1c95b083e062bd7221dea9 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sat, 9 Aug 2025 13:24:57 +0200 +Subject: [PATCH] cpufreq: airoha: Add support for AN7583 SoC + +New Airoha AN7583 SoC use the same exact logic to control the CPU +frequency. Add the Device compatible to the block list for +cpufreq-dt-plat and to the Airoha CPUFreq driver compatible list. + +Signed-off-by: Christian Marangi +--- + drivers/cpufreq/airoha-cpufreq.c | 1 + + drivers/cpufreq/cpufreq-dt-platdev.c | 1 + + 2 files changed, 2 insertions(+) + +--- a/drivers/cpufreq/airoha-cpufreq.c ++++ b/drivers/cpufreq/airoha-cpufreq.c +@@ -121,6 +121,7 @@ static struct platform_driver airoha_cpu + }; + + static const struct of_device_id airoha_cpufreq_match_list[] __initconst = { ++ { .compatible = "airoha,an7583" }, + { .compatible = "airoha,en7581" }, + {}, + }; +--- a/drivers/cpufreq/cpufreq-dt-platdev.c ++++ b/drivers/cpufreq/cpufreq-dt-platdev.c +@@ -103,6 +103,7 @@ static const struct of_device_id allowli + * platforms using "operating-points-v2" property. + */ + static const struct of_device_id blocklist[] __initconst = { ++ { .compatible = "airoha,an7583", }, + { .compatible = "airoha,en7581", }, + + { .compatible = "allwinner,sun50i-h6", }, diff --git a/lede/target/linux/airoha/patches-6.12/600-01-clk-en7523-convert-driver-to-regmap-API.patch b/lede/target/linux/airoha/patches-6.12/600-01-clk-en7523-convert-driver-to-regmap-API.patch new file mode 100644 index 0000000000..85bd2c214e --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/600-01-clk-en7523-convert-driver-to-regmap-API.patch @@ -0,0 +1,351 @@ +From 8d5a00b3b83f76d255bcffc91d5263f72b27547a Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Fri, 7 Feb 2025 23:51:23 +0100 +Subject: [PATCH 01/10] clk: en7523: convert driver to regmap API + +Convert driver to regmap API, in preparation for support of Airoha +AN7523 as the SCU will be an MFD and the regmap will be provided in the +parent node. + +Signed-off-by: Christian Marangi +--- + drivers/clk/clk-en7523.c | 137 ++++++++++++++++++++++----------------- + 1 file changed, 76 insertions(+), 61 deletions(-) + +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -1,5 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0-only + ++#include + #include + #include + #include +@@ -34,6 +35,7 @@ + #define REG_RESET_CONTROL_PCIE2 BIT(26) + /* EN7581 */ + #define REG_NP_SCU_PCIC 0x88 ++#define REG_PCIE_CTRL GENMASK(7, 0) + #define REG_NP_SCU_SSTR 0x9c + #define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13) + #define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11) +@@ -63,14 +65,14 @@ struct en_clk_desc { + }; + + struct en_clk_gate { +- void __iomem *base; ++ struct regmap *map; + struct clk_hw hw; + }; + + struct en_rst_data { + const u16 *bank_ofs; + const u16 *idx_map; +- void __iomem *base; ++ struct regmap *map; + struct reset_controller_dev rcdev; + }; + +@@ -388,44 +390,44 @@ static u32 en7523_get_div(const struct e + static int en7523_pci_is_enabled(struct clk_hw *hw) + { + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); ++ u32 val; + +- return !!(readl(cg->base + REG_PCI_CONTROL) & REG_PCI_CONTROL_REFCLK_EN1); ++ regmap_read(cg->map, REG_PCI_CONTROL, &val); ++ return !!(val & REG_PCI_CONTROL_REFCLK_EN1); + } + + static int en7523_pci_prepare(struct clk_hw *hw) + { + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); +- void __iomem *np_base = cg->base; +- u32 val, mask; ++ struct regmap *map = cg->map; ++ u32 mask; + + /* Need to pull device low before reset */ +- val = readl(np_base + REG_PCI_CONTROL); +- val &= ~(REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT); +- writel(val, np_base + REG_PCI_CONTROL); ++ regmap_clear_bits(map, REG_PCI_CONTROL, ++ REG_PCI_CONTROL_PERSTOUT1 | ++ REG_PCI_CONTROL_PERSTOUT); + usleep_range(1000, 2000); + + /* Enable PCIe port 1 */ +- val |= REG_PCI_CONTROL_REFCLK_EN1; +- writel(val, np_base + REG_PCI_CONTROL); ++ regmap_set_bits(map, REG_PCI_CONTROL, ++ REG_PCI_CONTROL_REFCLK_EN1); + usleep_range(1000, 2000); + + /* Reset to default */ +- val = readl(np_base + REG_RESET_CONTROL1); + mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 | + REG_RESET_CONTROL_PCIEHB; +- writel(val & ~mask, np_base + REG_RESET_CONTROL1); ++ regmap_clear_bits(map, REG_RESET_CONTROL1, mask); + usleep_range(1000, 2000); +- writel(val | mask, np_base + REG_RESET_CONTROL1); ++ regmap_set_bits(map, REG_RESET_CONTROL1, mask); + msleep(100); +- writel(val & ~mask, np_base + REG_RESET_CONTROL1); ++ regmap_clear_bits(map, REG_RESET_CONTROL1, mask); + usleep_range(5000, 10000); + + /* Release device */ + mask = REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT; +- val = readl(np_base + REG_PCI_CONTROL); +- writel(val & ~mask, np_base + REG_PCI_CONTROL); ++ regmap_clear_bits(map, REG_PCI_CONTROL, mask); + usleep_range(1000, 2000); +- writel(val | mask, np_base + REG_PCI_CONTROL); ++ regmap_set_bits(map, REG_PCI_CONTROL, mask); + msleep(250); + + return 0; +@@ -434,16 +436,13 @@ static int en7523_pci_prepare(struct clk + static void en7523_pci_unprepare(struct clk_hw *hw) + { + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); +- void __iomem *np_base = cg->base; +- u32 val; ++ struct regmap *map = cg->map; + +- val = readl(np_base + REG_PCI_CONTROL); +- val &= ~REG_PCI_CONTROL_REFCLK_EN1; +- writel(val, np_base + REG_PCI_CONTROL); ++ regmap_clear_bits(map, REG_PCI_CONTROL, REG_PCI_CONTROL_REFCLK_EN1); + } + + static struct clk_hw *en7523_register_pcie_clk(struct device *dev, +- void __iomem *np_base) ++ struct regmap *clk_map) + { + const struct en_clk_soc_data *soc_data = device_get_match_data(dev); + struct clk_init_data init = { +@@ -456,7 +455,7 @@ static struct clk_hw *en7523_register_pc + if (!cg) + return NULL; + +- cg->base = np_base; ++ cg->map = clk_map; + cg->hw.init = &init; + + if (init.ops->unprepare) +@@ -474,21 +473,20 @@ static int en7581_pci_is_enabled(struct + u32 val, mask; + + mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1; +- val = readl(cg->base + REG_PCI_CONTROL); ++ regmap_read(cg->map, REG_PCI_CONTROL, &val); + return (val & mask) == mask; + } + + static int en7581_pci_enable(struct clk_hw *hw) + { + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); +- void __iomem *np_base = cg->base; +- u32 val, mask; ++ struct regmap *map = cg->map; ++ u32 mask; + + mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 | + REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 | + REG_PCI_CONTROL_PERSTOUT; +- val = readl(np_base + REG_PCI_CONTROL); +- writel(val | mask, np_base + REG_PCI_CONTROL); ++ regmap_set_bits(map, REG_PCI_CONTROL, mask); + + return 0; + } +@@ -496,19 +494,18 @@ static int en7581_pci_enable(struct clk_ + static void en7581_pci_disable(struct clk_hw *hw) + { + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); +- void __iomem *np_base = cg->base; +- u32 val, mask; ++ struct regmap *map = cg->map; ++ u32 mask; + + mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 | + REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 | + REG_PCI_CONTROL_PERSTOUT; +- val = readl(np_base + REG_PCI_CONTROL); +- writel(val & ~mask, np_base + REG_PCI_CONTROL); ++ regmap_clear_bits(map, REG_PCI_CONTROL, mask); + usleep_range(1000, 2000); + } + + static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data, +- void __iomem *base, void __iomem *np_base) ++ struct regmap *map, struct regmap *clk_map) + { + struct clk_hw *hw; + u32 rate; +@@ -517,10 +514,12 @@ static void en7523_register_clocks(struc + for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) { + const struct en_clk_desc *desc = &en7523_base_clks[i]; + u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg; +- u32 val = readl(base + desc->base_reg); ++ u32 val; ++ ++ regmap_read(map, desc->base_reg, &val); + + rate = en7523_get_base_rate(desc, val); +- val = readl(base + reg); ++ regmap_read(map, reg, &val); + rate /= en7523_get_div(desc, val); + + hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate); +@@ -533,30 +532,47 @@ static void en7523_register_clocks(struc + clk_data->hws[desc->id] = hw; + } + +- hw = en7523_register_pcie_clk(dev, np_base); ++ hw = en7523_register_pcie_clk(dev, clk_map); + clk_data->hws[EN7523_CLK_PCIE] = hw; + } + ++static const struct regmap_config en7523_clk_regmap_config = { ++ .reg_bits = 32, ++ .val_bits = 32, ++ .reg_stride = 4, ++}; ++ + static int en7523_clk_hw_init(struct platform_device *pdev, + struct clk_hw_onecell_data *clk_data) + { + void __iomem *base, *np_base; ++ struct regmap *map, *clk_map; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + ++ map = devm_regmap_init_mmio(&pdev->dev, base, ++ &en7523_clk_regmap_config); ++ if (IS_ERR(map)) ++ return PTR_ERR(map); ++ + np_base = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(np_base)) + return PTR_ERR(np_base); + +- en7523_register_clocks(&pdev->dev, clk_data, base, np_base); ++ clk_map = devm_regmap_init_mmio(&pdev->dev, np_base, ++ &en7523_clk_regmap_config); ++ if (IS_ERR(clk_map)) ++ return PTR_ERR(clk_map); ++ ++ en7523_register_clocks(&pdev->dev, clk_data, map, clk_map); + + return 0; + } + + static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data, +- struct regmap *map, void __iomem *base) ++ struct regmap *map, struct regmap *clk_map) + { + struct clk_hw *hw; + u32 rate; +@@ -593,7 +609,7 @@ static void en7581_register_clocks(struc + clk_data->hws[desc->id] = hw; + } + +- hw = en7523_register_pcie_clk(dev, base); ++ hw = en7523_register_pcie_clk(dev, clk_map); + clk_data->hws[EN7523_CLK_PCIE] = hw; + } + +@@ -601,15 +617,10 @@ static int en7523_reset_update(struct re + unsigned long id, bool assert) + { + struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev); +- void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK]; +- u32 val; ++ u32 addr = rst_data->bank_ofs[id / RST_NR_PER_BANK]; + +- val = readl(addr); +- if (assert) +- val |= BIT(id % RST_NR_PER_BANK); +- else +- val &= ~BIT(id % RST_NR_PER_BANK); +- writel(val, addr); ++ regmap_update_bits(rst_data->map, addr, BIT(id % RST_NR_PER_BANK), ++ assert ? BIT(id % RST_NR_PER_BANK) : 0); + + return 0; + } +@@ -630,9 +641,11 @@ static int en7523_reset_status(struct re + unsigned long id) + { + struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev); +- void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK]; ++ u32 addr = rst_data->bank_ofs[id / RST_NR_PER_BANK]; ++ u32 val; + +- return !!(readl(addr) & BIT(id % RST_NR_PER_BANK)); ++ regmap_read(rst_data->map, addr, &val); ++ return !!(val & BIT(id % RST_NR_PER_BANK)); + } + + static int en7523_reset_xlate(struct reset_controller_dev *rcdev, +@@ -652,7 +665,7 @@ static const struct reset_control_ops en + .status = en7523_reset_status, + }; + +-static int en7581_reset_register(struct device *dev, void __iomem *base) ++static int en7581_reset_register(struct device *dev, struct regmap *map) + { + struct en_rst_data *rst_data; + +@@ -662,7 +675,7 @@ static int en7581_reset_register(struct + + rst_data->bank_ofs = en7581_rst_ofs; + rst_data->idx_map = en7581_rst_map; +- rst_data->base = base; ++ rst_data->map = map; + + rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map); + rst_data->rcdev.of_xlate = en7523_reset_xlate; +@@ -678,9 +691,8 @@ static int en7581_reset_register(struct + static int en7581_clk_hw_init(struct platform_device *pdev, + struct clk_hw_onecell_data *clk_data) + { +- struct regmap *map; ++ struct regmap *map, *clk_map; + void __iomem *base; +- u32 val; + + map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); + if (IS_ERR(map)) +@@ -690,15 +702,18 @@ static int en7581_clk_hw_init(struct pla + if (IS_ERR(base)) + return PTR_ERR(base); + +- en7581_register_clocks(&pdev->dev, clk_data, map, base); +- +- val = readl(base + REG_NP_SCU_SSTR); +- val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); +- writel(val, base + REG_NP_SCU_SSTR); +- val = readl(base + REG_NP_SCU_PCIC); +- writel(val | 3, base + REG_NP_SCU_PCIC); ++ clk_map = devm_regmap_init_mmio(&pdev->dev, base, &en7523_clk_regmap_config); ++ if (IS_ERR(clk_map)) ++ return PTR_ERR(clk_map); ++ ++ en7581_register_clocks(&pdev->dev, clk_data, map, clk_map); ++ ++ regmap_clear_bits(clk_map, REG_NP_SCU_SSTR, ++ REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); ++ regmap_update_bits(clk_map, REG_NP_SCU_PCIC, REG_PCIE_CTRL, ++ FIELD_PREP(REG_PCIE_CTRL, 3)); + +- return en7581_reset_register(&pdev->dev, base); ++ return en7581_reset_register(&pdev->dev, clk_map); + } + + static int en7523_clk_probe(struct platform_device *pdev) diff --git a/lede/target/linux/airoha/patches-6.12/600-02-clk-en7523-generalize-register-clocks-function.patch b/lede/target/linux/airoha/patches-6.12/600-02-clk-en7523-generalize-register-clocks-function.patch new file mode 100644 index 0000000000..b8d892ffb4 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/600-02-clk-en7523-generalize-register-clocks-function.patch @@ -0,0 +1,258 @@ +From 36a3a919391dea2000f355125f0a161c453fcf78 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sat, 8 Feb 2025 00:08:08 +0100 +Subject: [PATCH 02/10] clk: en7523: generalize register clocks function + +Generalize register clocks function for Airoha EN7523 and EN7581 clocks +driver. The same logic is applied for both clock hence code can be +reduced and simplified by putting the base_clocks struct in the soc_data +and passing that to a generic register clocks function. + +While at it rework some function to return error and use devm variant +for clk_hw_regiser. + +Signed-off-by: Christian Marangi +--- + drivers/clk/clk-en7523.c | 148 +++++++++++++++++---------------------- + 1 file changed, 66 insertions(+), 82 deletions(-) + +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -78,8 +78,10 @@ struct en_rst_data { + + struct en_clk_soc_data { + u32 num_clocks; ++ const struct en_clk_desc *base_clks; + const struct clk_ops pcie_ops; + int (*hw_init)(struct platform_device *pdev, ++ const struct en_clk_soc_data *soc_data, + struct clk_hw_onecell_data *clk_data); + }; + +@@ -450,10 +452,11 @@ static struct clk_hw *en7523_register_pc + .ops = &soc_data->pcie_ops, + }; + struct en_clk_gate *cg; ++ int err; + + cg = devm_kzalloc(dev, sizeof(*cg), GFP_KERNEL); + if (!cg) +- return NULL; ++ return ERR_PTR(-ENOMEM); + + cg->map = clk_map; + cg->hw.init = &init; +@@ -461,12 +464,62 @@ static struct clk_hw *en7523_register_pc + if (init.ops->unprepare) + init.ops->unprepare(&cg->hw); + +- if (clk_hw_register(dev, &cg->hw)) +- return NULL; ++ err = devm_clk_hw_register(dev, &cg->hw); ++ if (err) ++ return ERR_PTR(err); + + return &cg->hw; + } + ++static int en75xx_register_clocks(struct device *dev, ++ const struct en_clk_soc_data *soc_data, ++ struct clk_hw_onecell_data *clk_data, ++ struct regmap *map, struct regmap *clk_map) ++{ ++ struct clk_hw *hw; ++ u32 rate; ++ int i; ++ ++ for (i = 0; i < soc_data->num_clocks - 1; i++) { ++ const struct en_clk_desc *desc = &soc_data->base_clks[i]; ++ u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg; ++ int err; ++ ++ err = regmap_read(map, desc->base_reg, &val); ++ if (err) { ++ pr_err("Failed reading fixed clk rate %s: %d\n", ++ desc->name, err); ++ return err; ++ } ++ rate = en7523_get_base_rate(desc, val); ++ ++ err = regmap_read(map, reg, &val); ++ if (err) { ++ pr_err("Failed reading fixed clk div %s: %d\n", ++ desc->name, err); ++ return err; ++ } ++ rate /= en7523_get_div(desc, val); ++ ++ hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate); ++ if (IS_ERR(hw)) { ++ pr_err("Failed to register clk %s: %ld\n", ++ desc->name, PTR_ERR(hw)); ++ return PTR_ERR(hw); ++ } ++ ++ clk_data->hws[desc->id] = hw; ++ } ++ ++ hw = en7523_register_pcie_clk(dev, clk_map); ++ if (IS_ERR(hw)) ++ return PTR_ERR(hw); ++ ++ clk_data->hws[EN7523_CLK_PCIE] = hw; ++ ++ return 0; ++} ++ + static int en7581_pci_is_enabled(struct clk_hw *hw) + { + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); +@@ -504,38 +557,6 @@ static void en7581_pci_disable(struct cl + usleep_range(1000, 2000); + } + +-static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data, +- struct regmap *map, struct regmap *clk_map) +-{ +- struct clk_hw *hw; +- u32 rate; +- int i; +- +- for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) { +- const struct en_clk_desc *desc = &en7523_base_clks[i]; +- u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg; +- u32 val; +- +- regmap_read(map, desc->base_reg, &val); +- +- rate = en7523_get_base_rate(desc, val); +- regmap_read(map, reg, &val); +- rate /= en7523_get_div(desc, val); +- +- hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate); +- if (IS_ERR(hw)) { +- pr_err("Failed to register clk %s: %ld\n", +- desc->name, PTR_ERR(hw)); +- continue; +- } +- +- clk_data->hws[desc->id] = hw; +- } +- +- hw = en7523_register_pcie_clk(dev, clk_map); +- clk_data->hws[EN7523_CLK_PCIE] = hw; +-} +- + static const struct regmap_config en7523_clk_regmap_config = { + .reg_bits = 32, + .val_bits = 32, +@@ -543,6 +564,7 @@ static const struct regmap_config en7523 + }; + + static int en7523_clk_hw_init(struct platform_device *pdev, ++ const struct en_clk_soc_data *soc_data, + struct clk_hw_onecell_data *clk_data) + { + void __iomem *base, *np_base; +@@ -566,51 +588,7 @@ static int en7523_clk_hw_init(struct pla + if (IS_ERR(clk_map)) + return PTR_ERR(clk_map); + +- en7523_register_clocks(&pdev->dev, clk_data, map, clk_map); +- +- return 0; +-} +- +-static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data, +- struct regmap *map, struct regmap *clk_map) +-{ +- struct clk_hw *hw; +- u32 rate; +- int i; +- +- for (i = 0; i < ARRAY_SIZE(en7581_base_clks); i++) { +- const struct en_clk_desc *desc = &en7581_base_clks[i]; +- u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg; +- int err; +- +- err = regmap_read(map, desc->base_reg, &val); +- if (err) { +- pr_err("Failed reading fixed clk rate %s: %d\n", +- desc->name, err); +- continue; +- } +- rate = en7523_get_base_rate(desc, val); +- +- err = regmap_read(map, reg, &val); +- if (err) { +- pr_err("Failed reading fixed clk div %s: %d\n", +- desc->name, err); +- continue; +- } +- rate /= en7523_get_div(desc, val); +- +- hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate); +- if (IS_ERR(hw)) { +- pr_err("Failed to register clk %s: %ld\n", +- desc->name, PTR_ERR(hw)); +- continue; +- } +- +- clk_data->hws[desc->id] = hw; +- } +- +- hw = en7523_register_pcie_clk(dev, clk_map); +- clk_data->hws[EN7523_CLK_PCIE] = hw; ++ return en75xx_register_clocks(&pdev->dev, soc_data, clk_data, map, clk_map); + } + + static int en7523_reset_update(struct reset_controller_dev *rcdev, +@@ -689,10 +667,12 @@ static int en7581_reset_register(struct + } + + static int en7581_clk_hw_init(struct platform_device *pdev, ++ const struct en_clk_soc_data *soc_data, + struct clk_hw_onecell_data *clk_data) + { + struct regmap *map, *clk_map; + void __iomem *base; ++ int ret; + + map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); + if (IS_ERR(map)) +@@ -706,7 +686,9 @@ static int en7581_clk_hw_init(struct pla + if (IS_ERR(clk_map)) + return PTR_ERR(clk_map); + +- en7581_register_clocks(&pdev->dev, clk_data, map, clk_map); ++ ret = en75xx_register_clocks(&pdev->dev, soc_data, clk_data, map, clk_map); ++ if (ret) ++ return ret; + + regmap_clear_bits(clk_map, REG_NP_SCU_SSTR, + REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); +@@ -732,7 +714,7 @@ static int en7523_clk_probe(struct platf + return -ENOMEM; + + clk_data->num = soc_data->num_clocks; +- r = soc_data->hw_init(pdev, clk_data); ++ r = soc_data->hw_init(pdev, soc_data, clk_data); + if (r) + return r; + +@@ -740,6 +722,7 @@ static int en7523_clk_probe(struct platf + } + + static const struct en_clk_soc_data en7523_data = { ++ .base_clks = en7523_base_clks, + .num_clocks = ARRAY_SIZE(en7523_base_clks) + 1, + .pcie_ops = { + .is_enabled = en7523_pci_is_enabled, +@@ -750,6 +733,7 @@ static const struct en_clk_soc_data en75 + }; + + static const struct en_clk_soc_data en7581_data = { ++ .base_clks = en7581_base_clks, + /* We increment num_clocks by 1 to account for additional PCIe clock */ + .num_clocks = ARRAY_SIZE(en7581_base_clks) + 1, + .pcie_ops = { diff --git a/lede/target/linux/airoha/patches-6.12/600-03-clk-en7523-convert-to-full-clk_hw-implementation.patch b/lede/target/linux/airoha/patches-6.12/600-03-clk-en7523-convert-to-full-clk_hw-implementation.patch new file mode 100644 index 0000000000..31b5bce636 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/600-03-clk-en7523-convert-to-full-clk_hw-implementation.patch @@ -0,0 +1,147 @@ +From 933030fd268ac111eb9db13b5a90b7c66cd9df41 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 17 Jun 2025 11:38:21 +0200 +Subject: [PATCH 03/10] clk: en7523: convert to full clk_hw implementation + +In preparation for support of .set_rate, convert the clock register +logic from fixed clock implementation to full clk_hw implementation with +dedicated OPs. + +This is just a rework and no behaviour change is expected. + +Signed-off-by: Christian Marangi +--- + drivers/clk/clk-en7523.c | 83 ++++++++++++++++++++++++++++------------ + 1 file changed, 59 insertions(+), 24 deletions(-) + +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -69,6 +69,12 @@ struct en_clk_gate { + struct clk_hw hw; + }; + ++struct en_clk { ++ struct regmap *map; ++ const struct en_clk_desc *desc; ++ struct clk_hw hw; ++}; ++ + struct en_rst_data { + const u16 *bank_ofs; + const u16 *idx_map; +@@ -471,44 +477,73 @@ static struct clk_hw *en7523_register_pc + return &cg->hw; + } + ++static unsigned long en75xx_recalc_rate(struct clk_hw *hw, ++ unsigned long parent_rate) ++{ ++ struct en_clk *c = container_of(hw, struct en_clk, hw); ++ const struct en_clk_desc *desc = c->desc; ++ struct regmap *map = c->map; ++ u32 val, reg; ++ u32 rate; ++ int err; ++ ++ err = regmap_read(map, desc->base_reg, &val); ++ if (err) { ++ pr_err("Failed reading fixed clk rate %s: %d\n", ++ desc->name, err); ++ return err; ++ } ++ rate = en7523_get_base_rate(desc, val); ++ ++ reg = desc->div_reg ? desc->div_reg : desc->base_reg; ++ err = regmap_read(map, reg, &val); ++ if (err) { ++ pr_err("Failed reading fixed clk div %s: %d\n", ++ desc->name, err); ++ return err; ++ } ++ ++ return rate / en7523_get_div(desc, val); ++} ++ ++static const struct clk_ops en75xx_clk_ops = { ++ .recalc_rate = en75xx_recalc_rate, ++}; ++ + static int en75xx_register_clocks(struct device *dev, + const struct en_clk_soc_data *soc_data, + struct clk_hw_onecell_data *clk_data, + struct regmap *map, struct regmap *clk_map) + { + struct clk_hw *hw; +- u32 rate; + int i; + + for (i = 0; i < soc_data->num_clocks - 1; i++) { + const struct en_clk_desc *desc = &soc_data->base_clks[i]; +- u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg; ++ struct clk_init_data init = { ++ .ops = &en75xx_clk_ops, ++ }; ++ struct en_clk *en_clk; + int err; + +- err = regmap_read(map, desc->base_reg, &val); +- if (err) { +- pr_err("Failed reading fixed clk rate %s: %d\n", +- desc->name, err); +- return err; +- } +- rate = en7523_get_base_rate(desc, val); ++ en_clk = devm_kzalloc(dev, sizeof(*en_clk), GFP_KERNEL); ++ if (!en_clk) ++ return -ENOMEM; + +- err = regmap_read(map, reg, &val); ++ init.name = desc->name; ++ ++ en_clk->map = map; ++ en_clk->desc = desc; ++ en_clk->hw.init = &init; ++ ++ err = devm_clk_hw_register(dev, &en_clk->hw); + if (err) { +- pr_err("Failed reading fixed clk div %s: %d\n", ++ pr_err("Failed to register clk %s: %d\n", + desc->name, err); + return err; + } +- rate /= en7523_get_div(desc, val); +- +- hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate); +- if (IS_ERR(hw)) { +- pr_err("Failed to register clk %s: %ld\n", +- desc->name, PTR_ERR(hw)); +- return PTR_ERR(hw); +- } + +- clk_data->hws[desc->id] = hw; ++ clk_data->hws[desc->id] = &en_clk->hw; + } + + hw = en7523_register_pcie_clk(dev, clk_map); +@@ -672,7 +707,7 @@ static int en7581_clk_hw_init(struct pla + { + struct regmap *map, *clk_map; + void __iomem *base; +- int ret; ++ int err; + + map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); + if (IS_ERR(map)) +@@ -686,9 +721,9 @@ static int en7581_clk_hw_init(struct pla + if (IS_ERR(clk_map)) + return PTR_ERR(clk_map); + +- ret = en75xx_register_clocks(&pdev->dev, soc_data, clk_data, map, clk_map); +- if (ret) +- return ret; ++ err = en75xx_register_clocks(&pdev->dev, soc_data, clk_data, map, clk_map); ++ if (err) ++ return err; + + regmap_clear_bits(clk_map, REG_NP_SCU_SSTR, + REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); diff --git a/lede/target/linux/airoha/patches-6.12/600-04-clk-en7523-add-support-for-.set_rate.patch b/lede/target/linux/airoha/patches-6.12/600-04-clk-en7523-add-support-for-.set_rate.patch new file mode 100644 index 0000000000..fc2656aeb7 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/600-04-clk-en7523-add-support-for-.set_rate.patch @@ -0,0 +1,173 @@ +From fe71e8f734a5c9b808a68b8abaa0156de605df4f Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 17 Jun 2025 12:28:41 +0200 +Subject: [PATCH 04/10] clk: en7523: add support for .set_rate + +Add support for EN7523 driver to configure rate. The SoC expose both +base clock selector and clock divisor hence it's possible to change the +rate. + +This will be especially needed for new SoC AN7583 that require changes +for the MDIO and the eMMC. + +The clock were assumed correctly configured by the bootloader but this +goes against the rule of "kernel should not depend on external +configuration". + +Signed-off-by: Christian Marangi +--- + drivers/clk/clk-en7523.c | 141 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 141 insertions(+) + +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -506,8 +506,149 @@ static unsigned long en75xx_recalc_rate( + return rate / en7523_get_div(desc, val); + } + ++static int en75xx_get_base_val_for_rate(const struct en_clk_desc *desc, ++ int div, unsigned long rate) ++{ ++ int i; ++ ++ /* Single base rate */ ++ if (!desc->base_bits) { ++ if (rate != desc->base_value / div) ++ goto err; ++ ++ return 0; ++ } ++ ++ /* Check every base rate with provided divisor */ ++ for (i = 0; i < desc->n_base_values; i++) ++ if (rate == desc->base_values[i] / div) ++ return i; ++ ++err: ++ return -EINVAL; ++} ++ ++static int en75xx_get_vals_for_rate(const struct en_clk_desc *desc, ++ unsigned long rate, ++ u32 *base_val, u32 *div_val) ++{ ++ int tmp_base_val = 0; ++ int tmp_div_val = 0; ++ ++ if (!desc->base_bits && !desc->div_bits) ++ return -EINVAL; ++ ++ /* Divisor not supported, just search in base rate */ ++ if (!desc->div_bits) { ++ tmp_base_val = en75xx_get_base_val_for_rate(desc, 1, rate); ++ if (tmp_base_val < 0) { ++ pr_err("Invalid rate for clock %s\n", ++ desc->name); ++ return -EINVAL; ++ } ++ ++ goto exit; ++ } ++ ++ /* Check if div0 satisfy the request */ ++ if (desc->div_val0) { ++ tmp_base_val = en75xx_get_base_val_for_rate(desc, ++ desc->div_val0, ++ rate); ++ if (tmp_base_val >= 0) ++ goto exit; ++ ++ /* Skip checking first divisor val */ ++ tmp_div_val = 1; ++ } ++ ++ /* Simulate rate with every divisor supported */ ++ for (; tmp_div_val < BIT(desc->div_bits); tmp_div_val++) { ++ int div = (tmp_div_val + desc->div_offset) * desc->div_step; ++ ++ tmp_base_val = en75xx_get_base_val_for_rate(desc, div, ++ rate); ++ if (tmp_base_val >= 0) ++ goto exit; ++ } ++ ++ if (tmp_div_val == BIT(desc->div_bits)) { ++ pr_err("Invalid rate for clock %s\n", ++ desc->name); ++ return -EINVAL; ++ } ++ ++exit: ++ *base_val = tmp_base_val; ++ *div_val = tmp_div_val; ++ ++ return 0; ++} ++ ++static long en75xx_round_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long *parent_rate) ++{ ++ struct en_clk *en_clk = container_of(hw, struct en_clk, hw); ++ u32 div_val, base_val; ++ int err; ++ ++ /* Just check if the rate is possible */ ++ err = en75xx_get_vals_for_rate(en_clk->desc, rate, ++ &base_val, &div_val); ++ if (err) ++ return err; ++ ++ return rate; ++} ++ ++static int en75xx_set_rate(struct clk_hw *hw, unsigned long rate, ++ unsigned long parent_rate) ++{ ++ struct en_clk *en_clk = container_of(hw, struct en_clk, hw); ++ const struct en_clk_desc *desc = en_clk->desc; ++ struct regmap *map = en_clk->map; ++ u32 base_val, div_val; ++ u32 reg, val, mask; ++ int err; ++ ++ err = en75xx_get_vals_for_rate(en_clk->desc, rate, ++ &base_val, &div_val); ++ if (err) ++ return err; ++ ++ if (desc->div_bits) { ++ reg = desc->div_reg ? desc->div_reg : desc->base_reg; ++ ++ mask = (BIT(desc->div_bits) - 1) << desc->div_shift; ++ val = div_val << desc->div_shift; ++ ++ err = regmap_update_bits(map, reg, mask, val); ++ if (err) { ++ pr_err("Failed to update div reg for clock %s\n", ++ desc->name); ++ return -EINVAL; ++ } ++ } ++ ++ if (desc->base_bits) { ++ mask = (BIT(desc->base_bits) - 1) << desc->base_shift; ++ val = base_val << desc->base_shift; ++ ++ err = regmap_update_bits(map, desc->base_reg, mask, val); ++ if (err) { ++ pr_err("Failed to update reg for clock %s\n", ++ desc->name); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ + static const struct clk_ops en75xx_clk_ops = { + .recalc_rate = en75xx_recalc_rate, ++ .round_rate = en75xx_round_rate, ++ .set_rate = en75xx_set_rate, + }; + + static int en75xx_register_clocks(struct device *dev, diff --git a/lede/target/linux/airoha/patches-6.12/600-05-clk-en7523-permit-to-reference-Chip-SCU-from-phandle.patch b/lede/target/linux/airoha/patches-6.12/600-05-clk-en7523-permit-to-reference-Chip-SCU-from-phandle.patch new file mode 100644 index 0000000000..059d8083cf --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/600-05-clk-en7523-permit-to-reference-Chip-SCU-from-phandle.patch @@ -0,0 +1,37 @@ +From 397a132fb8173a9d728bc7c7a31ff5c0590d076f Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 17 Jun 2025 12:48:35 +0200 +Subject: [PATCH 05/10] clk: en7523: permit to reference Chip SCU from phandle + +In preparation for support of AN7583 and to make Chip SCU reference more +robust, permit to reference the Chip SCU syscon regmap also with the +"airoha,chip-scu" property in DT. + +Legacy implementation is kept by fallbacking in the absence of +"airoha,chip-scu" property. + +Signed-off-by: Christian Marangi +--- + drivers/clk/clk-en7523.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -846,11 +846,16 @@ static int en7581_clk_hw_init(struct pla + const struct en_clk_soc_data *soc_data, + struct clk_hw_onecell_data *clk_data) + { ++ struct device *dev = &pdev->dev; + struct regmap *map, *clk_map; + void __iomem *base; + int err; + +- map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); ++ if (of_property_present(dev->of_node, "airoha,chip-scu")) ++ map = syscon_regmap_lookup_by_phandle(dev->of_node, ++ "airoha,chip-scu"); ++ else ++ map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu"); + if (IS_ERR(map)) + return PTR_ERR(map); + diff --git a/lede/target/linux/airoha/patches-6.12/600-07-clk-en7523-reword-and-clean-clk_probe-variables.patch b/lede/target/linux/airoha/patches-6.12/600-07-clk-en7523-reword-and-clean-clk_probe-variables.patch new file mode 100644 index 0000000000..5de1768f1d --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/600-07-clk-en7523-reword-and-clean-clk_probe-variables.patch @@ -0,0 +1,53 @@ +From d05fc5c8a9ab7bbda80e4fc728902f8d48d3e8aa Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 17 Jun 2025 14:53:56 +0200 +Subject: [PATCH 07/10] clk: en7523: reword and clean clk_probe variables + +Rework and clean en7523_clk_probe variables to make them consistent with +the rest of the source. Also apply some minor cleanup for pdev +variables. + +Signed-off-by: Christian Marangi +--- + drivers/clk/clk-en7523.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -881,25 +881,27 @@ static int en7581_clk_hw_init(struct pla + + static int en7523_clk_probe(struct platform_device *pdev) + { +- struct device_node *node = pdev->dev.of_node; + const struct en_clk_soc_data *soc_data; + struct clk_hw_onecell_data *clk_data; +- int r; ++ struct device *dev = &pdev->dev; ++ int err; + +- soc_data = device_get_match_data(&pdev->dev); ++ soc_data = device_get_match_data(dev); + +- clk_data = devm_kzalloc(&pdev->dev, +- struct_size(clk_data, hws, soc_data->num_clocks), ++ clk_data = devm_kzalloc(dev, ++ struct_size(clk_data, hws, ++ soc_data->num_clocks), + GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + clk_data->num = soc_data->num_clocks; +- r = soc_data->hw_init(pdev, soc_data, clk_data); +- if (r) +- return r; ++ err = soc_data->hw_init(pdev, soc_data, clk_data); ++ if (err) ++ return err; + +- return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); ++ return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, ++ clk_data); + } + + static const struct en_clk_soc_data en7523_data = { diff --git a/lede/target/linux/airoha/patches-6.12/600-08-clk-en7523-add-support-for-probing-SCU-child.patch b/lede/target/linux/airoha/patches-6.12/600-08-clk-en7523-add-support-for-probing-SCU-child.patch new file mode 100644 index 0000000000..4d57996a07 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/600-08-clk-en7523-add-support-for-probing-SCU-child.patch @@ -0,0 +1,57 @@ +From 8f1aea6f4aa61e09eb29b41ff9fffeedd5b2fc0d Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 17 Jun 2025 13:15:19 +0200 +Subject: [PATCH 08/10] clk: en7523: add support for probing SCU child + +On new Airoha SoC in the SCU register space additional pheriperal might +be present aside from the clock/reset. The Airoha AN7583 SoC is an +example of this where 2 MDIO controller are present. + +Introduce a bool "probe_child" to trigger probe of child node of the SCU +node. + +Signed-off-by: Christian Marangi +--- + drivers/clk/clk-en7523.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -5,6 +5,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -83,6 +84,7 @@ struct en_rst_data { + }; + + struct en_clk_soc_data { ++ bool probe_child; + u32 num_clocks; + const struct en_clk_desc *base_clks; + const struct clk_ops pcie_ops; +@@ -900,8 +902,19 @@ static int en7523_clk_probe(struct platf + if (err) + return err; + +- return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, +- clk_data); ++ err = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, ++ clk_data); ++ if (err) ++ return err; ++ ++ if (soc_data->probe_child) { ++ err = of_platform_populate(dev->of_node, NULL, NULL, ++ dev); ++ if (err) ++ return err; ++ } ++ ++ return 0; + } + + static const struct en_clk_soc_data en7523_data = { diff --git a/lede/target/linux/airoha/patches-6.12/600-09-dt-bindings-clock-airoha-Document-support-for-AN7583.patch b/lede/target/linux/airoha/patches-6.12/600-09-dt-bindings-clock-airoha-Document-support-for-AN7583.patch new file mode 100644 index 0000000000..7c3430bb95 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/600-09-dt-bindings-clock-airoha-Document-support-for-AN7583.patch @@ -0,0 +1,122 @@ +From 12838dd20851a6eae67061c5f195f31981a4d8c1 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 28 May 2025 02:39:35 +0200 +Subject: [PATCH 09/10] dt-bindings: clock: airoha: Document support for AN7583 + clock + +Document support for Airoha AN7583 clock. This is based on the EN7523 +clock schema with the new requirement of the "airoha,chip-scu" +(previously optional for EN7581). + +Add additional binding for additional clock and reset lines. + +Signed-off-by: Christian Marangi +--- + .../bindings/clock/airoha,en7523-scu.yaml | 9 +++ + include/dt-bindings/clock/en7523-clk.h | 3 + + .../dt-bindings/reset/airoha,an7583-reset.h | 61 +++++++++++++++++++ + 3 files changed, 73 insertions(+) + create mode 100644 include/dt-bindings/reset/airoha,an7583-reset.h + +# diff --git a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +# index bce77a14c938..be9759b86fdc 100644 +# --- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +# +++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +# @@ -32,6 +32,7 @@ properties: +# - enum: +# - airoha,en7523-scu +# - airoha,en7581-scu +# + - airoha,an7583-scu + +# reg: +# items: +# @@ -82,6 +83,14 @@ allOf: +# reg: +# maxItems: 1 + +# + - if: +# + properties: +# + compatible: +# + const: airoha,an7583-scu +# + then: +# + required: +# + - airoha,chip-scu +# + +# additionalProperties: false + +# examples: +--- a/include/dt-bindings/clock/en7523-clk.h ++++ b/include/dt-bindings/clock/en7523-clk.h +@@ -14,4 +14,7 @@ + + #define EN7581_CLK_EMMC 8 + ++#define AN7583_CLK_MDIO0 9 ++#define AN7583_CLK_MDIO1 10 ++ + #endif /* _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ */ +--- /dev/null ++++ b/include/dt-bindings/reset/airoha,an7583-reset.h +@@ -0,0 +1,62 @@ ++/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ ++/* ++ * Copyright (c) 2024 AIROHA Inc ++ * Author: Christian Marangi ++ */ ++ ++#ifndef __DT_BINDINGS_RESET_CONTROLLER_AIROHA_AN7583_H_ ++#define __DT_BINDINGS_RESET_CONTROLLER_AIROHA_AN7583_H_ ++ ++/* RST_CTRL2 */ ++#define AN7583_XPON_PHY_RST 0 ++#define AN7583_GPON_OLT_RST 1 ++#define AN7583_CPU_TIMER2_RST 2 ++#define AN7583_HSUART_RST 3 ++#define AN7583_UART4_RST 4 ++#define AN7583_UART5_RST 5 ++#define AN7583_I2C2_RST 6 ++#define AN7583_XSI_MAC_RST 7 ++#define AN7583_XSI_PHY_RST 8 ++#define AN7583_NPU_RST 9 ++#define AN7583_TRNG_MSTART_RST 10 ++#define AN7583_DUAL_HSI0_RST 11 ++#define AN7583_DUAL_HSI1_RST 12 ++#define AN7583_DUAL_HSI0_MAC_RST 13 ++#define AN7583_DUAL_HSI1_MAC_RST 14 ++#define AN7583_XPON_XFI_RST 15 ++#define AN7583_WDMA_RST 16 ++#define AN7583_WOE0_RST 17 ++#define AN7583_HSDMA_RST 18 ++#define AN7583_TDMA_RST 19 ++#define AN7583_EMMC_RST 20 ++#define AN7583_SOE_RST 21 ++#define AN7583_XFP_MAC_RST 22 ++#define AN7583_MDIO0 23 ++#define AN7583_MDIO1 24 ++/* RST_CTRL1 */ ++#define AN7583_PCM1_ZSI_ISI_RST 25 ++#define AN7583_FE_PDMA_RST 26 ++#define AN7583_FE_QDMA_RST 27 ++#define AN7583_PCM_SPIWP_RST 28 ++#define AN7583_CRYPTO_RST 29 ++#define AN7583_TIMER_RST 30 ++#define AN7583_PCM1_RST 31 ++#define AN7583_UART_RST 32 ++#define AN7583_GPIO_RST 33 ++#define AN7583_GDMA_RST 34 ++#define AN7583_I2C_MASTER_RST 35 ++#define AN7583_PCM2_ZSI_ISI_RST 36 ++#define AN7583_SFC_RST 37 ++#define AN7583_UART2_RST 38 ++#define AN7583_GDMP_RST 39 ++#define AN7583_FE_RST 40 ++#define AN7583_USB_HOST_P0_RST 41 ++#define AN7583_GSW_RST 42 ++#define AN7583_SFC2_PCM_RST 43 ++#define AN7583_PCIE0_RST 44 ++#define AN7583_PCIE1_RST 45 ++#define AN7583_CPU_TIMER_RST 46 ++#define AN7583_PCIE_HB_RST 47 ++#define AN7583_XPON_MAC_RST 48 ++ ++#endif /* __DT_BINDINGS_RESET_CONTROLLER_AIROHA_AN7583_H_ */ diff --git a/lede/target/linux/airoha/patches-6.12/600-10-clk-en7523-add-support-for-Airoha-AN7583-clock.patch b/lede/target/linux/airoha/patches-6.12/600-10-clk-en7523-add-support-for-Airoha-AN7583-clock.patch new file mode 100644 index 0000000000..0a57e8a9fb --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/600-10-clk-en7523-add-support-for-Airoha-AN7583-clock.patch @@ -0,0 +1,328 @@ +From 3c5cd99f894c23650accf19fef18b5b9bbe83941 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sat, 8 Feb 2025 00:43:27 +0100 +Subject: [PATCH 10/10] clk: en7523: add support for Airoha AN7583 clock + +Add support for Airoha AN7583 clock and reset. + +Airoha AN7583 SoC have the same register address of EN7581 but implement +different bits and additional base clocks. Also reset are different with +the introduction of 2 dedicated MDIO line and drop of some reset lines. + +Signed-off-by: Christian Marangi +--- + drivers/clk/clk-en7523.c | 264 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 264 insertions(+) + +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + + #define RST_NR_PER_BANK 32 + +@@ -104,6 +105,14 @@ static const u32 bus7581_base[] = { 6000 + static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 }; + static const u32 crypto_base[] = { 540000000, 480000000 }; + static const u32 emmc7581_base[] = { 200000000, 150000000 }; ++/* AN7583 */ ++static const u32 gsw7583_base[] = { 540672000, 270336000, 400000000, 200000000 }; ++static const u32 emi7583_base[] = { 540672000, 480000000, 400000000, 300000000 }; ++static const u32 bus7583_base[] = { 600000000, 540672000, 480000000, 400000000 }; ++static const u32 spi7583_base[] = { 100000000, 12500000 }; ++static const u32 npu7583_base[] = { 666000000, 800000000, 720000000, 600000000 }; ++static const u32 crypto7583_base[] = { 540672000, 400000000 }; ++static const u32 emmc7583_base[] = { 150000000, 200000000 }; + + static const struct en_clk_desc en7523_base_clks[] = { + { +@@ -306,6 +315,138 @@ static const struct en_clk_desc en7581_b + } + }; + ++static const struct en_clk_desc an7583_base_clks[] = { ++ { ++ .id = EN7523_CLK_GSW, ++ .name = "gsw", ++ ++ .base_reg = REG_GSW_CLK_DIV_SEL, ++ .base_bits = 2, ++ .base_shift = 8, ++ .base_values = gsw7583_base, ++ .n_base_values = ARRAY_SIZE(gsw7583_base), ++ ++ .div_bits = 3, ++ .div_shift = 0, ++ .div_step = 1, ++ .div_offset = 1, ++ }, { ++ .id = EN7523_CLK_EMI, ++ .name = "emi", ++ ++ .base_reg = REG_EMI_CLK_DIV_SEL, ++ .base_bits = 2, ++ .base_shift = 8, ++ .base_values = emi7583_base, ++ .n_base_values = ARRAY_SIZE(emi7583_base), ++ ++ .div_bits = 3, ++ .div_shift = 0, ++ .div_step = 1, ++ .div_offset = 1, ++ }, { ++ .id = EN7523_CLK_BUS, ++ .name = "bus", ++ ++ .base_reg = REG_BUS_CLK_DIV_SEL, ++ .base_bits = 2, ++ .base_shift = 8, ++ .base_values = bus7583_base, ++ .n_base_values = ARRAY_SIZE(bus7583_base), ++ ++ .div_bits = 3, ++ .div_shift = 0, ++ .div_step = 1, ++ .div_offset = 1, ++ }, { ++ .id = EN7523_CLK_SLIC, ++ .name = "slic", ++ ++ .base_reg = REG_SPI_CLK_FREQ_SEL, ++ .base_bits = 1, ++ .base_shift = 0, ++ .base_values = slic_base, ++ .n_base_values = ARRAY_SIZE(slic_base), ++ ++ .div_reg = REG_SPI_CLK_DIV_SEL, ++ .div_bits = 5, ++ .div_shift = 24, ++ .div_val0 = 20, ++ .div_step = 2, ++ }, { ++ .id = EN7523_CLK_SPI, ++ .name = "spi", ++ ++ .base_reg = REG_SPI_CLK_FREQ_SEL, ++ .base_bits = 1, ++ .base_shift = 1, ++ .base_values = spi7583_base, ++ .n_base_values = ARRAY_SIZE(spi7583_base), ++ ++ .div_reg = REG_SPI_CLK_DIV_SEL, ++ .div_bits = 5, ++ .div_shift = 8, ++ .div_val0 = 40, ++ .div_step = 2, ++ }, { ++ .id = EN7523_CLK_NPU, ++ .name = "npu", ++ ++ .base_reg = REG_NPU_CLK_DIV_SEL, ++ .base_bits = 2, ++ .base_shift = 9, ++ .base_values = npu7583_base, ++ .n_base_values = ARRAY_SIZE(npu7583_base), ++ ++ .div_bits = 3, ++ .div_shift = 0, ++ .div_step = 1, ++ .div_offset = 1, ++ }, { ++ .id = EN7523_CLK_CRYPTO, ++ .name = "crypto", ++ ++ .base_reg = REG_CRYPTO_CLKSRC2, ++ .base_bits = 1, ++ .base_shift = 0, ++ .base_values = crypto7583_base, ++ .n_base_values = ARRAY_SIZE(crypto7583_base), ++ }, { ++ .id = EN7581_CLK_EMMC, ++ .name = "emmc", ++ ++ .base_reg = REG_CRYPTO_CLKSRC2, ++ .base_bits = 1, ++ .base_shift = 13, ++ .base_values = emmc7583_base, ++ .n_base_values = ARRAY_SIZE(emmc7583_base), ++ }, { ++ .id = AN7583_CLK_MDIO0, ++ .name = "mdio0", ++ ++ .base_reg = REG_CRYPTO_CLKSRC2, ++ ++ .base_value = 25000000, ++ ++ .div_bits = 4, ++ .div_shift = 15, ++ .div_step = 1, ++ .div_offset = 1, ++ }, { ++ .id = AN7583_CLK_MDIO1, ++ .name = "mdio1", ++ ++ .base_reg = REG_CRYPTO_CLKSRC2, ++ ++ .base_value = 25000000, ++ ++ .div_bits = 4, ++ .div_shift = 19, ++ .div_step = 1, ++ .div_offset = 1, ++ } ++}; ++ + static const u16 en7581_rst_ofs[] = { + REG_RST_CTRL2, + REG_RST_CTRL1, +@@ -369,6 +510,60 @@ static const u16 en7581_rst_map[] = { + [EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31, + }; + ++static const u16 an7583_rst_map[] = { ++ /* RST_CTRL2 */ ++ [AN7583_XPON_PHY_RST] = 0, ++ [AN7583_GPON_OLT_RST] = 1, ++ [AN7583_CPU_TIMER2_RST] = 2, ++ [AN7583_HSUART_RST] = 3, ++ [AN7583_UART4_RST] = 4, ++ [AN7583_UART5_RST] = 5, ++ [AN7583_I2C2_RST] = 6, ++ [AN7583_XSI_MAC_RST] = 7, ++ [AN7583_XSI_PHY_RST] = 8, ++ [AN7583_NPU_RST] = 9, ++ [AN7583_TRNG_MSTART_RST] = 12, ++ [AN7583_DUAL_HSI0_RST] = 13, ++ [AN7583_DUAL_HSI1_RST] = 14, ++ [AN7583_DUAL_HSI0_MAC_RST] = 16, ++ [AN7583_DUAL_HSI1_MAC_RST] = 17, ++ [AN7583_XPON_XFI_RST] = 18, ++ [AN7583_WDMA_RST] = 19, ++ [AN7583_WOE0_RST] = 20, ++ [AN7583_HSDMA_RST] = 22, ++ [AN7583_TDMA_RST] = 24, ++ [AN7583_EMMC_RST] = 25, ++ [AN7583_SOE_RST] = 26, ++ [AN7583_XFP_MAC_RST] = 28, ++ [AN7583_MDIO0] = 30, ++ [AN7583_MDIO1] = 31, ++ /* RST_CTRL1 */ ++ [AN7583_PCM1_ZSI_ISI_RST] = RST_NR_PER_BANK + 0, ++ [AN7583_FE_PDMA_RST] = RST_NR_PER_BANK + 1, ++ [AN7583_FE_QDMA_RST] = RST_NR_PER_BANK + 2, ++ [AN7583_PCM_SPIWP_RST] = RST_NR_PER_BANK + 4, ++ [AN7583_CRYPTO_RST] = RST_NR_PER_BANK + 6, ++ [AN7583_TIMER_RST] = RST_NR_PER_BANK + 8, ++ [AN7583_PCM1_RST] = RST_NR_PER_BANK + 11, ++ [AN7583_UART_RST] = RST_NR_PER_BANK + 12, ++ [AN7583_GPIO_RST] = RST_NR_PER_BANK + 13, ++ [AN7583_GDMA_RST] = RST_NR_PER_BANK + 14, ++ [AN7583_I2C_MASTER_RST] = RST_NR_PER_BANK + 16, ++ [AN7583_PCM2_ZSI_ISI_RST] = RST_NR_PER_BANK + 17, ++ [AN7583_SFC_RST] = RST_NR_PER_BANK + 18, ++ [AN7583_UART2_RST] = RST_NR_PER_BANK + 19, ++ [AN7583_GDMP_RST] = RST_NR_PER_BANK + 20, ++ [AN7583_FE_RST] = RST_NR_PER_BANK + 21, ++ [AN7583_USB_HOST_P0_RST] = RST_NR_PER_BANK + 22, ++ [AN7583_GSW_RST] = RST_NR_PER_BANK + 23, ++ [AN7583_SFC2_PCM_RST] = RST_NR_PER_BANK + 25, ++ [AN7583_PCIE0_RST] = RST_NR_PER_BANK + 26, ++ [AN7583_PCIE1_RST] = RST_NR_PER_BANK + 27, ++ [AN7583_CPU_TIMER_RST] = RST_NR_PER_BANK + 28, ++ [AN7583_PCIE_HB_RST] = RST_NR_PER_BANK + 29, ++ [AN7583_XPON_MAC_RST] = RST_NR_PER_BANK + 31, ++}; ++ + static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val) + { + if (!desc->base_bits) +@@ -881,6 +1076,62 @@ static int en7581_clk_hw_init(struct pla + return en7581_reset_register(&pdev->dev, clk_map); + } + ++static int an7583_reset_register(struct device *dev, struct regmap *map) ++{ ++ struct en_rst_data *rst_data; ++ ++ rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL); ++ if (!rst_data) ++ return -ENOMEM; ++ ++ rst_data->bank_ofs = en7581_rst_ofs; ++ rst_data->idx_map = an7583_rst_map; ++ rst_data->map = map; ++ ++ rst_data->rcdev.nr_resets = ARRAY_SIZE(an7583_rst_map); ++ rst_data->rcdev.of_xlate = en7523_reset_xlate; ++ rst_data->rcdev.ops = &en7581_reset_ops; ++ rst_data->rcdev.of_node = dev->of_node; ++ rst_data->rcdev.of_reset_n_cells = 1; ++ rst_data->rcdev.owner = THIS_MODULE; ++ rst_data->rcdev.dev = dev; ++ ++ return devm_reset_controller_register(dev, &rst_data->rcdev); ++} ++ ++static int an7583_clk_hw_init(struct platform_device *pdev, ++ const struct en_clk_soc_data *soc_data, ++ struct clk_hw_onecell_data *clk_data) ++{ ++ struct device *dev = &pdev->dev; ++ struct regmap *map, *clk_map; ++ void __iomem *base; ++ int err; ++ ++ map = syscon_regmap_lookup_by_phandle(dev->of_node, "airoha,chip-scu"); ++ if (IS_ERR(map)) ++ return PTR_ERR(map); ++ ++ base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ clk_map = devm_regmap_init_mmio(&pdev->dev, base, &en7523_clk_regmap_config); ++ if (IS_ERR(clk_map)) ++ return PTR_ERR(clk_map); ++ ++ err = en75xx_register_clocks(dev, soc_data, clk_data, map, clk_map); ++ if (err) ++ return err; ++ ++ regmap_clear_bits(clk_map, REG_NP_SCU_SSTR, ++ REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); ++ regmap_update_bits(clk_map, REG_NP_SCU_PCIC, REG_PCIE_CTRL, ++ FIELD_PREP(REG_PCIE_CTRL, 3)); ++ ++ return an7583_reset_register(dev, clk_map); ++} ++ + static int en7523_clk_probe(struct platform_device *pdev) + { + const struct en_clk_soc_data *soc_data; +@@ -940,9 +1191,23 @@ static const struct en_clk_soc_data en75 + .hw_init = en7581_clk_hw_init, + }; + ++static const struct en_clk_soc_data an7583_data = { ++ .probe_child = true, ++ .base_clks = an7583_base_clks, ++ /* We increment num_clocks by 1 to account for additional PCIe clock */ ++ .num_clocks = ARRAY_SIZE(an7583_base_clks) + 1, ++ .pcie_ops = { ++ .is_enabled = en7581_pci_is_enabled, ++ .enable = en7581_pci_enable, ++ .disable = en7581_pci_disable, ++ }, ++ .hw_init = an7583_clk_hw_init, ++}; ++ + static const struct of_device_id of_match_clk_en7523[] = { + { .compatible = "airoha,en7523-scu", .data = &en7523_data }, + { .compatible = "airoha,en7581-scu", .data = &en7581_data }, ++ { .compatible = "airoha,an7583-scu", .data = &an7583_data }, + { /* sentinel */ } + }; + diff --git a/lede/target/linux/airoha/patches-6.12/600-11-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch b/lede/target/linux/airoha/patches-6.12/600-11-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch new file mode 100644 index 0000000000..0c391ebce9 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/600-11-dt-bindings-clock-airoha-Add-reset-support-to-EN7523.patch @@ -0,0 +1,100 @@ +From 38195ddfcea372924a68b64f7a6f9235488160be Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Sat, 20 Sep 2025 03:57:25 +0300 +Subject: [PATCH 1/3] dt-bindings: clock: airoha: Add reset support to EN7523 + clock binding + +Introduce reset capability to EN7523 device-tree clock binding +documentation. + +Signed-off-by: Mikhail Kshevetskiy +Reviewed-by: Rob Herring (Arm) +--- + .../bindings/clock/airoha,en7523-scu.yaml | 3 +- + .../dt-bindings/reset/airoha,en7523-reset.h | 61 +++++++++++++++++++ + 2 files changed, 62 insertions(+), 2 deletions(-) + create mode 100644 include/dt-bindings/reset/airoha,en7523-reset.h + +--- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml ++++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +@@ -64,8 +64,6 @@ allOf: + - description: scu base address + - description: misc scu base address + +- '#reset-cells': false +- + - if: + properties: + compatible: +@@ -89,6 +87,7 @@ examples: + reg = <0x1fa20000 0x400>, + <0x1fb00000 0x1000>; + #clock-cells = <1>; ++ #reset-cells = <1>; + }; + + - | +--- /dev/null ++++ b/include/dt-bindings/reset/airoha,en7523-reset.h +@@ -0,0 +1,61 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * Copyright (C) 2024 iopsys Software Solutions AB. ++ * Copyright (C) 2025 Genexis AB. ++ * ++ * Author: Mikhail Kshevetskiy ++ * ++ * based on ++ * include/dt-bindings/reset/airoha,en7581-reset.h ++ * by Lorenzo Bianconi ++ */ ++ ++#ifndef __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_ ++#define __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_ ++ ++/* RST_CTRL2 */ ++#define EN7523_XPON_PHY_RST 0 ++#define EN7523_XSI_MAC_RST 1 ++#define EN7523_XSI_PHY_RST 2 ++#define EN7523_NPU_RST 3 ++#define EN7523_I2S_RST 4 ++#define EN7523_TRNG_RST 5 ++#define EN7523_TRNG_MSTART_RST 6 ++#define EN7523_DUAL_HSI0_RST 7 ++#define EN7523_DUAL_HSI1_RST 8 ++#define EN7523_HSI_RST 9 ++#define EN7523_DUAL_HSI0_MAC_RST 10 ++#define EN7523_DUAL_HSI1_MAC_RST 11 ++#define EN7523_HSI_MAC_RST 12 ++#define EN7523_WDMA_RST 13 ++#define EN7523_WOE0_RST 14 ++#define EN7523_WOE1_RST 15 ++#define EN7523_HSDMA_RST 16 ++#define EN7523_I2C2RBUS_RST 17 ++#define EN7523_TDMA_RST 18 ++/* RST_CTRL1 */ ++#define EN7523_PCM1_ZSI_ISI_RST 19 ++#define EN7523_FE_PDMA_RST 20 ++#define EN7523_FE_QDMA_RST 21 ++#define EN7523_PCM_SPIWP_RST 22 ++#define EN7523_CRYPTO_RST 23 ++#define EN7523_TIMER_RST 24 ++#define EN7523_PCM1_RST 25 ++#define EN7523_UART_RST 26 ++#define EN7523_GPIO_RST 27 ++#define EN7523_GDMA_RST 28 ++#define EN7523_I2C_MASTER_RST 29 ++#define EN7523_PCM2_ZSI_ISI_RST 30 ++#define EN7523_SFC_RST 31 ++#define EN7523_UART2_RST 32 ++#define EN7523_GDMP_RST 33 ++#define EN7523_FE_RST 34 ++#define EN7523_USB_HOST_P0_RST 35 ++#define EN7523_GSW_RST 36 ++#define EN7523_SFC2_PCM_RST 37 ++#define EN7523_PCIE0_RST 38 ++#define EN7523_PCIE1_RST 39 ++#define EN7523_PCIE_HB_RST 40 ++#define EN7523_XPON_MAC_RST 41 ++ ++#endif /* __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7523_H_ */ diff --git a/lede/target/linux/airoha/patches-6.12/600-12-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch b/lede/target/linux/airoha/patches-6.12/600-12-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch new file mode 100644 index 0000000000..c658e2f775 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/600-12-clk-en7523-Add-reset-controller-support-for-EN7523-S.patch @@ -0,0 +1,177 @@ +From 37de26f9d2f55cd74af55cb29c2860b5989bb728 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Sat, 20 Sep 2025 03:57:25 +0300 +Subject: [PATCH 2/3] clk: en7523: Add reset-controller support for EN7523 SoC + +Introduce reset API support to EN7523 clock driver. EN7523 uses the +same reset logic as EN7581, so just reuse existing code. + +Signed-off-by: Mikhail Kshevetskiy +Reviewed-by: AngeloGioacchino Del Regno +--- + drivers/clk/clk-en7523.c | 96 ++++++++++++++++++++++++++++------------ + 1 file changed, 67 insertions(+), 29 deletions(-) + +--- a/drivers/clk/clk-en7523.c ++++ b/drivers/clk/clk-en7523.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -452,6 +453,53 @@ static const u16 en7581_rst_ofs[] = { + REG_RST_CTRL1, + }; + ++static const u16 en7523_rst_map[] = { ++ /* RST_CTRL2 */ ++ [EN7523_XPON_PHY_RST] = 0, ++ [EN7523_XSI_MAC_RST] = 7, ++ [EN7523_XSI_PHY_RST] = 8, ++ [EN7523_NPU_RST] = 9, ++ [EN7523_I2S_RST] = 10, ++ [EN7523_TRNG_RST] = 11, ++ [EN7523_TRNG_MSTART_RST] = 12, ++ [EN7523_DUAL_HSI0_RST] = 13, ++ [EN7523_DUAL_HSI1_RST] = 14, ++ [EN7523_HSI_RST] = 15, ++ [EN7523_DUAL_HSI0_MAC_RST] = 16, ++ [EN7523_DUAL_HSI1_MAC_RST] = 17, ++ [EN7523_HSI_MAC_RST] = 18, ++ [EN7523_WDMA_RST] = 19, ++ [EN7523_WOE0_RST] = 20, ++ [EN7523_WOE1_RST] = 21, ++ [EN7523_HSDMA_RST] = 22, ++ [EN7523_I2C2RBUS_RST] = 23, ++ [EN7523_TDMA_RST] = 24, ++ /* RST_CTRL1 */ ++ [EN7523_PCM1_ZSI_ISI_RST] = RST_NR_PER_BANK + 0, ++ [EN7523_FE_PDMA_RST] = RST_NR_PER_BANK + 1, ++ [EN7523_FE_QDMA_RST] = RST_NR_PER_BANK + 2, ++ [EN7523_PCM_SPIWP_RST] = RST_NR_PER_BANK + 4, ++ [EN7523_CRYPTO_RST] = RST_NR_PER_BANK + 6, ++ [EN7523_TIMER_RST] = RST_NR_PER_BANK + 8, ++ [EN7523_PCM1_RST] = RST_NR_PER_BANK + 11, ++ [EN7523_UART_RST] = RST_NR_PER_BANK + 12, ++ [EN7523_GPIO_RST] = RST_NR_PER_BANK + 13, ++ [EN7523_GDMA_RST] = RST_NR_PER_BANK + 14, ++ [EN7523_I2C_MASTER_RST] = RST_NR_PER_BANK + 16, ++ [EN7523_PCM2_ZSI_ISI_RST] = RST_NR_PER_BANK + 17, ++ [EN7523_SFC_RST] = RST_NR_PER_BANK + 18, ++ [EN7523_UART2_RST] = RST_NR_PER_BANK + 19, ++ [EN7523_GDMP_RST] = RST_NR_PER_BANK + 20, ++ [EN7523_FE_RST] = RST_NR_PER_BANK + 21, ++ [EN7523_USB_HOST_P0_RST] = RST_NR_PER_BANK + 22, ++ [EN7523_GSW_RST] = RST_NR_PER_BANK + 23, ++ [EN7523_SFC2_PCM_RST] = RST_NR_PER_BANK + 25, ++ [EN7523_PCIE0_RST] = RST_NR_PER_BANK + 26, ++ [EN7523_PCIE1_RST] = RST_NR_PER_BANK + 27, ++ [EN7523_PCIE_HB_RST] = RST_NR_PER_BANK + 29, ++ [EN7523_XPON_MAC_RST] = RST_NR_PER_BANK + 31, ++}; ++ + static const u16 en7581_rst_map[] = { + /* RST_CTRL2 */ + [EN7581_XPON_PHY_RST] = 0, +@@ -564,6 +612,9 @@ static const u16 an7583_rst_map[] = { + [AN7583_XPON_MAC_RST] = RST_NR_PER_BANK + 31, + }; + ++static int en7581_reset_register(struct device *dev, struct regmap *map, ++ const u16 *rst_map, int nr_resets); ++ + static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val) + { + if (!desc->base_bits) +@@ -942,6 +993,7 @@ static int en7523_clk_hw_init(struct pla + { + void __iomem *base, *np_base; + struct regmap *map, *clk_map; ++ int err; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) +@@ -961,7 +1013,13 @@ static int en7523_clk_hw_init(struct pla + if (IS_ERR(clk_map)) + return PTR_ERR(clk_map); + +- return en75xx_register_clocks(&pdev->dev, soc_data, clk_data, map, clk_map); ++ ++ err = en75xx_register_clocks(&pdev->dev, soc_data, clk_data, map, clk_map); ++ if (err) ++ return err; ++ ++ return en7581_reset_register(&pdev->dev, clk_map, en7523_rst_map, ++ ARRAY_SIZE(en7523_rst_map)); + } + + static int en7523_reset_update(struct reset_controller_dev *rcdev, +@@ -1016,7 +1074,8 @@ static const struct reset_control_ops en + .status = en7523_reset_status, + }; + +-static int en7581_reset_register(struct device *dev, struct regmap *map) ++static int en7581_reset_register(struct device *dev, struct regmap *map, ++ const u16 *rst_map, int nr_resets) + { + struct en_rst_data *rst_data; + +@@ -1025,10 +1084,10 @@ static int en7581_reset_register(struct + return -ENOMEM; + + rst_data->bank_ofs = en7581_rst_ofs; +- rst_data->idx_map = en7581_rst_map; ++ rst_data->idx_map = rst_map; + rst_data->map = map; + +- rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map); ++ rst_data->rcdev.nr_resets = nr_resets; + rst_data->rcdev.of_xlate = en7523_reset_xlate; + rst_data->rcdev.ops = &en7581_reset_ops; + rst_data->rcdev.of_node = dev->of_node; +@@ -1073,30 +1132,8 @@ static int en7581_clk_hw_init(struct pla + regmap_update_bits(clk_map, REG_NP_SCU_PCIC, REG_PCIE_CTRL, + FIELD_PREP(REG_PCIE_CTRL, 3)); + +- return en7581_reset_register(&pdev->dev, clk_map); +-} +- +-static int an7583_reset_register(struct device *dev, struct regmap *map) +-{ +- struct en_rst_data *rst_data; +- +- rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL); +- if (!rst_data) +- return -ENOMEM; +- +- rst_data->bank_ofs = en7581_rst_ofs; +- rst_data->idx_map = an7583_rst_map; +- rst_data->map = map; +- +- rst_data->rcdev.nr_resets = ARRAY_SIZE(an7583_rst_map); +- rst_data->rcdev.of_xlate = en7523_reset_xlate; +- rst_data->rcdev.ops = &en7581_reset_ops; +- rst_data->rcdev.of_node = dev->of_node; +- rst_data->rcdev.of_reset_n_cells = 1; +- rst_data->rcdev.owner = THIS_MODULE; +- rst_data->rcdev.dev = dev; +- +- return devm_reset_controller_register(dev, &rst_data->rcdev); ++ return en7581_reset_register(&pdev->dev, clk_map, en7581_rst_map, ++ ARRAY_SIZE(en7581_rst_map)); + } + + static int an7583_clk_hw_init(struct platform_device *pdev, +@@ -1129,7 +1166,8 @@ static int an7583_clk_hw_init(struct pla + regmap_update_bits(clk_map, REG_NP_SCU_PCIC, REG_PCIE_CTRL, + FIELD_PREP(REG_PCIE_CTRL, 3)); + +- return an7583_reset_register(dev, clk_map); ++ return en7581_reset_register(dev, clk_map, an7583_rst_map, ++ ARRAY_SIZE(an7583_rst_map)); + } + + static int en7523_clk_probe(struct platform_device *pdev) diff --git a/lede/target/linux/airoha/patches-6.12/600-13-ARM-dts-airoha-update-EN7523-dtsi-to-support-resets.patch b/lede/target/linux/airoha/patches-6.12/600-13-ARM-dts-airoha-update-EN7523-dtsi-to-support-resets.patch new file mode 100644 index 0000000000..3ed155aaf0 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/600-13-ARM-dts-airoha-update-EN7523-dtsi-to-support-resets.patch @@ -0,0 +1,32 @@ +From 6e5e3a8e20d12f60a1b902160b92337b392b1c18 Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Sat, 20 Sep 2025 03:57:25 +0300 +Subject: [PATCH 3/3] ARM: dts: airoha: update EN7523 dtsi to support resets + +This patch updates EN7523 dtsi to reflect the reset-controller +support for EN7523 SoC. + +Signed-off-by: Mikhail Kshevetskiy +Reviewed-by: AngeloGioacchino Del Regno +--- + arch/arm/boot/dts/airoha/en7523.dtsi | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/arm/boot/dts/airoha/en7523.dtsi ++++ b/arch/arm/boot/dts/airoha/en7523.dtsi +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + + / { + interrupt-parent = <&gic>; +@@ -91,6 +92,7 @@ + reg = <0x1fa20000 0x400>, + <0x1fb00000 0x1000>; + #clock-cells = <1>; ++ #reset-cells = <1>; + }; + + gic: interrupt-controller@9000000 { diff --git a/lede/target/linux/airoha/patches-6.12/604-01-net-pcs-airoha-add-support-for-AN7583.patch b/lede/target/linux/airoha/patches-6.12/604-01-net-pcs-airoha-add-support-for-AN7583.patch new file mode 100644 index 0000000000..6f0b3c9622 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/604-01-net-pcs-airoha-add-support-for-AN7583.patch @@ -0,0 +1,3002 @@ +From 500f525a21bfc18605b23e7b39fc1d8f74393b30 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 25 Jun 2025 00:00:59 +0200 +Subject: [PATCH 6/8] net: pcs: airoha: add support for Airoha AN7583 SoC + +Add support for Airoha AN7583 PCS. This use a new analog PHY +implementation that doesn't require manual calibration but makes use of +internal algo to lock to the center of the band EYE. + +Signed-off-by: Christian Marangi +--- + drivers/net/pcs/airoha/Kconfig | 7 + + drivers/net/pcs/airoha/Makefile | 3 + + drivers/net/pcs/airoha/pcs-airoha-common.c | 50 +- + drivers/net/pcs/airoha/pcs-airoha.h | 430 ++++ + drivers/net/pcs/airoha/pcs-an7583.c | 2199 ++++++++++++++++++++ + 5 files changed, 2686 insertions(+), 3 deletions(-) + create mode 100644 drivers/net/pcs/airoha/pcs-an7583.c + +--- a/drivers/net/pcs/airoha/Kconfig ++++ b/drivers/net/pcs/airoha/Kconfig +@@ -9,3 +9,10 @@ config PCS_AIROHA_AN7581 + help + This module provides helper to phylink for managing the Airoha + AN7581 PCS for SoC Ethernet and PON SERDES. ++ ++config PCS_AIROHA_AN7583 ++ tristate "Airoha AN7583 PCS driver" ++ select PCS_AIROHA ++ help ++ This module provides helper to phylink for managing the Airoha ++ AN7583 PCS for SoC Ethernet and PON SERDES. +--- a/drivers/net/pcs/airoha/Makefile ++++ b/drivers/net/pcs/airoha/Makefile +@@ -5,3 +5,6 @@ pcs-airoha-objs := pcs-airoha-common.o + ifdef CONFIG_PCS_AIROHA_AN7581 + pcs-airoha-objs += pcs-an7581.o + endif ++ifdef CONFIG_PCS_AIROHA_AN7583 ++pcs-airoha-objs += pcs-an7583.o ++endif +--- a/drivers/net/pcs/airoha/pcs-airoha-common.c ++++ b/drivers/net/pcs/airoha/pcs-airoha-common.c +@@ -19,6 +19,7 @@ + static void airoha_pcs_setup_scu_eth(struct airoha_pcs_priv *priv, + phy_interface_t interface) + { ++ struct device *dev = priv->dev; + u32 xsi_sel; + + switch (interface) { +@@ -36,6 +37,12 @@ static void airoha_pcs_setup_scu_eth(str + regmap_update_bits(priv->scu, AIROHA_SCU_SSR3, + AIROHA_SCU_ETH_XSI_SEL, + xsi_sel); ++ ++ /* AN7583 require additional setting */ ++ if (device_is_compatible(dev, "airoha,an7583-pcs-eth")) ++ regmap_update_bits(priv->scu, AIROHA_SCU_WAN_CONF, ++ AIROHA_SCU_ETH_MAC_SEL, ++ AIROHA_SCU_ETH_MAC_SEL_XFI); + } + + static void airoha_pcs_setup_scu_pon(struct airoha_pcs_priv *priv, +@@ -100,16 +107,24 @@ static int airoha_pcs_setup_scu(struct a + + static void airoha_pcs_init_usxgmii(struct airoha_pcs_priv *priv) + { ++ const struct airoha_pcs_match_data *data = priv->data; ++ + regmap_set_bits(priv->multi_sgmii, AIROHA_PCS_MULTI_SGMII_MSG_RX_CTRL_0, + AIROHA_PCS_HSGMII_XFI_SEL); + + /* Disable Hibernation */ +- regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTROL_1, +- AIROHA_PCS_USXGMII_SPEED_SEL_H); ++ if (data->hibernation_workaround) ++ regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTROL_1, ++ AIROHA_PCS_USXGMII_SPEED_SEL_H); + + /* FIXME: wait Airoha */ + /* Avoid PCS sending garbage to MAC in some HW revision (E0) */ +- regmap_write(priv->usxgmii_pcs, AIROHA_PCS_USGMII_VENDOR_DEFINE_116, 0); ++ if (data->usxgmii_ber_time_fixup) ++ regmap_write(priv->usxgmii_pcs, AIROHA_PCS_USGMII_VENDOR_DEFINE_116, 0); ++ ++ if (data->usxgmii_rx_gb_out_vld_tweak) ++ regmap_clear_bits(priv->usxgmii_pcs, AN7583_PCS_USXGMII_RTL_MODIFIED, ++ AIROHA_PCS_USXGMII_MODIFIED_RX_GB_OUT_VLD); + } + + static void airoha_pcs_init_hsgmii(struct airoha_pcs_priv *priv) +@@ -434,6 +449,13 @@ static int airoha_pcs_config(struct phyl + regmap_clear_bits(priv->usxgmii_pcs, + AIROHA_PCS_USXGMII_PCS_AN_CONTROL_0, + AIROHA_PCS_USXGMII_AN_ENABLE); ++ ++ if (data->usxgmii_xfi_mode_sel && ++ neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) ++ regmap_set_bits(priv->usxgmii_pcs, ++ AIROHA_PCS_USXGMII_PCS_AN_CONTROL_7, ++ AIROHA_PCS_USXGMII_XFI_MODE_TX_SEL | ++ AIROHA_PCS_USXGMII_XFI_MODE_RX_SEL); + } + + /* Clear any force bit that my be set by bootloader */ +@@ -985,7 +1007,8 @@ static int airoha_pcs_probe(struct platf + * manual rx calibration is needed. This is only limited to + * any SoC revision before E2. + */ +- if (data->port_type == AIROHA_PCS_ETH) { ++ if (device_is_compatible(dev, "airoha,an7581-pcs-eth") && ++ data->port_type == AIROHA_PCS_ETH) { + u32 val; + + ret = regmap_read(priv->scu, AIROHA_SCU_PDIDR, &val); +@@ -1003,6 +1026,8 @@ static int airoha_pcs_probe(struct platf + + static const struct airoha_pcs_match_data an7581_pcs_eth = { + .port_type = AIROHA_PCS_ETH, ++ .hibernation_workaround = true, ++ .usxgmii_ber_time_fixup = true, + .bringup = an7581_pcs_bringup, + .link_up = an7581_pcs_phya_link_up, + .rxlock_workaround = an7581_pcs_rxlock_workaround, +@@ -1010,13 +1035,33 @@ static const struct airoha_pcs_match_dat + + static const struct airoha_pcs_match_data an7581_pcs_pon = { + .port_type = AIROHA_PCS_PON, ++ .hibernation_workaround = true, ++ .usxgmii_ber_time_fixup = true, + .bringup = an7581_pcs_bringup, + .link_up = an7581_pcs_phya_link_up, + }; + ++static const struct airoha_pcs_match_data an7583_pcs_eth = { ++ .port_type = AIROHA_PCS_ETH, ++ .usxgmii_rx_gb_out_vld_tweak = true, ++ .usxgmii_xfi_mode_sel = true, ++ .bringup = an7583_pcs_common_phya_bringup, ++ .link_up = an7583_pcs_common_phya_link_up, ++}; ++ ++static const struct airoha_pcs_match_data an7583_pcs_pon = { ++ .port_type = AIROHA_PCS_PON, ++ .usxgmii_rx_gb_out_vld_tweak = true, ++ .usxgmii_xfi_mode_sel = true, ++ .bringup = an7583_pcs_common_phya_bringup, ++ .link_up = an7583_pcs_common_phya_link_up, ++}; ++ + static const struct of_device_id airoha_pcs_of_table[] = { + { .compatible = "airoha,an7581-pcs-eth", .data = &an7581_pcs_eth }, + { .compatible = "airoha,an7581-pcs-pon", .data = &an7581_pcs_pon }, ++ { .compatible = "airoha,an7583-pcs-eth", .data = &an7583_pcs_eth }, ++ { .compatible = "airoha,an7583-pcs-pon", .data = &an7583_pcs_pon }, + { /* sentinel */ }, + }; + MODULE_DEVICE_TABLE(of, airoha_pcs_of_table); +--- a/drivers/net/pcs/airoha/pcs-airoha.h ++++ b/drivers/net/pcs/airoha/pcs-airoha.h +@@ -14,6 +14,9 @@ + #define AIROHA_SCU_PDIDR 0x5c + #define AIROHA_SCU_PRODUCT_ID GENMASK(15, 0) + #define AIROHA_SCU_WAN_CONF 0x70 ++#define AIROHA_SCU_ETH_MAC_SEL BIT(24) ++#define AIROHA_SCU_ETH_MAC_SEL_XFI FIELD_PREP_CONST(AIROHA_SCU_ETH_MAC_SEL, 0x0) ++#define AIROHA_SCU_ETH_MAC_SEL_PON FIELD_PREP_CONST(AIROHA_SCU_ETH_MAC_SEL, 0x1) + #define AIROHA_SCU_WAN_SEL GENMASK(7, 0) + #define AIROHA_SCU_WAN_SEL_SGMII FIELD_PREP_CONST(AIROHA_SCU_WAN_SEL, 0x10) + #define AIROHA_SCU_WAN_SEL_HSGMII FIELD_PREP_CONST(AIROHA_SCU_WAN_SEL, 0x11) +@@ -244,6 +247,8 @@ + #define AIROHA_PCS_USXGMII_PCS_AN_CONTROL_6 0x31c + #define AIROHA_PCS_USXGMII_TOG_PCS_AUTONEG_STS BIT(0) + #define AIROHA_PCS_USXGMII_PCS_AN_CONTROL_7 0x320 ++#define AIROHA_PCS_USXGMII_XFI_MODE_TX_SEL BIT(20) ++#define AIROHA_PCS_USXGMII_XFI_MODE_RX_SEL BIT(16) + #define AIROHA_PCS_USXGMII_RATE_UPDATE_MODE BIT(12) + #define AIROHA_PCS_USXGMII_MODE GENMASK(10, 8) + #define AIROHA_PCS_USXGMII_MODE_10000 FIELD_PREP_CONST(AIROHA_PCS_USXGMII_MODE, 0x0) +@@ -251,9 +256,27 @@ + #define AIROHA_PCS_USXGMII_MODE_2500 FIELD_PREP_CONST(AIROHA_PCS_USXGMII_MODE, 0x2) + #define AIROHA_PCS_USXGMII_MODE_1000 FIELD_PREP_CONST(AIROHA_PCS_USXGMII_MODE, 0x3) + #define AIROHA_PCS_USXGMII_MODE_100 FIELD_PREP_CONST(AIROHA_PCS_USXGMII_MODE, 0x4) ++#define AN7583_PCS_USXGMII_RTL_MODIFIED 0x334 ++#define AIROHA_PCS_USXGMII_MODIFIED_RX_GB_OUT_VLD BIT(25) + + /* PMA_PHYA */ + #define AIROHA_PCS_ANA_PXP_CMN_EN 0x0 ++#define AIROHA_PCS_ANA_CMN_VREFSEL GENMASK(18, 16) ++#define AIROHA_PCS_ANA_CMN_VREFSEL_8V FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x0) ++#define AIROHA_PCS_ANA_CMN_VREFSEL_8_25V FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x1) ++#define AIROHA_PCS_ANA_CMN_VREFSEL_8_5V FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x2) ++#define AIROHA_PCS_ANA_CMN_VREFSEL_8_75V FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x3) ++#define AIROHA_PCS_ANA_CMN_VREFSEL_9V FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x4) ++#define AIROHA_PCS_ANA_CMN_VREFSEL_9_25V FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x5) ++#define AIROHA_PCS_ANA_CMN_VREFSEL_9_5V FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x6) ++#define AIROHA_PCS_ANA_CMN_VREFSEL_9_75V FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x7) ++#define AIROHA_PCS_ANA_CMN_VREFSEL GENMASK(18, 16) ++/* GENMASK(2, 0) input selection from 0 to 7 ++ * BIT(3) OPAMP and path EN ++ * BIT(4) Current path measurement ++ * BIT(5) voltage/current path to PAD ++ */ ++#define AIROHA_PCS_ANA_CMN_MPXSELTOP_DC GENMASK(13, 8) + #define AIROHA_PCS_ANA_CMN_EN BIT(0) + #define AIROHA_PCS_ANA_PXP_JCPLL_IB_EXT_EN 0x4 + #define AIROHA_PCS_ANA_JCPLL_CHP_IOFST GENMASK(29, 24) +@@ -347,6 +370,8 @@ + #define AIROHA_PCS_ANA_JCPLL_TCL_KBAND_VREF GENMASK(20, 16) + #define AIROHA_PCS_ANA_JCPLL_SPARE_L GENMASK(15, 8) + #define AIROHA_PCS_ANA_JCPLL_SPARE_L_LDO FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SPARE_L, BIT(5)) ++#define AIROHA_PCS_ANA_PXP_JCPLL_FREQ_MEAS_EN 0x4c ++#define AIROHA_PCS_ANA_TXPLL_IB_EXT_EN BIT(24) + #define AIROHA_PCS_ANA_PXP_TXPLL_CHP_IBIAS 0x50 + #define AIROHA_PCS_ANA_TXPLL_LPF_BC GENMASK(28, 24) + #define AIROHA_PCS_ANA_TXPLL_LPF_BR GENMASK(20, 16) +@@ -370,6 +395,9 @@ + #define AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE, 0x3) + #define AIROHA_PCS_ANA_TXPLL_POSTDIV_EN BIT(8) + #define AIROHA_PCS_ANA_TXPLL_KBAND_KS GENMASK(1, 0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_PHY_CK1_EN 0x60 ++#define AIROHA_PCS_ANA_TXPLL_PHY_CK2_EN BIT(8) ++#define AIROHA_PCS_ANA_TXPLL_PHY_CK1_EN BIT(0) + #define AIROHA_PCS_ANA_PXP_TXPLL_REFIN_INTERNAL 0x64 + #define AIROHA_PCS_ANA_TXPLL_PLL_RSTB BIT(24) + #define AIROHA_PCS_ANA_TXPLL_RST_DLY GENMASK(18, 16) +@@ -435,16 +463,41 @@ + #define AIROHA_PCS_ANA_TXPLL_LDO_VCO_OUT GENMASK(25, 24) + #define AIROHA_PCS_ANA_TXPLL_LDO_OUT GENMASK(17, 16) + #define AIROHA_PCS_ANA_TXPLL_SSC_PERIOD GENMASK(15, 0) ++#define AIROHA_PCS_ANA_PXP_TXPLL_VTP_EN 0x88 ++#define AIROHA_PCS_ANA_TXPLL_VTP GENMASK(10, 8) ++#define AIROHA_PCS_ANA_TXPLL_VTP_EN BIT(0) + #define AIROHA_PCS_ANA_PXP_TXPLL_TCL_KBAND_VREF 0x94 ++#define AIROHA_PCS_ANA_TXPLL_POSTDIV_D256_EN BIT(25) /* 0: 128 1: 256 */ ++#define AIROHA_PCS_ANA_TXPLL_VCO_KBAND_MEAS_EN BIT(24) ++#define AIROHA_PCS_ANA_TXPLL_FREQ_MEAS_EN BIT(16) ++#define AIROHA_PCS_ANA_TXPLL_VREF_SEL BIT(8) ++#define AIROHA_PCS_ANA_TXPLL_VREF_SEL_VBG FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_VREF_SEL, 0x0) ++#define AIROHA_PCS_ANA_TXPLL_VREF_SEL_AVDD FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_VREF_SEL, 0x1) + #define AIROHA_PCS_ANA_TXPLL_TCL_KBAND_VREF GENMASK(4, 0) ++#define AN7583_PCS_ANA_PXP_TXPLL_CHP_DOUBLE_EN 0x98 ++#define AIROHA_PCS_ANA_TXPLL_SPARE_L BIT(0) /* ICHP_DOUBLE */ ++#define AIROHA_PCS_ANA_PXP_PLL_MONCLK_SEL 0xa0 ++#define AIROHA_PCS_ANA_TDC_AUTOEN BIT(24) ++#define AIROHA_PCS_ANA_PXP_TDC_SYNC_CK_SEL 0xa8 ++#define AIROHA_PCS_ANA_PLL_LDO_CKDRV_VSEL GENMASK(17, 16) ++#define AIROHA_PCS_ANA_PLL_LDO_CKDRV_EN BIT(8) ++#define AIROHA_PCS_ANA_PXP_TX_TXLBRC_EN 0xc0 ++#define AIROHA_PCS_ANA_TX_TERMCAL_VREF_L GENMASK(26, 24) ++#define AIROHA_PCS_ANA_TX_TERMCAL_VREF_H GENMASK(18, 16) + #define AIROHA_PCS_ANA_PXP_TX_CKLDO_EN 0xc4 + #define AIROHA_PCS_ANA_TX_DMEDGEGEN_EN BIT(24) + #define AIROHA_PCS_ANA_TX_CKLDO_EN BIT(0) ++#define AIROHA_PCS_ANA_PXP_TX_TERMCAL_SELPN 0xc8 ++#define AIROHA_PCS_ANA_TX_TDC_CK_SEL GENMASK(17, 16) + #define AIROHA_PCS_ANA_PXP_RX_BUSBIT_SEL 0xcc + #define AIROHA_PCS_ANA_RX_PHY_CK_SEL_FORCE BIT(24) + #define AIROHA_PCS_ANA_RX_PHY_CK_SEL BIT(16) + #define AIROHA_PCS_ANA_RX_PHY_CK_SEL_FROM_PR FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_PHY_CK_SEL, 0x0) + #define AIROHA_PCS_ANA_RX_PHY_CK_SEL_FROM_DES FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_PHY_CK_SEL, 0x1) ++#define AIROHA_PCS_ANA_RX_BUSBIT_SEL_FORCE BIT(8) ++#define AIROHA_PCS_ANA_RX_BUSBIT_SEL BIT(0) ++#define AIROHA_PCS_ANA_RX_BUSBIT_SEL_8BIT FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_BUSBIT_SEL, 0x0) ++#define AIROHA_PCS_ANA_RX_BUSBIT_SEL_16BIT FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_BUSBIT_SEL, 0x1) + #define AIROHA_PCS_ANA_PXP_RX_REV_0 0xd4 + #define AIROHA_PCS_ANA_RX_REV_1 GENMASK(31, 16) + #define AIROHA_PCS_ANA_REV_1_FE_EQ_BIAS_CTRL GENMASK(30, 28) +@@ -452,6 +505,16 @@ + #define AIROHA_PCS_ANA_REV_1_FE_BUF2_BIAS_CTRL GENMASK(22, 20) + #define AIROHA_PCS_ANA_REV_1_SIGDET_ILEAK GENMASK(19, 18) + #define AIROHA_PCS_ANA_REV_1_FECUR_PWDB BIT(16) ++#define AIROHA_PCS_ANA_RX_REV_0 GENMASK(15, 0) ++#define AIROHA_PCS_ANA_REV_0_FE_BUF2_BIAS_TYPE GENMASK(13, 12) ++#define AIROHA_PCS_ANA_REV_0_OSCAL_FE_MODE_SET_SEL BIT(11) ++#define AIROHA_PCS_ANA_REV_0_FE_EQ_GAIN_MODE_TRAINING BIT(10) ++#define AIROHA_PCS_ANA_REV_0_FE_BUF_GAIN_MODE_TRAINING GENMASK(9, 8) ++#define AIROHA_PCS_ANA_REV_0_FE_EQ_GAIN_MODE_NORMAL BIT(6) ++#define AIROHA_PCS_ANA_REV_0_FE_BUF_GAIN_MODE_NORMAL GENMASK(5, 4) ++#define AIROHA_PCS_ANA_REV_0_VOS_PNINV GENMASK(3, 2) ++#define AIROHA_PCS_ANA_REV_0_PLEYEBD4 BIT(1) ++#define AIROHA_PCS_ANA_REV_0_PLEYE_XOR_MON_EN BIT(0) + #define AIROHA_PCS_ANA_PXP_RX_PHYCK_DIV 0xd8 + #define AIROHA_PCS_ANA_RX_TDC_CK_SEL BIT(24) + #define AIROHA_PCS_ANA_RX_PHYCK_RSTB BIT(16) +@@ -460,6 +523,8 @@ + #define AIROHA_PCS_ANA_PXP_CDR_PD_PICAL_CKD8_INV 0xdc + #define AIROHA_PCS_ANA_CDR_PD_EDGE_DIS BIT(8) + #define AIROHA_PCS_ANA_CDR_PD_PICAL_CKD8_INV BIT(0) ++#define AIROHA_PCS_ANA_PXP_CDR_LPF_BOT_LIM 0xe0 ++#define AIROHA_PCS_ANA_CDR_LPF_BOT_LIM GENMASK(18, 0) + #define AIROHA_PCS_ANA_PXP_CDR_LPF_RATIO 0xe8 + #define AIROHA_PCS_ANA_CDR_LPF_TOP_LIM GENMASK(26, 8) + #define AIROHA_PCS_ANA_CDR_LPF_RATIO GENMASK(1, 0) +@@ -475,6 +540,19 @@ + #define AIROHA_PCS_ANA_CDR_PR_DAC_BAND GENMASK(20, 16) + #define AIROHA_PCS_ANA_CDR_PR_VREG_CKBUF_VAL GENMASK(10, 8) + #define AIROHA_PCS_ANA_CDR_PR_VREG_IBAND_VAL GENMASK(2, 0) ++#define AIROHA_PCS_ANA_PXP_CDR_PR_CKREF_DIV 0x100 ++#define AIROHA_PCS_ANA_CDR_PR_RSTB_BYPASS BIT(16) ++#define AIROHA_PCS_ANA_CDR_PR_CKREF_DIV GENMASK(1, 0) ++#define AIROHA_PCS_ANA_CDR_PR_CKREF_DIV_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV, 0x0) ++#define AIROHA_PCS_ANA_CDR_PR_CKREF_DIV_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV, 0x1) ++#define AIROHA_PCS_ANA_CDR_PR_CKREF_DIV_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV, 0x2) ++#define AIROHA_PCS_ANA_CDR_PR_CKREF_DIV_X FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV, 0x3) ++#define AIROHA_PCS_ANA_PXP_CDR_PR_TDC_REF_SEL 0x108 ++#define AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1 GENMASK(25, 24) ++#define AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1, 0x0) ++#define AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1, 0x1) ++#define AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1, 0x2) ++#define AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1_X FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1, 0x3) + #define AIROHA_PCS_ANA_PXP_CDR_PR_MONPR_EN 0x10c + #define AIROHA_PCS_ANA_RX_DAC_MON GENMASK(28, 24) + #define AIROHA_PCS_ANA_CDR_PR_CAP_EN BIT(19) +@@ -484,6 +562,7 @@ + #define AIROHA_PCS_ANA_CDR_PR_MONDPR_EN BIT(0) + #define AIROHA_PCS_ANA_PXP_RX_DAC_RANGE 0x110 + #define AIROHA_PCS_ANA_RX_SIGDET_LPF_CTRL GENMASK(25, 24) ++#define AIROHA_PCS_ANA_RX_DAC_RANGE_EYE GENMASK(9, 8) + #define AIROHA_PCS_ANA_PXP_RX_SIGDET_NOVTH 0x114 + #define AIROHA_PCS_ANA_RX_FE_50OHMS_SEL GENMASK(25, 24) + #define AIROHA_PCS_ANA_RX_SIGDET_VTH_SEL GENMASK(20, 16) +@@ -532,7 +611,70 @@ + #define AIROHA_PCS_PMA_SS_LCPLL_PWCTL_SETTING_0 0x0 + #define AIROHA_PCS_PMA_SW_LCPLL_EN BIT(24) + #define AIROHA_PCS_PMA_SS_LCPLL_PWCTL_SETTING_1 0x4 ++#define AIROHA_PCS_PMA_LCPLL_CK_STB_TIMER GENMASK(31, 24) ++#define AIROHA_PCS_PMA_LCPLL_PCW_MAN_LOAD_TIMER GENMASK(23, 16) ++#define AIROHA_PCS_PMA_LCPLL_EN_TIMER GENMASK(15, 8) + #define AIROHA_PCS_PMA_LCPLL_MAN_PWDB BIT(0) ++#define AIROHA_PCS_PMA_LCPLL_TDC_PW_0 0x10 ++#define AIROHA_PCS_PMA_LCPLL_TDC_DIG_PWDB BIT(0) ++#define AIROHA_PCS_PMA_LCPLL_TDC_PW_5 0x24 ++#define AIROHA_PCS_PMA_LCPLL_TDC_SYNC_IN_MODE BIT(24) ++#define AIROHA_PCS_PMA_LCPLL_AUTOK_TDC BIT(16) ++#define AIROHA_PCS_PMA_LCPLL_TDC_FLT_0 0x28 ++#define AIROHA_PCS_PMA_LCPLL_KI GENMASK(10, 8) ++#define AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC GENMASK(1, 0) ++#define AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC_32 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC, 0x0) ++#define AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC_16 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC, 0x1) ++#define AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC_8 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC, 0x2) ++#define AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC_4 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC, 0x3) ++#define AIROHA_PCS_PMA_LCPLL_TDC_FLT_1 0x2c ++#define AIROHA_PCS_PMA_LCPLL_A_TDC GENMASK(11, 8) ++#define AIROHA_PCS_PMA_LCPLL_GPON_SEL BIT(0) ++#define AIROHA_PCS_PMA_LCPLL_GPON_SEL_FROM_EPON FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_GPON_SEL, 0x0) ++#define AIROHA_PCS_PMA_LCPLL_GPON_SEL_FROM_GPON FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_GPON_SEL, 0x1) ++#define AIROHA_PCS_PMA_LCPLL_TDC_FLT_3 0x34 ++#define AIROHA_PCS_PMA_LCPLL_NCPO_LOAD BIT(8) ++#define AIROHA_PCS_PMA_LCPLL_NCPO_SHIFT GENMASK(1, 0) ++#define AIROHA_PCS_PMA_LCPLL_TDC_FLT_5 0x3c ++#define AIROHA_PCS_PMA_LCPLL_TDC_AUTOPW_NCPO BIT(16) ++#define AIROHA_PCS_PMA_LCPLL_TDC_FLT_6 0x40 ++#define AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY GENMASK(9, 8) ++#define AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY_SEL FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY, 0x0) ++#define AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY_SEL_D1 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY, 0x1) ++#define AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY_SEL_D2 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY, 0x2) ++#define AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY_SEL_D3 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY, 0x3) ++#define AIROHA_PCS_PMA_LCPLL_TDC_PCW_1 0x48 ++#define AIROHA_PCS_PMA_LCPLL_PON_HRDDS_PCW_NCPO_GPON GENMASK(30, 0) ++#define AIROHA_PCS_PMA_LCPLL_TDC_PCW_2 0x4c ++#define AIROHA_PCS_PMA_LCPLL_PON_HRDDS_PCW_NCPO_EPON GENMASK(30, 0) ++#define AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_0 0x68 ++#define AIROHA_PCS_PMA_X_MAX GENMASK(26, 16) ++#define AIROHA_PCS_PMA_X_MIN GENMASK(10, 0) ++#define AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_1 0x6c ++#define AIROHA_PCS_PMA_INDEX_MODE BIT(16) ++#define AIROHA_PCS_PMA_Y_MAX GENMASK(14, 8) ++#define AIROHA_PCS_PMA_Y_MIN GENMASK(6, 0) ++#define AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_2 0x70 ++#define AIROHA_PCS_PMA_EYEDUR GENMASK(19, 0) ++#define AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_3 0x74 ++#define AIROHA_PCS_PMA_EYE_NEXTPTS BIT(16) ++#define AIROHA_PCS_PMA_EYE_NEXTPTS_TOGGLE BIT(8) ++#define AIROHA_PCS_PMA_EYE_NEXTPTS_SEL BIT(0) ++#define AIROHA_PCS_PMA_RX_EYE_TOP_EYEOPENING_CTRL_0 0x78 ++#define AIROHA_PCS_PMA_EYECNT_VTH GENMASK(15, 8) ++#define AIROHA_PCS_PMA_EYECNT_HTH GENMASK(7, 0) ++#define AIROHA_PCS_PMA_RX_EYE_TOP_EYEOPENING_CTRL_1 0x7c ++#define AIROHA_PCS_PMA_EO_VTH GENMASK(23, 16) ++#define AIROHA_PCS_PMA_EO_HTH GENMASK(10, 0) ++#define AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_0 0x80 ++#define AIROHA_PCS_PMA_EYE_MASK GENMASK(31, 24) ++#define AIROHA_PCS_PMA_CNTFOREVER BIT(16) ++#define AIROHA_PCS_PMA_CNTLEN GENMASK(9, 0) ++#define AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1 0x84 ++#define AIROHA_PCS_PMA_FORCE_EYEDUR_INIT_B BIT(24) ++#define AIROHA_PCS_PMA_FORCE_EYEDUR_EN BIT(16) ++#define AIROHA_PCS_PMA_DISB_EYEDUR_INIT_B BIT(8) ++#define AIROHA_PCS_PMA_DISB_EYEDUR_EN BIT(0) + #define AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_2 0x88 + #define AIROHA_PCS_PMA_DATA_SHIFT BIT(8) + #define AIROHA_PCS_PMA_EYECNT_FAST BIT(0) +@@ -564,14 +706,49 @@ + #define AIROHA_PCS_PMA_RX_BLWC_RDY_EN GENMASK(15, 0) + #define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_6 0x104 + #define AIROHA_PCS_PMA_RX_OS_END GENMASK(15, 0) ++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0 0x108 ++#define AIROHA_PCS_PMA_DISB_RX_FEOS_EN BIT(24) ++#define AIROHA_PCS_PMA_DISB_RX_PDOS_EN BIT(16) ++#define AIROHA_PCS_PMA_DISB_RX_PICAL_EN BIT(8) ++#define AIROHA_PCS_PMA_DISB_RX_OS_EN BIT(0) + #define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1 0x10c + #define AIROHA_PCS_PMA_DISB_RX_RDY BIT(24) ++#define AIROHA_PCS_PMA_DISB_RX_BLWC_EN BIT(16) ++#define AIROHA_PCS_PMA_DISB_RX_OS_RDY BIT(8) ++#define AIROHA_PCS_PMA_DISB_RX_SDCAL_EN BIT(0) ++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0 0x110 ++#define AIROHA_PCS_PMA_FORCE_RX_FEOS_EN BIT(24) ++#define AIROHA_PCS_PMA_FORCE_RX_PDOS_EN BIT(16) ++#define AIROHA_PCS_PMA_FORCE_RX_PICAL_EN BIT(8) ++#define AIROHA_PCS_PMA_FORCE_RX_OS_EN BIT(0) + #define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1 0x114 + #define AIROHA_PCS_PMA_FORCE_RX_RDY BIT(24) ++#define AIROHA_PCS_PMA_FORCE_RX_BLWC_EN BIT(16) ++#define AIROHA_PCS_PMA_FORCE_RX_OS_RDY BIT(8) ++#define AIROHA_PCS_PMA_FORCE_RX_SDCAL_EN BIT(0) ++#define AIROHA_PCS_PMA_PHY_EQ_CTRL_0 0x118 ++#define AIROHA_PCS_PMA_VEO_MASK GENMASK(31, 24) ++#define AIROHA_PCS_PMA_HEO_MASK GENMASK(18, 8) ++#define AIROHA_PCS_PMA_EQ_EN_DELAY GENMASK(7, 0) ++#define AIROHA_PCS_PMA_PHY_EQ_CTRL_1 0x11c ++#define AIROHA_PCS_PMA_B_ZERO_SEL BIT(24) ++#define AIROHA_PCS_PMA_HEO_EMPHASIS BIT(16) ++#define AIROHA_PCS_PMA_A_MGAIN BIT(8) ++#define AIROHA_PCS_PMA_A_LGAIN BIT(0) + #define AIROHA_PCS_PMA_PHY_EQ_CTRL_2 0x120 + #define AIROHA_PCS_PMA_EQ_DEBUG_SEL GENMASK(17, 16) + #define AIROHA_PCS_PMA_FOM_NUM_ORDER GENMASK(12, 8) + #define AIROHA_PCS_PMA_A_SEL GENMASK(1, 0) ++#define AIROHA_PCS_PMA_SS_RX_FEOS 0x144 ++#define AIROHA_PCS_PMA_EQ_FORCE_BLWC_FREEZE BIT(8) ++#define AIROHA_PCS_PMA_LFSEL GENMASK(7, 0) ++#define AIROHA_PCS_PMA_SS_RX_BLWC 0x148 ++#define AIROHA_PCS_PMA_EQ_BLWC_CNT_BOT_LIM GENMASK(29, 23) ++#define AIROHA_PCS_PMA_EQ_BLWC_CNT_TOP_LIM GENMASK(22, 16) ++#define AIROHA_PCS_PMA_EQ_BLWC_GAIN GENMASK(11, 8) ++#define AIROHA_PCS_PMA_EQ_BLWC_POL BIT(0) ++#define AIROHA_PCS_PMA_EQ_BLWC_POL_NORMAL FIELD_PREP_CONST(AIROHA_PCS_PMA_EQ_BLWC_POL, 0x0) ++#define AIROHA_PCS_PMA_EQ_BLWC_POL_INVERSION FIELD_PREP_CONST(AIROHA_PCS_PMA_EQ_BLWC_POL, 0x1) + #define AIROHA_PCS_PMA_SS_RX_FREQ_DET_1 0x14c + #define AIROHA_PCS_PMA_UNLOCK_CYCLECNT GENMASK(31, 16) + #define AIROHA_PCS_PMA_LOCK_CYCLECNT GENMASK(15, 0) +@@ -590,31 +767,182 @@ + #define AIROHA_PCS_PMA_FREQLOCK_DET_EN_WAIT FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x2) + #define AIROHA_PCS_PMA_FREQLOCK_DET_EN_NORMAL FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x3) + #define AIROHA_PCS_PMA_FREQLOCK_DET_EN_RX_STATE FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x7) ++#define AIROHA_PCS_PMA_RX_PI_CAL 0x15c ++#define AIROHA_PCS_PMA_KPGAIN GENMASK(10, 8) ++#define AIROHA_PCS_PMA_RX_CAL1 0x160 ++#define AIROHA_PCS_PMA_CAL_CYC GENMASK(25, 24) ++#define AIROHA_PCS_PMA_CAL_CYC_63 FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_CYC, 0x0) ++#define AIROHA_PCS_PMA_CAL_CYC_15 FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_CYC, 0x1) ++#define AIROHA_PCS_PMA_CAL_CYC_31 FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_CYC, 0x2) ++#define AIROHA_PCS_PMA_CAL_CYC_127 FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_CYC, 0x3) ++#define AIROHA_PCS_PMA_CAL_STB GENMASK(17, 16) ++#define AIROHA_PCS_PMA_CAL_STB_5US FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_STB, 0x0) ++#define AIROHA_PCS_PMA_CAL_STB_8US FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_STB, 0x1) ++#define AIROHA_PCS_PMA_CAL_STB_16US FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_STB, 0x2) ++#define AIROHA_PCS_PMA_CAL_STB_32US FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_STB, 0x3) ++#define AIROHA_PCS_PMA_CAL_1US_SET GENMASK(15, 8) ++#define AIROHA_PCS_PMA_SIM_FAST_EN BIT(0) ++#define AIROHA_PCS_PMA_RX_CAL2 0x164 ++#define AIROHA_PCS_PMA_CAL_CYC_TIME GENMASK(17, 16) ++#define AIROHA_PCS_PMA_CAL_OUT_OS GENMASK(11, 8) ++#define AIROHA_PCS_PMA_CAL_OS_PULSE BIT(0) + #define AIROHA_PCS_PMA_SS_RX_SIGDET_1 0x16c + #define AIROHA_PCS_PMA_SIGDET_EN BIT(0) ++#define AIROHA_PCS_PMA_RX_FLL_0 0x170 ++#define AIROHA_PCS_PMA_KBAND_KFC GENMASK(25, 24) ++#define AIROHA_PCS_PMA_KBAND_KFC_8 FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_KFC, 0x0) ++#define AIROHA_PCS_PMA_KBAND_KFC_16 FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_KFC, 0x1) ++#define AIROHA_PCS_PMA_KBAND_KFC_32 FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_KFC, 0x2) ++#define AIROHA_PCS_PMA_KBAND_KFC_64 FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_KFC, 0x3) ++#define AIROHA_PCS_PMA_FPKDIV GENMASK(18, 8) ++#define AIROHA_PCS_PMA_KBAND_PREDIV GENMASK(2, 0) ++#define AIROHA_PCS_PMA_KBAND_PREDIV_1 FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_PREDIV, 0x0) ++#define AIROHA_PCS_PMA_KBAND_PREDIV_2 FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_PREDIV, 0x1) ++#define AIROHA_PCS_PMA_KBAND_PREDIV_4 FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_PREDIV, 0x2) ++#define AIROHA_PCS_PMA_KBAND_PREDIV_8 FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_PREDIV, 0x3) + #define AIROHA_PCS_PMA_RX_FLL_1 0x174 ++#define AIROHA_PCS_PMA_SYMBOL_WD GENMASK(26, 24) ++#define AIROHA_PCS_PMA_SETTLE_TIME_SEL GENMASK(18, 16) + #define AIROHA_PCS_PMA_LPATH_IDAC GENMASK(10, 0) + #define AIROHA_PCS_PMA_RX_FLL_2 0x178 + #define AIROHA_PCS_PMA_CK_RATE GENMASK(18, 16) + #define AIROHA_PCS_PMA_CK_RATE_20 FIELD_PREP_CONST(AIROHA_PCS_PMA_CK_RATE, 0x0) + #define AIROHA_PCS_PMA_CK_RATE_10 FIELD_PREP_CONST(AIROHA_PCS_PMA_CK_RATE, 0x1) + #define AIROHA_PCS_PMA_CK_RATE_5 FIELD_PREP_CONST(AIROHA_PCS_PMA_CK_RATE, 0x2) ++#define AIROHA_PCS_PMA_AMP GENMASK(10, 8) ++#define AIROHA_PCS_PMA_PRBS_SEL GENMASK(2, 0) + #define AIROHA_PCS_PMA_RX_FLL_5 0x184 + #define AIROHA_PCS_PMA_FLL_IDAC_MIN GENMASK(26, 16) + #define AIROHA_PCS_PMA_FLL_IDAC_MAX GENMASK(10, 0) ++#define AIROHA_PCS_PMA_RX_FLL_6 0x188 ++#define AIROHA_PCS_PMA_LNX_SW_FLL_4_LATCH_EN BIT(24) ++#define AIROHA_PCS_PMA_LNX_SW_FLL_3_LATCH_EN BIT(16) ++#define AIROHA_PCS_PMA_LNX_SW_FLL_2_LATCH_EN BIT(8) ++#define AIROHA_PCS_PMA_LNX_SW_FLL_1_LATCH_EN BIT(0) + #define AIROHA_PCS_PMA_RX_FLL_B 0x19c + #define AIROHA_PCS_PMA_LOAD_EN BIT(0) ++#define AIROHA_PCS_PMA_RX_PDOS_CTRL_0 0x200 ++#define AIROHA_PCS_PMA_SAP_SEL GENMASK(18, 16) ++#define AIROHA_PCS_PMA_SAP_SEL_SHIFT_6 FIELD_PREP_CONST(AIROHA_PCS_PMA_SAP_SEL, 0x0) ++#define AIROHA_PCS_PMA_SAP_SEL_SHIFT_7 FIELD_PREP_CONST(AIROHA_PCS_PMA_SAP_SEL, 0x1) ++#define AIROHA_PCS_PMA_SAP_SEL_SHIFT_8 FIELD_PREP_CONST(AIROHA_PCS_PMA_SAP_SEL, 0x2) ++#define AIROHA_PCS_PMA_SAP_SEL_SHIFT_9 FIELD_PREP_CONST(AIROHA_PCS_PMA_SAP_SEL, 0x3) ++#define AIROHA_PCS_PMA_SAP_SEL_SHIFT_10 FIELD_PREP_CONST(AIROHA_PCS_PMA_SAP_SEL, 0x4) ++#define AIROHA_PCS_PMA_EYE_BLWC_ADD BIT(8) ++#define AIROHA_PCS_PMA_DATA_BLWC_ADD BIT(0) ++#define AIROHA_PCS_PMA_RX_RESET_0 0x204 ++#define AIROHA_PCS_PMA_CAL_RST_B BIT(24) ++#define AIROHA_PCS_PMA_EQ_PI_CAL_RST_B BIT(16) ++#define AIROHA_PCS_PMA_FEOS_RST_B BIT(8) + #define AIROHA_PCS_PMA_RX_RESET_1 0x208 + #define AIROHA_PCS_PMA_SIGDET_RST_B BIT(8) ++#define AIROHA_PCS_PMA_PDOS_RST_B BIT(0) ++#define AIROHA_PCS_PMA_RX_DEBUG_0 0x20c ++#define AIROHA_PCS_PMA_RO_TOGGLE BIT(24) ++#define AIROHA_PCS_PMA_BISTCTL_CONTROL 0x210 ++#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL GENMASK(4, 0) ++/* AIROHA_PCS_PMA_BISTCTL_PAT_SEL_ALL_0 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x0) */ ++#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PRBS7 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x1) ++#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PRBS9 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x2) ++#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PRBS15 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x3) ++#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PRBS23 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x4) ++#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PRBS31 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x5) ++#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_HFTP FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x6) ++#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_MFTP FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x7) ++#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_4 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x8) ++#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_5_LFTP FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x9) ++#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_6 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0xa) ++#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_7 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0xb) ++#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_8_LFTP FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0xc) ++#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_9 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0xd) ++#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_10 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0xe) ++#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_11 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0xf) ++#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PROG_80 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x10) ++#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_ALL_1 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x11) ++#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_ALL_0 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x12) ++#define AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PRBS11 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x13) ++#define AIROHA_PCS_PMA_BISTCTL_ALIGN_PAT 0x214 ++#define AIROHA_PCS_PMA_BISTCTL_POLLUTION 0x220 ++#define AIROHA_PCS_PMA_BIST_TX_DATA_POLLUTION_LATCH BIT(16) ++#define AIROHA_PCS_PMA_BISTCTL_PRBS_INITIAL_SEED 0x224 ++#define AIROHA_PCS_PMA_BISTCTL_PRBS_FAIL_THRESHOLD 0x230 ++#define AIROHA_PCS_PMA_BISTCTL_PRBS_FAIL_THRESHOLD_MASK GENMASK(15, 0) ++#define AIROHA_PCS_PMA_RX_TORGS_DEBUG_2 0x23c ++#define AIROHA_PCS_PMA_PI_CAL_DATA_OUT GENMASK(22, 16) ++#define AIROHA_PCS_PMA_RX_TORGS_DEBUG_5 0x248 ++#define AIROHA_PCS_PMA_VEO_RDY BIT(24) ++#define AIROHA_PCS_PMA_HEO_RDY BIT(16) ++#define AIROHA_PCS_PMA_RX_TORGS_DEBUG_9 0x258 ++#define AIROHA_PCS_PMA_EO_Y_DONE BIT(24) ++#define AIROHA_PCS_PMA_EO_X_DONE BIT(16) ++#define AIROHA_PCS_PMA_RX_TORGS_DEBUG_10 0x25c ++#define AIROHA_PCS_PMA_EYE_EL GENMASK(26, 16) ++#define AIROHA_PCS_PMA_EYE_ER GENMASK(10, 0) + #define AIROHA_PCS_PMA_TX_RST_B 0x260 + #define AIROHA_PCS_PMA_TXCALIB_RST_B BIT(8) + #define AIROHA_PCS_PMA_TX_TOP_RST_B BIT(0) ++#define AIROHA_PCS_PMA_TX_CALIB_0 0x264 ++#define AIROHA_PCS_PMA_TXCALIB_FORCE_TERMP_SEL GENMASK(25, 24) ++#define AIROHA_PCS_PMA_TXCALIB_FORCE_TERMP_SEL_EN BIT(16) ++#define AIROHA_PCS_PMA_RX_TORGS_DEBUG_11 0x290 ++#define AIROHA_PCS_PMA_EYE_EB GENMASK(14, 8) ++#define AIROHA_PCS_PMA_EYE_EU GENMASK(6, 0) ++#define AIROHA_PCS_PMA_RX_FORCE_MODE_0 0x294 ++#define AIROHA_PCS_PMA_FORCE_DA_XPON_CDR_LPF_RSTB BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_XPON_RX_FE_GAIN_CTRL GENMASK(1, 0) ++#define AIROHA_PCS_PMA_RX_DISB_MODE_0 0x300 ++#define AIROHA_PCS_PMA_DISB_DA_XPON_CDR_LPF_RSTB BIT(24) ++#define AIROHA_PCS_PMA_DISB_DA_XPON_RX_FE_GAIN_CTRL BIT(0) ++#define AIROHA_PCS_PMA_RX_DISB_MODE_1 0x304 ++#define AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_E0 BIT(24) ++#define AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_D1 BIT(16) ++#define AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_D0 BIT(8) ++#define AIROHA_PCS_PMA_RX_DISB_MODE_2 0x308 ++#define AIROHA_PCS_PMA_DISB_DA_XPON_CDR_PR_PIEYE BIT(24) ++#define AIROHA_PCS_PMA_DISB_DA_XPON_RX_FE_VOS BIT(16) ++#define AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_EYE BIT(8) ++#define AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_E1 BIT(0) ++#define AIROHA_PCS_PMA_RX_FORCE_MODE_3 0x30c ++#define AIROHA_PCS_PMA_FORCE_EQ_PI_CAL_RDY BIT(0) ++#define AIROHA_PCS_PMA_RX_FORCE_MODE_6 0x318 ++#define AIROHA_PCS_PMA_FORCE_RX_OR_PICAL_EN BIT(8) ++#define AIROHA_PCS_PMA_FORCE_EYECNT_RDY BIT(0) ++#define AIROHA_PCS_PMA_RX_DISB_MODE_3 0x31c ++#define AIROHA_PCS_PMA_DISB_RQ_PI_CAL_RDY BIT(0) + #define AIROHA_PCS_PMA_RX_DISB_MODE_4 0x320 + #define AIROHA_PCS_PMA_DISB_BLWC_OFFSET BIT(24) ++#define AIROHA_PCS_PMA_RX_DISB_MODE_5 0x324 ++#define AIROHA_PCS_PMA_DISB_RX_OR_PICAL_EN BIT(24) ++#define AIROHA_PCS_PMA_DISB_EYECNT_RDY BIT(16) ++#define AIROHA_PCS_PMA_RX_FORCE_MODE_7 0x328 ++#define AIROHA_PCS_PMA_FORCE_PDOS_RX_RST_B BIT(16) ++#define AIROHA_PCS_PMA_FORCE_RX_AND_PICAL_RSTB BIT(8) ++#define AIROHA_PCS_PMA_FORCE_REF_AND_PICAL_RSTB BIT(0) ++#define AIROHA_PCS_PMA_RX_FORCE_MODE_8 0x32c ++#define AIROHA_PCS_PMA_FORCE_EYECNT_RX_RST_B BIT(24) ++#define AIROHA_PCS_PMA_FORCE_FEOS_RX_RST_B BIT(16) ++#define AIROHA_PCS_PMA_FORCE_SDCAL_REF_RST_B BIT(8) ++#define AIROHA_PCS_PMA_FORCE_BLWC_RX_RST_B BIT(0) + #define AIROHA_PCS_PMA_RX_FORCE_MODE_9 0x330 ++#define AIROHA_PCS_PMA_FORCE_EYE_TOP_EN BIT(16) ++#define AIROHA_PCS_PMA_FORCE_EYE_RESET_PLU_O BIT(8) + #define AIROHA_PCS_PMA_FORCE_FBCK_LOCK BIT(0) ++#define AIROHA_PCS_PMA_RX_DISB_MODE_6 0x334 ++#define AIROHA_PCS_PMA_DISB_PDOS_RX_RST_B BIT(16) ++#define AIROHA_PCS_PMA_DISB_RX_AND_PICAL_RSTB BIT(8) ++#define AIROHA_PCS_PMA_DISB_REF_AND_PICAL_RSTB BIT(0) ++#define AIROHA_PCS_PMA_RX_DISB_MODE_7 0x338 ++#define AIROHA_PCS_PMA_DISB_EYECNT_RX_RST_B BIT(24) ++#define AIROHA_PCS_PMA_DISB_FEOS_RX_RST_B BIT(16) ++#define AIROHA_PCS_PMA_DISB_SDCAL_REF_RST_B BIT(8) ++#define AIROHA_PCS_PMA_DISB_BLWC_RX_RST_B BIT(0) + #define AIROHA_PCS_PMA_RX_DISB_MODE_8 0x33c ++#define AIROHA_PCS_PMA_DISB_EYE_TOP_EN BIT(16) ++#define AIROHA_PCS_PMA_DISB_EYE_RESET_PLU_O BIT(8) + #define AIROHA_PCS_PMA_DISB_FBCK_LOCK BIT(0) ++#define AIROHA_PCS_PMA_SS_BIST_1 0x344 ++#define AIROHA_PCS_PMA_LNX_BISTCTL_BIT_ERROR_RST_SEL BIT(24) ++#define AIROHA_PCS_PMA_ANLT_PX_LNX_LT_LOS BIT(0) + #define AIROHA_PCS_PMA_SS_DA_XPON_PWDB_0 0x34c + #define AIROHA_PCS_PMA_XPON_CDR_PD_PWDB BIT(24) + #define AIROHA_PCS_PMA_XPON_CDR_PR_PIEYE_PWDB BIT(16) +@@ -637,7 +965,32 @@ + #define AIROHA_PCS_PMA_PLL_LOCK_TARGET_BEG GENMASK(15, 0) + #define AIROHA_PCS_PMA_PLL_TDC_FREQDET_3 0x39c + #define AIROHA_PCS_PMA_PLL_LOCK_LOCKTH GENMASK(11, 8) ++#define AIROHA_PCS_PMA_ADD_CLKPATH_RST_0 0x410 ++#define AIROHA_PCS_PMA_CLKPATH_RSTB_CK BIT(8) ++#define AIROHA_PCS_PMA_CLKPATH_RST_EN BIT(0) ++#define AIROHA_PCS_PMA_ADD_XPON_MODE_1 0x414 ++#define AIROHA_PCS_PMA_TX_BIST_GEN_EN BIT(16) ++#define AIROHA_PCS_PMA_R2T_MODE BIT(8) ++#define AIROHA_PCS_PMA_ADD_RX2ANA_1 0x424 ++#define AIROHA_PCS_PMA_RX_DAC_E0 GENMASK(30, 24) ++#define AIROHA_PCS_PMA_RX_DAC_D1 GENMASK(22, 16) ++#define AIROHA_PCS_PMA_RX_DAC_D0 GENMASK(14, 8) ++#define AIROHA_PCS_PMA_RX_DAC_EYE GENMASK(6, 0) ++#define AIROHA_PCS_PMA_ADD_RX2ANA_2 0x428 ++#define AIROHA_PCS_PMA_RX_FEOS_OUT GENMASK(13, 8) ++#define AIROHA_PCS_PMA_RX_DAC_E1 GENMASK(6, 0) ++#define AIROHA_PCS_PMA_PON_TX_COUNTER_0 0x440 ++#define AIROHA_PCS_PMA_TXCALIB_5US GENMASK(31, 16) ++#define AIROHA_PCS_PMA_TXCALIB_50US GENMASK(15, 0) ++#define AIROHA_PCS_PMA_PON_TX_COUNTER_1 0x444 ++#define AIROHA_PCS_PMA_TX_HSDATA_EN_WAIT GENMASK(31, 16) ++#define AIROHA_PCS_PMA_TX_CK_EN_WAIT GENMASK(15, 0) ++#define AIROHA_PCS_PMA_PON_TX_COUNTER_2 0x448 ++#define AIROHA_PCS_PMA_TX_SERDES_RDY_WAIT GENMASK(31, 16) ++#define AIROHA_PCS_PMA_TX_POWER_ON_WAIT GENMASK(15, 0) + #define AIROHA_PCS_PMA_SW_RST_SET 0x460 ++#define AIROHA_PCS_PMA_SW_XFI_RXMAC_RST_N BIT(17) ++#define AIROHA_PCS_PMA_SW_XFI_TXMAC_RST_N BIT(16) + #define AIROHA_PCS_PMA_SW_HSG_RXPCS_RST_N BIT(11) + #define AIROHA_PCS_PMA_SW_HSG_TXPCS_RST_N BIT(10) + #define AIROHA_PCS_PMA_SW_XFI_RXPCS_BIST_RST_N BIT(9) +@@ -650,17 +1003,32 @@ + #define AIROHA_PCS_PMA_SW_TX_RST_N BIT(2) + #define AIROHA_PCS_PMA_SW_RX_RST_N BIT(1) + #define AIROHA_PCS_PMA_SW_RX_FIFO_RST_N BIT(0) ++#define AIROHA_PCS_PMA_TX_DLY_CTRL 0x468 ++#define AIROHA_PCS_PMA_OUTBEN_DATA_MODE GENMASK(30, 28) ++#define AIROHA_PCS_PMA_TX_BEN_EXTEN_FTUNE GENMASK(23, 16) ++#define AIROHA_PCS_PMA_TX_DLY_BEN_FTUNE GENMASK(14, 8) ++#define AIROHA_PCS_PMA_TX_DLY_DATA_FTUNE GENMASK(6, 0) + #define AIROHA_PCS_PMA_XPON_INT_EN_3 0x474 + #define AIROHA_PCS_PMA_RX_SIGDET_INT_EN BIT(16) + #define AIROHA_PCS_PMA_XPON_INT_STA_3 0x47c + #define AIROHA_PCS_PMA_RX_SIGDET_INT BIT(16) + #define AIROHA_PCS_PMA_RX_EXTRAL_CTRL 0x48c ++/* 4ref_ck step: ++ * - 0x1 4ref_ck ++ * - 0x2 8ref_ck ++ * - 0x3 12ref_ck ++ * ... ++ */ ++#define AIROHA_PCS_PMA_L2D_TRIG_EQ_EN_TIME GENMASK(15, 8) ++#define AIROHA_PCS_PMA_OS_RDY_LATCH BIT(1) + #define AIROHA_PCS_PMA_DISB_LEQ BIT(0) + #define AIROHA_PCS_PMA_RX_FREQDET 0x530 + #define AIROHA_PCS_PMA_FL_OUT GENMASK(31, 16) + #define AIROHA_PCS_PMA_FBCK_LOCK BIT(0) + #define AIROHA_PCS_PMA_XPON_TX_RATE_CTRL 0x580 + #define AIROHA_PCS_PMA_PON_TX_RATE_CTRL GENMASK(1, 0) ++#define AIROHA_PCS_PMA_MD32_MEM_CLK_CTRL 0x60c ++#define AIROHA_PCS_PMA_MD32PM_CK_SEL GENMASK(31, 0) + #define AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN 0x768 + #define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PEAKING_CTRL BIT(24) + #define AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL GENMASK(19, 16) +@@ -683,8 +1051,13 @@ + #define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C1 BIT(8) + #define AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C1 GENMASK(5, 0) + #define AIROHA_PCS_PMA_PXP_TX_RATE_CTRL 0x784 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PIEYE BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PIEYE GENMASK(22, 16) + #define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_RATE_CTRL BIT(8) + #define AIROHA_PCS_PMA_FORCE_DA_TX_RATE_CTRL GENMASK(1, 0) ++#define AIROHA_PCS_PMA_PXP_CDR_PR_FLL_COR 0x790 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_DAC_EYE BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_RX_DAC_EYE GENMASK(22, 16) + #define AIROHA_PCS_PMA_PXP_CDR_PR_IDAC 0x794 + #define AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_SDM_PCW BIT(24) + #define AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_IDAC BIT(16) +@@ -729,6 +1102,14 @@ + #define AIROHA_PCS_PMA_FORCE_DA_JCPLL_EN BIT(16) + #define AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_CKOUT_EN BIT(8) + #define AIROHA_PCS_PMA_FORCE_DA_JCPLL_CKOUT_EN BIT(0) ++#define AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN_RSTB 0x83c ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_CKON BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_CKON BIT(16) ++#define AIROHA_PCS_PMA_PXP_RX_OSCAL_EN 0x840 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_RSTB BIT(24) ++#define AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_RSTB BIT(16) ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_EN BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_EN BIT(0) + #define AIROHA_PCS_PMA_PXP_RX_SCAN_RST_B 0x84c + #define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_PWDB BIT(24) + #define AIROHA_PCS_PMA_FORCE_DA_RX_SIGDET_PWDB BIT(16) +@@ -739,6 +1120,12 @@ + #define AIROHA_PCS_PMA_FORCE_DA_TXPLL_EN BIT(16) + #define AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_CKOUT_EN BIT(8) + #define AIROHA_PCS_PMA_FORCE_DA_TXPLL_CKOUT_EN BIT(0) ++#define AIROHA_PCS_PMA_PXP_TXPLL_KBAND_LOAD_EN 0x858 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_KBAND_LOAD_EN BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_TXPLL_KBAND_LOAD_EN BIT(0) ++#define AIROHA_PCS_PMA_PXP_TXPLL_SDM_PCW_CHG 0x864 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_SDM_PCW_CHG BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_TXPLL_SDM_PCW_CHG BIT(0) + #define AIROHA_PCS_PMA_PXP_TX_ACJTAG_EN 0x874 + #define AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_SEL BIT(24) + #define AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_SEL BIT(16) +@@ -750,10 +1137,31 @@ + #define AIROHA_PCS_PMA_FORCE_DA_RX_PDOSCAL_EN BIT(16) + #define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PWDB BIT(8) + #define AIROHA_PCS_PMA_FORCE_DA_RX_FE_PWDB BIT(0) ++#define AIROHA_PCS_PMA_PXP_RX_SIGDET_CAL_EN 0x898 ++#define AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_CAL_EN BIT(8) ++#define AIROHA_PCS_PMA_FORCE_DA_RX_SIGDET_CAL_EN BIT(0) ++#define AIROHA_PCS_PMA_DIG_RESERVE_12 0x8b8 ++#define AIROHA_PCS_PMA_RESERVE_12_FEOS_0 BIT(0) ++#define AIROHA_PCS_PMA_DIG_RESERVE_24 0x8fc ++#define AIROHA_PCS_PMA_FORCE_RX_GEARBOX BIT(12) ++#define AIROHA_PCS_PMA_FORCE_SEL_RX_GEARBOX BIT(8) + + #define AIROHA_PCS_MAX_CALIBRATION_TRY 50 + #define AIROHA_PCS_MAX_NUM_RSTS 2 + ++enum pon_eo_buf_vals { ++ EYE_EU, ++ EYE_EB, ++ DAC_D0, ++ DAC_D1, ++ DAC_E0, ++ DAC_E1, ++ DAC_EYE, ++ FEOS, ++ ++ EO_BUF_MAX, ++}; ++ + enum xfi_port_type { + AIROHA_PCS_ETH, + AIROHA_PCS_PON, +@@ -790,6 +1198,11 @@ struct airoha_pcs_port { + struct airoha_pcs_match_data { + enum xfi_port_type port_type; + ++ bool hibernation_workaround; ++ bool usxgmii_ber_time_fixup; ++ bool usxgmii_rx_gb_out_vld_tweak; ++ bool usxgmii_xfi_mode_sel; ++ + int (*bringup)(struct airoha_pcs_priv *priv, + phy_interface_t interface); + void (*link_up)(struct airoha_pcs_priv *priv); +@@ -820,3 +1233,20 @@ static inline int an7581_pcs_rxlock_work + return 0; + } + #endif ++ ++#ifdef CONFIG_PCS_AIROHA_AN7583 ++int an7583_pcs_common_phya_bringup(struct airoha_pcs_priv *priv, ++ phy_interface_t interface); ++ ++void an7583_pcs_common_phya_link_up(struct airoha_pcs_priv *priv); ++#else ++static inline int an7583_pcs_common_phya_bringup(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static inline void an7583_pcs_common_phya_link_up(struct airoha_pcs_priv *priv) ++{ ++} ++#endif +--- /dev/null ++++ b/drivers/net/pcs/airoha/pcs-an7583.c +@@ -0,0 +1,2199 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2024 AIROHA Inc ++ * Author: Christian Marangi ++ */ ++#include ++#include ++ ++#include "pcs-airoha.h" ++ ++static void an7583_pcs_dig_reset_hold(struct airoha_pcs_priv *priv) ++{ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_RX_FIFO_RST_N | ++ AIROHA_PCS_PMA_SW_TX_FIFO_RST_N); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_REF_RST_N); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_ALLPCS_RST_N); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_TX_RST_N | ++ AIROHA_PCS_PMA_SW_RX_RST_N); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_PMA_RST_N); ++ ++ usleep_range(50, 100); ++} ++ ++static void an7583_pcs_dig_reset_release(struct airoha_pcs_priv *priv) ++{ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_REF_RST_N); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_TX_RST_N | ++ AIROHA_PCS_PMA_SW_RX_RST_N); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_PMA_RST_N); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_RX_FIFO_RST_N | ++ AIROHA_PCS_PMA_SW_TX_FIFO_RST_N); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_ALLPCS_RST_N); ++ ++ usleep_range(100, 200); ++} ++ ++static void an7583_pcs_common_phya_txpll(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ u32 pcw, tdc_pcw; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: /* DS(RX)_1.25G / US(TX)_1.25G*/ ++ case PHY_INTERFACE_MODE_1000BASEX: ++ pcw = 0x32000000; ++ tdc_pcw = 0x64000000; ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: /* DS(RX)_3.125G / US(TX)_3.125G */ ++ pcw = 0x3e800000; ++ tdc_pcw = 0x7d000000; ++ break; ++ case PHY_INTERFACE_MODE_5GBASER: /* DS(RX)_5.15625G / US(TX)_5.15625G */ ++ case PHY_INTERFACE_MODE_USXGMII: /* DS(RX)_10.31252G / US(TX)_10.3125G */ ++ case PHY_INTERFACE_MODE_10GBASER: ++ pcw = 0x33900000; ++ tdc_pcw = 0x67200000; ++ break; ++ default: ++ return; ++ } ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_IDAC, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_SDM_PCW); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_LCPLL_TDC_FLT_3, ++ AIROHA_PCS_PMA_LCPLL_NCPO_LOAD); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_SDM_PCW, ++ AIROHA_PCS_PMA_FORCE_DA_TXPLL_SDM_PCW, ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TXPLL_SDM_PCW, pcw)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_LCPLL_TDC_PCW_1, ++ AIROHA_PCS_PMA_LCPLL_PON_HRDDS_PCW_NCPO_GPON, ++ FIELD_PREP(AIROHA_PCS_PMA_LCPLL_PON_HRDDS_PCW_NCPO_GPON, ++ tdc_pcw)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_LCPLL_TDC_PCW_2, ++ AIROHA_PCS_PMA_LCPLL_PON_HRDDS_PCW_NCPO_EPON, ++ FIELD_PREP(AIROHA_PCS_PMA_LCPLL_PON_HRDDS_PCW_NCPO_EPON, ++ tdc_pcw)); ++} ++ ++static void an7583_pcs_common_phya_tx(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ const struct airoha_pcs_match_data *data = priv->data; ++ u32 tx_rate_ctrl; ++ u32 ckin_divisor; ++ u32 fir_cn1, fir_c0b, fir_c1, fir_c2; ++ u32 tx_ben_exten_ftune; ++ u32 tx_dly_ben_ftune; ++ u32 tx_dly_data_ftune; ++ ++ if (data->port_type == AIROHA_PCS_ETH) ++ tx_ben_exten_ftune = 0x2; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ ckin_divisor = BIT(1); ++ tx_rate_ctrl = BIT(0); ++ fir_cn1 = 0; ++ fir_c0b = 8; ++ fir_c1 = 0; ++ fir_c2 = 0; ++ ++ if (data->port_type == AIROHA_PCS_PON) { ++ tx_ben_exten_ftune = 0x7; ++ tx_dly_ben_ftune = 0x2; ++ tx_dly_data_ftune = 0x6; ++ } ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: ++ ckin_divisor = BIT(2); ++ tx_rate_ctrl = BIT(0); ++ fir_cn1 = 0; ++ fir_c0b = 8; ++ fir_c1 = 1; ++ fir_c2 = 0; ++ if (data->port_type == AIROHA_PCS_PON) ++ tx_ben_exten_ftune = 0x2; ++ break; ++ case PHY_INTERFACE_MODE_5GBASER: ++ ckin_divisor = BIT(2); ++ tx_rate_ctrl = BIT(1); ++ fir_cn1 = 0; ++ fir_c0b = 14; ++ fir_c1 = 4; ++ fir_c2 = 0; ++ if (data->port_type == AIROHA_PCS_PON) ++ tx_ben_exten_ftune = 0x2; ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ ckin_divisor = BIT(2) | BIT(0); ++ tx_rate_ctrl = BIT(1); ++ fir_cn1 = 0; ++ fir_c0b = 14; ++ fir_c1 = 4; ++ fir_c2 = 0; ++ ++ if (data->port_type == AIROHA_PCS_PON) { ++ tx_ben_exten_ftune = 0x16; ++ tx_dly_ben_ftune = 0xd; ++ tx_dly_data_ftune = 0x30; ++ } ++ ++ break; ++ default: ++ return; ++ } ++ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TX_CKLDO_EN, ++ AIROHA_PCS_ANA_TX_DMEDGEGEN_EN | ++ AIROHA_PCS_ANA_TX_CKLDO_EN); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CMN_EN, ++ AIROHA_PCS_ANA_CMN_VREFSEL | ++ AIROHA_PCS_ANA_CMN_MPXSELTOP_DC | ++ AIROHA_PCS_ANA_CMN_EN, ++ AIROHA_PCS_ANA_CMN_VREFSEL_9V | ++ FIELD_PREP(AIROHA_PCS_ANA_CMN_MPXSELTOP_DC, 0x1) | ++ AIROHA_PCS_ANA_CMN_EN); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_ACJTAG_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_SEL | ++ AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_SEL); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_FIR_C0B, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_CN1 | ++ AIROHA_PCS_PMA_FORCE_DA_TX_FIR_CN1 | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C0B | ++ AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C0B, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_CN1 | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_FIR_CN1, fir_cn1) | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C0B | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C0B, fir_c0b)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_FIR_C1, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C2 | ++ AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C2 | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C1 | ++ AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C1, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C2 | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C2, fir_c2) | ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C1 | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C1, fir_c1)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_TERM_SEL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_DIVISOR | ++ AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_DIVISOR, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_DIVISOR | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_DIVISOR, ++ ckin_divisor)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_RATE_CTRL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_RATE_CTRL | ++ AIROHA_PCS_PMA_FORCE_DA_TX_RATE_CTRL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TX_RATE_CTRL | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_RATE_CTRL, ++ tx_rate_ctrl)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_XPON_TX_RATE_CTRL, ++ AIROHA_PCS_PMA_PON_TX_RATE_CTRL, ++ FIELD_PREP(AIROHA_PCS_PMA_PON_TX_RATE_CTRL, ++ tx_rate_ctrl)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_TX_DLY_CTRL, ++ AIROHA_PCS_PMA_TX_BEN_EXTEN_FTUNE, ++ FIELD_PREP(AIROHA_PCS_PMA_TX_BEN_EXTEN_FTUNE, tx_ben_exten_ftune)); ++ ++ if (data->port_type == AIROHA_PCS_PON) { ++ if (interface == PHY_INTERFACE_MODE_SGMII || interface == PHY_INTERFACE_MODE_1000BASEX || ++ interface == PHY_INTERFACE_MODE_USXGMII || interface == PHY_INTERFACE_MODE_10GBASER) ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_TX_DLY_CTRL, ++ AIROHA_PCS_PMA_TX_DLY_BEN_FTUNE | ++ AIROHA_PCS_PMA_TX_DLY_DATA_FTUNE, ++ FIELD_PREP(AIROHA_PCS_PMA_TX_DLY_BEN_FTUNE, tx_dly_ben_ftune) | ++ FIELD_PREP(AIROHA_PCS_PMA_TX_DLY_DATA_FTUNE, tx_dly_data_ftune)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_MD32_MEM_CLK_CTRL, ++ AIROHA_PCS_PMA_MD32PM_CK_SEL, ++ FIELD_PREP(AIROHA_PCS_PMA_MD32PM_CK_SEL, 0x3)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_TX_DLY_CTRL, ++ AIROHA_PCS_PMA_OUTBEN_DATA_MODE, ++ FIELD_PREP(AIROHA_PCS_PMA_OUTBEN_DATA_MODE, 0x1)); ++ } ++} ++ ++static void an7583_pcs_common_phya_rx(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ const struct airoha_pcs_match_data *data = priv->data; ++ ++ u32 rx_rev0; ++ u32 fe_gain_ctrl; ++ u32 dig_reserve_0; ++ u32 rx_force_mode_0; ++ u32 cdr_pr_beta_dac; ++ u32 phyck_sel; ++ u32 phyck_div; ++ u32 lpf_ratio; ++ u32 busbit_sel; ++ u32 rx_rate_ctrl; ++ u32 osr; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ dig_reserve_0 = 0x300; ++ cdr_pr_beta_dac = 0x8; ++ phyck_sel = 0x1; ++ phyck_div = 0x29; ++ lpf_ratio = 0x3; ++ osr = 0x3; ++ rx_rate_ctrl = 0x0; ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: ++ dig_reserve_0 = 0x300; ++ cdr_pr_beta_dac = 0x6; ++ phyck_sel = 0x1; ++ phyck_div = 0xb; ++ lpf_ratio = 0x1; ++ osr = 0x1; ++ rx_rate_ctrl = 0x0; ++ break; ++ case PHY_INTERFACE_MODE_5GBASER: ++ dig_reserve_0 = 0x400; ++ cdr_pr_beta_dac = 0x8; ++ phyck_sel = 0x2; ++ phyck_div = 0x42; ++ lpf_ratio = 0x1; ++ osr = 0x1; ++ rx_rate_ctrl = 0x2; ++ break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GBASER: ++ dig_reserve_0 = 0x100; ++ cdr_pr_beta_dac = 0x8; ++ phyck_sel = 0x2; ++ phyck_div = 0x42; ++ lpf_ratio = 0x0; ++ osr = 0x0; ++ rx_rate_ctrl = 0x2; ++ break; ++ default: ++ return; ++ } ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_REV_0, ++ AIROHA_PCS_ANA_REV_1_FE_BUF1_BIAS_CTRL | ++ AIROHA_PCS_ANA_REV_1_FE_BUF2_BIAS_CTRL | ++ AIROHA_PCS_ANA_REV_1_SIGDET_ILEAK, ++ FIELD_PREP(AIROHA_PCS_ANA_REV_1_FE_BUF1_BIAS_CTRL, BIT(2)) | ++ FIELD_PREP(AIROHA_PCS_ANA_REV_1_FE_BUF2_BIAS_CTRL, BIT(2)) | ++ FIELD_PREP(AIROHA_PCS_ANA_REV_1_SIGDET_ILEAK, 0x0)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_OSCAL_WATCH_WNDW, ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE, ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA2VOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA2IOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA1VOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA1IOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE2VOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE2IOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE1VOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE1IOS | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_LVSH | ++ AIROHA_PCS_ANA_RX_OSCAL_FORCE_COMPOS); ++ ++ regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PD_PICAL_CKD8_INV, ++ AIROHA_PCS_ANA_CDR_PD_EDGE_DIS | ++ AIROHA_PCS_ANA_CDR_PD_PICAL_CKD8_INV); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_AEQ_RSTB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_INJCK_SEL | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_INJCK_SEL); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_FE_GAIN_CTRL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_GAIN_CTRL); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_DIG_RESERVE_12, ++ AIROHA_PCS_PMA_RESERVE_12_FEOS_0); ++ ++ if (interface == PHY_INTERFACE_MODE_USXGMII || ++ interface == PHY_INTERFACE_MODE_10GBASER) { ++ rx_rev0 = FIELD_PREP(AIROHA_PCS_ANA_REV_0_FE_BUF2_BIAS_TYPE, 0x1) | ++ FIELD_PREP(AIROHA_PCS_ANA_REV_0_FE_BUF_GAIN_MODE_NORMAL, 0x3); ++ fe_gain_ctrl = 0x1; ++ rx_force_mode_0 = 0x1; ++ } else { ++ rx_rev0 = FIELD_PREP(AIROHA_PCS_ANA_REV_0_FE_BUF2_BIAS_TYPE, 0x1) | ++ AIROHA_PCS_ANA_REV_0_OSCAL_FE_MODE_SET_SEL | ++ BIT(7) | /* FIXME: Missing documentation for this BIT */ ++ FIELD_PREP(AIROHA_PCS_ANA_REV_0_FE_BUF_GAIN_MODE_NORMAL, 0x3); ++ fe_gain_ctrl = 0x3; ++ rx_force_mode_0 = 0x3; ++ } ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_REV_0, ++ AIROHA_PCS_ANA_RX_REV_0, rx_rev0); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_FE_GAIN_CTRL, ++ AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL, ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL, ++ fe_gain_ctrl)); ++ ++ regmap_write(priv->xfi_pma, AIROHA_PCS_PMA_DIG_RESERVE_0, ++ dig_reserve_0); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_0, ++ AIROHA_PCS_PMA_FORCE_DA_XPON_RX_FE_GAIN_CTRL, ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_XPON_RX_FE_GAIN_CTRL, ++ rx_force_mode_0)); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_0, ++ AIROHA_PCS_PMA_DISB_DA_XPON_RX_FE_GAIN_CTRL); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_BETA_DAC, ++ AIROHA_PCS_ANA_CDR_PR_BETA_DAC, ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_BETA_DAC, ++ cdr_pr_beta_dac)); ++ ++ if (data->port_type == AIROHA_PCS_ETH && ++ interface == PHY_INTERFACE_MODE_2500BASEX) ++ regmap_update_bits(priv->xfi_ana, ++ AIROHA_PCS_ANA_PXP_CDR_PR_VREG_IBAND_VAL, ++ AIROHA_PCS_ANA_CDR_PR_DAC_BAND, ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_DAC_BAND, ++ 0x6)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_PHYCK_DIV, ++ AIROHA_PCS_ANA_RX_PHYCK_SEL, ++ FIELD_PREP(AIROHA_PCS_ANA_RX_PHYCK_SEL, phyck_sel)); ++ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_MONPR_EN, ++ AIROHA_PCS_ANA_CDR_PR_XFICK_EN); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_BUSBIT_SEL, ++ AIROHA_PCS_ANA_RX_PHY_CK_SEL_FORCE | ++ AIROHA_PCS_ANA_RX_PHY_CK_SEL, ++ AIROHA_PCS_ANA_RX_PHY_CK_SEL_FORCE); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_PHYCK_DIV, ++ AIROHA_PCS_ANA_RX_PHYCK_RSTB | ++ AIROHA_PCS_ANA_RX_PHYCK_DIV, ++ AIROHA_PCS_ANA_RX_PHYCK_RSTB | ++ FIELD_PREP(AIROHA_PCS_ANA_RX_PHYCK_DIV, phyck_div)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_LPF_RATIO, ++ AIROHA_PCS_ANA_CDR_LPF_RATIO, ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_LPF_RATIO, ++ lpf_ratio)); ++ ++ if (interface == PHY_INTERFACE_MODE_5GBASER) ++ busbit_sel = AIROHA_PCS_ANA_RX_BUSBIT_SEL_FORCE | ++ AIROHA_PCS_ANA_RX_BUSBIT_SEL_16BIT; ++ else ++ busbit_sel = 0; ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_BUSBIT_SEL, ++ AIROHA_PCS_ANA_RX_BUSBIT_SEL_FORCE | ++ AIROHA_PCS_ANA_RX_BUSBIT_SEL, ++ busbit_sel); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_AEQ_SPEED, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_OSR_SEL | ++ AIROHA_PCS_PMA_FORCE_DA_OSR_SEL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_OSR_SEL | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_OSR_SEL, osr)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_XPON_RX_RESERVED_1, ++ AIROHA_PCS_PMA_XPON_RX_RATE_CTRL, ++ FIELD_PREP(AIROHA_PCS_PMA_XPON_RX_RATE_CTRL, rx_rate_ctrl)); ++} ++ ++static void an7583_pcs_common_phya_ana(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ const struct airoha_pcs_match_data *data = priv->data; ++ u32 txpll_chp_br, txpll_chp_ibias; ++ u32 lpf_bwr; ++ u32 vco_cfix; ++ u32 tcl_amp_vref; ++ bool sdm_ifm; ++ bool sdm_di; ++ bool sdm_hren; ++ bool vcodiv; ++ bool chp_double_en; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ if (data->port_type == AIROHA_PCS_PON) { ++ txpll_chp_br = 0xa; ++ txpll_chp_ibias = 0x18; ++ lpf_bwr = 0x16; ++ } else { ++ txpll_chp_br = 0x5; ++ txpll_chp_ibias = 0x31; ++ lpf_bwr = 0xb; ++ } ++ vco_cfix = 0x3; ++ tcl_amp_vref = 0xb; ++ vcodiv = false; ++ sdm_hren = data->port_type == AIROHA_PCS_PON; ++ sdm_ifm = data->port_type == AIROHA_PCS_PON; ++ sdm_di = data->port_type == AIROHA_PCS_PON; ++ chp_double_en = false; ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: ++ txpll_chp_br = 0x5; ++ txpll_chp_ibias = 0x1e; ++ lpf_bwr = 0xb; ++ vco_cfix = 0x0; ++ tcl_amp_vref = 0xe; ++ vcodiv = true; ++ sdm_hren = false; ++ sdm_ifm = false; ++ sdm_di = false; ++ chp_double_en = data->port_type == AIROHA_PCS_PON; ++ break; ++ case PHY_INTERFACE_MODE_5GBASER: ++ case PHY_INTERFACE_MODE_10GBASER: ++ case PHY_INTERFACE_MODE_USXGMII: ++ txpll_chp_br = 0xa; ++ txpll_chp_ibias = 0x18; ++ lpf_bwr = 0x16; ++ sdm_hren = true; ++ vco_cfix = 0x2; ++ tcl_amp_vref = 0xb; ++ vcodiv = false; ++ sdm_ifm = true; ++ sdm_di = true; ++ chp_double_en = false; ++ break; ++ default: ++ return; ++ } ++ ++ if (data->port_type == AIROHA_PCS_PON) ++ /* XPON TDC */ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_PLL_MONCLK_SEL, ++ AIROHA_PCS_ANA_TDC_AUTOEN); ++ ++ /* TXPLL VCO LDO Out */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SSC_PERIOD, ++ AIROHA_PCS_ANA_TXPLL_LDO_VCO_OUT | ++ AIROHA_PCS_ANA_TXPLL_LDO_OUT, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LDO_VCO_OUT, 0x1) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LDO_OUT, 0x1)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_VTP_EN, ++ AIROHA_PCS_ANA_TXPLL_VTP | ++ AIROHA_PCS_ANA_TXPLL_VTP_EN, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VTP, 0x0) | ++ AIROHA_PCS_ANA_TXPLL_VTP_EN); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TDC_SYNC_CK_SEL, ++ AIROHA_PCS_ANA_PLL_LDO_CKDRV_VSEL | ++ AIROHA_PCS_ANA_PLL_LDO_CKDRV_EN, ++ FIELD_PREP(AIROHA_PCS_ANA_PLL_LDO_CKDRV_VSEL, 0x1) | ++ AIROHA_PCS_ANA_PLL_LDO_CKDRV_EN); ++ ++ /* Setup RSTB */ ++ /* FIXME: different order */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_REFIN_INTERNAL, ++ AIROHA_PCS_ANA_TXPLL_PLL_RSTB | ++ AIROHA_PCS_ANA_TXPLL_RST_DLY | ++ AIROHA_PCS_ANA_TXPLL_REFIN_DIV | ++ AIROHA_PCS_ANA_TXPLL_REFIN_INTERNAL, ++ AIROHA_PCS_ANA_TXPLL_PLL_RSTB | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_RST_DLY, 0x4) | ++ AIROHA_PCS_ANA_TXPLL_REFIN_DIV_1); ++ ++ /* Setup SDM */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SDM_DI_EN, ++ AIROHA_PCS_ANA_TXPLL_SDM_MODE | ++ AIROHA_PCS_ANA_TXPLL_SDM_IFM | ++ AIROHA_PCS_ANA_TXPLL_SDM_DI_LS | ++ AIROHA_PCS_ANA_TXPLL_SDM_DI_EN, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_SDM_MODE, 0) | ++ (sdm_ifm ? AIROHA_PCS_ANA_TXPLL_SDM_IFM : 0) | ++ AIROHA_PCS_ANA_TXPLL_SDM_DI_LS_2_23 | ++ (sdm_di ? AIROHA_PCS_ANA_TXPLL_SDM_DI_EN : 0)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SDM_ORD, ++ AIROHA_PCS_ANA_TXPLL_SDM_HREN | ++ AIROHA_PCS_ANA_TXPLL_SDM_OUT | ++ AIROHA_PCS_ANA_TXPLL_SDM_ORD, ++ (sdm_hren ? AIROHA_PCS_ANA_TXPLL_SDM_HREN : 0) | ++ AIROHA_PCS_ANA_TXPLL_SDM_ORD_3SDM); ++ ++ /* Setup SSC */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SSC_DELTA1, ++ AIROHA_PCS_ANA_TXPLL_SSC_DELTA | ++ AIROHA_PCS_ANA_TXPLL_SSC_DELTA1, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_SSC_DELTA, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_SSC_DELTA1, 0x0)); ++ ++ regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SSC_EN, ++ AIROHA_PCS_ANA_TXPLL_SSC_TRI_EN | ++ AIROHA_PCS_ANA_TXPLL_SSC_PHASE_INI | ++ AIROHA_PCS_ANA_TXPLL_SSC_EN); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SSC_PERIOD, ++ AIROHA_PCS_ANA_TXPLL_SSC_PERIOD, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_SSC_PERIOD, 0x0)); ++ ++ regmap_update_bits(priv->xfi_ana, AN7583_PCS_ANA_PXP_TXPLL_CHP_DOUBLE_EN, ++ AIROHA_PCS_ANA_TXPLL_SPARE_L, ++ chp_double_en ? AIROHA_PCS_ANA_TXPLL_SPARE_L : 0); ++ ++ /* Setup LPF */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_CHP_IBIAS, ++ AIROHA_PCS_ANA_TXPLL_LPF_BC | ++ AIROHA_PCS_ANA_TXPLL_LPF_BR | ++ AIROHA_PCS_ANA_TXPLL_CHP_IOFST | ++ AIROHA_PCS_ANA_TXPLL_CHP_IBIAS, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BC, 0x1f) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BR, txpll_chp_br) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_CHP_IOFST, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_CHP_IBIAS, txpll_chp_ibias)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_LPF_BP, ++ AIROHA_PCS_ANA_TXPLL_LPF_BWC | ++ AIROHA_PCS_ANA_TXPLL_LPF_BWR | ++ AIROHA_PCS_ANA_TXPLL_LPF_BP, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BWC, 0x18) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BWR, lpf_bwr) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BP, 0x2)); ++ ++ /* Setup VCO */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_LPF_EN, ++ AIROHA_PCS_ANA_TXPLL_VCO_CFIX, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_CFIX, vco_cfix)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_VCO_HALFLSB_EN, ++ AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_L | ++ AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_H | ++ AIROHA_PCS_ANA_TXPLL_VCO_TCLVAR | ++ AIROHA_PCS_ANA_TXPLL_VCO_SCAPWR | ++ AIROHA_PCS_ANA_TXPLL_VCO_HALFLSB_EN, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_L, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_H, 0x4) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_TCLVAR, 0x4) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_SCAPWR, 0x7) | ++ AIROHA_PCS_ANA_TXPLL_VCO_HALFLSB_EN); ++ ++ /* Setup KBand */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_KBAND_CODE, ++ AIROHA_PCS_ANA_TXPLL_KBAND_KF | ++ AIROHA_PCS_ANA_TXPLL_KBAND_KFC | ++ AIROHA_PCS_ANA_TXPLL_KBAND_DIV | ++ AIROHA_PCS_ANA_TXPLL_KBAND_CODE, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_KF, 0x3) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_KFC, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_DIV, 0x2) | ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_CODE, 0xe4)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_KBAND_KS, ++ AIROHA_PCS_ANA_TXPLL_KBAND_KS, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_KS, 0x1)); ++ ++ regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_LPF_BP, ++ AIROHA_PCS_ANA_TXPLL_KBAND_OPTION); ++ ++ regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_KBAND_VREF, ++ AIROHA_PCS_ANA_TXPLL_VCO_KBAND_MEAS_EN); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_KBAND_LOAD_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_KBAND_LOAD_EN | ++ AIROHA_PCS_PMA_FORCE_DA_TXPLL_KBAND_LOAD_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_KBAND_LOAD_EN); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_KBAND_KS, ++ AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE | ++ AIROHA_PCS_ANA_TXPLL_POSTDIV_EN, ++ AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE_2 | ++ AIROHA_PCS_ANA_TXPLL_POSTDIV_EN); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_AMP_GAIN, ++ AIROHA_PCS_ANA_TXPLL_TCL_AMP_VREF | ++ AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_TCL_AMP_VREF, tcl_amp_vref) | ++ AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN_4); ++ ++ if (interface == PHY_INTERFACE_MODE_2500BASEX) ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_KBAND_VREF, ++ AIROHA_PCS_ANA_TXPLL_POSTDIV_D256_EN); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_LPF_EN, ++ AIROHA_PCS_ANA_TXPLL_VCODIV, ++ vcodiv ? AIROHA_PCS_ANA_TXPLL_VCODIV_2 : ++ AIROHA_PCS_ANA_TXPLL_VCODIV_1); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_KBAND_VREF, ++ AIROHA_PCS_ANA_TXPLL_TCL_KBAND_VREF, ++ FIELD_PREP(AIROHA_PCS_ANA_TXPLL_TCL_KBAND_VREF, 0xf)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_LPF_EN, ++ AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW | ++ AIROHA_PCS_ANA_TXPLL_TCL_LPF_EN, ++ AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_0_5 | ++ AIROHA_PCS_ANA_TXPLL_TCL_LPF_EN); ++ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SDM_ORD, ++ AIROHA_PCS_ANA_TXPLL_TCL_AMP_EN); ++ ++ /* Setup TX TermCal */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TX_TXLBRC_EN, ++ AIROHA_PCS_ANA_TX_TERMCAL_VREF_L | ++ AIROHA_PCS_ANA_TX_TERMCAL_VREF_H, ++ FIELD_PREP(AIROHA_PCS_ANA_TX_TERMCAL_VREF_L, 0x2) | ++ FIELD_PREP(AIROHA_PCS_ANA_TX_TERMCAL_VREF_H, 0x2)); ++ ++ /* Setup XPON RX */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_FE_EQ_HZEN, ++ AIROHA_PCS_ANA_RX_FE_VB_EQ3_EN | ++ AIROHA_PCS_ANA_RX_FE_VB_EQ2_EN | ++ AIROHA_PCS_ANA_RX_FE_VB_EQ1_EN | ++ AIROHA_PCS_ANA_RX_FE_EQ_HZEN, ++ AIROHA_PCS_ANA_RX_FE_VB_EQ3_EN | ++ AIROHA_PCS_ANA_RX_FE_VB_EQ2_EN | ++ AIROHA_PCS_ANA_RX_FE_VB_EQ1_EN); ++ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_FE_VCM_GEN_PWDB, ++ AIROHA_PCS_ANA_FE_VCM_GEN_PWDB); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_LPF_RATIO, ++ AIROHA_PCS_ANA_CDR_LPF_TOP_LIM, ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_LPF_TOP_LIM, 0x8000)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_LPF_BOT_LIM, ++ AIROHA_PCS_ANA_CDR_LPF_BOT_LIM, ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_LPF_BOT_LIM, 0x78000)); ++ ++ regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_CKREF_DIV, ++ AIROHA_PCS_ANA_CDR_PR_RSTB_BYPASS); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_DAC_RANGE, ++ AIROHA_PCS_ANA_RX_DAC_RANGE_EYE, ++ FIELD_PREP(AIROHA_PCS_ANA_RX_DAC_RANGE_EYE, 0x2)); ++} ++ ++static void an7583_pcs_cfg_phy_type(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ const struct airoha_pcs_match_data *data = priv->data; ++ ++ /* Enable PLL force selection and Force Disable */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_CKOUT_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_EN | ++ AIROHA_PCS_PMA_FORCE_DA_TXPLL_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_EN); ++ ++ if (data->port_type == AIROHA_PCS_PON) { ++ /* TDC */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_LCPLL_TDC_FLT_3, ++ AIROHA_PCS_PMA_LCPLL_NCPO_SHIFT, ++ FIELD_PREP(AIROHA_PCS_PMA_LCPLL_NCPO_SHIFT, 0x1)); ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_LCPLL_TDC_FLT_1, ++ AIROHA_PCS_PMA_LCPLL_A_TDC, ++ FIELD_PREP(AIROHA_PCS_PMA_LCPLL_A_TDC, 0x5)); ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TX_TERMCAL_SELPN, ++ AIROHA_PCS_ANA_TX_TDC_CK_SEL, ++ FIELD_PREP(AIROHA_PCS_ANA_TX_TDC_CK_SEL, 0x0)); ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_PHYCK_DIV, ++ AIROHA_PCS_ANA_RX_TDC_CK_SEL); ++ } ++ ++ /* PLL EN HW Mode */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_LCPLL_PWCTL_SETTING_1, ++ AIROHA_PCS_PMA_LCPLL_CK_STB_TIMER | ++ AIROHA_PCS_PMA_LCPLL_PCW_MAN_LOAD_TIMER | ++ AIROHA_PCS_PMA_LCPLL_EN_TIMER | ++ AIROHA_PCS_PMA_LCPLL_MAN_PWDB, ++ FIELD_PREP(AIROHA_PCS_PMA_LCPLL_CK_STB_TIMER, 0x1) | ++ FIELD_PREP(AIROHA_PCS_PMA_LCPLL_PCW_MAN_LOAD_TIMER, 0x10) | ++ FIELD_PREP(AIROHA_PCS_PMA_LCPLL_EN_TIMER, 0xa) | ++ AIROHA_PCS_PMA_LCPLL_MAN_PWDB); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PON_TX_COUNTER_1, ++ AIROHA_PCS_PMA_TX_HSDATA_EN_WAIT | ++ AIROHA_PCS_PMA_TX_CK_EN_WAIT, ++ FIELD_PREP(AIROHA_PCS_PMA_TX_HSDATA_EN_WAIT, 0x113) | ++ FIELD_PREP(AIROHA_PCS_PMA_TX_CK_EN_WAIT, 0xfa)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PON_TX_COUNTER_2, ++ AIROHA_PCS_PMA_TX_SERDES_RDY_WAIT | ++ AIROHA_PCS_PMA_TX_POWER_ON_WAIT, ++ FIELD_PREP(AIROHA_PCS_PMA_TX_SERDES_RDY_WAIT, 0x9b) | ++ FIELD_PREP(AIROHA_PCS_PMA_TX_POWER_ON_WAIT, 0x210)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PON_TX_COUNTER_0, ++ AIROHA_PCS_PMA_TXCALIB_5US | ++ AIROHA_PCS_PMA_TXCALIB_50US, ++ FIELD_PREP(AIROHA_PCS_PMA_TXCALIB_5US, 0x4) | ++ FIELD_PREP(AIROHA_PCS_PMA_TXCALIB_50US, 0x26)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_LCPLL_TDC_FLT_0, ++ AIROHA_PCS_PMA_LCPLL_KI, ++ FIELD_PREP(AIROHA_PCS_PMA_LCPLL_KI, 0x3)); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_LCPLL_TDC_PW_5, ++ AIROHA_PCS_PMA_LCPLL_TDC_SYNC_IN_MODE); ++ ++ an7583_pcs_common_phya_txpll(priv, interface); ++ an7583_pcs_common_phya_tx(priv, interface); ++ ++ /* RX HW mode counter */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_0, ++ AIROHA_PCS_PMA_RX_OS_START, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_OS_START, 0x1)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_6, ++ AIROHA_PCS_PMA_RX_OS_END, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_OS_END, 0x2)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_0, ++ AIROHA_PCS_PMA_OSC_SPEED_OPT, ++ AIROHA_PCS_PMA_OSC_SPEED_OPT_0_1); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_1, ++ AIROHA_PCS_PMA_RX_PICAL_END | ++ AIROHA_PCS_PMA_RX_PICAL_START, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_PICAL_END, 0x3e8) | ++ FIELD_PREP(AIROHA_PCS_PMA_RX_PICAL_START, 0x2)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_4, ++ AIROHA_PCS_PMA_RX_SDCAL_END | ++ AIROHA_PCS_PMA_RX_SDCAL_START, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_SDCAL_END, 0x3e8) | ++ FIELD_PREP(AIROHA_PCS_PMA_RX_SDCAL_START, 0x2)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_2, ++ AIROHA_PCS_PMA_RX_PDOS_END | ++ AIROHA_PCS_PMA_RX_PDOS_START, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_PDOS_END, 0x3e8) | ++ FIELD_PREP(AIROHA_PCS_PMA_RX_PDOS_START, 0x2)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_3, ++ AIROHA_PCS_PMA_RX_FEOS_END | ++ AIROHA_PCS_PMA_RX_FEOS_START, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_FEOS_END, 0x3e8) | ++ FIELD_PREP(AIROHA_PCS_PMA_RX_FEOS_START, 0x2)); ++ ++ /* RX Settings */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PHY_EQ_CTRL_2, ++ AIROHA_PCS_PMA_FOM_NUM_ORDER | ++ AIROHA_PCS_PMA_A_SEL, ++ FIELD_PREP(AIROHA_PCS_PMA_FOM_NUM_ORDER, 0x1) | ++ FIELD_PREP(AIROHA_PCS_PMA_A_SEL, 0x3)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_0, ++ AIROHA_PCS_PMA_X_MAX | AIROHA_PCS_PMA_X_MIN, ++ FIELD_PREP(AIROHA_PCS_PMA_X_MAX, 0x240) | ++ FIELD_PREP(AIROHA_PCS_PMA_X_MIN, 0x1c0)); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_2, ++ AIROHA_PCS_PMA_DATA_SHIFT); ++ ++ an7583_pcs_common_phya_rx(priv, interface); ++ an7583_pcs_common_phya_ana(priv, interface); ++ ++ /* Setup EYE */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_2, ++ AIROHA_PCS_PMA_EYECNT_FAST); ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_3, ++ AIROHA_PCS_PMA_EYE_NEXTPTS); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEOPENING_CTRL_0, ++ AIROHA_PCS_PMA_EYECNT_VTH | ++ AIROHA_PCS_PMA_EYECNT_HTH, ++ FIELD_PREP(AIROHA_PCS_PMA_EYECNT_VTH, 0x4) | ++ FIELD_PREP(AIROHA_PCS_PMA_EYECNT_HTH, 0x4)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEOPENING_CTRL_1, ++ AIROHA_PCS_PMA_EO_VTH | ++ AIROHA_PCS_PMA_EO_HTH, ++ FIELD_PREP(AIROHA_PCS_PMA_EO_VTH, 0x4) | ++ FIELD_PREP(AIROHA_PCS_PMA_EO_HTH, 0x4)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_0, ++ AIROHA_PCS_PMA_EYE_MASK | ++ AIROHA_PCS_PMA_CNTLEN, ++ FIELD_PREP(AIROHA_PCS_PMA_EYE_MASK, 0xff) | ++ FIELD_PREP(AIROHA_PCS_PMA_CNTLEN, 0xd0)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PHY_EQ_CTRL_0, ++ AIROHA_PCS_PMA_VEO_MASK | ++ AIROHA_PCS_PMA_HEO_MASK | ++ AIROHA_PCS_PMA_EQ_EN_DELAY, ++ FIELD_PREP(AIROHA_PCS_PMA_VEO_MASK, 0x0) | ++ FIELD_PREP(AIROHA_PCS_PMA_HEO_MASK, 0x0) | ++ FIELD_PREP(AIROHA_PCS_PMA_EQ_EN_DELAY, 0x1)); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PHY_EQ_CTRL_1, ++ AIROHA_PCS_PMA_A_LGAIN); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CAL1, ++ AIROHA_PCS_PMA_CAL_CYC | ++ AIROHA_PCS_PMA_CAL_STB | ++ AIROHA_PCS_PMA_CAL_1US_SET | ++ AIROHA_PCS_PMA_SIM_FAST_EN, ++ AIROHA_PCS_PMA_CAL_CYC_15 | ++ AIROHA_PCS_PMA_CAL_STB_8US | ++ FIELD_PREP(AIROHA_PCS_PMA_CAL_1US_SET, 0x2e) | ++ AIROHA_PCS_PMA_SIM_FAST_EN); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CAL2, ++ AIROHA_PCS_PMA_CAL_CYC_TIME | ++ AIROHA_PCS_PMA_CAL_OUT_OS | ++ AIROHA_PCS_PMA_CAL_OS_PULSE, ++ FIELD_PREP(AIROHA_PCS_PMA_CAL_CYC_TIME, 0x0) | ++ FIELD_PREP(AIROHA_PCS_PMA_CAL_OUT_OS, 0x0)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_5, ++ AIROHA_PCS_PMA_RX_RDY | ++ AIROHA_PCS_PMA_RX_BLWC_RDY_EN, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_RDY, 0xa) | ++ FIELD_PREP(AIROHA_PCS_PMA_RX_BLWC_RDY_EN, 0x5)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FEOS, ++ AIROHA_PCS_PMA_EQ_FORCE_BLWC_FREEZE | ++ AIROHA_PCS_PMA_LFSEL, ++ FIELD_PREP(AIROHA_PCS_PMA_EQ_FORCE_BLWC_FREEZE, 0x0)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_1, ++ AIROHA_PCS_PMA_INDEX_MODE | ++ AIROHA_PCS_PMA_Y_MAX | ++ AIROHA_PCS_PMA_Y_MIN, ++ AIROHA_PCS_PMA_INDEX_MODE | ++ FIELD_PREP(AIROHA_PCS_PMA_Y_MAX, 0x3f) | ++ FIELD_PREP(AIROHA_PCS_PMA_Y_MIN, 0x40)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_2, ++ AIROHA_PCS_PMA_EYEDUR, ++ FIELD_PREP(AIROHA_PCS_PMA_EYEDUR, 0x18)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EXTRAL_CTRL, ++ AIROHA_PCS_PMA_L2D_TRIG_EQ_EN_TIME | ++ AIROHA_PCS_PMA_OS_RDY_LATCH | ++ AIROHA_PCS_PMA_DISB_LEQ, ++ FIELD_PREP(AIROHA_PCS_PMA_L2D_TRIG_EQ_EN_TIME, 0x2) | ++ AIROHA_PCS_PMA_OS_RDY_LATCH); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_0, ++ AIROHA_PCS_PMA_KBAND_KFC | ++ AIROHA_PCS_PMA_FPKDIV | ++ AIROHA_PCS_PMA_KBAND_PREDIV, ++ AIROHA_PCS_PMA_KBAND_KFC_8 | ++ FIELD_PREP(AIROHA_PCS_PMA_FPKDIV, 0xa5) | ++ AIROHA_PCS_PMA_KBAND_PREDIV_4); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_1, ++ AIROHA_PCS_PMA_SYMBOL_WD | ++ AIROHA_PCS_PMA_SETTLE_TIME_SEL, ++ FIELD_PREP(AIROHA_PCS_PMA_SYMBOL_WD, 0x4) | ++ FIELD_PREP(AIROHA_PCS_PMA_SETTLE_TIME_SEL, 0x1)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_5, ++ AIROHA_PCS_PMA_FLL_IDAC_MIN | ++ AIROHA_PCS_PMA_FLL_IDAC_MAX, ++ FIELD_PREP(AIROHA_PCS_PMA_FLL_IDAC_MIN, 0x400) | ++ FIELD_PREP(AIROHA_PCS_PMA_FLL_IDAC_MAX, 0x1ff)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_2, ++ AIROHA_PCS_PMA_AMP | ++ AIROHA_PCS_PMA_PRBS_SEL, ++ FIELD_PREP(AIROHA_PCS_PMA_AMP, 0x4) | ++ FIELD_PREP(AIROHA_PCS_PMA_PRBS_SEL, 0x3)); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_4, ++ AIROHA_PCS_PMA_DISB_BLWC_OFFSET); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_PDOS_CTRL_0, ++ AIROHA_PCS_PMA_EYE_BLWC_ADD | ++ AIROHA_PCS_PMA_DATA_BLWC_ADD, ++ AIROHA_PCS_PMA_DATA_BLWC_ADD); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_BLWC, ++ AIROHA_PCS_PMA_EQ_BLWC_CNT_BOT_LIM | ++ AIROHA_PCS_PMA_EQ_BLWC_CNT_TOP_LIM | ++ AIROHA_PCS_PMA_EQ_BLWC_GAIN | ++ AIROHA_PCS_PMA_EQ_BLWC_POL, ++ FIELD_PREP(AIROHA_PCS_PMA_EQ_BLWC_CNT_BOT_LIM, 0x10) | ++ FIELD_PREP(AIROHA_PCS_PMA_EQ_BLWC_CNT_TOP_LIM, 0x70) | ++ FIELD_PREP(AIROHA_PCS_PMA_EQ_BLWC_GAIN, 0xa) | ++ AIROHA_PCS_PMA_EQ_BLWC_POL_INVERSION); ++} ++ ++static void an7583_pcs_common_phya_txpll_on(struct airoha_pcs_priv *priv) ++{ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_CKOUT_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_CKOUT_EN | ++ AIROHA_PCS_PMA_FORCE_DA_TXPLL_CKOUT_EN); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_LCPLL_PWCTL_SETTING_0, ++ AIROHA_PCS_PMA_SW_LCPLL_EN); ++ ++ udelay(6); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_CKOUT_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_EN | ++ AIROHA_PCS_PMA_FORCE_DA_TXPLL_EN); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_KBAND_VREF, ++ AIROHA_PCS_ANA_TXPLL_FREQ_MEAS_EN | ++ AIROHA_PCS_ANA_TXPLL_VREF_SEL, ++ AIROHA_PCS_ANA_TXPLL_FREQ_MEAS_EN | ++ AIROHA_PCS_ANA_TXPLL_VREF_SEL_VBG); ++ ++ regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_PHY_CK1_EN, ++ AIROHA_PCS_ANA_TXPLL_PHY_CK2_EN | ++ AIROHA_PCS_ANA_TXPLL_PHY_CK1_EN); ++ ++ regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_KBAND_VREF, ++ AIROHA_PCS_ANA_TXPLL_FREQ_MEAS_EN); ++ ++ regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_FREQ_MEAS_EN, ++ AIROHA_PCS_ANA_TXPLL_IB_EXT_EN); ++ ++ usleep_range(500, 1000); ++} ++ ++static void an7583_pcs_common_phya_tx_on(struct airoha_pcs_priv *priv) ++{ ++ u32 xfi_tx_term_sel = 0x1; ++ // int efuse_valid; ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_TX_RST_B, ++ AIROHA_PCS_PMA_TX_TOP_RST_B); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_ADD_CLKPATH_RST_0, ++ AIROHA_PCS_PMA_CLKPATH_RSTB_CK | ++ AIROHA_PCS_PMA_CLKPATH_RST_EN); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_TX_RST_B, ++ AIROHA_PCS_PMA_TXCALIB_RST_B | ++ AIROHA_PCS_PMA_TX_TOP_RST_B); ++ ++ usleep_range(100, 200); ++ ++ /* TODO handle efuse */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_TX_CALIB_0, ++ AIROHA_PCS_PMA_TXCALIB_FORCE_TERMP_SEL | ++ AIROHA_PCS_PMA_TXCALIB_FORCE_TERMP_SEL_EN, ++ FIELD_PREP(AIROHA_PCS_PMA_TXCALIB_FORCE_TERMP_SEL, ++ xfi_tx_term_sel) | ++ AIROHA_PCS_PMA_TXCALIB_FORCE_TERMP_SEL_EN); ++} ++ ++static void an7583_pcs_common_phya_rx_preset(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ u32 cdr_pr_buf_in_sr; ++ bool cdr_pr_cap_en; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_2500BASEX: ++ cdr_pr_cap_en = true; ++ cdr_pr_buf_in_sr = 0x6; ++ break; ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_5GBASER: ++ case PHY_INTERFACE_MODE_10GBASER: ++ case PHY_INTERFACE_MODE_USXGMII: ++ cdr_pr_cap_en = false; ++ cdr_pr_buf_in_sr = 0x7; ++ break; ++ default: ++ return; ++ } ++ ++ /* Setup RX Precondition */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_SIGDET_NOVTH, ++ AIROHA_PCS_ANA_RX_SIGDET_VTH_SEL | ++ AIROHA_PCS_ANA_RX_SIGDET_PEAK, ++ FIELD_PREP(AIROHA_PCS_ANA_RX_SIGDET_VTH_SEL, 0x2) | ++ FIELD_PREP(AIROHA_PCS_ANA_RX_SIGDET_PEAK, 0x2)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_DAC_RANGE, ++ AIROHA_PCS_ANA_RX_SIGDET_LPF_CTRL, ++ FIELD_PREP(AIROHA_PCS_ANA_RX_SIGDET_LPF_CTRL, 0x3)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_MONPR_EN, ++ AIROHA_PCS_ANA_CDR_PR_CAP_EN | ++ AIROHA_PCS_ANA_CDR_BUF_IN_SR, ++ (cdr_pr_cap_en ? AIROHA_PCS_ANA_CDR_PR_CAP_EN : 0) | ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_BUF_IN_SR, cdr_pr_buf_in_sr)); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1, ++ AIROHA_PCS_PMA_FORCE_RX_OS_RDY); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1, ++ AIROHA_PCS_PMA_DISB_RX_OS_RDY); ++ ++ /* Setup L2R */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA); ++ ++ /* Setup LEQ setting */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PEAKING_CTRL | ++ AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PEAKING_CTRL | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL, 0x0)); ++ ++ /* Keep EYE reset */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9, ++ AIROHA_PCS_PMA_FORCE_EYE_RESET_PLU_O); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_8, ++ AIROHA_PCS_PMA_DISB_EYE_RESET_PLU_O); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9, ++ AIROHA_PCS_PMA_FORCE_EYE_TOP_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_8, ++ AIROHA_PCS_PMA_DISB_EYE_TOP_EN); ++ ++ /* Kepp BLWC reset */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_7, ++ AIROHA_PCS_PMA_DISB_BLWC_RX_RST_B); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_8, ++ AIROHA_PCS_PMA_FORCE_BLWC_RX_RST_B); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1, ++ AIROHA_PCS_PMA_DISB_RX_BLWC_EN); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1, ++ AIROHA_PCS_PMA_FORCE_RX_BLWC_EN); ++} ++ ++static void an7583_pcs_common_phya_rx_on(struct airoha_pcs_priv *priv) ++{ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PWDB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PIEYE_PWDB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PIEYE_PWDB); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PD_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_KBAND_RSTB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_KBAND_RSTB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PD_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PD_PWDB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PD_PWDB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_FE_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PWDB | ++ AIROHA_PCS_PMA_FORCE_DA_RX_FE_PWDB); ++ ++ /* RX SigDet Pwdb */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_SCAN_RST_B, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_PWDB | ++ AIROHA_PCS_PMA_FORCE_DA_RX_SIGDET_PWDB); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_SCAN_RST_B, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SCAN_RST_B | ++ AIROHA_PCS_PMA_FORCE_DA_RX_SCAN_RST_B); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_DA_XPON_PWDB_0, ++ AIROHA_PCS_PMA_XPON_CDR_PD_PWDB | ++ AIROHA_PCS_PMA_XPON_CDR_PR_PIEYE_PWDB | ++ AIROHA_PCS_PMA_XPON_CDR_PW_PWDB | ++ AIROHA_PCS_PMA_XPON_RX_FE_PWDB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_DA_XPON_PWDB_1, ++ AIROHA_PCS_PMA_RX_SIDGET_PWDB); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_SYS_EN_SEL_0, ++ AIROHA_PCS_PMA_RX_SYS_EN_SEL, ++ FIELD_PREP(AIROHA_PCS_PMA_RX_SYS_EN_SEL, 0x1)); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_VREG_IBAND_VAL, ++ AIROHA_PCS_ANA_CDR_PR_FBKSEL | ++ AIROHA_PCS_ANA_CDR_PR_VREG_CKBUF_VAL | ++ AIROHA_PCS_ANA_CDR_PR_VREG_IBAND_VAL, ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_FBKSEL, 0x0) | ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_VREG_CKBUF_VAL, 0x5) | ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_VREG_IBAND_VAL, 0x5)); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0, ++ AIROHA_PCS_PMA_DISB_RX_PICAL_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0, ++ AIROHA_PCS_PMA_DISB_RX_PDOS_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0, ++ AIROHA_PCS_PMA_DISB_RX_FEOS_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1, ++ AIROHA_PCS_PMA_DISB_RX_SDCAL_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0, ++ AIROHA_PCS_PMA_DISB_RX_OS_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1, ++ AIROHA_PCS_PMA_DISB_RX_BLWC_EN); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_CKREF_DIV, ++ AIROHA_PCS_ANA_CDR_PR_CKREF_DIV, ++ AIROHA_PCS_ANA_CDR_PR_CKREF_DIV_1); ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_TDC_REF_SEL, ++ AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1, ++ AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1_1); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_RX_RST_N); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_REF_RST_N); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB); ++ ++ usleep_range(100, 200); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB); ++} ++ ++static void an7583_pcs_common_phya_l2d(struct airoha_pcs_priv *priv) ++{ ++ /* Setup LPF L2D force and disable */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA); ++ ++ usleep_range(200, 300); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB); ++} ++ ++static void an7583_pcs_common_phya_tdc_off(struct airoha_pcs_priv *priv) ++{ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_IDAC, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_SDM_PCW); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_LCPLL_TDC_FLT_3, ++ AIROHA_PCS_PMA_LCPLL_NCPO_LOAD); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_SDM_PCW_CHG, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_SDM_PCW_CHG); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_SDM_PCW_CHG, ++ AIROHA_PCS_PMA_FORCE_DA_TXPLL_SDM_PCW_CHG); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_SDM_PCW_CHG, ++ AIROHA_PCS_PMA_FORCE_DA_TXPLL_SDM_PCW_CHG); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_LCPLL_TDC_FLT_1, ++ AIROHA_PCS_PMA_LCPLL_GPON_SEL, ++ AIROHA_PCS_PMA_LCPLL_GPON_SEL_FROM_EPON); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_LCPLL_TDC_PW_0, ++ AIROHA_PCS_PMA_LCPLL_TDC_DIG_PWDB); ++ ++ usleep_range(100, 200); ++} ++ ++static void an7583_pcs_common_phya_rx_oscal(struct airoha_pcs_priv *priv) ++{ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_8, ++ AIROHA_PCS_PMA_DISB_FBCK_LOCK); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9, ++ AIROHA_PCS_PMA_FORCE_FBCK_LOCK); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN_RSTB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_CKON | ++ AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_CKON); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_OSCAL_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_RSTB | ++ AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_RSTB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_OSCAL_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_EN | ++ AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_EN); ++ ++ usleep_range(200, 300); ++ ++ /* Set normal of force mode */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0, ++ AIROHA_PCS_PMA_DISB_RX_OS_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1, ++ AIROHA_PCS_PMA_DISB_RX_OS_RDY); ++ ++ /* Disable force mode signal */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0, ++ AIROHA_PCS_PMA_FORCE_RX_OS_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1, ++ AIROHA_PCS_PMA_FORCE_RX_OS_RDY); ++ ++ /* Release reset enable */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0, ++ AIROHA_PCS_PMA_FORCE_RX_OS_EN); ++} ++ ++static void an7583_pcs_common_phya_pical(struct airoha_pcs_priv *priv) ++{ ++ /* Pre Condition */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_2, ++ AIROHA_PCS_PMA_DISB_DA_XPON_CDR_PR_PIEYE); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_PI_CAL, ++ AIROHA_PCS_PMA_KPGAIN, ++ FIELD_PREP(AIROHA_PCS_PMA_KPGAIN, 0x4)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PHY_EQ_CTRL_0, ++ AIROHA_PCS_PMA_EQ_EN_DELAY, ++ FIELD_PREP(AIROHA_PCS_PMA_EQ_EN_DELAY, 0x8)); ++ ++ /* Reset Block */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_RESET_0, ++ AIROHA_PCS_PMA_EQ_PI_CAL_RST_B); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_7, ++ AIROHA_PCS_PMA_FORCE_RX_AND_PICAL_RSTB); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_6, ++ AIROHA_PCS_PMA_DISB_RX_AND_PICAL_RSTB); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_7, ++ AIROHA_PCS_PMA_FORCE_REF_AND_PICAL_RSTB); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_6, ++ AIROHA_PCS_PMA_DISB_REF_AND_PICAL_RSTB); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_3, ++ AIROHA_PCS_PMA_DISB_RQ_PI_CAL_RDY); ++ ++ /* Enable */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_6, ++ AIROHA_PCS_PMA_FORCE_RX_OR_PICAL_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_5, ++ AIROHA_PCS_PMA_DISB_RX_OR_PICAL_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0, ++ AIROHA_PCS_PMA_FORCE_RX_PICAL_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0, ++ AIROHA_PCS_PMA_DISB_RX_PICAL_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_3, ++ AIROHA_PCS_PMA_FORCE_EQ_PI_CAL_RDY); ++ ++ /* Release Reset and Enable */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_RESET_0, ++ AIROHA_PCS_PMA_EQ_PI_CAL_RST_B); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_7, ++ AIROHA_PCS_PMA_FORCE_RX_AND_PICAL_RSTB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_7, ++ AIROHA_PCS_PMA_FORCE_REF_AND_PICAL_RSTB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_6, ++ AIROHA_PCS_PMA_FORCE_RX_OR_PICAL_EN); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0, ++ AIROHA_PCS_PMA_FORCE_RX_PICAL_EN); ++ ++ usleep_range(200, 300); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0, ++ AIROHA_PCS_PMA_FORCE_RX_PICAL_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_6, ++ AIROHA_PCS_PMA_FORCE_RX_OR_PICAL_EN); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_3, ++ AIROHA_PCS_PMA_FORCE_EQ_PI_CAL_RDY); ++} ++ ++static void an7583_pcs_common_phya_pdos(struct airoha_pcs_priv *priv) ++{ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_FE_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_PDOSCAL_EN | ++ AIROHA_PCS_PMA_FORCE_DA_RX_PDOSCAL_EN); ++ ++ /* Pre Condition */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1, ++ AIROHA_PCS_PMA_FORCE_RX_OS_RDY); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1, ++ AIROHA_PCS_PMA_DISB_RX_OS_RDY); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_1, ++ AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_E0); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_1, ++ AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_D1); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_1, ++ AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_D0); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_2, ++ AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_E1); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_2, ++ AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_EYE); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_8, ++ AIROHA_PCS_PMA_FORCE_BLWC_RX_RST_B); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_7, ++ AIROHA_PCS_PMA_DISB_BLWC_RX_RST_B); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1, ++ AIROHA_PCS_PMA_FORCE_EYEDUR_INIT_B); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1, ++ AIROHA_PCS_PMA_DISB_EYEDUR_INIT_B); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_8, ++ AIROHA_PCS_PMA_FORCE_EYECNT_RX_RST_B); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_7, ++ AIROHA_PCS_PMA_DISB_EYECNT_RX_RST_B); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1, ++ AIROHA_PCS_PMA_FORCE_EYEDUR_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1, ++ AIROHA_PCS_PMA_DISB_EYEDUR_EN); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_PDOS_CTRL_0, ++ AIROHA_PCS_PMA_SAP_SEL, ++ AIROHA_PCS_PMA_SAP_SEL_SHIFT_8); ++ ++ /* Reset Block */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_7, ++ AIROHA_PCS_PMA_FORCE_PDOS_RX_RST_B); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_6, ++ AIROHA_PCS_PMA_DISB_PDOS_RX_RST_B); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_RESET_1, ++ AIROHA_PCS_PMA_PDOS_RST_B); ++ ++ /* Disable */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0, ++ AIROHA_PCS_PMA_FORCE_RX_PDOS_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0, ++ AIROHA_PCS_PMA_DISB_RX_PDOS_EN); ++ ++ /* Release Reset and Enable */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0, ++ AIROHA_PCS_PMA_FORCE_RX_OS_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0, ++ AIROHA_PCS_PMA_DISB_RX_OS_EN); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_7, ++ AIROHA_PCS_PMA_FORCE_PDOS_RX_RST_B); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_RESET_1, ++ AIROHA_PCS_PMA_PDOS_RST_B); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0, ++ AIROHA_PCS_PMA_FORCE_RX_PDOS_EN); ++ ++ usleep_range(200, 300); ++ ++ /* Disable (again) */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0, ++ AIROHA_PCS_PMA_FORCE_RX_PDOS_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0, ++ AIROHA_PCS_PMA_FORCE_RX_OS_EN); ++ ++ /* Release EYE related */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1, ++ AIROHA_PCS_PMA_FORCE_EYEDUR_INIT_B); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1, ++ AIROHA_PCS_PMA_DISB_EYEDUR_INIT_B); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_8, ++ AIROHA_PCS_PMA_FORCE_EYECNT_RX_RST_B); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_7, ++ AIROHA_PCS_PMA_DISB_EYECNT_RX_RST_B); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1, ++ AIROHA_PCS_PMA_FORCE_EYEDUR_EN); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1, ++ AIROHA_PCS_PMA_DISB_EYEDUR_EN); ++ ++ /* Disable PDOS */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_FE_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_PDOSCAL_EN | ++ AIROHA_PCS_PMA_FORCE_DA_RX_PDOSCAL_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_PDOSCAL_EN); ++} ++ ++static void an7583_pcs_common_phya_feos(struct airoha_pcs_priv *priv) ++{ ++ /* Pre Condition */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1, ++ AIROHA_PCS_PMA_FORCE_RX_OS_RDY); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1, ++ AIROHA_PCS_PMA_DISB_RX_OS_RDY); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_2, ++ AIROHA_PCS_PMA_DISB_DA_XPON_RX_FE_VOS); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_8, ++ AIROHA_PCS_PMA_FORCE_BLWC_RX_RST_B); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_7, ++ AIROHA_PCS_PMA_DISB_BLWC_RX_RST_B); ++ ++ /* Setting */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FEOS, ++ AIROHA_PCS_PMA_LFSEL, ++ FIELD_PREP(AIROHA_PCS_PMA_LFSEL, 0x30)); ++ ++ /* Reset */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_8, ++ AIROHA_PCS_PMA_FORCE_FEOS_RX_RST_B); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_7, ++ AIROHA_PCS_PMA_DISB_FEOS_RX_RST_B); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_RESET_0, ++ AIROHA_PCS_PMA_FEOS_RST_B); ++ ++ /* Disable */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0, ++ AIROHA_PCS_PMA_FORCE_RX_FEOS_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0, ++ AIROHA_PCS_PMA_DISB_RX_FEOS_EN); ++ ++ /* Release Reset and Enable */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0, ++ AIROHA_PCS_PMA_FORCE_RX_OS_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0, ++ AIROHA_PCS_PMA_DISB_RX_OS_EN); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_8, ++ AIROHA_PCS_PMA_FORCE_FEOS_RX_RST_B); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_RESET_0, ++ AIROHA_PCS_PMA_FEOS_RST_B); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0, ++ AIROHA_PCS_PMA_FORCE_RX_FEOS_EN); ++ ++ usleep_range(1000, 1500); ++ ++ /* Disable */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0, ++ AIROHA_PCS_PMA_FORCE_RX_FEOS_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0, ++ AIROHA_PCS_PMA_FORCE_RX_OS_EN); ++} ++ ++static void an7583_pcs_common_phya_sdcal(struct airoha_pcs_priv *priv) ++{ ++ /* Pre Condition */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_SIGDET_CAL_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_CAL_EN | ++ AIROHA_PCS_PMA_FORCE_DA_RX_SIGDET_CAL_EN); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_OSCAL_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_EN | ++ AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_EN); ++ ++ /* Reset */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_RESET_0, ++ AIROHA_PCS_PMA_CAL_RST_B); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_8, ++ AIROHA_PCS_PMA_FORCE_SDCAL_REF_RST_B); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1, ++ AIROHA_PCS_PMA_DISB_RX_SDCAL_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_7, ++ AIROHA_PCS_PMA_DISB_SDCAL_REF_RST_B); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1, ++ AIROHA_PCS_PMA_FORCE_RX_SDCAL_EN); ++ ++ /* Release Reset and Enable */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_RESET_0, ++ AIROHA_PCS_PMA_CAL_RST_B); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_8, ++ AIROHA_PCS_PMA_FORCE_SDCAL_REF_RST_B); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1, ++ AIROHA_PCS_PMA_FORCE_RX_SDCAL_EN); ++ ++ usleep_range(200, 300); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1, ++ AIROHA_PCS_PMA_FORCE_RX_SDCAL_EN); ++ ++ /* SigDet Cal Disable */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_SIGDET_CAL_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_CAL_EN | ++ AIROHA_PCS_PMA_FORCE_DA_RX_SIGDET_CAL_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_CAL_EN); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN_RSTB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_CKON | ++ AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_CKON, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_CKON); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_OSCAL_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_RSTB | ++ AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_RSTB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_RSTB); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_OSCAL_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_EN | ++ AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_EN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_EN); ++} ++ ++static void an7583_pcs_common_phya_phy_status(struct airoha_pcs_priv *priv) ++{ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1, ++ AIROHA_PCS_PMA_FORCE_RX_OS_RDY); ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1, ++ AIROHA_PCS_PMA_DISB_RX_OS_RDY); ++ udelay(1); ++} ++ ++static void an7583_pcs_common_phya_eye_setting(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ u32 x_min, x_max; ++ u32 cdr_lpf_ratio; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ x_min = 0x0; ++ x_max = 0x400; ++ cdr_lpf_ratio = 0x3; ++ break; ++ case PHY_INTERFACE_MODE_2500BASEX: ++ x_min = 0x140; ++ x_max = 0x2c0; ++ cdr_lpf_ratio = 0x0; ++ break; ++ case PHY_INTERFACE_MODE_5GBASER: ++ x_min = 0x180; ++ x_max = 0x280; ++ cdr_lpf_ratio = 0x1; ++ break; ++ case PHY_INTERFACE_MODE_10GBASER: ++ case PHY_INTERFACE_MODE_USXGMII: ++ x_min = 0x1c0; ++ x_max = 0x234; ++ cdr_lpf_ratio = 0x0; ++ break; ++ default: ++ return; ++ } ++ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_LPF_RATIO, ++ AIROHA_PCS_ANA_CDR_LPF_RATIO, ++ FIELD_PREP(AIROHA_PCS_ANA_CDR_LPF_RATIO, ++ cdr_lpf_ratio)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_0, ++ AIROHA_PCS_PMA_EYE_MASK, ++ FIELD_PREP(AIROHA_PCS_PMA_EYE_MASK, 0xff)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_0, ++ AIROHA_PCS_PMA_X_MAX | AIROHA_PCS_PMA_X_MIN, ++ FIELD_PREP(AIROHA_PCS_PMA_X_MAX, x_max) | ++ FIELD_PREP(AIROHA_PCS_PMA_X_MIN, x_min)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_0, ++ AIROHA_PCS_PMA_CNTLEN, ++ FIELD_PREP(AIROHA_PCS_PMA_CNTLEN, 0xf8)); ++ ++ regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_0, ++ AIROHA_PCS_PMA_CNTFOREVER); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_2, ++ AIROHA_PCS_PMA_DATA_SHIFT); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_1, ++ AIROHA_PCS_PMA_INDEX_MODE); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_2, ++ AIROHA_PCS_PMA_EYEDUR, ++ FIELD_PREP(AIROHA_PCS_PMA_EYEDUR, 0x44c)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_3, ++ AIROHA_PCS_PMA_EYE_NEXTPTS | ++ AIROHA_PCS_PMA_EYE_NEXTPTS_TOGGLE | ++ AIROHA_PCS_PMA_EYE_NEXTPTS_SEL, ++ AIROHA_PCS_PMA_EYE_NEXTPTS); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEOPENING_CTRL_0, ++ AIROHA_PCS_PMA_EYECNT_VTH | ++ AIROHA_PCS_PMA_EYECNT_HTH, ++ FIELD_PREP(AIROHA_PCS_PMA_EYECNT_VTH, 0x4) | ++ FIELD_PREP(AIROHA_PCS_PMA_EYECNT_HTH, 0x4)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEOPENING_CTRL_1, ++ AIROHA_PCS_PMA_EO_VTH | ++ AIROHA_PCS_PMA_EO_HTH, ++ FIELD_PREP(AIROHA_PCS_PMA_EO_VTH, 0x4) | ++ FIELD_PREP(AIROHA_PCS_PMA_EO_HTH, 0x4)); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PHY_EQ_CTRL_1, ++ AIROHA_PCS_PMA_B_ZERO_SEL | ++ AIROHA_PCS_PMA_HEO_EMPHASIS | ++ AIROHA_PCS_PMA_A_MGAIN | ++ AIROHA_PCS_PMA_A_LGAIN); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PHY_EQ_CTRL_2, ++ AIROHA_PCS_PMA_A_SEL, ++ FIELD_PREP(AIROHA_PCS_PMA_A_SEL, 0x1)); ++} ++ ++static void an7583_pcs_common_phya_eye_cal(struct airoha_pcs_priv *priv) ++{ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_RATE_CTRL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PIEYE | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PIEYE, ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PIEYE, 0x0)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_FLL_COR, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_DAC_EYE | ++ AIROHA_PCS_PMA_FORCE_DA_RX_DAC_EYE, ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_RX_DAC_EYE, 0x0)); ++ ++ /* Redo PICal and reset Block */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PHY_EQ_CTRL_0, ++ AIROHA_PCS_PMA_EQ_EN_DELAY, ++ FIELD_PREP(AIROHA_PCS_PMA_EQ_EN_DELAY, 0x80)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_PI_CAL, ++ AIROHA_PCS_PMA_KPGAIN, ++ FIELD_PREP(AIROHA_PCS_PMA_KPGAIN, 0x1)); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_RESET_0, ++ AIROHA_PCS_PMA_EQ_PI_CAL_RST_B); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_7, ++ AIROHA_PCS_PMA_FORCE_RX_AND_PICAL_RSTB); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_6, ++ AIROHA_PCS_PMA_DISB_RX_AND_PICAL_RSTB); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_7, ++ AIROHA_PCS_PMA_FORCE_REF_AND_PICAL_RSTB); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_6, ++ AIROHA_PCS_PMA_DISB_REF_AND_PICAL_RSTB); ++ ++ /* Enable PICal */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_5, ++ AIROHA_PCS_PMA_DISB_RX_OR_PICAL_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_6, ++ AIROHA_PCS_PMA_FORCE_RX_OR_PICAL_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0, ++ AIROHA_PCS_PMA_DISB_RX_PICAL_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0, ++ AIROHA_PCS_PMA_FORCE_RX_PICAL_EN); ++ ++ /* Release Reset */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_RESET_0, ++ AIROHA_PCS_PMA_EQ_PI_CAL_RST_B); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_7, ++ AIROHA_PCS_PMA_FORCE_RX_AND_PICAL_RSTB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_7, ++ AIROHA_PCS_PMA_FORCE_REF_AND_PICAL_RSTB); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_6, ++ AIROHA_PCS_PMA_FORCE_RX_OR_PICAL_EN); ++ ++ usleep_range(1000, 1500); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_6, ++ AIROHA_PCS_PMA_FORCE_RX_OR_PICAL_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_3, ++ AIROHA_PCS_PMA_DISB_RQ_PI_CAL_RDY); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_3, ++ AIROHA_PCS_PMA_FORCE_EQ_PI_CAL_RDY); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_5, ++ AIROHA_PCS_PMA_DISB_EYECNT_RDY); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_6, ++ AIROHA_PCS_PMA_FORCE_EYECNT_RDY); ++ ++ usleep_range(1000, 1500); ++} ++ ++static void an7583_pcs_common_phya_eye_eo_read(struct airoha_pcs_priv *priv, ++ u32 *heo, u32 *veo) ++{ ++ u32 eo_buf[EO_BUF_MAX]; ++ u32 eye_el, eye_er; ++ u32 feos; ++ u32 val; ++ int i; ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_6, ++ AIROHA_PCS_PMA_LNX_SW_FLL_4_LATCH_EN | ++ AIROHA_PCS_PMA_LNX_SW_FLL_3_LATCH_EN | ++ AIROHA_PCS_PMA_LNX_SW_FLL_2_LATCH_EN | ++ AIROHA_PCS_PMA_LNX_SW_FLL_1_LATCH_EN); ++ ++ usleep_range(50, 100); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_6, ++ AIROHA_PCS_PMA_LNX_SW_FLL_4_LATCH_EN | ++ AIROHA_PCS_PMA_LNX_SW_FLL_3_LATCH_EN | ++ AIROHA_PCS_PMA_LNX_SW_FLL_2_LATCH_EN | ++ AIROHA_PCS_PMA_LNX_SW_FLL_1_LATCH_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DEBUG_0, ++ AIROHA_PCS_PMA_RO_TOGGLE); ++ ++ usleep_range(100, 200); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DEBUG_0, ++ AIROHA_PCS_PMA_RO_TOGGLE); ++ ++ regmap_read(priv->xfi_pma, AIROHA_PCS_PMA_RX_TORGS_DEBUG_10, &val); ++ eye_el = FIELD_GET(AIROHA_PCS_PMA_EYE_EL, val); ++ eye_er = FIELD_GET(AIROHA_PCS_PMA_EYE_ER, val); ++ ++ regmap_read(priv->xfi_pma, AIROHA_PCS_PMA_RX_TORGS_DEBUG_11, &val); ++ eo_buf[EYE_EU] = FIELD_GET(AIROHA_PCS_PMA_EYE_EU, val); ++ eo_buf[EYE_EB] = FIELD_GET(AIROHA_PCS_PMA_EYE_EB, val); ++ ++ regmap_read(priv->xfi_pma, AIROHA_PCS_PMA_ADD_RX2ANA_1, &val); ++ eo_buf[DAC_EYE] = FIELD_GET(AIROHA_PCS_PMA_RX_DAC_EYE, val); ++ eo_buf[DAC_D0] = FIELD_GET(AIROHA_PCS_PMA_RX_DAC_D0, val); ++ eo_buf[DAC_D1] = FIELD_GET(AIROHA_PCS_PMA_RX_DAC_D1, val); ++ eo_buf[DAC_E0] = FIELD_GET(AIROHA_PCS_PMA_RX_DAC_E0, val); ++ ++ regmap_read(priv->xfi_pma, AIROHA_PCS_PMA_ADD_RX2ANA_2, &val); ++ eo_buf[FEOS] = FIELD_GET(AIROHA_PCS_PMA_RX_FEOS_OUT, val); ++ eo_buf[DAC_E1] = FIELD_GET(AIROHA_PCS_PMA_RX_DAC_E1, val); ++ ++ feos = eo_buf[FEOS]; ++ ++ for (i = 0; i < ARRAY_SIZE(eo_buf); i++) { ++ if ((eo_buf[i] == feos) && (eo_buf[i] >= 32)) ++ eo_buf[i] = eo_buf[i] - 64; ++ else if (eo_buf[i] >= 64) ++ eo_buf[i] = eo_buf[i] - 128; ++ } ++ ++ /* Check if CLK unlocking happens (E0 result validity) */ ++ regmap_read(priv->xfi_pma, AIROHA_PCS_PMA_RX_TORGS_DEBUG_5, &val); ++ if (!FIELD_GET(AIROHA_PCS_PMA_HEO_RDY, val)) { ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_0, ++ AIROHA_PCS_PMA_DISB_DA_XPON_CDR_LPF_RSTB); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_0, ++ AIROHA_PCS_PMA_FORCE_DA_XPON_CDR_LPF_RSTB); ++ ++ usleep_range(500, 700); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_0, ++ AIROHA_PCS_PMA_FORCE_DA_XPON_CDR_LPF_RSTB); ++ ++ usleep_range(500, 700); ++ } ++ ++ *heo = abs(eye_er - eye_el); ++ *veo = abs(eo_buf[EYE_EU] - eo_buf[EYE_EB]); ++} ++ ++static void an7583_pcs_common_phya_eye_eo(struct airoha_pcs_priv *priv, ++ phy_interface_t interface, ++ u32 *heo, u32 *veo) ++{ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_8, ++ AIROHA_PCS_PMA_DISB_EYE_RESET_PLU_O); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9, ++ AIROHA_PCS_PMA_FORCE_EYE_RESET_PLU_O); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9, ++ AIROHA_PCS_PMA_FORCE_EYE_RESET_PLU_O); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_8, ++ AIROHA_PCS_PMA_DISB_EYE_TOP_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9, ++ AIROHA_PCS_PMA_FORCE_EYE_TOP_EN); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9, ++ AIROHA_PCS_PMA_FORCE_EYE_TOP_EN); ++ ++ if (interface == PHY_INTERFACE_MODE_10GBASER || ++ interface == PHY_INTERFACE_MODE_USXGMII) ++ usleep_range(5500, 6000); ++ else ++ msleep(55); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_2, ++ AIROHA_PCS_PMA_DISB_DA_XPON_CDR_PR_PIEYE | ++ AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_EYE); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1, ++ AIROHA_PCS_PMA_DISB_EYEDUR_INIT_B); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_7, ++ AIROHA_PCS_PMA_DISB_EYECNT_RX_RST_B); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1, ++ AIROHA_PCS_PMA_DISB_EYEDUR_EN); ++ ++ an7583_pcs_common_phya_eye_eo_read(priv, heo, veo); ++ ++ /* Clear Eye SW value */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9, ++ AIROHA_PCS_PMA_FORCE_EYE_RESET_PLU_O); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_8, ++ AIROHA_PCS_PMA_DISB_EYE_TOP_EN); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9, ++ AIROHA_PCS_PMA_FORCE_EYE_TOP_EN); ++ ++ /* Reset PICal Rdy */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_3, ++ AIROHA_PCS_PMA_DISB_RQ_PI_CAL_RDY); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_3, ++ AIROHA_PCS_PMA_FORCE_EQ_PI_CAL_RDY); ++ ++ /* Reset Eyecnt Rdy */ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_5, ++ AIROHA_PCS_PMA_DISB_EYECNT_RDY); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_6, ++ AIROHA_PCS_PMA_FORCE_EYECNT_RDY); ++} ++ ++static void an7583_pcs_common_phya_eo_scan(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ ++ u32 best_heo = 0, best_veo = 0; ++ u32 leq_gain, best_leq_gain; ++ u32 best_leq_peacking = 0; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ case PHY_INTERFACE_MODE_5GBASER: ++ leq_gain = 3; ++ break; ++ case PHY_INTERFACE_MODE_10GBASER: ++ case PHY_INTERFACE_MODE_USXGMII: ++ leq_gain = 1; ++ break; ++ default: ++ return; ++ } ++ ++ best_leq_gain = leq_gain; ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PIEYE_PWDB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PIEYE_PWDB); ++ ++ an7583_pcs_common_phya_eye_setting(priv, interface); ++ ++ /* EYE Open */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PHY_EQ_CTRL_0, ++ AIROHA_PCS_PMA_EQ_EN_DELAY, ++ FIELD_PREP(AIROHA_PCS_PMA_EQ_EN_DELAY, 0x80)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_PI_CAL, ++ AIROHA_PCS_PMA_KPGAIN, ++ FIELD_PREP(AIROHA_PCS_PMA_KPGAIN, 0x4)); ++ ++ for (; leq_gain <= FIELD_MAX(AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL); leq_gain++) { ++ u32 leq_peaking; ++ u32 heo, veo; ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_FE_GAIN_CTRL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_GAIN_CTRL | ++ AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_GAIN_CTRL | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL, leq_gain)); ++ ++ for (leq_peaking = 0; leq_peaking <= FIELD_MAX(AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL); leq_peaking++) { ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PEAKING_CTRL | ++ AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PEAKING_CTRL | ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL, leq_peaking)); ++ ++ usleep_range(500, 700); ++ ++ an7583_pcs_common_phya_eye_cal(priv); ++ an7583_pcs_common_phya_eye_eo(priv, interface, &heo, &veo); ++ ++ if (veo > 53 && best_veo > 53) { ++ if (heo > best_heo) { ++ best_heo = heo; ++ best_veo = veo; ++ best_leq_peacking = leq_peaking; ++ best_leq_gain = leq_gain; ++ } else if (heo == best_heo && veo > best_veo) { ++ best_heo = heo; ++ best_veo = veo; ++ best_leq_peacking = leq_peaking; ++ best_leq_gain = leq_gain; ++ } ++ } else { ++ if (veo > best_veo) { ++ best_heo = heo; ++ best_veo = veo; ++ best_leq_peacking = leq_peaking; ++ best_leq_gain = leq_gain; ++ } ++ } ++ } ++ } ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_FE_GAIN_CTRL, ++ AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL, ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL, best_leq_gain)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN, ++ AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL, ++ FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL, best_leq_peacking)); ++} ++ ++static void an7583_pcs_common_phya_rxrdy(struct airoha_pcs_priv *priv) ++{ ++ u32 xfi_rx_term_sel = 0x1; ++ // int efuse_valid; ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1, ++ AIROHA_PCS_PMA_FORCE_RX_RDY); ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1, ++ AIROHA_PCS_PMA_DISB_RX_RDY); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_RX_FIFO_RST_N); ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_RX_FIFO_RST_N); ++ ++ /* TODO HANDLE EFUSE */ ++ regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_SIGDET_NOVTH, ++ AIROHA_PCS_ANA_RX_FE_50OHMS_SEL, ++ FIELD_PREP(AIROHA_PCS_ANA_RX_FE_50OHMS_SEL, ++ xfi_rx_term_sel)); ++} ++ ++static void an7583_pcs_common_phya_bist_setting(struct airoha_pcs_priv *priv) ++{ ++ regmap_write(priv->xfi_pma, AIROHA_PCS_PMA_BISTCTL_ALIGN_PAT, ++ 0x8ff1fd53); ++ regmap_write(priv->xfi_pma, AIROHA_PCS_PMA_BISTCTL_PRBS_INITIAL_SEED, ++ 0xFF1FD53); ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_BISTCTL_PRBS_FAIL_THRESHOLD, ++ AIROHA_PCS_PMA_BISTCTL_PRBS_FAIL_THRESHOLD_MASK, ++ FIELD_PREP(AIROHA_PCS_PMA_BISTCTL_PRBS_FAIL_THRESHOLD_MASK, 0x1)); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_BISTCTL_CONTROL, ++ AIROHA_PCS_PMA_BISTCTL_PAT_SEL, ++ AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PRBS31); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_BISTCTL_POLLUTION, ++ AIROHA_PCS_PMA_BIST_TX_DATA_POLLUTION_LATCH); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_BIST_1, ++ AIROHA_PCS_PMA_LNX_BISTCTL_BIT_ERROR_RST_SEL | ++ AIROHA_PCS_PMA_ANLT_PX_LNX_LT_LOS); ++} ++ ++static void an7583_pcs_first_plug_in(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ const struct airoha_pcs_match_data *data = priv->data; ++ ++ an7583_pcs_common_phya_rx_preset(priv, interface); ++ if (data->port_type == AIROHA_PCS_PON) ++ an7583_pcs_common_phya_tdc_off(priv); ++ an7583_pcs_common_phya_rx_on(priv); ++ an7583_pcs_common_phya_l2d(priv); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_REF_RST_N); ++ ++ an7583_pcs_common_phya_rx_oscal(priv); ++ an7583_pcs_common_phya_pical(priv); ++ an7583_pcs_common_phya_pdos(priv); ++ an7583_pcs_common_phya_feos(priv); ++ an7583_pcs_common_phya_sdcal(priv); ++ an7583_pcs_common_phya_phy_status(priv); ++ ++ an7583_pcs_dig_reset_release(priv); ++ ++ an7583_pcs_common_phya_l2d(priv); ++ ++ if (data->port_type == AIROHA_PCS_PON) ++ an7583_pcs_common_phya_eo_scan(priv, interface); ++ an7583_pcs_common_phya_rxrdy(priv); ++ if (data->port_type == AIROHA_PCS_PON) ++ an7583_pcs_common_phya_bist_setting(priv); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_ADD_XPON_MODE_1, ++ AIROHA_PCS_PMA_TX_BIST_GEN_EN | ++ AIROHA_PCS_PMA_R2T_MODE); ++} ++ ++static void an7583_pcs_ana_reset_release(struct airoha_pcs_priv *priv) ++{ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_XFI_RXPCS_RST_N | ++ AIROHA_PCS_PMA_SW_XFI_TXPCS_RST_N); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_XFI_RXPCS_BIST_RST_N); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_HSG_RXPCS_RST_N | ++ AIROHA_PCS_PMA_SW_HSG_TXPCS_RST_N); ++ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET, ++ AIROHA_PCS_PMA_SW_XFI_RXMAC_RST_N | ++ AIROHA_PCS_PMA_SW_XFI_TXMAC_RST_N); ++} ++ ++int an7583_pcs_common_phya_bringup(struct airoha_pcs_priv *priv, ++ phy_interface_t interface) ++{ ++ an7583_pcs_dig_reset_hold(priv); ++ ++ an7583_pcs_cfg_phy_type(priv, interface); ++ ++ an7583_pcs_common_phya_txpll_on(priv); ++ ++ an7583_pcs_common_phya_tx_on(priv); ++ ++ an7583_pcs_first_plug_in(priv, interface); ++ ++ an7583_pcs_ana_reset_release(priv); ++ ++ return 0; ++} ++ ++void an7583_pcs_common_phya_link_up(struct airoha_pcs_priv *priv) ++{ ++ /* First CDR reset */ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB); ++ ++ usleep_range(700, 1000); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB); ++ ++ usleep_range(100, 200); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB); ++ ++ regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA, ++ AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA | ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA, ++ AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA); ++ ++ /* Then RX Rdy reset */ ++ regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1, ++ AIROHA_PCS_PMA_DISB_RX_RDY); ++ ++ regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1, ++ AIROHA_PCS_PMA_DISB_RX_RDY); ++} diff --git a/lede/target/linux/airoha/patches-6.12/604-02-net-ethernet-airoha-define-sport-value-for-GDM3.patch b/lede/target/linux/airoha/patches-6.12/604-02-net-ethernet-airoha-define-sport-value-for-GDM3.patch new file mode 100644 index 0000000000..db0e9b4f48 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/604-02-net-ethernet-airoha-define-sport-value-for-GDM3.patch @@ -0,0 +1,26 @@ +From 6548e580509397a622b7c504a79de93414771459 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 25 Jun 2025 00:04:36 +0200 +Subject: [PATCH 6/6] net: ethernet: airoha: define sport value for GDM3 + +On Airoha AN7583, the Serdes Ethernet goes through the GDM3 port. +To correctly receive packet for QDMA, add the sport value to identify +packet from GDM3 port. + +Signed-off-by: Christian Marangi +--- + drivers/net/ethernet/airoha/airoha_eth.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -599,6 +599,9 @@ static int airoha_qdma_get_gdm_port(stru + case 0x18: + port = 3; /* GDM4 */ + break; ++ case 0x16: ++ port = 2; /* GDM3 */ ++ break; + case 0x10 ... 0x14: + port = 0; /* GDM1 */ + break; diff --git a/lede/target/linux/airoha/patches-6.12/605-net-pcs-airoha-add-support-for-optional-xfi-reset-li.patch b/lede/target/linux/airoha/patches-6.12/605-net-pcs-airoha-add-support-for-optional-xfi-reset-li.patch new file mode 100644 index 0000000000..5f48c34753 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/605-net-pcs-airoha-add-support-for-optional-xfi-reset-li.patch @@ -0,0 +1,63 @@ +From 961800f3badd72e4efda39f219ac4cbec5791433 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sat, 26 Jul 2025 22:58:10 +0200 +Subject: [PATCH 7/8] net: pcs: airoha: add support for optional xfi reset line + +On Airoha AN7583 there is a dedicated reset line for the PON XFI Serdes. +This is needed to permit changing the WAN sel register or the system +will stall on accessing the XFI register. + +Add support for this optional dedicated reset to permit correct +configuration of the PON Serdes. + +Signed-off-by: Christian Marangi +--- + drivers/net/pcs/airoha/pcs-airoha-common.c | 12 ++++++++++++ + drivers/net/pcs/airoha/pcs-airoha.h | 1 + + 2 files changed, 13 insertions(+) + +--- a/drivers/net/pcs/airoha/pcs-airoha-common.c ++++ b/drivers/net/pcs/airoha/pcs-airoha-common.c +@@ -82,6 +82,10 @@ static int airoha_pcs_setup_scu(struct a + const struct airoha_pcs_match_data *data = priv->data; + int ret; + ++ ret = reset_control_assert(priv->xfi_rst); ++ if (ret) ++ return ret; ++ + switch (data->port_type) { + case AIROHA_PCS_ETH: + airoha_pcs_setup_scu_eth(priv, interface); +@@ -91,6 +95,10 @@ static int airoha_pcs_setup_scu(struct a + break; + } + ++ ret = reset_control_deassert(priv->xfi_rst); ++ if (ret) ++ return ret; ++ + /* TODO better handle reset from MAC */ + ret = reset_control_bulk_assert(ARRAY_SIZE(priv->rsts), + priv->rsts); +@@ -1003,6 +1011,10 @@ static int airoha_pcs_probe(struct platf + if (ret) + return dev_err_probe(dev, ret, "failed to get bulk reset lines\n"); + ++ priv->xfi_rst = devm_reset_control_get_optional_exclusive(dev, "xfi"); ++ if (IS_ERR(priv->xfi_rst)) ++ return dev_err_probe(dev, PTR_ERR(priv->xfi_rst), "failed to get xfi reset lines\n"); ++ + /* For Ethernet PCS, read the AN7581 SoC revision to check if + * manual rx calibration is needed. This is only limited to + * any SoC revision before E2. +--- a/drivers/net/pcs/airoha/pcs-airoha.h ++++ b/drivers/net/pcs/airoha/pcs-airoha.h +@@ -1184,6 +1184,7 @@ struct airoha_pcs_priv { + struct regmap *xfi_pma; + struct regmap *xfi_ana; + ++ struct reset_control *xfi_rst; + struct reset_control_bulk_data rsts[AIROHA_PCS_MAX_NUM_RSTS]; + + bool manual_rx_calib; diff --git a/lede/target/linux/airoha/patches-6.12/606-net-airoha-disable-external-phy-code-if-PCS_AIROHA-i.patch b/lede/target/linux/airoha/patches-6.12/606-net-airoha-disable-external-phy-code-if-PCS_AIROHA-i.patch new file mode 100644 index 0000000000..bcc80b002d --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/606-net-airoha-disable-external-phy-code-if-PCS_AIROHA-i.patch @@ -0,0 +1,145 @@ +From 843e2892f2d9353bf039e0dfb5442a600e75009e Mon Sep 17 00:00:00 2001 +From: Mikhail Kshevetskiy +Date: Thu, 9 Oct 2025 23:46:08 +0300 +Subject: [PATCH] net: airoha: disable external phy code if PCS_AIROHA is not + enabled + +External phy code breaks building for EN7523, so disable it if +PCS_AIROHA is not selected. + +Signed-off-by: Mikhail Kshevetskiy +--- + drivers/net/ethernet/airoha/airoha_eth.c | 16 ++++++++++++++++ + drivers/net/ethernet/airoha/airoha_eth.h | 2 ++ + 2 files changed, 18 insertions(+) + +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -72,10 +72,12 @@ static void airoha_qdma_irq_disable(stru + airoha_qdma_set_irqmask(irq_bank, index, mask, 0); + } + ++#if defined(CONFIG_PCS_AIROHA) + static bool airhoa_is_phy_external(struct airoha_gdm_port *port) + { + return port->id != 1; + } ++#endif + + static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr) + { +@@ -1630,6 +1632,7 @@ static int airoha_dev_open(struct net_de + struct airoha_gdm_port *port = netdev_priv(dev); + struct airoha_qdma *qdma = port->qdma; + ++#if defined(CONFIG_PCS_AIROHA) + if (airhoa_is_phy_external(port)) { + err = phylink_of_phy_connect(port->phylink, dev->dev.of_node, 0); + if (err) { +@@ -1640,6 +1643,7 @@ static int airoha_dev_open(struct net_de + + phylink_start(port->phylink); + } ++#endif + + netif_tx_start_all_queues(dev); + err = airoha_set_vip_for_gdm_port(port, true); +@@ -1694,10 +1698,12 @@ static int airoha_dev_stop(struct net_de + } + } + ++#if defined(CONFIG_PCS_AIROHA) + if (airhoa_is_phy_external(port)) { + phylink_stop(port->phylink); + phylink_disconnect_phy(port->phylink); + } ++#endif + + return 0; + } +@@ -2841,6 +2847,7 @@ static const struct ethtool_ops airoha_e + .get_link = ethtool_op_get_link, + }; + ++#if defined(CONFIG_PCS_AIROHA) + static struct phylink_pcs *airoha_phylink_mac_select_pcs(struct phylink_config *config, + phy_interface_t interface) + { +@@ -2854,6 +2861,7 @@ static void airoha_mac_config(struct phy + const struct phylink_link_state *state) + { + } ++#endif + + static int airoha_metadata_dst_alloc(struct airoha_gdm_port *port) + { +@@ -2899,6 +2907,7 @@ bool airoha_is_valid_gdm_port(struct air + return false; + } + ++#if defined(CONFIG_PCS_AIROHA) + static void airoha_mac_link_up(struct phylink_config *config, struct phy_device *phy, + unsigned int mode, phy_interface_t interface, + int speed, int duplex, bool tx_pause, bool rx_pause) +@@ -2991,6 +3000,7 @@ static int airoha_setup_phylink(struct n + + return 0; + } ++#endif + + static int airoha_alloc_gdm_port(struct airoha_eth *eth, + struct device_node *np, int index) +@@ -3070,11 +3080,13 @@ static int airoha_alloc_gdm_port(struct + if (err) + return err; + ++#if defined(CONFIG_PCS_AIROHA) + if (airhoa_is_phy_external(port)) { + err = airoha_setup_phylink(dev); + if (err) + goto free_metadata_dst; + } ++#endif + + err = register_netdev(dev); + if (err) +@@ -3191,10 +3203,12 @@ error_hw_cleanup: + if (port && port->dev->reg_state == NETREG_REGISTERED) { + unregister_netdev(port->dev); + airoha_metadata_dst_free(port); ++#if defined(CONFIG_PCS_AIROHA) + if (airhoa_is_phy_external(port)) { + phylink_destroy(port->phylink); + airoha_pcs_destroy(port->pcs); + } ++#endif + } + } + free_netdev(eth->napi_dev); +@@ -3222,10 +3236,12 @@ static void airoha_remove(struct platfor + airoha_dev_stop(port->dev); + unregister_netdev(port->dev); + airoha_metadata_dst_free(port); ++#if defined(CONFIG_PCS_AIROHA) + if (airhoa_is_phy_external(port)) { + phylink_destroy(port->phylink); + airoha_pcs_destroy(port->pcs); + } ++#endif + } + free_netdev(eth->napi_dev); + +--- a/drivers/net/ethernet/airoha/airoha_eth.h ++++ b/drivers/net/ethernet/airoha/airoha_eth.h +@@ -536,9 +536,11 @@ struct airoha_gdm_port { + struct net_device *dev; + int id; + ++#if defined(CONFIG_PCS_AIROHA) + struct phylink *phylink; + struct phylink_config phylink_config; + struct phylink_pcs *pcs; ++#endif + + struct airoha_hw_stats stats; + diff --git a/lede/target/linux/airoha/patches-6.12/801-01-net-phy-add-PHY_DETACH_NO_HW_RESET-PHY-flag.patch b/lede/target/linux/airoha/patches-6.12/801-01-net-phy-add-PHY_DETACH_NO_HW_RESET-PHY-flag.patch new file mode 100644 index 0000000000..53ea635ffe --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/801-01-net-phy-add-PHY_DETACH_NO_HW_RESET-PHY-flag.patch @@ -0,0 +1,129 @@ +From f2c6f8711c3866caafee997cfa60af4f38879be0 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 25 Jun 2025 00:45:11 +0200 +Subject: [PATCH 1/2] net: phy: add PHY_DETACH_NO_HW_RESET PHY flag + +Some PHY require a firmware to correctly work and such firmware might +get reset when the GPIO reset is assert. + +This is the case for the Aeonsemi PHY where when the PHY is torn down, +phy_detach() is called that assert the GPIO reset pin resetting the +firmware. + +To handle this introduce a flag, PHY_DETACH_NO_HW_RESET that instruct +phy_detach() to skip asserting the GPIO reset on detaching the PHY. + +The PHY is still reset in all other case where it's removed or the PHY +fails to probe. + +Signed-off-by: Christian Marangi +--- + drivers/net/phy/as21xxx.c | 10 ++++++++++ + drivers/net/phy/phy_device.c | 3 ++- + include/linux/phy.h | 1 + + 3 files changed, 13 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/as21xxx.c ++++ b/drivers/net/phy/as21xxx.c +@@ -964,6 +964,7 @@ static struct phy_driver as21xxx_drivers + .led_hw_control_set = as21xxx_led_hw_control_set, + .led_hw_control_get = as21xxx_led_hw_control_get, + .led_polarity_set = as21xxx_led_polarity_set, ++ .flags = PHY_DETACH_NO_RESET, + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_AS21011PB1), +@@ -976,6 +977,7 @@ static struct phy_driver as21xxx_drivers + .led_hw_control_set = as21xxx_led_hw_control_set, + .led_hw_control_get = as21xxx_led_hw_control_get, + .led_polarity_set = as21xxx_led_polarity_set, ++ .flags = PHY_DETACH_NO_RESET, + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_AS21010PB1), +@@ -988,6 +990,7 @@ static struct phy_driver as21xxx_drivers + .led_hw_control_set = as21xxx_led_hw_control_set, + .led_hw_control_get = as21xxx_led_hw_control_get, + .led_polarity_set = as21xxx_led_polarity_set, ++ .flags = PHY_DETACH_NO_RESET, + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_AS21010JB1), +@@ -1000,6 +1003,7 @@ static struct phy_driver as21xxx_drivers + .led_hw_control_set = as21xxx_led_hw_control_set, + .led_hw_control_get = as21xxx_led_hw_control_get, + .led_polarity_set = as21xxx_led_polarity_set, ++ .flags = PHY_DETACH_NO_RESET, + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_AS21210PB1), +@@ -1012,6 +1016,7 @@ static struct phy_driver as21xxx_drivers + .led_hw_control_set = as21xxx_led_hw_control_set, + .led_hw_control_get = as21xxx_led_hw_control_get, + .led_polarity_set = as21xxx_led_polarity_set, ++ .flags = PHY_DETACH_NO_RESET, + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_AS21510JB1), +@@ -1024,6 +1029,7 @@ static struct phy_driver as21xxx_drivers + .led_hw_control_set = as21xxx_led_hw_control_set, + .led_hw_control_get = as21xxx_led_hw_control_get, + .led_polarity_set = as21xxx_led_polarity_set, ++ .flags = PHY_DETACH_NO_RESET, + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_AS21510PB1), +@@ -1036,6 +1042,7 @@ static struct phy_driver as21xxx_drivers + .led_hw_control_set = as21xxx_led_hw_control_set, + .led_hw_control_get = as21xxx_led_hw_control_get, + .led_polarity_set = as21xxx_led_polarity_set, ++ .flags = PHY_DETACH_NO_RESET, + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_AS21511JB1), +@@ -1048,6 +1055,7 @@ static struct phy_driver as21xxx_drivers + .led_hw_control_set = as21xxx_led_hw_control_set, + .led_hw_control_get = as21xxx_led_hw_control_get, + .led_polarity_set = as21xxx_led_polarity_set, ++ .flags = PHY_DETACH_NO_RESET, + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_AS21210JB1), +@@ -1060,6 +1068,7 @@ static struct phy_driver as21xxx_drivers + .led_hw_control_set = as21xxx_led_hw_control_set, + .led_hw_control_get = as21xxx_led_hw_control_get, + .led_polarity_set = as21xxx_led_polarity_set, ++ .flags = PHY_DETACH_NO_RESET, + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_AS21511PB1), +@@ -1072,6 +1081,7 @@ static struct phy_driver as21xxx_drivers + .led_hw_control_set = as21xxx_led_hw_control_set, + .led_hw_control_get = as21xxx_led_hw_control_get, + .led_polarity_set = as21xxx_led_polarity_set, ++ .flags = PHY_DETACH_NO_RESET, + }, + }; + module_phy_driver(as21xxx_drivers); +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -2074,7 +2074,8 @@ void phy_detach(struct phy_device *phyde + device_release_driver(&phydev->mdio.dev); + + /* Assert the reset signal */ +- phy_device_reset(phydev, 1); ++ if (!phydev->drv || !(phydev->drv->flags & PHY_DETACH_NO_HW_RESET)) ++ phy_device_reset(phydev, 1); + + /* + * The phydev might go away on the put_device() below, so avoid +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -90,6 +90,7 @@ extern const int phy_10gbit_features_arr + #define PHY_RST_AFTER_CLK_EN 0x00000002 + #define PHY_POLL_CABLE_TEST 0x00000004 + #define PHY_ALWAYS_CALL_SUSPEND 0x00000008 ++#define PHY_DETACH_NO_HW_RESET 0x00000010 + #define MDIO_DEVICE_IS_PHY 0x80000000 + + /** diff --git a/lede/target/linux/airoha/patches-6.12/801-02-net-phy-as21xxx-add-flag-PHY_DETACH_NO_HW_RESET.patch b/lede/target/linux/airoha/patches-6.12/801-02-net-phy-as21xxx-add-flag-PHY_DETACH_NO_HW_RESET.patch new file mode 100644 index 0000000000..f2078310d2 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/801-02-net-phy-as21xxx-add-flag-PHY_DETACH_NO_HW_RESET.patch @@ -0,0 +1,108 @@ +From 7ad1470c3d08c1abea747aa0c789e924f63fcbc4 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Wed, 25 Jun 2025 00:51:45 +0200 +Subject: [PATCH 2/2] net: phy: as21xxx: add flag PHY_DETACH_NO_HW_RESET + +Add flag PHY_DETACH_NO_HW_RESET to handle firmware getting reset on +calling phy_detach() if the GPIO reset PIN is defined in DT. + +This will skip the firmware from getting reset permitting the PHY to +continue work when the PHY is torn down and gets up again. + +Signed-off-by: Christian Marangi +--- + drivers/net/phy/as21xxx.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +--- a/drivers/net/phy/as21xxx.c ++++ b/drivers/net/phy/as21xxx.c +@@ -964,7 +964,7 @@ static struct phy_driver as21xxx_drivers + .led_hw_control_set = as21xxx_led_hw_control_set, + .led_hw_control_get = as21xxx_led_hw_control_get, + .led_polarity_set = as21xxx_led_polarity_set, +- .flags = PHY_DETACH_NO_RESET, ++ .flags = PHY_DETACH_NO_HW_RESET, + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_AS21011PB1), +@@ -977,7 +977,7 @@ static struct phy_driver as21xxx_drivers + .led_hw_control_set = as21xxx_led_hw_control_set, + .led_hw_control_get = as21xxx_led_hw_control_get, + .led_polarity_set = as21xxx_led_polarity_set, +- .flags = PHY_DETACH_NO_RESET, ++ .flags = PHY_DETACH_NO_HW_RESET, + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_AS21010PB1), +@@ -990,7 +990,7 @@ static struct phy_driver as21xxx_drivers + .led_hw_control_set = as21xxx_led_hw_control_set, + .led_hw_control_get = as21xxx_led_hw_control_get, + .led_polarity_set = as21xxx_led_polarity_set, +- .flags = PHY_DETACH_NO_RESET, ++ .flags = PHY_DETACH_NO_HW_RESET, + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_AS21010JB1), +@@ -1003,7 +1003,7 @@ static struct phy_driver as21xxx_drivers + .led_hw_control_set = as21xxx_led_hw_control_set, + .led_hw_control_get = as21xxx_led_hw_control_get, + .led_polarity_set = as21xxx_led_polarity_set, +- .flags = PHY_DETACH_NO_RESET, ++ .flags = PHY_DETACH_NO_HW_RESET, + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_AS21210PB1), +@@ -1016,7 +1016,7 @@ static struct phy_driver as21xxx_drivers + .led_hw_control_set = as21xxx_led_hw_control_set, + .led_hw_control_get = as21xxx_led_hw_control_get, + .led_polarity_set = as21xxx_led_polarity_set, +- .flags = PHY_DETACH_NO_RESET, ++ .flags = PHY_DETACH_NO_HW_RESET, + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_AS21510JB1), +@@ -1029,7 +1029,7 @@ static struct phy_driver as21xxx_drivers + .led_hw_control_set = as21xxx_led_hw_control_set, + .led_hw_control_get = as21xxx_led_hw_control_get, + .led_polarity_set = as21xxx_led_polarity_set, +- .flags = PHY_DETACH_NO_RESET, ++ .flags = PHY_DETACH_NO_HW_RESET, + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_AS21510PB1), +@@ -1042,7 +1042,7 @@ static struct phy_driver as21xxx_drivers + .led_hw_control_set = as21xxx_led_hw_control_set, + .led_hw_control_get = as21xxx_led_hw_control_get, + .led_polarity_set = as21xxx_led_polarity_set, +- .flags = PHY_DETACH_NO_RESET, ++ .flags = PHY_DETACH_NO_HW_RESET, + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_AS21511JB1), +@@ -1055,7 +1055,7 @@ static struct phy_driver as21xxx_drivers + .led_hw_control_set = as21xxx_led_hw_control_set, + .led_hw_control_get = as21xxx_led_hw_control_get, + .led_polarity_set = as21xxx_led_polarity_set, +- .flags = PHY_DETACH_NO_RESET, ++ .flags = PHY_DETACH_NO_HW_RESET, + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_AS21210JB1), +@@ -1068,7 +1068,7 @@ static struct phy_driver as21xxx_drivers + .led_hw_control_set = as21xxx_led_hw_control_set, + .led_hw_control_get = as21xxx_led_hw_control_get, + .led_polarity_set = as21xxx_led_polarity_set, +- .flags = PHY_DETACH_NO_RESET, ++ .flags = PHY_DETACH_NO_HW_RESET, + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_AS21511PB1), +@@ -1081,7 +1081,7 @@ static struct phy_driver as21xxx_drivers + .led_hw_control_set = as21xxx_led_hw_control_set, + .led_hw_control_get = as21xxx_led_hw_control_get, + .led_polarity_set = as21xxx_led_polarity_set, +- .flags = PHY_DETACH_NO_RESET, ++ .flags = PHY_DETACH_NO_HW_RESET, + }, + }; + module_phy_driver(as21xxx_drivers); diff --git a/lede/target/linux/airoha/patches-6.12/802-01-net-phy-as21xxx-handle-corner-case-with-link-and-aut.patch b/lede/target/linux/airoha/patches-6.12/802-01-net-phy-as21xxx-handle-corner-case-with-link-and-aut.patch new file mode 100644 index 0000000000..6e599cdd3f --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/802-01-net-phy-as21xxx-handle-corner-case-with-link-and-aut.patch @@ -0,0 +1,31 @@ +From 0146a02d9d182796c3d8e4a432c4d94cac042f8e Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Mon, 7 Jul 2025 18:58:25 +0200 +Subject: [PATCH 1/4] net: phy: as21xxx: handle corner case with link and + autoneg complete + +Add missing case in custom read_link, when autoneg is started, autoneg +complete bit is reset but link is still not up. + +Fixes: 830877d89edc ("net: phy: Add support for Aeonsemi AS21xxx PHYs") +Signed-off-by: Christian Marangi +--- + drivers/net/phy/as21xxx.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/net/phy/as21xxx.c ++++ b/drivers/net/phy/as21xxx.c +@@ -658,6 +658,13 @@ static int as21xxx_read_link(struct phy_ + return status; + + phydev->link = !!(status & MDIO_STAT1_LSTATUS); ++ phydev->autoneg_complete = !!(status & MDIO_AN_STAT1_COMPLETE); ++ ++ /* Consider the case that autoneg was started and "aneg complete" ++ * bit has been reset, but "link up" bit not yet. ++ */ ++ if (phydev->autoneg == AUTONEG_ENABLE && !phydev->autoneg_complete) ++ phydev->link = 0; + + return 0; + } diff --git a/lede/target/linux/airoha/patches-6.12/802-02-net-phy-as21xxx-fix-read_status-speed-handling.patch b/lede/target/linux/airoha/patches-6.12/802-02-net-phy-as21xxx-fix-read_status-speed-handling.patch new file mode 100644 index 0000000000..4010c4093b --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/802-02-net-phy-as21xxx-fix-read_status-speed-handling.patch @@ -0,0 +1,156 @@ +From d90186b1e48dd4a428abf889b1eb17d2469de08b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 8 Jul 2025 10:50:42 +0200 +Subject: [PATCH 2/4] net: phy: as21xxx: fix read_status speed handling + +With further test with 2.5G NIC it was discovered that +phy_resolve_aneg_linkmode is not enough to detect speed higher that 1G +when autoneg is enabled. + +Also in the switch case there is a typo where the speed mask is AND with +VEND1_SPEED_STATUS instead of the correct mask VEND1_SPEED_MASK. + +Rework the read_status code to always read the speed from the vendor +register and parse the generic bit only for the pause frame. + +Fixes: 830877d89edc ("net: phy: Add support for Aeonsemi AS21xxx PHYs") +Signed-off-by: Christian Marangi +--- + drivers/net/phy/as21xxx.c | 96 +++++++++++++++++++++------------------ + 1 file changed, 53 insertions(+), 43 deletions(-) + +--- a/drivers/net/phy/as21xxx.c ++++ b/drivers/net/phy/as21xxx.c +@@ -671,7 +671,7 @@ static int as21xxx_read_link(struct phy_ + + static int as21xxx_read_c22_lpa(struct phy_device *phydev) + { +- int lpagb; ++ int lpagb, lpa; + + /* MII_STAT1000 are only filled in the mapped C22 + * in C45, use that to fill lpagb values and check. +@@ -698,12 +698,20 @@ static int as21xxx_read_c22_lpa(struct p + mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, + lpagb); + ++ lpa = phy_read_mmd(phydev, MDIO_MMD_AN, ++ AS21XXX_MDIO_AN_C22 + MII_LPA); ++ if (lpa < 0) ++ return lpa; ++ ++ mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, lpa); ++ + return 0; + } + + static int as21xxx_read_status(struct phy_device *phydev) + { + int bmcr, old_link = phydev->link; ++ int speed; + int ret; + + ret = as21xxx_read_link(phydev, &bmcr); +@@ -720,58 +728,60 @@ static int as21xxx_read_status(struct ph + phydev->asym_pause = 0; + + if (phydev->autoneg == AUTONEG_ENABLE) { +- ret = genphy_c45_read_lpa(phydev); +- if (ret) +- return ret; ++ if (!phydev->autoneg_complete) { ++ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, ++ 0); ++ mii_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, 0); ++ return 0; ++ } + + ret = as21xxx_read_c22_lpa(phydev); + if (ret) + return ret; +- +- phy_resolve_aneg_linkmode(phydev); + } else { +- int speed; +- + linkmode_zero(phydev->lp_advertising); ++ } + +- speed = phy_read_mmd(phydev, MDIO_MMD_VEND1, +- VEND1_SPEED_STATUS); +- if (speed < 0) +- return speed; +- +- switch (speed & VEND1_SPEED_STATUS) { +- case VEND1_SPEED_10000: +- phydev->speed = SPEED_10000; ++ speed = phy_read_mmd(phydev, MDIO_MMD_VEND1, ++ VEND1_SPEED_STATUS); ++ if (speed < 0) ++ return speed; ++ ++ switch (speed & VEND1_SPEED_MASK) { ++ case VEND1_SPEED_10000: ++ phydev->speed = SPEED_10000; ++ phydev->duplex = DUPLEX_FULL; ++ break; ++ case VEND1_SPEED_5000: ++ phydev->speed = SPEED_5000; ++ phydev->duplex = DUPLEX_FULL; ++ break; ++ case VEND1_SPEED_2500: ++ phydev->speed = SPEED_2500; ++ phydev->duplex = DUPLEX_FULL; ++ break; ++ case VEND1_SPEED_1000: ++ phydev->speed = SPEED_1000; ++ if (bmcr & BMCR_FULLDPLX) + phydev->duplex = DUPLEX_FULL; +- break; +- case VEND1_SPEED_5000: +- phydev->speed = SPEED_5000; +- phydev->duplex = DUPLEX_FULL; +- break; +- case VEND1_SPEED_2500: +- phydev->speed = SPEED_2500; +- phydev->duplex = DUPLEX_FULL; +- break; +- case VEND1_SPEED_1000: +- phydev->speed = SPEED_1000; +- if (bmcr & BMCR_FULLDPLX) +- phydev->duplex = DUPLEX_FULL; +- else +- phydev->duplex = DUPLEX_HALF; +- break; +- case VEND1_SPEED_100: +- phydev->speed = SPEED_100; +- phydev->duplex = DUPLEX_FULL; +- break; +- case VEND1_SPEED_10: +- phydev->speed = SPEED_10; +- phydev->duplex = DUPLEX_FULL; +- break; +- default: +- return -EINVAL; +- } ++ else ++ phydev->duplex = DUPLEX_HALF; ++ break; ++ case VEND1_SPEED_100: ++ phydev->speed = SPEED_100; ++ phydev->duplex = DUPLEX_FULL; ++ break; ++ case VEND1_SPEED_10: ++ phydev->speed = SPEED_10; ++ phydev->duplex = DUPLEX_FULL; ++ break; ++ default: ++ return -EINVAL; + } + ++ if (phydev->autoneg == AUTONEG_ENABLE) ++ phy_resolve_aneg_pause(phydev); ++ + return 0; + } + diff --git a/lede/target/linux/airoha/patches-6.12/802-03-net-phy-as21xxx-force-C45-OPs-for-AUTONEG.patch b/lede/target/linux/airoha/patches-6.12/802-03-net-phy-as21xxx-force-C45-OPs-for-AUTONEG.patch new file mode 100644 index 0000000000..19118db786 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/802-03-net-phy-as21xxx-force-C45-OPs-for-AUTONEG.patch @@ -0,0 +1,34 @@ +From 6003da596beb6b8974e61b7ff494476a323fbef5 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Tue, 8 Jul 2025 11:29:49 +0200 +Subject: [PATCH 3/4] net: phy: as21xxx: force C45 OPs for AUTONEG + +With further testing with 2.5G NIC, it was discovered that the PHY +require the C45 OPs to configure and restart ANEG or speed higher than +1G doesn't function correctly. + +To force C45 OPs with generic PHY function, clear the C22 bit from +devices_in_package bitmask. + +Fixes: 830877d89edc ("net: phy: Add support for Aeonsemi AS21xxx PHYs") +Signed-off-by: Christian Marangi +--- + drivers/net/phy/as21xxx.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/net/phy/as21xxx.c ++++ b/drivers/net/phy/as21xxx.c +@@ -616,6 +616,13 @@ static int as21xxx_probe(struct phy_devi + if (ret) + return ret; + ++ /* Even if PHY declare support for Clause 22 register, ++ * Clause 45 register should be used for ANEG configuration ++ * and restart. Clear the C22 bit for devices_in_package to ++ * force C45 generic OPs in generic PHY ANGE OPs. ++ */ ++ phydev->c45_ids.devices_in_package &= ~BIT(0); ++ + ret = aeon_ipc_sync_parity(phydev, priv); + if (ret) + return ret; diff --git a/lede/target/linux/airoha/patches-6.12/804-net-phy-as21xxx-implement-read-workaround-for-C45-re.patch b/lede/target/linux/airoha/patches-6.12/804-net-phy-as21xxx-implement-read-workaround-for-C45-re.patch new file mode 100644 index 0000000000..24cddf8307 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/804-net-phy-as21xxx-implement-read-workaround-for-C45-re.patch @@ -0,0 +1,132 @@ +From fabaa8a7183d10217e14af437fd3805bd6dd9eba Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Sat, 18 Oct 2025 04:12:41 +0200 +Subject: [PATCH] net: phy: as21xxx: implement read workaround for C45 read + +This PHY have lots of problems with MDIO read operation. We somehow +workaround this with using C45 operation for pretty much everything but +this is not enough. The reference code for this PHY makes a write to an +unused PHY to workaround this read problem. This was also confirmed by +Aeonsemi. + +Various test were made to try to workaround this ins alternative way +than the random write. + +One effective solution was to limit the write only to BMSR. And also +write to BMSR is safe since they are only read only registers. + +This is only done for read operation as write operation doesn't suffer +from this problem. + +Worth to mention that when multiple Aeonsemi PHY are mounted, the +workaround doesn't work if we write to another Aeonsemi PHY. + +Signed-off-by: Christian Marangi +--- + drivers/net/phy/as21xxx.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +--- a/drivers/net/phy/as21xxx.c ++++ b/drivers/net/phy/as21xxx.c +@@ -966,6 +966,21 @@ out: + return ret; + } + ++static int as21xxx_read_mmd(struct phy_device *phydev, int devad, ++ u16 regnum) ++{ ++ struct mii_bus *bus = phydev->mdio.bus; ++ int val; ++ ++ val = __mdiobus_c45_read(bus, phydev->mdio.addr, devad, ++ regnum); ++ ++ /* FIXME: verify if it's actually ok to limit this to MII_BMSR */ ++ __mdiobus_write(bus, 0x0, MII_BMSR, 0x1); ++ ++ return val; ++} ++ + static struct phy_driver as21xxx_drivers[] = { + { + /* PHY expose in C45 as 0x7500 0x9410 +@@ -983,6 +998,7 @@ static struct phy_driver as21xxx_drivers + .probe = as21xxx_probe, + .match_phy_device = as21xxx_match_phy_device, + .read_status = as21xxx_read_status, ++ .read_mmd = as21xxx_read_mmd, + .led_brightness_set = as21xxx_led_brightness_set, + .led_hw_is_supported = as21xxx_led_hw_is_supported, + .led_hw_control_set = as21xxx_led_hw_control_set, +@@ -996,6 +1012,7 @@ static struct phy_driver as21xxx_drivers + .probe = as21xxx_probe, + .match_phy_device = as21xxx_match_phy_device, + .read_status = as21xxx_read_status, ++ .read_mmd = as21xxx_read_mmd, + .led_brightness_set = as21xxx_led_brightness_set, + .led_hw_is_supported = as21xxx_led_hw_is_supported, + .led_hw_control_set = as21xxx_led_hw_control_set, +@@ -1009,6 +1026,7 @@ static struct phy_driver as21xxx_drivers + .probe = as21xxx_probe, + .match_phy_device = as21xxx_match_phy_device, + .read_status = as21xxx_read_status, ++ .read_mmd = as21xxx_read_mmd, + .led_brightness_set = as21xxx_led_brightness_set, + .led_hw_is_supported = as21xxx_led_hw_is_supported, + .led_hw_control_set = as21xxx_led_hw_control_set, +@@ -1022,6 +1040,7 @@ static struct phy_driver as21xxx_drivers + .probe = as21xxx_probe, + .match_phy_device = as21xxx_match_phy_device, + .read_status = as21xxx_read_status, ++ .read_mmd = as21xxx_read_mmd, + .led_brightness_set = as21xxx_led_brightness_set, + .led_hw_is_supported = as21xxx_led_hw_is_supported, + .led_hw_control_set = as21xxx_led_hw_control_set, +@@ -1035,6 +1054,7 @@ static struct phy_driver as21xxx_drivers + .probe = as21xxx_probe, + .match_phy_device = as21xxx_match_phy_device, + .read_status = as21xxx_read_status, ++ .read_mmd = as21xxx_read_mmd, + .led_brightness_set = as21xxx_led_brightness_set, + .led_hw_is_supported = as21xxx_led_hw_is_supported, + .led_hw_control_set = as21xxx_led_hw_control_set, +@@ -1048,6 +1068,7 @@ static struct phy_driver as21xxx_drivers + .probe = as21xxx_probe, + .match_phy_device = as21xxx_match_phy_device, + .read_status = as21xxx_read_status, ++ .read_mmd = as21xxx_read_mmd, + .led_brightness_set = as21xxx_led_brightness_set, + .led_hw_is_supported = as21xxx_led_hw_is_supported, + .led_hw_control_set = as21xxx_led_hw_control_set, +@@ -1061,6 +1082,7 @@ static struct phy_driver as21xxx_drivers + .probe = as21xxx_probe, + .match_phy_device = as21xxx_match_phy_device, + .read_status = as21xxx_read_status, ++ .read_mmd = as21xxx_read_mmd, + .led_brightness_set = as21xxx_led_brightness_set, + .led_hw_is_supported = as21xxx_led_hw_is_supported, + .led_hw_control_set = as21xxx_led_hw_control_set, +@@ -1074,6 +1096,7 @@ static struct phy_driver as21xxx_drivers + .probe = as21xxx_probe, + .match_phy_device = as21xxx_match_phy_device, + .read_status = as21xxx_read_status, ++ .read_mmd = as21xxx_read_mmd, + .led_brightness_set = as21xxx_led_brightness_set, + .led_hw_is_supported = as21xxx_led_hw_is_supported, + .led_hw_control_set = as21xxx_led_hw_control_set, +@@ -1087,6 +1110,7 @@ static struct phy_driver as21xxx_drivers + .probe = as21xxx_probe, + .match_phy_device = as21xxx_match_phy_device, + .read_status = as21xxx_read_status, ++ .read_mmd = as21xxx_read_mmd, + .led_brightness_set = as21xxx_led_brightness_set, + .led_hw_is_supported = as21xxx_led_hw_is_supported, + .led_hw_control_set = as21xxx_led_hw_control_set, +@@ -1100,6 +1124,7 @@ static struct phy_driver as21xxx_drivers + .probe = as21xxx_probe, + .match_phy_device = as21xxx_match_phy_device, + .read_status = as21xxx_read_status, ++ .read_mmd = as21xxx_read_mmd, + .led_brightness_set = as21xxx_led_brightness_set, + .led_hw_is_supported = as21xxx_led_hw_is_supported, + .led_hw_control_set = as21xxx_led_hw_control_set, diff --git a/lede/target/linux/airoha/patches-6.12/900-airoha-bmt-support.patch b/lede/target/linux/airoha/patches-6.12/900-airoha-bmt-support.patch new file mode 100644 index 0000000000..5ba31c0829 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/900-airoha-bmt-support.patch @@ -0,0 +1,578 @@ +--- /dev/null ++++ b/drivers/mtd/nand/airoha_bmt.c +@@ -0,0 +1,575 @@ ++ ++/* ++ * Airoha BMT algorithm ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "mtk_bmt.h" ++ ++#define MAX_BMT_SIZE (250) ++#define MAX_RAW_BAD_BLOCK_SIZE (250) ++#define POOL_GOOD_BLOCK_PERCENT 8/100 ++#define MAX_BMT_PERCENT 1/8 ++ ++typedef struct { ++ char signature[3]; ++ u8 version; ++ u8 bad_count; // this field is useless ++ u8 size; ++ u8 checksum; ++ u8 reseverd[13]; ++} bmt_table_header; ++ ++typedef struct { ++ u16 from; ++ u16 to; ++} bmt_entry; ++ ++typedef struct { ++ bmt_table_header header; ++ bmt_entry table[MAX_BMT_SIZE]; ++} bmt_table; ++ ++typedef struct { ++ char signature[4]; ++ u32 checksum; ++ u8 version; ++ u8 size; ++ u8 reserved[2]; ++} bbt_table_header; ++ ++typedef struct { ++ bbt_table_header header; ++ u16 table[MAX_RAW_BAD_BLOCK_SIZE]; ++} bbt_table; ++ ++bbt_table bbt; ++bmt_table bmt; ++ ++int bmt_index=0xffff; ++int bbt_index=0xffff; ++unsigned int total_blks , system_blks , bmt_blks, _to, _to2, val; ++ ++module_param(bmt_index, int, S_IRUSR | S_IWUSR); ++module_param(bbt_index, int, S_IRUSR | S_IWUSR); ++module_param(total_blks, int, S_IRUSR | S_IWUSR); ++module_param(system_blks, int, S_IRUSR | S_IWUSR); ++module_param(bmt_blks, int, S_IRUSR | S_IWUSR); ++module_param(_to, int, S_IRUSR | S_IWUSR); ++module_param(_to2, int, S_IRUSR | S_IWUSR); ++module_param(val, int, S_IRUSR | S_IWUSR); ++ ++ ++static bool is_bad_raw(int block) { ++ u8 fdm[4]; ++ int ret; ++ ret = bbt_nand_read(blk_pg(block), bmtd.data_buf, bmtd.pg_size, ++ fdm, sizeof(fdm)); ++ if (ret || fdm[0] != 0xff ){ ++ return true; ++ } ++ return false; ++} ++ ++static bool is_bad( int block) { ++ u8 fdm[4]; ++ int ret; ++ ret = bbt_nand_read(blk_pg(block), bmtd.data_buf, bmtd.pg_size, ++ fdm, sizeof(fdm)); ++ //printk("%x %x %x %x\n", fdm[0], fdm[1], fdm[2], fdm[3]); ++ if (ret || fdm[0] != 0xff || fdm[1] != 0xff ){ ++ return true; ++ } ++ return false; ++} ++ ++ ++static bool is_mapped( int block) { ++ u16 mapped_block; ++ u8 fdm[4]; ++ int ret; ++ ++ ret = bbt_nand_read(blk_pg(block), bmtd.data_buf, bmtd.pg_size, ++ fdm, sizeof(fdm)); ++ mapped_block = (fdm[2] << 8) | fdm[3]; ++ //printk("%u is mapped to %d\n", mapped_block); ++ if (mapped_block == 0xffff) ++ return false; ++ else return true; ++} ++ ++static void mark_bad(int block) { ++ u8 fdm[4] = {0xff, 0xff, 0xff, 0xff}; ++ struct mtd_oob_ops ops = { ++ .mode = MTD_OPS_PLACE_OOB, ++ .ooboffs = 0, ++ .ooblen = 4, ++ .oobbuf = fdm, ++ .datbuf = NULL, ++ .len = 0, ++ }; ++ int retlen; ++ ++ printk("marking bad :%d\n", block); ++ if (block < system_blks) ++ fdm[0] = 0x00; ++ else fdm[1] = 0x00; ++ ++ retlen = bmtd._write_oob(bmtd.mtd, block << bmtd.blk_shift , &ops) ; ++ if (retlen < 0) { ++ printk("marking bad block failed \n"); ++ } ++} ++ ++ ++static void mark_good(int block) { ++ u8 fdm[4] = {0xff, 0xff, 0xff, 0xff}; ++ struct mtd_oob_ops ops = { ++ .mode = MTD_OPS_PLACE_OOB, ++ .ooboffs = 0, ++ .ooblen = 4, ++ .oobbuf = fdm, ++ .datbuf = NULL, ++ .len = 0, ++ }; ++ int retlen; ++ retlen = bmtd._write_oob(bmtd.mtd, block << bmtd.blk_shift , &ops) ; ++ if (retlen < 0) { ++ printk("marking bad block failed \n"); ++ } ++} ++ ++static void make_mapping(u16 from , u16 to) { ++ u8 fdm[4] = {0xff, 0xff, 0xff , 0xff}; ++ struct mtd_oob_ops ops = { ++ .mode = MTD_OPS_PLACE_OOB, ++ .ooboffs = 0, ++ .ooblen = 4, ++ .oobbuf = fdm, ++ .datbuf = NULL, ++ .len = 0, ++ }; ++ int retlen; ++ ++ memcpy(fdm + 2, &to, sizeof(to)); // this has to be exactly like this . ++ retlen = bmtd._write_oob(bmtd.mtd, from << bmtd.blk_shift , &ops) ; ++ if (retlen < 0) { ++ printk("marking bad block failed \n"); ++ } ++} ++ ++static u16 bbt_checksum(void) { ++ int i=0; ++ u16 checksum =0; ++ u8 *data = (u8*) &bbt; ++ checksum += bbt.header.version; ++ checksum += bbt.header.size; ++ data += sizeof(bbt_table_header); ++ for (; i < sizeof(bbt.table); i++) ++ checksum += data[i]; ++ return checksum; ++} ++ ++static bool parse_bbt(void) { ++ int i = system_blks; ++ u8 fdm[4]; ++ for (; i < total_blks; i++) { ++ if( !is_bad(i) ++ && !bbt_nand_read(blk_pg(i),(unsigned char *)&bbt, sizeof(bbt), fdm, sizeof(fdm)) ++ && (strncmp(bbt.header.signature , "RAWB", 4)==0) ++ && (bbt.header.checksum == bbt_checksum()) ++ ) { ++ bbt_index = i; ++ return true; ++ } ++ } ++ return false; ++} ++ ++static u8 bmt_checksum(void) { ++ int i; ++ u8 checksum = 0; ++ u8* data = (u8*)&bmt; ++ checksum += bmt.header.version; ++ checksum += bmt.header.size; ++ data += sizeof(bmt_table_header); ++ for (i=0;i system_blks;i--) { ++ if ( !is_bad(i) ++ && !bbt_nand_read(blk_pg(i),(unsigned char *)&bmt, sizeof(bmt), fdm, sizeof(fdm)) ++ && (strncmp(bmt.header.signature , "BMT", 3)==0) ++ && (bmt.header.checksum == bmt_checksum()) ++ ) { ++ bmt_index = i ; ++ return true; ++ } ++ } ++ return false; ++} ++ ++static void variable_setup(void) { ++ unsigned int need_valid_block_num; ++ int valid_blks = 0; ++ int last_blk; ++ ++ total_blks = bmtd.total_blks; ++ last_blk = total_blks - 1; ++ need_valid_block_num = total_blks * POOL_GOOD_BLOCK_PERCENT; ++ ++ for (; last_blk > 0 ;last_blk--) { ++ if (is_bad_raw(last_blk)) { ++ continue; ++ } ++ valid_blks++; ++ if (valid_blks == need_valid_block_num) { ++ break; ++ } ++ } ++ bmt_blks = total_blks - last_blk; ++ system_blks = total_blks - bmt_blks; ++ bmtd.mtd->size = (total_blks - total_blks * MAX_BMT_PERCENT) * bmtd.mtd->erasesize; ++} ++ ++ ++static int find_available_block(bool start_from_end) { ++ int i=system_blks,d=1; ++ int count = 0; ++ if (start_from_end) ++ i=total_blks-1,d=-1; ++ for (; count < (total_blks - system_blks); count++, i+=d) { ++ if(bmt_index == i || bbt_index == i || is_bad(i) || is_mapped(i)) ++ continue; ++ return i ; ++ } ++ //TODO: handle OOM ++ return -1; ++} ++ ++static void update_bmt_bbt( void ) { ++ int retlen = 0; ++ struct mtd_oob_ops ops , ops1; ++ ++ bbt.header.checksum = bbt_checksum(); ++ bmt.header.checksum = bmt_checksum(); ++ ++ if(bbt_index ==0xffff) bbt_index = find_available_block(false); ++ if(bmt_index ==0xffff) bmt_index = find_available_block(true); ++ ++ bbt_nand_erase(bmt_index); ++ bbt_nand_erase(bbt_index); ++ printk("putting back in bbt_index: %d, bmt_index: %d\n" , bbt_index, bmt_index); ++ ++ ops = (struct mtd_oob_ops) { ++ .mode = MTD_OPS_PLACE_OOB, ++ .ooboffs = 0, ++ .ooblen = 0, ++ .oobbuf = NULL, ++ .len = sizeof(bmt), ++ .datbuf = (u8 *)&bmt, ++ }; ++ ++retry_bmt: ++ retlen = bmtd._write_oob(bmtd.mtd, bmt_index << bmtd.blk_shift, &ops); ++ if (retlen) { ++ printk("error while write"); ++ mark_bad(bmt_index); ++ if (bmt_index > system_blks) { ++ bmt_index--; ++ goto retry_bmt; ++ } ++ return; ++ } ++ ops1 = (struct mtd_oob_ops) { ++ .mode = MTD_OPS_PLACE_OOB, ++ .ooboffs = 0, ++ .ooblen = 0, ++ .oobbuf = NULL, ++ .len = sizeof(bbt), ++ .datbuf = (u8 *)&bbt, ++ }; ++ ++retry_bbt: ++ retlen = bmtd._write_oob(bmtd.mtd, bbt_index << bmtd.blk_shift, &ops1); ++ if (retlen) { ++ printk("error while write"); ++ mark_bad(bbt_index); ++ if (bbt_index < total_blks) { ++ bbt_index++; ++ goto retry_bbt; ++ } ++ return; ++ } ++} ++ ++static bool is_in_bmt(int block) { ++ int i; ++ for (i=0;i= system_blks ;i--) { ++ unsigned short mapped_block; ++ u8 fdm[4]; ++ int ret; ++ ++ if (is_bad(i)) continue; ++ ret = bbt_nand_read(blk_pg(i), bmtd.data_buf, bmtd.pg_size, ++ fdm, sizeof(fdm)); ++ if (ret < 0) ++ mark_bad(i); ++ ++ memcpy(&mapped_block,fdm+2,2); // need to be this way ++ if (mapped_block >= system_blks) continue; ++ printk("block %X was mapped to :%X\n", mapped_block, i); ++ bmt.table[bmt.header.size++] = (bmt_entry){.from = mapped_block , .to = i}; ++ } ++ memset(&bbt,0x00,sizeof(bbt)); ++ memcpy(&bbt.header.signature , "RAWB", 4); ++ bbt.header.version = 1; ++ bbt.header.size = 0; ++ for ( i = 0 ; i < system_blks; i++) { ++ if (is_bad_raw(i) && !is_in_bmt(i)) ++ bbt.table[bbt.header.size++] = (u16)i; ++ } ++ bmt.header.checksum = bmt_checksum(); ++ bbt.header.checksum = bbt_checksum(); ++ update_bmt_bbt(); ++ printk("bbt and bmt reconstructed successfully\n"); ++} ++ ++ ++static bool remap_block(u16 block , u16 mapped_block, int copy_len) { ++ bool mapped_already_in_bbt = false; ++ bool mapped_already_in_bmt = false; ++ bool block_already_in_bbt = false; ++ u16 new_block = find_available_block(false); ++ int i; ++ // TODO check for -1 ++ ++ bbt_nand_erase(new_block); ++ if (copy_len) ++ bbt_nand_copy(new_block , mapped_block , copy_len); ++ ++ for (i=0; i < bmt.header.size; i++) ++ if (bmt.table[i].from == block) { ++ bmt.table[i].to = new_block; ++ mapped_already_in_bmt = true; ++ break; ++ } ++ ++ if (!mapped_already_in_bmt) ++ bmt.table[bmt.header.size++] = (bmt_entry){ .from = block, .to = new_block}; ++ ++ for (i=0;i system_blks) ++ return block; ++ for (i = 0; i < bmt.header.size; i++) ++ if (bmt.table[i].from == block) ++ return bmt.table[i].to; ++ return block; ++} ++ ++static void unmap_block( u16 block) { // not required ++ printk("unmapping is called on block : %d\n", block); ++} ++ ++ ++static int debug( void* data , u64 cmd) { ++ int i; ++ printk("val: %d\n", val); ++ printk("_to: %d\n", _to); ++ if (val == 0 ) { ++ printk("fixing all\n"); ++ for (i=0;ierasesize); ++ mapped_block = get_mapping_block(_to); ++ printk("after mapped to: %d\n", mapped_block); ++ } else if(val ==2 ) { ++ printk("bmt table: \n"); ++ for (i = 0 ; i < bmt.header.size;i++) { ++ printk("%d->%d\n", bmt.table[i].from , bmt.table[i].to); ++ } ++ printk("bbt table\n"); ++ for (i =0;i< bbt.header.size;i++) { ++ printk("%d ", bbt.table[i]); ++ } ++ printk("\n"); ++ } else if(val == 3) { ++ printk("reconstruct from oob\n"); ++ reconstruct_from_oob(); ++ } else if (val == 4) { ++ printk("showing the oobreconstruct_from_oob of %d\n", _to); ++ printk("%d\n",is_bad(_to)); ++ } else if (val == 5 ) { ++ printk("trying to parse_bmt again %d\n", parse_bmt()); ++ } else if (val == 6 ) { ++ printk("marking bad : %d", _to); ++ mark_bad(_to); ++ } else if ( val == 7) { ++ struct mtd_oob_ops opsk = { ++ .mode = MTD_OPS_PLACE_OOB, ++ .ooboffs = 0, ++ .ooblen = 0, ++ .oobbuf = NULL, ++ .len = sizeof(bmt), ++ .datbuf = (u8 *)&bmt, ++ }; ++ int retlen; ++ printk("parse bmt from the %d block \n", _to); ++ retlen = bmtd._read_oob(bmtd.mtd, _to << bmtd.blk_shift , &opsk); ++ ++ printk("status : %d\n", retlen); ++ } else if (val == 8) { ++ u8 *data; ++ int j; ++ printk("dump bmt hex\n"); ++ data = (u8 *)&bmt; ++ for (j =0;j < 50;j++) { ++ if(j%20==0) printk("\n"); ++ printk("%X ", data[j]); ++ } ++ printk("bbt table\n"); ++ data = (u8 *)&bbt; ++ for (j =0;j < 50;j++) { ++ if(j%20==0) printk("\n"); ++ printk("%X ", data[j]); ++ } ++ } else if (val == 9) { ++ struct mtd_oob_ops ops = { ++ .mode = MTD_OPS_PLACE_OOB, ++ .ooboffs = 0, ++ .ooblen = 0, ++ .oobbuf = NULL, ++ .len = sizeof(bmt), ++ .datbuf = (u8 *)&bmt, ++ }; ++ int retlen; ++ printk("put bmt at index\n"); ++ retlen = bmtd._write_oob(bmtd.mtd, _to << bmtd.blk_shift, &ops); ++ bmt.header.checksum = bmt_checksum(); ++ if (retlen < 0) { ++ printk("error while write"); ++ } ++ } else if (val == 10) { ++ printk("erase block %d\n", _to); ++ bbt_nand_erase(_to); ++ } else if (val == 11) { ++ char *buf1, *buf2; ++ struct mtd_oob_ops ops = { ++ .mode = MTD_OPS_PLACE_OOB, ++ .ooboffs = 0, ++ .ooblen = 0, ++ .oobbuf = NULL, ++ }; ++ struct mtd_oob_ops ops1 = { ++ .mode = MTD_OPS_PLACE_OOB, ++ .ooboffs = 0, ++ .ooblen = 0, ++ .oobbuf = NULL, ++ }; ++ int retlen; ++ int j; ++ ++ printk("tranfering content from block :%d to %d\n", _to , _to2); ++ bbt_nand_copy(_to2, _to, bmtd.mtd->erasesize); ++ printk("now we check size\n"); ++ ++ buf1 = (char*) kzalloc(sizeof(char) * bmtd.mtd->erasesize , GFP_KERNEL); ++ buf2 = (char*) kzalloc(sizeof(char) * bmtd.mtd->erasesize , GFP_KERNEL); ++ ++ ops.len = sizeof(char) * bmtd.mtd->erasesize; ++ ops.datbuf = buf1; ++ retlen = bmtd._read_oob(bmtd.mtd, _to << bmtd.blk_shift, &ops); ++ if (retlen < 0) { ++ printk("error while write\n"); ++ } ++ ++ ops1.len = sizeof(char) * bmtd.mtd->erasesize; ++ ops1.datbuf = buf2; ++ retlen = bmtd._read_oob(bmtd.mtd, _to << bmtd.blk_shift, &ops1); ++ if (retlen < 0) { ++ printk("error while write"); ++ } ++ for (j = 0 ; j < bmtd.mtd->erasesize ;j++) { ++ if (j%20==0) { ++ printk("\n"); ++ } ++ printk("%X %X ", buf1[j], buf2[j]); ++ } ++ printk("\n"); ++ ++ } ++ return 0; ++} ++ ++ ++const struct mtk_bmt_ops airoha_bmt_ops = { ++ .sig = "bmt", ++ .sig_len = 3, ++ .init = init, ++ .remap_block = remap_block, ++ .unmap_block = unmap_block, ++ .get_mapping_block = get_mapping_block, ++ .debug = debug, ++}; diff --git a/lede/target/linux/airoha/patches-6.12/901-snand-mtk-bmt-support.patch b/lede/target/linux/airoha/patches-6.12/901-snand-mtk-bmt-support.patch new file mode 100644 index 0000000000..eb77fde066 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/901-snand-mtk-bmt-support.patch @@ -0,0 +1,34 @@ +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val) + { +@@ -1574,6 +1575,7 @@ static int spinand_probe(struct spi_mem + if (ret) + return ret; + ++ mtk_bmt_attach(mtd); + ret = mtd_device_register(mtd, NULL, 0); + if (ret) + goto err_spinand_cleanup; +@@ -1581,6 +1583,7 @@ static int spinand_probe(struct spi_mem + return 0; + + err_spinand_cleanup: ++ mtk_bmt_detach(mtd); + spinand_cleanup(spinand); + + return ret; +@@ -1599,6 +1602,7 @@ static int spinand_remove(struct spi_mem + if (ret) + return ret; + ++ mtk_bmt_detach(mtd); + spinand_cleanup(spinand); + + return 0; diff --git a/lede/target/linux/airoha/patches-6.12/992-01-v6.14-mtd-spinand-Introduce-a-way-to-avoid-raw-access.patch b/lede/target/linux/airoha/patches-6.12/992-01-v6.14-mtd-spinand-Introduce-a-way-to-avoid-raw-access.patch new file mode 100644 index 0000000000..53e72bdeb8 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/992-01-v6.14-mtd-spinand-Introduce-a-way-to-avoid-raw-access.patch @@ -0,0 +1,88 @@ +From 6d9d6ab3a82af50e36e13e7bc8e2d1b970e39f79 Mon Sep 17 00:00:00 2001 +From: Takahiro Kuwano +Date: Tue, 3 Dec 2024 11:46:49 +0900 +Subject: [PATCH 1/1] mtd: spinand: Introduce a way to avoid raw access + +SkyHigh spinand device has ECC enable bit in configuration register but +it must be always enabled. If ECC is disabled, read and write ops +results in undetermined state. For such devices, a way to avoid raw +access is needed. + +Introduce SPINAND_NO_RAW_ACCESS flag to advertise the device does not +support raw access. In such devices, the on-die ECC engine ops returns +error to I/O request in raw mode. + +Checking and marking BBM need to be cared as special case, by adding +fallback mechanism that tries read/write OOB with ECC enabled. + +Signed-off-by: Takahiro Kuwano +Signed-off-by: Miquel Raynal +--- + drivers/mtd/nand/spi/core.c | 22 ++++++++++++++++++++-- + include/linux/mtd/spinand.h | 1 + + 2 files changed, 21 insertions(+), 2 deletions(-) + +diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c +index 00e1bfa416ce..f46769eda388 100644 +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -294,6 +294,9 @@ static int spinand_ondie_ecc_prepare_io_req(struct nand_device *nand, + struct spinand_device *spinand = nand_to_spinand(nand); + bool enable = (req->mode != MTD_OPS_RAW); + ++ if (!enable && spinand->flags & SPINAND_NO_RAW_ACCESS) ++ return -EOPNOTSUPP; ++ + memset(spinand->oobbuf, 0xff, nanddev_per_page_oobsize(nand)); + + /* Only enable or disable the engine */ +@@ -901,9 +904,17 @@ static bool spinand_isbad(struct nand_device *nand, const struct nand_pos *pos) + .oobbuf.in = marker, + .mode = MTD_OPS_RAW, + }; ++ int ret; + + spinand_select_target(spinand, pos->target); +- spinand_read_page(spinand, &req); ++ ++ ret = spinand_read_page(spinand, &req); ++ if (ret == -EOPNOTSUPP) { ++ /* Retry with ECC in case raw access is not supported */ ++ req.mode = MTD_OPS_PLACE_OOB; ++ spinand_read_page(spinand, &req); ++ } ++ + if (marker[0] != 0xff || marker[1] != 0xff) + return true; + +@@ -942,7 +953,14 @@ static int spinand_markbad(struct nand_device *nand, const struct nand_pos *pos) + if (ret) + return ret; + +- return spinand_write_page(spinand, &req); ++ ret = spinand_write_page(spinand, &req); ++ if (ret == -EOPNOTSUPP) { ++ /* Retry with ECC in case raw access is not supported */ ++ req.mode = MTD_OPS_PLACE_OOB; ++ ret = spinand_write_page(spinand, &req); ++ } ++ ++ return ret; + } + + static int spinand_mtd_block_markbad(struct mtd_info *mtd, loff_t offs) +diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h +index 702e5fb13dae..5cf11005b41a 100644 +--- a/include/linux/mtd/spinand.h ++++ b/include/linux/mtd/spinand.h +@@ -314,6 +314,7 @@ struct spinand_ecc_info { + #define SPINAND_HAS_CR_FEAT_BIT BIT(1) + #define SPINAND_HAS_PROG_PLANE_SELECT_BIT BIT(2) + #define SPINAND_HAS_READ_PLANE_SELECT_BIT BIT(3) ++#define SPINAND_NO_RAW_ACCESS BIT(4) + + /** + * struct spinand_ondie_ecc_conf - private SPI-NAND on-die ECC engine structure +-- +2.40.1 + diff --git a/lede/target/linux/airoha/patches-6.12/992-02-v6.14-mtd-spinand-Add-support-for-SkyHigh-S35ML-3-family.patch b/lede/target/linux/airoha/patches-6.12/992-02-v6.14-mtd-spinand-Add-support-for-SkyHigh-S35ML-3-family.patch new file mode 100644 index 0000000000..586e9cf153 --- /dev/null +++ b/lede/target/linux/airoha/patches-6.12/992-02-v6.14-mtd-spinand-Add-support-for-SkyHigh-S35ML-3-family.patch @@ -0,0 +1,213 @@ +From 1a50e3612de9187857f55ee14a573f7f8e7d4ebc Mon Sep 17 00:00:00 2001 +From: Takahiro Kuwano +Date: Tue, 3 Dec 2024 11:46:50 +0900 +Subject: [PATCH] mtd: spinand: Add support for SkyHigh S35ML-3 family + +SkyHigh S35ML01G300, S35ML01G301, S35ML02G300, and S35ML04G300 are 1Gb, +2Gb, and 4Gb SLC SPI NAND flash family. This family of devices has +on-die ECC which parity bits are stored to hidden area. In this family +the on-die ECC cannot be disabled so raw access needs to be prevented. + +Link: https://www.skyhighmemory.com/download/SPI_S35ML01_04G3_002_19205.pdf?v=P +Co-developed-by: KR Kim +Signed-off-by: KR Kim +Signed-off-by: Takahiro Kuwano +Signed-off-by: Miquel Raynal +--- + drivers/mtd/nand/spi/Makefile | 2 +- + drivers/mtd/nand/spi/core.c | 1 + + drivers/mtd/nand/spi/skyhigh.c | 147 +++++++++++++++++++++++++++++++++ + include/linux/mtd/spinand.h | 1 + + 4 files changed, 150 insertions(+), 1 deletion(-) + create mode 100644 drivers/mtd/nand/spi/skyhigh.c + +diff --git a/drivers/mtd/nand/spi/Makefile b/drivers/mtd/nand/spi/Makefile +index f725f0c..7fb8e21 100644 +--- a/drivers/mtd/nand/spi/Makefile ++++ b/drivers/mtd/nand/spi/Makefile +@@ -1,4 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0 + spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o fmsh.o foresee.o gigadevice.o +-spinand-objs += macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o ++spinand-objs += macronix.o micron.o paragon.o skyhigh.o toshiba.o winbond.o xtx.o + obj-$(CONFIG_MTD_SPI_NAND) += spinand.o +diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c +index 8e56ca6..61158d9 100644 +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -1166,6 +1166,7 @@ static const struct spinand_manufacturer *spinand_manufacturers[] = { + ¯onix_spinand_manufacturer, + µn_spinand_manufacturer, + ¶gon_spinand_manufacturer, ++ &skyhigh_spinand_manufacturer, + &toshiba_spinand_manufacturer, + &winbond_spinand_manufacturer, + &xtx_spinand_manufacturer, +diff --git a/drivers/mtd/nand/spi/skyhigh.c b/drivers/mtd/nand/spi/skyhigh.c +new file mode 100644 +index 0000000..8b32b74 +--- /dev/null ++++ b/drivers/mtd/nand/spi/skyhigh.c +@@ -0,0 +1,147 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2024 SkyHigh Memory Limited ++ * ++ * Author: Takahiro Kuwano ++ * Co-Author: KR Kim ++ */ ++ ++#include ++#include ++#include ++ ++#define SPINAND_MFR_SKYHIGH 0x01 ++#define SKYHIGH_STATUS_ECC_1TO2_BITFLIPS (1 << 4) ++#define SKYHIGH_STATUS_ECC_3TO6_BITFLIPS (2 << 4) ++#define SKYHIGH_STATUS_ECC_UNCOR_ERROR (3 << 4) ++#define SKYHIGH_CONFIG_PROTECT_EN BIT(1) ++ ++static SPINAND_OP_VARIANTS(read_cache_variants, ++ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 4, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 2, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); ++ ++static SPINAND_OP_VARIANTS(write_cache_variants, ++ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), ++ SPINAND_PROG_LOAD(true, 0, NULL, 0)); ++ ++static SPINAND_OP_VARIANTS(update_cache_variants, ++ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), ++ SPINAND_PROG_LOAD(false, 0, NULL, 0)); ++ ++static int skyhigh_spinand_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ /* ECC bytes are stored in hidden area. */ ++ return -ERANGE; ++} ++ ++static int skyhigh_spinand_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section) ++ return -ERANGE; ++ ++ /* ECC bytes are stored in hidden area. Reserve 2 bytes for the BBM. */ ++ region->offset = 2; ++ region->length = mtd->oobsize - 2; ++ ++ return 0; ++} ++ ++static const struct mtd_ooblayout_ops skyhigh_spinand_ooblayout = { ++ .ecc = skyhigh_spinand_ooblayout_ecc, ++ .free = skyhigh_spinand_ooblayout_free, ++}; ++ ++static int skyhigh_spinand_ecc_get_status(struct spinand_device *spinand, ++ u8 status) ++{ ++ switch (status & STATUS_ECC_MASK) { ++ case STATUS_ECC_NO_BITFLIPS: ++ return 0; ++ ++ case SKYHIGH_STATUS_ECC_UNCOR_ERROR: ++ return -EBADMSG; ++ ++ case SKYHIGH_STATUS_ECC_1TO2_BITFLIPS: ++ return 2; ++ ++ case SKYHIGH_STATUS_ECC_3TO6_BITFLIPS: ++ return 6; ++ ++ default: ++ break; ++ } ++ ++ return -EINVAL; ++} ++ ++static const struct spinand_info skyhigh_spinand_table[] = { ++ SPINAND_INFO("S35ML01G301", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x15), ++ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), ++ NAND_ECCREQ(6, 32), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_NO_RAW_ACCESS, ++ SPINAND_ECCINFO(&skyhigh_spinand_ooblayout, ++ skyhigh_spinand_ecc_get_status)), ++ SPINAND_INFO("S35ML01G300", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14), ++ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), ++ NAND_ECCREQ(6, 32), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_NO_RAW_ACCESS, ++ SPINAND_ECCINFO(&skyhigh_spinand_ooblayout, ++ skyhigh_spinand_ecc_get_status)), ++ SPINAND_INFO("S35ML02G300", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x25), ++ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1), ++ NAND_ECCREQ(6, 32), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_NO_RAW_ACCESS, ++ SPINAND_ECCINFO(&skyhigh_spinand_ooblayout, ++ skyhigh_spinand_ecc_get_status)), ++ SPINAND_INFO("S35ML04G300", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35), ++ NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 2, 1, 1), ++ NAND_ECCREQ(6, 32), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_NO_RAW_ACCESS, ++ SPINAND_ECCINFO(&skyhigh_spinand_ooblayout, ++ skyhigh_spinand_ecc_get_status)), ++}; ++ ++static int skyhigh_spinand_init(struct spinand_device *spinand) ++{ ++ /* ++ * Config_Protect_En (bit 1 in Block Lock register) must be set to 1 ++ * before writing other bits. Do it here before core unlocks all blocks ++ * by writing block protection bits. ++ */ ++ return spinand_write_reg_op(spinand, REG_BLOCK_LOCK, ++ SKYHIGH_CONFIG_PROTECT_EN); ++} ++ ++static const struct spinand_manufacturer_ops skyhigh_spinand_manuf_ops = { ++ .init = skyhigh_spinand_init, ++}; ++ ++const struct spinand_manufacturer skyhigh_spinand_manufacturer = { ++ .id = SPINAND_MFR_SKYHIGH, ++ .name = "SkyHigh", ++ .chips = skyhigh_spinand_table, ++ .nchips = ARRAY_SIZE(skyhigh_spinand_table), ++ .ops = &skyhigh_spinand_manuf_ops, ++}; +diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h +index 5cf11005b41ae2..cbbcd44ac22565 100644 +--- a/include/linux/mtd/spinand.h ++++ b/include/linux/mtd/spinand.h +@@ -268,6 +268,7 @@ extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; + extern const struct spinand_manufacturer macronix_spinand_manufacturer; + extern const struct spinand_manufacturer micron_spinand_manufacturer; + extern const struct spinand_manufacturer paragon_spinand_manufacturer; ++extern const struct spinand_manufacturer skyhigh_spinand_manufacturer; + extern const struct spinand_manufacturer toshiba_spinand_manufacturer; + extern const struct spinand_manufacturer winbond_spinand_manufacturer; + extern const struct spinand_manufacturer xtx_spinand_manufacturer; +-- +2.40.1 + diff --git a/lede/target/linux/generic/backport-6.12/401-v6.17-mtd-spinand-add-support-for-FudanMicro-FM25S01A.patch b/lede/target/linux/generic/backport-6.12/401-v6.17-mtd-spinand-add-support-for-FudanMicro-FM25S01A.patch new file mode 100644 index 0000000000..ad1116dc26 --- /dev/null +++ b/lede/target/linux/generic/backport-6.12/401-v6.17-mtd-spinand-add-support-for-FudanMicro-FM25S01A.patch @@ -0,0 +1,124 @@ +From 5f284dc15ca8695d0394414045ac64616a3b0e69 Mon Sep 17 00:00:00 2001 +From: Tianling Shen +Date: Mon, 25 Aug 2025 01:00:13 +0800 +Subject: [PATCH] mtd: spinand: add support for FudanMicro FM25S01A + +Add support for FudanMicro FM25S01A SPI NAND. +Datasheet: http://eng.fmsh.com/nvm/FM25S01A_ds_eng.pdf + +Signed-off-by: Tianling Shen +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20250824170013.3328777-1-cnsztl@gmail.com +--- + drivers/mtd/nand/spi/Makefile | 2 +- + drivers/mtd/nand/spi/core.c | 1 + + drivers/mtd/nand/spi/fmsh.c | 74 +++++++++++++++++++++++++++++++++++ + include/linux/mtd/spinand.h | 1 + + 4 files changed, 77 insertions(+), 1 deletion(-) + create mode 100644 drivers/mtd/nand/spi/fmsh.c + +--- a/drivers/mtd/nand/spi/Makefile ++++ b/drivers/mtd/nand/spi/Makefile +@@ -1,4 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0 +-spinand-objs := core.o alliancememory.o ato.o esmt.o foresee.o gigadevice.o macronix.o ++spinand-objs := core.o alliancememory.o ato.o esmt.o fmsh.o foresee.o gigadevice.o macronix.o + spinand-objs += micron.o paragon.o toshiba.o winbond.o xtx.o + obj-$(CONFIG_MTD_SPI_NAND) += spinand.o +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -1112,6 +1112,7 @@ static const struct spinand_manufacturer + &alliancememory_spinand_manufacturer, + &ato_spinand_manufacturer, + &esmt_c8_spinand_manufacturer, ++ &fmsh_spinand_manufacturer, + &foresee_spinand_manufacturer, + &gigadevice_spinand_manufacturer, + ¯onix_spinand_manufacturer, +--- /dev/null ++++ b/drivers/mtd/nand/spi/fmsh.c +@@ -0,0 +1,74 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd. ++ * ++ * Author: Dingqiang Lin ++ */ ++ ++#include ++#include ++#include ++ ++#define SPINAND_MFR_FMSH 0xA1 ++ ++static SPINAND_OP_VARIANTS(read_cache_variants, ++ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); ++ ++static SPINAND_OP_VARIANTS(write_cache_variants, ++ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), ++ SPINAND_PROG_LOAD(true, 0, NULL, 0)); ++ ++static SPINAND_OP_VARIANTS(update_cache_variants, ++ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), ++ SPINAND_PROG_LOAD(false, 0, NULL, 0)); ++ ++static int fm25s01a_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ return -ERANGE; ++} ++ ++static int fm25s01a_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section) ++ return -ERANGE; ++ ++ region->offset = 2; ++ region->length = 62; ++ ++ return 0; ++} ++ ++static const struct mtd_ooblayout_ops fm25s01a_ooblayout = { ++ .ecc = fm25s01a_ooblayout_ecc, ++ .free = fm25s01a_ooblayout_free, ++}; ++ ++static const struct spinand_info fmsh_spinand_table[] = { ++ SPINAND_INFO("FM25S01A", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4), ++ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), ++ NAND_ECCREQ(1, 512), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&fm25s01a_ooblayout, NULL)), ++}; ++ ++static const struct spinand_manufacturer_ops fmsh_spinand_manuf_ops = { ++}; ++ ++const struct spinand_manufacturer fmsh_spinand_manufacturer = { ++ .id = SPINAND_MFR_FMSH, ++ .name = "Fudan Micro", ++ .chips = fmsh_spinand_table, ++ .nchips = ARRAY_SIZE(fmsh_spinand_table), ++ .ops = &fmsh_spinand_manuf_ops, ++}; +--- a/include/linux/mtd/spinand.h ++++ b/include/linux/mtd/spinand.h +@@ -263,6 +263,7 @@ struct spinand_manufacturer { + extern const struct spinand_manufacturer alliancememory_spinand_manufacturer; + extern const struct spinand_manufacturer ato_spinand_manufacturer; + extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; ++extern const struct spinand_manufacturer fmsh_spinand_manufacturer; + extern const struct spinand_manufacturer foresee_spinand_manufacturer; + extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; + extern const struct spinand_manufacturer macronix_spinand_manufacturer; diff --git a/lede/target/linux/generic/pending-6.12/421-v6.18-mtd-spinand-add-support-for-FudanMicro-FM25G02B.patch b/lede/target/linux/generic/pending-6.12/421-v6.18-mtd-spinand-add-support-for-FudanMicro-FM25G02B.patch new file mode 100644 index 0000000000..7fe5cdb2aa --- /dev/null +++ b/lede/target/linux/generic/pending-6.12/421-v6.18-mtd-spinand-add-support-for-FudanMicro-FM25G02B.patch @@ -0,0 +1,61 @@ +From c2c3a051b96614d899cd2fb9b29e000a670a8066 Mon Sep 17 00:00:00 2001 +From: Willem Lee <1980490718@qq.com> +Date: Sat, 27 Sep 2025 22:04:51 +0800 +Subject: [PATCH] mtd: spinand: add support for FudanMicro FM25G02B + +--- + drivers/mtd/nand/spi/fmsh.c | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +--- a/drivers/mtd/nand/spi/fmsh.c ++++ b/drivers/mtd/nand/spi/fmsh.c +@@ -50,6 +50,33 @@ static const struct mtd_ooblayout_ops fm + .free = fm25s01a_ooblayout_free, + }; + ++static int fm25g02b_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section >= 8) ++ return -ERANGE; ++ region->offset = 64 + section * 8; ++ region->length = 8; ++ ++ return 0; ++} ++ ++static int fm25g02b_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section) ++ return -ERANGE; ++ region->offset = 2; ++ region->length = 62; ++ ++ return 0; ++} ++ ++static const struct mtd_ooblayout_ops fm25g02b_ooblayout = { ++ .ecc = fm25g02b_ooblayout_ecc, ++ .free = fm25g02b_ooblayout_free, ++}; ++ + static const struct spinand_info fmsh_spinand_table[] = { + SPINAND_INFO("FM25S01A", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xE4), +@@ -60,6 +87,15 @@ static const struct spinand_info fmsh_sp + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&fm25s01a_ooblayout, NULL)), ++ SPINAND_INFO("FM25G02B", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xD2), ++ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), ++ NAND_ECCREQ(8, 528), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_HAS_QE_BIT, ++ SPINAND_ECCINFO(&fm25g02b_ooblayout, NULL)), + }; + + static const struct spinand_manufacturer_ops fmsh_spinand_manuf_ops = { diff --git a/lede/target/linux/generic/pending-6.12/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch b/lede/target/linux/generic/pending-6.12/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch index cc23125b3d..df22fda59c 100644 --- a/lede/target/linux/generic/pending-6.12/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch +++ b/lede/target/linux/generic/pending-6.12/487-mtd-spinand-Add-support-for-Etron-EM73D044VCx.patch @@ -42,9 +42,9 @@ Submitted-by: Daniel Danzberger +++ b/drivers/mtd/nand/spi/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 --spinand-objs := core.o alliancememory.o ato.o esmt.o foresee.o gigadevice.o macronix.o +-spinand-objs := core.o alliancememory.o ato.o esmt.o fmsh.o foresee.o gigadevice.o macronix.o -spinand-objs += micron.o paragon.o toshiba.o winbond.o xtx.o -+spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o foresee.o gigadevice.o ++spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o fmsh.o foresee.o gigadevice.o +spinand-objs += macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o obj-$(CONFIG_MTD_SPI_NAND) += spinand.o --- a/drivers/mtd/nand/spi/core.c @@ -54,9 +54,9 @@ Submitted-by: Daniel Danzberger &ato_spinand_manufacturer, &esmt_c8_spinand_manufacturer, + &etron_spinand_manufacturer, + &fmsh_spinand_manufacturer, &foresee_spinand_manufacturer, &gigadevice_spinand_manufacturer, - ¯onix_spinand_manufacturer, --- /dev/null +++ b/drivers/mtd/nand/spi/etron.c @@ -0,0 +1,98 @@ @@ -165,6 +165,6 @@ Submitted-by: Daniel Danzberger extern const struct spinand_manufacturer ato_spinand_manufacturer; extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; +extern const struct spinand_manufacturer etron_spinand_manufacturer; + extern const struct spinand_manufacturer fmsh_spinand_manufacturer; extern const struct spinand_manufacturer foresee_spinand_manufacturer; extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; - extern const struct spinand_manufacturer macronix_spinand_manufacturer; diff --git a/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/global/backup.htm b/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/global/backup.htm index 0c8a91667c..2261160230 100644 --- a/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/global/backup.htm +++ b/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/global/backup.htm @@ -134,10 +134,10 @@ local api = require "luci.passwall.api" setTimeout(function () { if (confirm("<%: Are you sure you want to restore the client to default settings?%>")) { var xhr1 = new XMLHttpRequest(); - xhr1.open("GET",'<%= api.url("clear_log") %>', true); + xhr1.open("GET",'<%= api.url("clear_log") %>', false); xhr1.send(); var xhr2 = new XMLHttpRequest(); - xhr2.open("GET",'<%= api.url("reset_config") %>', true); + xhr2.open("GET",'<%= api.url("reset_config") %>', false); xhr2.send(); window.location.href = '<%= api.url("log") %>' } diff --git a/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm b/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm index 94e231ca75..05f3c84d5c 100644 --- a/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm +++ b/openwrt-passwall/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm @@ -647,7 +647,7 @@ table td, .table .td { } tab_ul_html += tab_ul_li_html + '' - tab_content_html += tab_content_html + '' + tab_content_html += '' var tab_html = tab_ul_html + tab_content_html document.getElementById("node_list").innerHTML = tab_html @@ -659,6 +659,21 @@ table td, .table .td { if (default_group) { cbi_t_switch("passwall.nodes", default_group) } + + //clear expire data + if (localStorage && localStorage.length > 0) { + const now = Date.now(); + for (let i = 0; i < localStorage.length; i++) { + let key = localStorage.key(i); + if (key && (key.startsWith("icmp") || key.startsWith("tcping"))) { + let value_str = localStorage.getItem(key); + const value = JSON.parse(value_str); + if (!(value && value.savetime && (now - value.timestamp) < value.savetime)) { + localStorage.removeItem(key); + } + } + } + } get_now_use_node(); diff --git a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/subscribe.lua b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/subscribe.lua index efaeb899d0..5e7c69c582 100755 --- a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/subscribe.lua +++ b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/subscribe.lua @@ -449,6 +449,26 @@ local function get_subscribe_info(cfgid, value) end end +-- 设置 ss 协议实现类型 +local function set_ss_implementation(result) + if ss_type_default == "shadowsocks-libev" and has_ss then + result.type = "SS" + elseif ss_type_default == "shadowsocks-rust" and has_ss_rust then + result.type = 'SS-Rust' + elseif ss_type_default == "xray" and has_xray then + result.type = 'Xray' + result.protocol = 'shadowsocks' + result.transport = 'raw' + elseif ss_type_default == "sing-box" and has_singbox then + result.type = 'sing-box' + result.protocol = 'shadowsocks' + else + log("跳过 SS 节点,因未适配到 SS 核心程序,或未正确设置节点使用类型。") + return nil + end + return result +end + -- 处理数据 local function processData(szType, content, add_mode, group) --log(content, add_mode, group) @@ -602,21 +622,8 @@ local function processData(szType, content, add_mode, group) return nil end elseif szType == "ss" then - if ss_type_default == "shadowsocks-libev" and has_ss then - result.type = "SS" - elseif ss_type_default == "shadowsocks-rust" and has_ss_rust then - result.type = 'SS-Rust' - elseif ss_type_default == "xray" and has_xray then - result.type = 'Xray' - result.protocol = 'shadowsocks' - result.transport = 'raw' - elseif ss_type_default == "sing-box" and has_singbox then - result.type = 'sing-box' - result.protocol = 'shadowsocks' - else - log("跳过 SS 节点,因未适配到 SS 核心程序,或未正确设置节点使用类型。") - return nil - end + result = set_ss_implementation(result) + if not result then return nil end --SS-URI = "ss://" userinfo "@" hostname ":" port [ "/" ] [ "?" plugin ] [ "#" tag ] --userinfo = websafe-base64-encode-utf8(method ":" password) @@ -1069,7 +1076,8 @@ local function processData(szType, content, add_mode, group) end elseif szType == "ssd" then - result.type = "SS" + result = set_ss_implementation(result) + if not result then return nil end result.address = content.server result.port = content.port result.password = content.password @@ -1831,7 +1839,7 @@ local function parse_link(raw, add_mode, group, cfgid) end for _, v in ipairs(nodes) do - if v and not string.match(v, "^%s*$") then + if v and (szType == 'ssd' or not string.match(v, "^%s*$")) then xpcall(function () local result if szType == 'ssd' then diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/global/backup.htm b/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/global/backup.htm index c10c6ce81e..eba48ff6b8 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/global/backup.htm +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/global/backup.htm @@ -134,10 +134,10 @@ local api = require "luci.passwall2.api" setTimeout(function () { if (confirm("<%: Are you sure you want to restore the client to default settings?%>")) { var xhr1 = new XMLHttpRequest(); - xhr1.open("GET",'<%= api.url("clear_log") %>', true); + xhr1.open("GET",'<%= api.url("clear_log") %>', false); xhr1.send(); var xhr2 = new XMLHttpRequest(); - xhr2.open("GET",'<%= api.url("reset_config") %>', true); + xhr2.open("GET",'<%= api.url("reset_config") %>', false); xhr2.send(); window.location.href = '<%= api.url("log") %>' } diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/node_list/node_list.htm b/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/node_list/node_list.htm index 42afc0376b..f03c7b2ea5 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/node_list/node_list.htm +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/node_list/node_list.htm @@ -659,6 +659,21 @@ table td, .table .td { cbi_t_switch("passwall2.nodes", default_group) } + //clear expire data + if (localStorage && localStorage.length > 0) { + const now = Date.now(); + for (let i = 0; i < localStorage.length; i++) { + let key = localStorage.key(i); + if (key && (key.startsWith("icmp") || key.startsWith("tcping"))) { + let value_str = localStorage.getItem(key); + const value = JSON.parse(value_str); + if (!(value && value.savetime && (now - value.timestamp) < value.savetime)) { + localStorage.removeItem(key); + } + } + } + } + get_now_use_node(); pingAllNodes(); diff --git a/shadowsocks-rust/Cargo.lock b/shadowsocks-rust/Cargo.lock index 85a644fa86..b74784609a 100644 --- a/shadowsocks-rust/Cargo.lock +++ b/shadowsocks-rust/Cargo.lock @@ -1468,9 +1468,9 @@ checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" [[package]] name = "hyper" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +checksum = "1744436df46f0bde35af3eda22aeaba453aada65d8f1c171cd8a5f59030bd69f" dependencies = [ "atomic-waker", "bytes", diff --git a/small/luci-app-passwall/luasrc/view/passwall/global/backup.htm b/small/luci-app-passwall/luasrc/view/passwall/global/backup.htm index 0c8a91667c..2261160230 100644 --- a/small/luci-app-passwall/luasrc/view/passwall/global/backup.htm +++ b/small/luci-app-passwall/luasrc/view/passwall/global/backup.htm @@ -134,10 +134,10 @@ local api = require "luci.passwall.api" setTimeout(function () { if (confirm("<%: Are you sure you want to restore the client to default settings?%>")) { var xhr1 = new XMLHttpRequest(); - xhr1.open("GET",'<%= api.url("clear_log") %>', true); + xhr1.open("GET",'<%= api.url("clear_log") %>', false); xhr1.send(); var xhr2 = new XMLHttpRequest(); - xhr2.open("GET",'<%= api.url("reset_config") %>', true); + xhr2.open("GET",'<%= api.url("reset_config") %>', false); xhr2.send(); window.location.href = '<%= api.url("log") %>' } diff --git a/small/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm b/small/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm index 94e231ca75..05f3c84d5c 100644 --- a/small/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm +++ b/small/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm @@ -647,7 +647,7 @@ table td, .table .td { } tab_ul_html += tab_ul_li_html + '' - tab_content_html += tab_content_html + '' + tab_content_html += '' var tab_html = tab_ul_html + tab_content_html document.getElementById("node_list").innerHTML = tab_html @@ -659,6 +659,21 @@ table td, .table .td { if (default_group) { cbi_t_switch("passwall.nodes", default_group) } + + //clear expire data + if (localStorage && localStorage.length > 0) { + const now = Date.now(); + for (let i = 0; i < localStorage.length; i++) { + let key = localStorage.key(i); + if (key && (key.startsWith("icmp") || key.startsWith("tcping"))) { + let value_str = localStorage.getItem(key); + const value = JSON.parse(value_str); + if (!(value && value.savetime && (now - value.timestamp) < value.savetime)) { + localStorage.removeItem(key); + } + } + } + } get_now_use_node(); diff --git a/small/luci-app-passwall/root/usr/share/passwall/subscribe.lua b/small/luci-app-passwall/root/usr/share/passwall/subscribe.lua index efaeb899d0..5e7c69c582 100755 --- a/small/luci-app-passwall/root/usr/share/passwall/subscribe.lua +++ b/small/luci-app-passwall/root/usr/share/passwall/subscribe.lua @@ -449,6 +449,26 @@ local function get_subscribe_info(cfgid, value) end end +-- 设置 ss 协议实现类型 +local function set_ss_implementation(result) + if ss_type_default == "shadowsocks-libev" and has_ss then + result.type = "SS" + elseif ss_type_default == "shadowsocks-rust" and has_ss_rust then + result.type = 'SS-Rust' + elseif ss_type_default == "xray" and has_xray then + result.type = 'Xray' + result.protocol = 'shadowsocks' + result.transport = 'raw' + elseif ss_type_default == "sing-box" and has_singbox then + result.type = 'sing-box' + result.protocol = 'shadowsocks' + else + log("跳过 SS 节点,因未适配到 SS 核心程序,或未正确设置节点使用类型。") + return nil + end + return result +end + -- 处理数据 local function processData(szType, content, add_mode, group) --log(content, add_mode, group) @@ -602,21 +622,8 @@ local function processData(szType, content, add_mode, group) return nil end elseif szType == "ss" then - if ss_type_default == "shadowsocks-libev" and has_ss then - result.type = "SS" - elseif ss_type_default == "shadowsocks-rust" and has_ss_rust then - result.type = 'SS-Rust' - elseif ss_type_default == "xray" and has_xray then - result.type = 'Xray' - result.protocol = 'shadowsocks' - result.transport = 'raw' - elseif ss_type_default == "sing-box" and has_singbox then - result.type = 'sing-box' - result.protocol = 'shadowsocks' - else - log("跳过 SS 节点,因未适配到 SS 核心程序,或未正确设置节点使用类型。") - return nil - end + result = set_ss_implementation(result) + if not result then return nil end --SS-URI = "ss://" userinfo "@" hostname ":" port [ "/" ] [ "?" plugin ] [ "#" tag ] --userinfo = websafe-base64-encode-utf8(method ":" password) @@ -1069,7 +1076,8 @@ local function processData(szType, content, add_mode, group) end elseif szType == "ssd" then - result.type = "SS" + result = set_ss_implementation(result) + if not result then return nil end result.address = content.server result.port = content.port result.password = content.password @@ -1831,7 +1839,7 @@ local function parse_link(raw, add_mode, group, cfgid) end for _, v in ipairs(nodes) do - if v and not string.match(v, "^%s*$") then + if v and (szType == 'ssd' or not string.match(v, "^%s*$")) then xpcall(function () local result if szType == 'ssd' then diff --git a/small/luci-app-passwall2/luasrc/view/passwall2/global/backup.htm b/small/luci-app-passwall2/luasrc/view/passwall2/global/backup.htm index c10c6ce81e..eba48ff6b8 100644 --- a/small/luci-app-passwall2/luasrc/view/passwall2/global/backup.htm +++ b/small/luci-app-passwall2/luasrc/view/passwall2/global/backup.htm @@ -134,10 +134,10 @@ local api = require "luci.passwall2.api" setTimeout(function () { if (confirm("<%: Are you sure you want to restore the client to default settings?%>")) { var xhr1 = new XMLHttpRequest(); - xhr1.open("GET",'<%= api.url("clear_log") %>', true); + xhr1.open("GET",'<%= api.url("clear_log") %>', false); xhr1.send(); var xhr2 = new XMLHttpRequest(); - xhr2.open("GET",'<%= api.url("reset_config") %>', true); + xhr2.open("GET",'<%= api.url("reset_config") %>', false); xhr2.send(); window.location.href = '<%= api.url("log") %>' } diff --git a/small/luci-app-passwall2/luasrc/view/passwall2/node_list/link_add_node.htm b/small/luci-app-passwall2/luasrc/view/passwall2/node_list/link_add_node.htm index 9f258c3f91..cbf4aa8c67 100644 --- a/small/luci-app-passwall2/luasrc/view/passwall2/node_list/link_add_node.htm +++ b/small/luci-app-passwall2/luasrc/view/passwall2/node_list/link_add_node.htm @@ -177,13 +177,13 @@ local api = require "luci.passwall2.api"