diff --git a/.github/update.log b/.github/update.log index 1f84e4b038..da7c65306e 100644 --- a/.github/update.log +++ b/.github/update.log @@ -993,3 +993,4 @@ Update On Mon May 5 20:33:21 CEST 2025 Update On Tue May 6 20:37:12 CEST 2025 Update On Wed May 7 20:36:18 CEST 2025 Update On Thu May 8 20:37:23 CEST 2025 +Update On Fri May 9 20:36:45 CEST 2025 diff --git a/clash-nyanpasu/frontend/nyanpasu/package.json b/clash-nyanpasu/frontend/nyanpasu/package.json index 9399c48fb2..bf05f7ff95 100644 --- a/clash-nyanpasu/frontend/nyanpasu/package.json +++ b/clash-nyanpasu/frontend/nyanpasu/package.json @@ -30,7 +30,7 @@ "country-code-emoji": "2.3.0", "country-emoji": "1.5.6", "dayjs": "1.11.13", - "framer-motion": "12.10.1", + "framer-motion": "12.10.5", "i18next": "25.0.2", "jotai": "2.12.4", "json-schema": "0.4.0", diff --git a/clash-nyanpasu/frontend/ui/package.json b/clash-nyanpasu/frontend/ui/package.json index a2f85cc689..e4c457315b 100644 --- a/clash-nyanpasu/frontend/ui/package.json +++ b/clash-nyanpasu/frontend/ui/package.json @@ -23,7 +23,7 @@ "@vitejs/plugin-react": "4.4.1", "ahooks": "3.8.4", "d3": "7.9.0", - "framer-motion": "12.10.1", + "framer-motion": "12.10.5", "react": "19.1.0", "react-dom": "19.1.0", "react-error-boundary": "6.0.0", diff --git a/clash-nyanpasu/package.json b/clash-nyanpasu/package.json index d8ce594fb8..8a92585f57 100644 --- a/clash-nyanpasu/package.json +++ b/clash-nyanpasu/package.json @@ -65,7 +65,7 @@ "@tauri-apps/cli": "2.5.0", "@types/fs-extra": "11.0.4", "@types/lodash-es": "4.17.12", - "@types/node": "22.15.16", + "@types/node": "22.15.17", "@typescript-eslint/eslint-plugin": "8.32.0", "@typescript-eslint/parser": "8.32.0", "autoprefixer": "10.4.21", @@ -73,11 +73,11 @@ "cross-env": "7.0.3", "dedent": "1.6.0", "eslint": "9.26.0", - "eslint-config-prettier": "10.1.3", + "eslint-config-prettier": "10.1.5", "eslint-import-resolver-alias": "1.1.2", "eslint-plugin-html": "8.1.2", "eslint-plugin-import": "2.31.0", - "eslint-plugin-n": "17.17.0", + "eslint-plugin-n": "17.18.0", "eslint-plugin-prettier": "5.4.0", "eslint-plugin-promise": "7.2.1", "eslint-plugin-react": "7.37.5", @@ -94,7 +94,7 @@ "postcss-scss": "4.0.9", "prettier": "3.5.3", "prettier-plugin-tailwindcss": "0.6.11", - "prettier-plugin-toml": "2.0.4", + "prettier-plugin-toml": "2.0.5", "react-devtools": "6.1.2", "stylelint": "16.19.1", "stylelint-config-html": "1.1.0", diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index 5bb3242946..7d136a449b 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -20,7 +20,7 @@ importers: devDependencies: '@commitlint/cli': specifier: 19.8.1 - version: 19.8.1(@types/node@22.15.16)(typescript@5.8.3) + version: 19.8.1(@types/node@22.15.17)(typescript@5.8.3) '@commitlint/config-conventional': specifier: 19.8.1 version: 19.8.1 @@ -43,8 +43,8 @@ importers: specifier: 4.17.12 version: 4.17.12 '@types/node': - specifier: 22.15.16 - version: 22.15.16 + specifier: 22.15.17 + version: 22.15.17 '@typescript-eslint/eslint-plugin': specifier: 8.32.0 version: 8.32.0(@typescript-eslint/parser@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) @@ -67,8 +67,8 @@ importers: specifier: 9.26.0 version: 9.26.0(jiti@2.4.2) eslint-config-prettier: - specifier: 10.1.3 - version: 10.1.3(eslint@9.26.0(jiti@2.4.2)) + specifier: 10.1.5 + version: 10.1.5(eslint@9.26.0(jiti@2.4.2)) eslint-import-resolver-alias: specifier: 1.1.2 version: 1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.26.0(jiti@2.4.2))) @@ -79,11 +79,11 @@ importers: specifier: 2.31.0 version: 2.31.0(@typescript-eslint/parser@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.26.0(jiti@2.4.2)) eslint-plugin-n: - specifier: 17.17.0 - version: 17.17.0(eslint@9.26.0(jiti@2.4.2)) + specifier: 17.18.0 + version: 17.18.0(eslint@9.26.0(jiti@2.4.2)) eslint-plugin-prettier: specifier: 5.4.0 - version: 5.4.0(eslint-config-prettier@10.1.3(eslint@9.26.0(jiti@2.4.2)))(eslint@9.26.0(jiti@2.4.2))(prettier@3.5.3) + version: 5.4.0(eslint-config-prettier@10.1.5(eslint@9.26.0(jiti@2.4.2)))(eslint@9.26.0(jiti@2.4.2))(prettier@3.5.3) eslint-plugin-promise: specifier: 7.2.1 version: 7.2.1(eslint@9.26.0(jiti@2.4.2)) @@ -101,7 +101,7 @@ importers: version: 16.0.0 knip: specifier: 5.54.1 - version: 5.54.1(@types/node@22.15.16)(typescript@5.8.3) + version: 5.54.1(@types/node@22.15.17)(typescript@5.8.3) lint-staged: specifier: 15.5.2 version: 15.5.2 @@ -130,8 +130,8 @@ importers: specifier: 0.6.11 version: 0.6.11(@ianvs/prettier-plugin-sort-imports@4.4.1(prettier@3.5.3))(@trivago/prettier-plugin-sort-imports@4.3.0(prettier@3.5.3))(prettier@3.5.3) prettier-plugin-toml: - specifier: 2.0.4 - version: 2.0.4(prettier@3.5.3) + specifier: 2.0.5 + version: 2.0.5(prettier@3.5.3) react-devtools: specifier: 6.1.2 version: 6.1.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) @@ -266,8 +266,8 @@ importers: specifier: 1.11.13 version: 1.11.13 framer-motion: - specifier: 12.10.1 - version: 12.10.1(@emotion/is-prop-valid@1.3.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: 12.10.5 + version: 12.10.5(@emotion/is-prop-valid@1.3.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) i18next: specifier: 25.0.2 version: 25.0.2(typescript@5.8.3) @@ -349,7 +349,7 @@ importers: version: 1.119.1(@tanstack/react-router@1.119.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@tanstack/router-core@1.119.0)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(tiny-invariant@1.3.3) '@tanstack/router-plugin': specifier: 1.119.0 - version: 1.119.0(@tanstack/react-router@1.119.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) + version: 1.119.0(@tanstack/react-router@1.119.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) '@tauri-apps/plugin-clipboard-manager': specifier: 2.2.2 version: 2.2.2 @@ -385,13 +385,13 @@ importers: version: 13.15.0 '@vitejs/plugin-legacy': specifier: 6.1.1 - version: 6.1.1(terser@5.36.0)(vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) + version: 6.1.1(terser@5.36.0)(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) '@vitejs/plugin-react': specifier: 4.4.1 - version: 4.4.1(vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) + version: 4.4.1(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) '@vitejs/plugin-react-swc': specifier: 3.9.0 - version: 3.9.0(vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) + version: 3.9.0(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) change-case: specifier: 5.4.4 version: 5.4.4 @@ -430,19 +430,19 @@ importers: version: 13.15.0 vite: specifier: 6.3.5 - version: 6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) + version: 6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) vite-plugin-html: specifier: 3.2.2 - version: 3.2.2(vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) + version: 3.2.2(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) vite-plugin-sass-dts: specifier: 1.3.31 - version: 1.3.31(postcss@8.5.3)(prettier@3.5.3)(sass-embedded@1.87.0)(vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) + version: 1.3.31(postcss@8.5.3)(prettier@3.5.3)(sass-embedded@1.87.0)(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) vite-plugin-svgr: specifier: 4.3.0 - version: 4.3.0(rollup@4.40.0)(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) + version: 4.3.0(rollup@4.40.0)(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) vite-tsconfig-paths: specifier: 5.1.4 - version: 5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) + version: 5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) zod: specifier: 3.24.4 version: 3.24.4 @@ -478,7 +478,7 @@ importers: version: 19.1.3 '@vitejs/plugin-react': specifier: 4.4.1 - version: 4.4.1(vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) + version: 4.4.1(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) ahooks: specifier: 3.8.4 version: 3.8.4(react@19.1.0) @@ -486,8 +486,8 @@ importers: specifier: 7.9.0 version: 7.9.0 framer-motion: - specifier: 12.10.1 - version: 12.10.1(@emotion/is-prop-valid@1.3.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + specifier: 12.10.5 + version: 12.10.5(@emotion/is-prop-valid@1.3.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react: specifier: 19.1.0 version: 19.1.0 @@ -508,10 +508,10 @@ importers: version: 4.1.5 vite: specifier: 6.3.5 - version: 6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) + version: 6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) vite-tsconfig-paths: specifier: 5.1.4 - version: 5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) + version: 5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) devDependencies: '@emotion/react': specifier: 11.14.0 @@ -536,13 +536,13 @@ importers: version: 5.1.0(typescript@5.8.3) vite-plugin-dts: specifier: 4.5.3 - version: 4.5.3(@types/node@22.15.16)(rollup@4.40.0)(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) + version: 4.5.3(@types/node@22.15.17)(rollup@4.40.0)(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)) scripts: dependencies: '@actions/github': - specifier: 6.0.0 - version: 6.0.0 + specifier: 6.0.1 + version: 6.0.1 '@types/figlet': specifier: 1.7.0 version: 1.7.0 @@ -613,8 +613,8 @@ importers: packages: - '@actions/github@6.0.0': - resolution: {integrity: sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g==} + '@actions/github@6.0.1': + resolution: {integrity: sha512-xbZVcaqD4XnQAe35qSQqskb3SqIAfRyLBrHMd/8TuL7hJSz2QtbDwnNM8zWx4zO5l2fnGtseNE3MbEvD7BxVMw==} '@actions/http-client@2.2.1': resolution: {integrity: sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw==} @@ -2067,16 +2067,12 @@ packages: resolution: {integrity: sha512-vvmsN0r7rguA+FySiCsbaTTobSftpIDIpPW81trAmsv9TGxg3YCujAxRYp/Uy8xmDgYCzzgulG62H7KYUFmeIg==} engines: {node: '>= 18'} - '@octokit/endpoint@10.1.3': - resolution: {integrity: sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==} - engines: {node: '>= 18'} - '@octokit/endpoint@10.1.4': resolution: {integrity: sha512-OlYOlZIsfEVZm5HCSR8aSg02T2lbUWOsCQoPKfTXJwDzcHQBrVBGdGXb89dv2Kw2ToZaRtudp8O3ZIYoaOjKlA==} engines: {node: '>= 18'} - '@octokit/endpoint@9.0.5': - resolution: {integrity: sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==} + '@octokit/endpoint@9.0.6': + resolution: {integrity: sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==} engines: {node: '>= 18'} '@octokit/graphql@7.1.0': @@ -2127,8 +2123,8 @@ packages: peerDependencies: '@octokit/core': '>=6' - '@octokit/plugin-paginate-rest@9.2.1': - resolution: {integrity: sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==} + '@octokit/plugin-paginate-rest@9.2.2': + resolution: {integrity: sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==} engines: {node: '>= 18'} peerDependencies: '@octokit/core': '5' @@ -2157,20 +2153,16 @@ packages: peerDependencies: '@octokit/core': ^6.1.3 - '@octokit/request-error@5.1.0': - resolution: {integrity: sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==} + '@octokit/request-error@5.1.1': + resolution: {integrity: sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==} engines: {node: '>= 18'} '@octokit/request-error@6.1.8': resolution: {integrity: sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ==} engines: {node: '>= 18'} - '@octokit/request@8.4.0': - resolution: {integrity: sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw==} - engines: {node: '>= 18'} - - '@octokit/request@9.2.2': - resolution: {integrity: sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg==} + '@octokit/request@8.4.1': + resolution: {integrity: sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==} engines: {node: '>= 18'} '@octokit/request@9.2.3': @@ -3220,8 +3212,8 @@ packages: '@types/node@16.18.108': resolution: {integrity: sha512-fj42LD82fSv6yN9C6Q4dzS+hujHj+pTv0IpRR3kI20fnYeS0ytBpjFO9OjmDowSPPt4lNKN46JLaKbCyP+BW2A==} - '@types/node@22.15.16': - resolution: {integrity: sha512-3pr+KjwpVujqWqOKT8mNR+rd09FqhBLwg+5L/4t0cNYBzm/yEiYGCxWttjaPBsLtAo+WFNoXzGJfolM1JuRXoA==} + '@types/node@22.15.17': + resolution: {integrity: sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==} '@types/node@22.15.3': resolution: {integrity: sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==} @@ -4566,8 +4558,8 @@ packages: peerDependencies: eslint: '>=6.0.0' - eslint-config-prettier@10.1.3: - resolution: {integrity: sha512-vDo4d9yQE+cS2tdIT4J02H/16veRvkHgiLDRpej+WL67oCfbOb97itZXn8wMPJ/GsiEBVjrjs//AVNw2Cp1EcA==} + eslint-config-prettier@10.1.5: + resolution: {integrity: sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==} hasBin: true peerDependencies: eslint: '>=7.0.0' @@ -4641,8 +4633,8 @@ packages: '@typescript-eslint/parser': optional: true - eslint-plugin-n@17.17.0: - resolution: {integrity: sha512-2VvPK7Mo73z1rDFb6pTvkH6kFibAmnTubFq5l83vePxu0WiY1s0LOtj2WHb6Sa40R3w4mnh8GFYbHBQyMlotKw==} + eslint-plugin-n@17.18.0: + resolution: {integrity: sha512-hvZ/HusueqTJ7VDLoCpjN0hx4N4+jHIWTXD4TMLHy9F23XkDagR9v+xQWRWR57yY55GPF8NnD4ox9iGTxirY8A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: '>=8.23.0' @@ -4922,8 +4914,8 @@ packages: fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - framer-motion@12.10.1: - resolution: {integrity: sha512-g+fANUVC17SzQc6eA0CtomBW4n67ckhS2hq5fjkKZneKzv7sbdXK3zzjnnAKB22Ck+Qhh+IlO5RjHNKULsq99Q==} + framer-motion@12.10.5: + resolution: {integrity: sha512-p6VF1YkwWvNDFzg5IQ5lqPx11Td4TQ6LqDnshV7sWj0Nrp4dwz2/aEzmgh9WA9ridcTIJ625Fr0oiuhgqIoFwQ==} peerDependencies: '@emotion/is-prop-valid': '*' react: ^18.0.0 || ^19.0.0 @@ -6238,8 +6230,8 @@ packages: peerDependencies: monaco-editor: '>=0.36' - motion-dom@12.10.1: - resolution: {integrity: sha512-rY8DNqgKh4LeFSQBkuXpe/7sycYS9RM+4luukjHpHogF1liSvIp0Hedx0q2QsWNz+AHuZ5bZQ9j9QZSUCA8bbw==} + motion-dom@12.10.5: + resolution: {integrity: sha512-F7XKmhxXEH/y3aWWf0N2w69wNSN+6PcJ1seqR1WolClmXpPhj+xwzs9j5CpsMFzeHR1D7irl3JcWMToPRwX6Hg==} motion-utils@12.9.4: resolution: {integrity: sha512-BW3I65zeM76CMsfh3kHid9ansEJk9Qvl+K5cu4DVHKGsI52n76OJ4z2CUJUV+Mn3uEP9k1JJA3tClG0ggSrRcg==} @@ -6796,8 +6788,8 @@ packages: prettier-plugin-svelte: optional: true - prettier-plugin-toml@2.0.4: - resolution: {integrity: sha512-uOTNPClqnE3T9XJ8hCqAJek70Jnk3/ZuAG/aXRTmrWbVe8lJyuZ60KV7OtgWqF+iGZOPVpkh+giHhX9GZYRHGA==} + prettier-plugin-toml@2.0.5: + resolution: {integrity: sha512-WjXXKQyY4TdXWHU1v73UJxK/oDLSppf+b9KrSVl2kC4ZOr9CIVPKTQ/JxttgbYMaH8r3ihw7WYhMpI1EFa1obg==} engines: {node: '>=16.0.0'} peerDependencies: prettier: ^3.0.3 @@ -7960,8 +7952,8 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - undici@5.28.4: - resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} + undici@5.29.0: + resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==} engines: {node: '>=14.0'} undici@7.8.0: @@ -8435,17 +8427,20 @@ packages: snapshots: - '@actions/github@6.0.0': + '@actions/github@6.0.1': dependencies: '@actions/http-client': 2.2.1 '@octokit/core': 5.2.0 - '@octokit/plugin-paginate-rest': 9.2.1(@octokit/core@5.2.0) + '@octokit/plugin-paginate-rest': 9.2.2(@octokit/core@5.2.0) '@octokit/plugin-rest-endpoint-methods': 10.4.1(@octokit/core@5.2.0) + '@octokit/request': 8.4.1 + '@octokit/request-error': 5.1.1 + undici: 5.29.0 '@actions/http-client@2.2.1': dependencies: tunnel: 0.0.6 - undici: 5.28.4 + undici: 5.29.0 '@adobe/css-tools@4.3.3': {} @@ -9309,11 +9304,11 @@ snapshots: '@bufbuild/protobuf@2.2.3': {} - '@commitlint/cli@19.8.1(@types/node@22.15.16)(typescript@5.8.3)': + '@commitlint/cli@19.8.1(@types/node@22.15.17)(typescript@5.8.3)': dependencies: '@commitlint/format': 19.8.1 '@commitlint/lint': 19.8.1 - '@commitlint/load': 19.8.1(@types/node@22.15.16)(typescript@5.8.3) + '@commitlint/load': 19.8.1(@types/node@22.15.17)(typescript@5.8.3) '@commitlint/read': 19.8.1 '@commitlint/types': 19.8.1 tinyexec: 1.0.1 @@ -9360,7 +9355,7 @@ snapshots: '@commitlint/rules': 19.8.1 '@commitlint/types': 19.8.1 - '@commitlint/load@19.8.1(@types/node@22.15.16)(typescript@5.8.3)': + '@commitlint/load@19.8.1(@types/node@22.15.17)(typescript@5.8.3)': dependencies: '@commitlint/config-validator': 19.8.1 '@commitlint/execute-rule': 19.8.1 @@ -9368,7 +9363,7 @@ snapshots: '@commitlint/types': 19.8.1 chalk: 5.4.1 cosmiconfig: 9.0.0(typescript@5.8.3) - cosmiconfig-typescript-loader: 6.1.0(@types/node@22.15.16)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3) + cosmiconfig-typescript-loader: 6.1.0(@types/node@22.15.17)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -9805,23 +9800,23 @@ snapshots: '@material/material-color-utilities@0.3.0': {} - '@microsoft/api-extractor-model@7.30.3(@types/node@22.15.16)': + '@microsoft/api-extractor-model@7.30.3(@types/node@22.15.17)': dependencies: '@microsoft/tsdoc': 0.15.1 '@microsoft/tsdoc-config': 0.17.1 - '@rushstack/node-core-library': 5.11.0(@types/node@22.15.16) + '@rushstack/node-core-library': 5.11.0(@types/node@22.15.17) transitivePeerDependencies: - '@types/node' - '@microsoft/api-extractor@7.51.0(@types/node@22.15.16)': + '@microsoft/api-extractor@7.51.0(@types/node@22.15.17)': dependencies: - '@microsoft/api-extractor-model': 7.30.3(@types/node@22.15.16) + '@microsoft/api-extractor-model': 7.30.3(@types/node@22.15.17) '@microsoft/tsdoc': 0.15.1 '@microsoft/tsdoc-config': 0.17.1 - '@rushstack/node-core-library': 5.11.0(@types/node@22.15.16) + '@rushstack/node-core-library': 5.11.0(@types/node@22.15.17) '@rushstack/rig-package': 0.5.3 - '@rushstack/terminal': 0.15.0(@types/node@22.15.16) - '@rushstack/ts-command-line': 4.23.5(@types/node@22.15.16) + '@rushstack/terminal': 0.15.0(@types/node@22.15.17) + '@rushstack/ts-command-line': 4.23.5(@types/node@22.15.17) lodash: 4.17.21 minimatch: 3.0.8 resolve: 1.22.8 @@ -10106,7 +10101,7 @@ snapshots: dependencies: '@octokit/auth-oauth-device': 7.1.3 '@octokit/auth-oauth-user': 5.1.3 - '@octokit/request': 9.2.2 + '@octokit/request': 9.2.3 '@octokit/types': 13.10.0 universal-user-agent: 7.0.2 @@ -10121,7 +10116,7 @@ snapshots: '@octokit/auth-oauth-device@7.1.3': dependencies: '@octokit/oauth-methods': 5.1.4 - '@octokit/request': 9.2.2 + '@octokit/request': 9.2.3 '@octokit/types': 13.10.0 universal-user-agent: 7.0.2 @@ -10136,7 +10131,7 @@ snapshots: dependencies: '@octokit/auth-oauth-device': 7.1.3 '@octokit/oauth-methods': 5.1.4 - '@octokit/request': 9.2.2 + '@octokit/request': 9.2.3 '@octokit/types': 13.10.0 universal-user-agent: 7.0.2 @@ -10166,8 +10161,8 @@ snapshots: dependencies: '@octokit/auth-token': 4.0.0 '@octokit/graphql': 7.1.0 - '@octokit/request': 8.4.0 - '@octokit/request-error': 5.1.0 + '@octokit/request': 8.4.1 + '@octokit/request-error': 5.1.1 '@octokit/types': 13.10.0 before-after-hook: 2.2.3 universal-user-agent: 6.0.1 @@ -10182,24 +10177,19 @@ snapshots: before-after-hook: 3.0.2 universal-user-agent: 7.0.2 - '@octokit/endpoint@10.1.3': - dependencies: - '@octokit/types': 13.10.0 - universal-user-agent: 7.0.2 - '@octokit/endpoint@10.1.4': dependencies: '@octokit/types': 14.0.0 universal-user-agent: 7.0.2 - '@octokit/endpoint@9.0.5': + '@octokit/endpoint@9.0.6': dependencies: '@octokit/types': 13.10.0 universal-user-agent: 6.0.1 '@octokit/graphql@7.1.0': dependencies: - '@octokit/request': 8.4.0 + '@octokit/request': 8.4.1 '@octokit/types': 13.10.0 universal-user-agent: 6.0.1 @@ -10225,7 +10215,7 @@ snapshots: '@octokit/oauth-methods@5.1.4': dependencies: '@octokit/oauth-authorization-url': 7.1.1 - '@octokit/request': 9.2.2 + '@octokit/request': 9.2.3 '@octokit/request-error': 6.1.8 '@octokit/types': 13.10.0 @@ -10253,7 +10243,7 @@ snapshots: '@octokit/core': 6.1.5 '@octokit/types': 14.0.0 - '@octokit/plugin-paginate-rest@9.2.1(@octokit/core@5.2.0)': + '@octokit/plugin-paginate-rest@9.2.2(@octokit/core@5.2.0)': dependencies: '@octokit/core': 5.2.0 '@octokit/types': 12.6.0 @@ -10281,7 +10271,7 @@ snapshots: '@octokit/types': 14.0.0 bottleneck: 2.19.5 - '@octokit/request-error@5.1.0': + '@octokit/request-error@5.1.1': dependencies: '@octokit/types': 13.10.0 deprecation: 2.3.1 @@ -10291,21 +10281,13 @@ snapshots: dependencies: '@octokit/types': 14.0.0 - '@octokit/request@8.4.0': + '@octokit/request@8.4.1': dependencies: - '@octokit/endpoint': 9.0.5 - '@octokit/request-error': 5.1.0 + '@octokit/endpoint': 9.0.6 + '@octokit/request-error': 5.1.1 '@octokit/types': 13.10.0 universal-user-agent: 6.0.1 - '@octokit/request@9.2.2': - dependencies: - '@octokit/endpoint': 10.1.3 - '@octokit/request-error': 6.1.8 - '@octokit/types': 13.10.0 - fast-content-type-parse: 2.0.1 - universal-user-agent: 7.0.2 - '@octokit/request@9.2.3': dependencies: '@octokit/endpoint': 10.1.4 @@ -10568,7 +10550,7 @@ snapshots: '@rtsao/scc@1.1.0': {} - '@rushstack/node-core-library@5.11.0(@types/node@22.15.16)': + '@rushstack/node-core-library@5.11.0(@types/node@22.15.17)': dependencies: ajv: 8.13.0 ajv-draft-04: 1.0.0(ajv@8.13.0) @@ -10579,23 +10561,23 @@ snapshots: resolve: 1.22.8 semver: 7.5.4 optionalDependencies: - '@types/node': 22.15.16 + '@types/node': 22.15.17 '@rushstack/rig-package@0.5.3': dependencies: resolve: 1.22.8 strip-json-comments: 3.1.1 - '@rushstack/terminal@0.15.0(@types/node@22.15.16)': + '@rushstack/terminal@0.15.0(@types/node@22.15.17)': dependencies: - '@rushstack/node-core-library': 5.11.0(@types/node@22.15.16) + '@rushstack/node-core-library': 5.11.0(@types/node@22.15.17) supports-color: 8.1.1 optionalDependencies: - '@types/node': 22.15.16 + '@types/node': 22.15.17 - '@rushstack/ts-command-line@4.23.5(@types/node@22.15.16)': + '@rushstack/ts-command-line@4.23.5(@types/node@22.15.17)': dependencies: - '@rushstack/terminal': 0.15.0(@types/node@22.15.16) + '@rushstack/terminal': 0.15.0(@types/node@22.15.17) '@types/argparse': 1.0.38 argparse: 1.0.10 string-argv: 0.3.2 @@ -10923,7 +10905,7 @@ snapshots: optionalDependencies: '@tanstack/react-router': 1.119.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@tanstack/router-plugin@1.119.0(@tanstack/react-router@1.119.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0))': + '@tanstack/router-plugin@1.119.0(@tanstack/react-router@1.119.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0))': dependencies: '@babel/core': 7.26.10 '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.10) @@ -10944,7 +10926,7 @@ snapshots: zod: 3.24.4 optionalDependencies: '@tanstack/react-router': 1.119.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - vite: 6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) + vite: 6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) transitivePeerDependencies: - supports-color @@ -11101,12 +11083,12 @@ snapshots: dependencies: '@types/http-cache-semantics': 4.0.4 '@types/keyv': 3.1.4 - '@types/node': 22.15.16 + '@types/node': 22.15.17 '@types/responselike': 1.0.3 '@types/conventional-commits-parser@5.0.0': dependencies: - '@types/node': 22.15.16 + '@types/node': 22.15.17 '@types/d3-array@3.2.1': {} @@ -11244,7 +11226,7 @@ snapshots: '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 - '@types/node': 22.15.16 + '@types/node': 22.15.17 '@types/geojson@7946.0.14': {} @@ -11262,11 +11244,11 @@ snapshots: '@types/jsonfile@6.1.4': dependencies: - '@types/node': 22.15.16 + '@types/node': 22.15.17 '@types/keyv@3.1.4': dependencies: - '@types/node': 22.15.16 + '@types/node': 22.15.17 '@types/lodash-es@4.17.12': dependencies: @@ -11282,7 +11264,7 @@ snapshots: '@types/node@16.18.108': {} - '@types/node@22.15.16': + '@types/node@22.15.17': dependencies: undici-types: 6.21.0 @@ -11316,7 +11298,7 @@ snapshots: '@types/responselike@1.0.3': dependencies: - '@types/node': 22.15.16 + '@types/node': 22.15.17 '@types/retry@0.12.2': {} @@ -11336,7 +11318,7 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.15.16 + '@types/node': 22.15.17 optional: true '@typescript-eslint/eslint-plugin@8.32.0(@typescript-eslint/parser@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)': @@ -11423,7 +11405,7 @@ snapshots: '@typescript-eslint/utils@8.30.1(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3)': dependencies: - '@eslint-community/eslint-utils': 4.5.1(eslint@9.26.0(jiti@2.4.2)) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0(jiti@2.4.2)) '@typescript-eslint/scope-manager': 8.30.1 '@typescript-eslint/types': 8.30.1 '@typescript-eslint/typescript-estree': 8.30.1(typescript@5.8.3) @@ -11455,7 +11437,7 @@ snapshots: '@ungap/structured-clone@1.2.0': {} - '@vitejs/plugin-legacy@6.1.1(terser@5.36.0)(vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0))': + '@vitejs/plugin-legacy@6.1.1(terser@5.36.0)(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0))': dependencies: '@babel/core': 7.26.10 '@babel/preset-env': 7.26.9(@babel/core@7.26.10) @@ -11466,25 +11448,25 @@ snapshots: regenerator-runtime: 0.14.1 systemjs: 6.15.1 terser: 5.36.0 - vite: 6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) + vite: 6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) transitivePeerDependencies: - supports-color - '@vitejs/plugin-react-swc@3.9.0(vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0))': + '@vitejs/plugin-react-swc@3.9.0(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0))': dependencies: '@swc/core': 1.11.21 - vite: 6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) + vite: 6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) transitivePeerDependencies: - '@swc/helpers' - '@vitejs/plugin-react@4.4.1(vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0))': + '@vitejs/plugin-react@4.4.1(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0))': dependencies: '@babel/core': 7.26.10 '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.10) '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.10) '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) + vite: 6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) transitivePeerDependencies: - supports-color @@ -12156,9 +12138,9 @@ snapshots: object-assign: 4.1.1 vary: 1.1.2 - cosmiconfig-typescript-loader@6.1.0(@types/node@22.15.16)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3): + cosmiconfig-typescript-loader@6.1.0(@types/node@22.15.17)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3): dependencies: - '@types/node': 22.15.16 + '@types/node': 22.15.17 cosmiconfig: 9.0.0(typescript@5.8.3) jiti: 2.4.2 typescript: 5.8.3 @@ -12886,7 +12868,7 @@ snapshots: eslint: 9.26.0(jiti@2.4.2) semver: 7.7.1 - eslint-config-prettier@10.1.3(eslint@9.26.0(jiti@2.4.2)): + eslint-config-prettier@10.1.5(eslint@9.26.0(jiti@2.4.2)): dependencies: eslint: 9.26.0(jiti@2.4.2) @@ -12931,7 +12913,7 @@ snapshots: eslint-plugin-es-x@7.8.0(eslint@9.26.0(jiti@2.4.2)): dependencies: - '@eslint-community/eslint-utils': 4.5.1(eslint@9.26.0(jiti@2.4.2)) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0(jiti@2.4.2)) '@eslint-community/regexpp': 4.12.1 eslint: 9.26.0(jiti@2.4.2) eslint-compat-utils: 0.5.1(eslint@9.26.0(jiti@2.4.2)) @@ -12987,9 +12969,9 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-n@17.17.0(eslint@9.26.0(jiti@2.4.2)): + eslint-plugin-n@17.18.0(eslint@9.26.0(jiti@2.4.2)): dependencies: - '@eslint-community/eslint-utils': 4.5.1(eslint@9.26.0(jiti@2.4.2)) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0(jiti@2.4.2)) enhanced-resolve: 5.18.1 eslint: 9.26.0(jiti@2.4.2) eslint-plugin-es-x: 7.8.0(eslint@9.26.0(jiti@2.4.2)) @@ -12999,14 +12981,14 @@ snapshots: minimatch: 9.0.5 semver: 7.7.1 - eslint-plugin-prettier@5.4.0(eslint-config-prettier@10.1.3(eslint@9.26.0(jiti@2.4.2)))(eslint@9.26.0(jiti@2.4.2))(prettier@3.5.3): + eslint-plugin-prettier@5.4.0(eslint-config-prettier@10.1.5(eslint@9.26.0(jiti@2.4.2)))(eslint@9.26.0(jiti@2.4.2))(prettier@3.5.3): dependencies: eslint: 9.26.0(jiti@2.4.2) prettier: 3.5.3 prettier-linter-helpers: 1.0.0 synckit: 0.11.1 optionalDependencies: - eslint-config-prettier: 10.1.3(eslint@9.26.0(jiti@2.4.2)) + eslint-config-prettier: 10.1.5(eslint@9.26.0(jiti@2.4.2)) eslint-plugin-promise@7.2.1(eslint@9.26.0(jiti@2.4.2)): dependencies: @@ -13373,9 +13355,9 @@ snapshots: fraction.js@4.3.7: {} - framer-motion@12.10.1(@emotion/is-prop-valid@1.3.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + framer-motion@12.10.5(@emotion/is-prop-valid@1.3.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: - motion-dom: 12.10.1 + motion-dom: 12.10.5 motion-utils: 12.9.4 tslib: 2.8.1 optionalDependencies: @@ -14228,10 +14210,10 @@ snapshots: kind-of@6.0.3: {} - knip@5.54.1(@types/node@22.15.16)(typescript@5.8.3): + knip@5.54.1(@types/node@22.15.17)(typescript@5.8.3): dependencies: '@nodelib/fs.walk': 1.2.8 - '@types/node': 22.15.16 + '@types/node': 22.15.17 enhanced-resolve: 5.18.1 fast-glob: 3.3.3 formatly: 0.2.3 @@ -14812,7 +14794,7 @@ snapshots: vscode-uri: 3.0.8 yaml: 2.7.0 - motion-dom@12.10.1: + motion-dom@12.10.5: dependencies: motion-utils: 12.9.4 @@ -14869,7 +14851,7 @@ snapshots: eslint: 9.26.0(jiti@2.4.2) eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import-x@4.5.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.26.0(jiti@2.4.2)))(eslint@9.26.0(jiti@2.4.2)) eslint-plugin-import-x: 4.5.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.8.3) - eslint-plugin-n: 17.17.0(eslint@9.26.0(jiti@2.4.2)) + eslint-plugin-n: 17.18.0(eslint@9.26.0(jiti@2.4.2)) eslint-plugin-promise: 7.2.1(eslint@9.26.0(jiti@2.4.2)) eslint-plugin-react: 7.37.5(eslint@9.26.0(jiti@2.4.2)) find-up: 5.0.0 @@ -15322,7 +15304,7 @@ snapshots: '@ianvs/prettier-plugin-sort-imports': 4.4.1(prettier@3.5.3) '@trivago/prettier-plugin-sort-imports': 4.3.0(prettier@3.5.3) - prettier-plugin-toml@2.0.4(prettier@3.5.3): + prettier-plugin-toml@2.0.5(prettier@3.5.3): dependencies: '@taplo/lib': 0.5.0 prettier: 3.5.3 @@ -16649,7 +16631,7 @@ snapshots: undici-types@6.21.0: {} - undici@5.28.4: + undici@5.29.0: dependencies: '@fastify/busboy': 2.1.1 @@ -16859,9 +16841,9 @@ snapshots: - rollup - supports-color - vite-plugin-dts@4.5.3(@types/node@22.15.16)(rollup@4.40.0)(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)): + vite-plugin-dts@4.5.3(@types/node@22.15.17)(rollup@4.40.0)(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)): dependencies: - '@microsoft/api-extractor': 7.51.0(@types/node@22.15.16) + '@microsoft/api-extractor': 7.51.0(@types/node@22.15.17) '@rollup/pluginutils': 5.1.4(rollup@4.40.0) '@volar/typescript': 2.4.11 '@vue/language-core': 2.2.0(typescript@5.8.3) @@ -16872,13 +16854,13 @@ snapshots: magic-string: 0.30.17 typescript: 5.8.3 optionalDependencies: - vite: 6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) + vite: 6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) transitivePeerDependencies: - '@types/node' - rollup - supports-color - vite-plugin-html@3.2.2(vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)): + vite-plugin-html@3.2.2(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)): dependencies: '@rollup/pluginutils': 4.2.1 colorette: 2.0.20 @@ -16892,39 +16874,39 @@ snapshots: html-minifier-terser: 6.1.0 node-html-parser: 5.4.2 pathe: 0.2.0 - vite: 6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) + vite: 6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) - vite-plugin-sass-dts@1.3.31(postcss@8.5.3)(prettier@3.5.3)(sass-embedded@1.87.0)(vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)): + vite-plugin-sass-dts@1.3.31(postcss@8.5.3)(prettier@3.5.3)(sass-embedded@1.87.0)(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)): dependencies: postcss: 8.5.3 postcss-js: 4.0.1(postcss@8.5.3) prettier: 3.5.3 sass-embedded: 1.87.0 - vite: 6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) + vite: 6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) - vite-plugin-svgr@4.3.0(rollup@4.40.0)(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)): + vite-plugin-svgr@4.3.0(rollup@4.40.0)(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)): dependencies: '@rollup/pluginutils': 5.1.3(rollup@4.40.0) '@svgr/core': 8.1.0(typescript@5.8.3) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.8.3)) - vite: 6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) + vite: 6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) transitivePeerDependencies: - rollup - supports-color - typescript - vite-tsconfig-paths@5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)): + vite-tsconfig-paths@5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0)): dependencies: debug: 4.3.7 globrex: 0.1.2 tsconfck: 3.0.3(typescript@5.8.3) optionalDependencies: - vite: 6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) + vite: 6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0) transitivePeerDependencies: - supports-color - typescript - vite@6.3.5(@types/node@22.15.16)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0): + vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.29.2)(sass-embedded@1.87.0)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.0): dependencies: esbuild: 0.25.0 fdir: 6.4.4(picomatch@4.0.2) @@ -16933,7 +16915,7 @@ snapshots: rollup: 4.40.0 tinyglobby: 0.2.13 optionalDependencies: - '@types/node': 22.15.16 + '@types/node': 22.15.17 fsevents: 2.3.3 jiti: 2.4.2 less: 4.2.0 diff --git a/clash-nyanpasu/scripts/package.json b/clash-nyanpasu/scripts/package.json index 7b7dc8d13c..7016a6326a 100644 --- a/clash-nyanpasu/scripts/package.json +++ b/clash-nyanpasu/scripts/package.json @@ -3,7 +3,7 @@ "type": "module", "version": "2.0.0", "dependencies": { - "@actions/github": "6.0.0", + "@actions/github": "6.0.1", "@types/figlet": "1.7.0", "@types/semver": "7.7.0", "figlet": "1.8.1", diff --git a/clash-verge-rev/UPDATELOG.md b/clash-verge-rev/UPDATELOG.md index 030ee3375d..b53843b5f6 100644 --- a/clash-verge-rev/UPDATELOG.md +++ b/clash-verge-rev/UPDATELOG.md @@ -18,6 +18,7 @@ - 切换自定义代理地址导致系统代理状态异常 - Macos TUN 默认无效网卡名称 - 托盘更改订阅后 UI 不同步的问题 + - 修复提权漏洞,改用带认证的 IPC 通信(后续还可以加强完善认证密钥创建和管理机制) #### 新增了: - 允许代理主机地址设置为非 127.0.0.1 对 WSL 代理友好 @@ -47,6 +48,7 @@ - 重构前端通知系统分离通知线程防止前端卡死 - 优化网络请求和错误处理 - 重构通知系统 + - 使用异步方法重构 UI 启动逻辑,解决启动软件过程中的各种卡死问题 ## v2.2.3 diff --git a/clash-verge-rev/src-tauri/src/cmd/app.rs b/clash-verge-rev/src-tauri/src/cmd/app.rs index 76cf9829e9..f44928ce70 100644 --- a/clash-verge-rev/src-tauri/src/cmd/app.rs +++ b/clash-verge-rev/src-tauri/src/cmd/app.rs @@ -87,23 +87,18 @@ pub async fn download_icon_cache(url: String, name: String) -> CmdResult let icon_cache_dir = wrap_err!(dirs::app_home_dir())?.join("icons").join("cache"); let icon_path = icon_cache_dir.join(&name); - // 如果文件已存在,直接返回路径 if icon_path.exists() { return Ok(icon_path.to_string_lossy().to_string()); } - // 确保缓存目录存在 if !icon_cache_dir.exists() { let _ = std::fs::create_dir_all(&icon_cache_dir); } - // 使用临时文件名来下载 let temp_path = icon_cache_dir.join(format!("{}.downloading", &name)); - // 下载文件到临时位置 let response = wrap_err!(reqwest::get(&url).await)?; - // 检查内容类型是否为图片 let content_type = response .headers() .get(reqwest::header::CONTENT_TYPE) @@ -112,16 +107,13 @@ pub async fn download_icon_cache(url: String, name: String) -> CmdResult let is_image = content_type.starts_with("image/"); - // 获取响应内容 let content = wrap_err!(response.bytes().await)?; - // 检查内容是否为HTML (针对CDN错误页面) let is_html = content.len() > 15 && (content.starts_with(b" CmdResult wrap_err!(std::io::copy(&mut content.as_ref(), &mut file))?; } - // 再次检查目标文件是否已存在,避免重命名覆盖其他线程已完成的文件 if !icon_path.exists() { match std::fs::rename(&temp_path, &icon_path) { Ok(_) => {} @@ -223,6 +214,29 @@ pub fn notify_ui_ready() -> CmdResult<()> { Ok(()) } +/// UI加载阶段 +#[tauri::command] +pub fn update_ui_stage(stage: String) -> CmdResult<()> { + log::info!(target: "app", "UI加载阶段更新: {}", stage); + + use crate::utils::resolve::UiReadyStage; + + let stage_enum = match stage.as_str() { + "NotStarted" => UiReadyStage::NotStarted, + "Loading" => UiReadyStage::Loading, + "DomReady" => UiReadyStage::DomReady, + "ResourcesLoaded" => UiReadyStage::ResourcesLoaded, + "Ready" => UiReadyStage::Ready, + _ => { + log::warn!(target: "app", "未知的UI加载阶段: {}", stage); + return Err(format!("未知的UI加载阶段: {}", stage)); + } + }; + + crate::utils::resolve::update_ui_ready_stage(stage_enum); + Ok(()) +} + /// 重置UI就绪状态 #[tauri::command] pub fn reset_ui_ready_state() -> CmdResult<()> { diff --git a/clash-verge-rev/src-tauri/src/core/tray/mod.rs b/clash-verge-rev/src-tauri/src/core/tray/mod.rs index f7e12fe989..79fcc08787 100644 --- a/clash-verge-rev/src-tauri/src/core/tray/mod.rs +++ b/clash-verge-rev/src-tauri/src/core/tray/mod.rs @@ -11,7 +11,7 @@ use crate::{ mihomo::Rate, }, resolve, - utils::{dirs::find_target_icons, i18n::t, logging::Type, resolve::VERSION}, + utils::{dirs::find_target_icons, i18n::t, resolve::VERSION}, }; use anyhow::Result; @@ -29,7 +29,7 @@ use std::sync::Arc; use tauri::{ menu::{CheckMenuItem, IsMenuItem, MenuEvent, MenuItem, PredefinedMenuItem, Submenu}, tray::{MouseButton, MouseButtonState, TrayIconEvent}, - App, AppHandle, Wry, + AppHandle, Wry, }; #[cfg(target_os = "macos")] use tokio::sync::broadcast; @@ -178,52 +178,6 @@ impl Tray { Ok(()) } - pub fn create_systray(&self, app: &App) -> Result<()> { - let mut builder = TrayIconBuilder::with_id("main") - .icon(app.default_window_icon().unwrap().clone()) - .icon_as_template(false); - - #[cfg(any(target_os = "macos", target_os = "windows"))] - { - let tray_event = { Config::verge().latest().tray_event.clone() }; - let tray_event: String = tray_event.unwrap_or("main_window".into()); - if tray_event.as_str() != "tray_menu" { - builder = builder.show_menu_on_left_click(false); - } - } - - let tray = builder.build(app)?; - - tray.on_tray_icon_event(|_, event| { - let tray_event = { Config::verge().latest().tray_event.clone() }; - let tray_event: String = tray_event.unwrap_or("main_window".into()); - log::debug!(target: "app","tray event: {:?}", tray_event); - - if let TrayIconEvent::Click { - button: MouseButton::Left, - button_state: MouseButtonState::Down, - .. - } = event - { - match tray_event.as_str() { - "system_proxy" => feat::toggle_system_proxy(), - "tun_mode" => feat::toggle_tun_mode(None), - "main_window" => { - // 如果在轻量模式中,先退出轻量模式 - if crate::module::lightweight::is_in_lightweight_mode() { - crate::module::lightweight::exit_lightweight_mode(); - } - // 然后创建窗口 - resolve::create_window(true) - } - _ => {} - } - } - }); - tray.on_menu_event(on_menu_event); - Ok(()) - } - /// 更新托盘点击行为 pub fn update_click_behavior(&self) -> Result<()> { let app_handle = handle::Handle::global().app_handle().unwrap(); @@ -239,7 +193,14 @@ impl Tray { /// 更新托盘菜单 pub fn update_menu(&self) -> Result<()> { - let app_handle = handle::Handle::global().app_handle().unwrap(); + let app_handle = match handle::Handle::global().app_handle() { + Some(handle) => handle, + None => { + log::warn!(target: "app", "更新托盘菜单失败: app_handle不存在"); + return Ok(()); // 早期返回,避免panic + } + }; + let verge = Config::verge().latest().clone(); let system_proxy = verge.enable_system_proxy.as_ref().unwrap_or(&false); let tun_mode = verge.enable_tun_mode.as_ref().unwrap_or(&false); @@ -258,27 +219,47 @@ impl Tray { .unwrap_or_default(); let is_lightweight_mode = is_in_lightweight_mode(); - let tray = app_handle.tray_by_id("main").unwrap(); - let _ = tray.set_menu(Some(create_tray_menu( - &app_handle, - Some(mode.as_str()), - *system_proxy, - *tun_mode, - profile_uid_and_name, - is_lightweight_mode, - )?)); - Ok(()) + match app_handle.tray_by_id("main") { + Some(tray) => { + let _ = tray.set_menu(Some(create_tray_menu( + &app_handle, + Some(mode.as_str()), + *system_proxy, + *tun_mode, + profile_uid_and_name, + is_lightweight_mode, + )?)); + Ok(()) + } + None => { + log::warn!(target: "app", "更新托盘菜单失败: 托盘不存在"); + Ok(()) + } + } } /// 更新托盘图标 pub fn update_icon(&self, rate: Option) -> Result<()> { + let app_handle = match handle::Handle::global().app_handle() { + Some(handle) => handle, + None => { + log::warn!(target: "app", "更新托盘图标失败: app_handle不存在"); + return Ok(()); + } + }; + + let tray = match app_handle.tray_by_id("main") { + Some(tray) => tray, + None => { + log::warn!(target: "app", "更新托盘图标失败: 托盘不存在"); + return Ok(()); + } + }; + let verge = Config::verge().latest().clone(); let system_mode = verge.enable_system_proxy.as_ref().unwrap_or(&false); let tun_mode = verge.enable_tun_mode.as_ref().unwrap_or(&false); - let app_handle = handle::Handle::global().app_handle().unwrap(); - let tray = app_handle.tray_by_id("main").unwrap(); - let (is_custom_icon, icon_bytes) = match (*system_mode, *tun_mode) { (true, true) => TrayState::get_tun_tray_icon(), (true, false) => TrayState::get_sysproxy_tray_icon(), @@ -302,8 +283,12 @@ impl Tray { Some(rate) } else { let guard = self.speed_rate.lock(); - if let Some(rate) = guard.as_ref().unwrap().get_curent_rate() { - Some(rate) + if let Some(guard) = guard.as_ref() { + if let Some(rate) = guard.get_curent_rate() { + Some(rate) + } else { + Some(Rate::default()) + } } else { Some(Rate::default()) } @@ -320,9 +305,10 @@ impl Tray { }; let rate = rate_guard.as_ref(); - let rate_bytes = SpeedRate::add_speed_text(is_custom_icon, bytes, rate).unwrap(); - let _ = tray.set_icon(Some(tauri::image::Image::from_bytes(&rate_bytes)?)); - let _ = tray.set_icon_as_template(!is_custom_icon && !is_colorful); + if let Ok(rate_bytes) = SpeedRate::add_speed_text(is_custom_icon, bytes, rate) { + let _ = tray.set_icon(Some(tauri::image::Image::from_bytes(&rate_bytes)?)); + let _ = tray.set_icon_as_template(!is_custom_icon && !is_colorful); + } } Ok(()) } @@ -336,8 +322,21 @@ impl Tray { /// 更新托盘提示 pub fn update_tooltip(&self) -> Result<()> { - let app_handle = handle::Handle::global().app_handle().unwrap(); - let version = VERSION.get().unwrap(); + let app_handle = match handle::Handle::global().app_handle() { + Some(handle) => handle, + None => { + log::warn!(target: "app", "更新托盘提示失败: app_handle不存在"); + return Ok(()); + } + }; + + let version = match VERSION.get() { + Some(v) => v, + None => { + log::warn!(target: "app", "更新托盘提示失败: 版本信息不存在"); + return Ok(()); + } + }; let verge = Config::verge().latest().clone(); let system_proxy = verge.enable_system_proxy.as_ref().unwrap_or(&false); @@ -354,23 +353,28 @@ impl Tray { let profiles = Config::profiles(); let profiles = profiles.latest(); if let Some(current_profile_uid) = profiles.get_current() { - let current_profile = profiles.get_item(¤t_profile_uid); - current_profile_name = match ¤t_profile.unwrap().name { - Some(profile_name) => profile_name.to_string(), - None => current_profile_name, - }; + if let Ok(profile) = profiles.get_item(¤t_profile_uid) { + current_profile_name = match &profile.name { + Some(profile_name) => profile_name.to_string(), + None => current_profile_name, + }; + } }; - let tray = app_handle.tray_by_id("main").unwrap(); - let _ = tray.set_tooltip(Some(&format!( - "Clash Verge {version}\n{}: {}\n{}: {}\n{}: {}", - t("SysProxy"), - switch_map[system_proxy], - t("TUN"), - switch_map[tun_mode], - t("Profile"), - current_profile_name - ))); + if let Some(tray) = app_handle.tray_by_id("main") { + let _ = tray.set_tooltip(Some(&format!( + "Clash Verge {version}\n{}: {}\n{}: {}\n{}: {}", + t("SysProxy"), + switch_map[system_proxy], + t("TUN"), + switch_map[tun_mode], + t("Profile"), + current_profile_name + ))); + } else { + log::warn!(target: "app", "更新托盘提示失败: 托盘不存在"); + } + Ok(()) } @@ -532,6 +536,57 @@ impl Tray { drop(tx); } } + + pub fn create_tray_from_handle(&self, app_handle: &AppHandle) -> Result<()> { + log::info!(target: "app", "正在从AppHandle创建系统托盘"); + + // 获取图标 + let icon_bytes = TrayState::get_common_tray_icon().1; + let icon = tauri::image::Image::from_bytes(&icon_bytes)?; + + let mut builder = TrayIconBuilder::with_id("main") + .icon(icon) + .icon_as_template(false); + + #[cfg(any(target_os = "macos", target_os = "windows"))] + { + let tray_event = { Config::verge().latest().tray_event.clone() }; + let tray_event: String = tray_event.unwrap_or("main_window".into()); + if tray_event.as_str() != "tray_menu" { + builder = builder.show_menu_on_left_click(false); + } + } + + let tray = builder.build(app_handle)?; + + tray.on_tray_icon_event(|_, event| { + let tray_event = { Config::verge().latest().tray_event.clone() }; + let tray_event: String = tray_event.unwrap_or("main_window".into()); + log::debug!(target: "app","tray event: {:?}", tray_event); + + if let TrayIconEvent::Click { + button: MouseButton::Left, + button_state: MouseButtonState::Down, + .. + } = event + { + match tray_event.as_str() { + "system_proxy" => feat::toggle_system_proxy(), + "tun_mode" => feat::toggle_tun_mode(None), + "main_window" => { + if crate::module::lightweight::is_in_lightweight_mode() { + crate::module::lightweight::exit_lightweight_mode(); + } + let _ = resolve::create_window(true); + } + _ => {} + } + } + }); + tray.on_menu_event(on_menu_event); + log::info!(target: "app", "系统托盘创建成功"); + Ok(()) + } } fn create_tray_menu( @@ -543,7 +598,10 @@ fn create_tray_menu( is_lightweight_mode: bool, ) -> Result> { let mode = mode.unwrap_or(""); - let version = VERSION.get().unwrap(); + + let unknown_version = String::from("unknown"); + let version = VERSION.get().unwrap_or(&unknown_version); + let hotkeys = Config::verge() .latest() .hotkeys @@ -779,14 +837,20 @@ fn on_menu_event(_: &AppHandle, event: MenuEvent) { crate::module::lightweight::exit_lightweight_mode(); } // 然后创建窗口 - resolve::create_window(true) + let _ = resolve::create_window(true); } "system_proxy" => feat::toggle_system_proxy(), "tun_mode" => feat::toggle_tun_mode(None), "copy_env" => feat::copy_clash_env(), - "open_app_dir" => crate::logging_error!(Type::Cmd, true, cmd::open_app_dir()), - "open_core_dir" => crate::logging_error!(Type::Cmd, true, cmd::open_core_dir()), - "open_logs_dir" => crate::logging_error!(Type::Cmd, true, cmd::open_logs_dir()), + "open_app_dir" => { + let _ = cmd::open_app_dir(); + } + "open_core_dir" => { + let _ = cmd::open_core_dir(); + } + "open_logs_dir" => { + let _ = cmd::open_logs_dir(); + } "restart_clash" => feat::restart_clash_core(), "restart_app" => feat::restart_app(), "entry_lightweight_mode" => entry_lightweight_mode(), diff --git a/clash-verge-rev/src-tauri/src/lib.rs b/clash-verge-rev/src-tauri/src/lib.rs index 2d0430cd07..40a52af20b 100644 --- a/clash-verge-rev/src-tauri/src/lib.rs +++ b/clash-verge-rev/src-tauri/src/lib.rs @@ -86,23 +86,30 @@ impl AppHandleManager { #[allow(clippy::panic)] pub fn run() { - // 初始化网络管理器 utils::network::NetworkManager::global().init(); - // 单例检测 - 使用超时机制防止阻塞 + let _ = utils::dirs::init_portable_flag(); + + // 单例检测 let app_exists: bool = AsyncHandler::block_on(move || async move { + logging!(info, Type::Setup, true, "开始检查单例实例..."); match timeout(Duration::from_secs(3), server::check_singleton()).await { Ok(result) => { if result.is_err() { - println!("app exists"); + logging!(info, Type::Setup, true, "检测到已有应用实例运行"); true } else { + logging!(info, Type::Setup, true, "未检测到其他应用实例"); false } } Err(_) => { - // 超时处理 - println!("singleton check timeout, assuming app doesn't exist"); + logging!( + warn, + Type::Setup, + true, + "单例检查超时,假定没有其他实例运行" + ); false } } @@ -136,9 +143,11 @@ pub fn run() { .build(), ) .setup(|app| { + logging!(info, Type::Setup, true, "开始应用初始化..."); #[cfg(any(target_os = "linux", all(debug_assertions, windows)))] { use tauri_plugin_deep_link::DeepLinkExt; + logging!(info, Type::Setup, true, "注册深层链接..."); logging_error!(Type::System, true, app.deep_link().register_all()); } app.deep_link().on_open_url(|event| { @@ -152,23 +161,49 @@ pub fn run() { }); }); - // 使用 block_on 但增加超时保护 - AsyncHandler::block_on(|| async { - match timeout(Duration::from_secs(30), resolve::resolve_setup(app)).await { + // 异步处理 + let app_handle = app.handle().clone(); + AsyncHandler::spawn(move || async move { + logging!(info, Type::Setup, true, "异步执行应用设置..."); + match timeout( + Duration::from_secs(30), + resolve::resolve_setup_async(&app_handle), + ) + .await + { Ok(_) => { - logging!(info, Type::Setup, true, "App setup completed successfully"); + logging!(info, Type::Setup, true, "应用设置成功完成"); } Err(_) => { logging!( error, Type::Setup, true, - "App setup timed out, proceeding anyway" + "应用设置超时(30秒),继续执行后续流程" ); } } }); + logging!(info, Type::Setup, true, "执行主要设置操作..."); + + logging!(info, Type::Setup, true, "初始化AppHandleManager..."); + AppHandleManager::global().init(app.handle().clone()); + + logging!(info, Type::Setup, true, "初始化核心句柄..."); + core::handle::Handle::global().init(app.handle()); + + logging!(info, Type::Setup, true, "初始化配置..."); + if let Err(e) = utils::init::init_config() { + logging!(error, Type::Setup, true, "初始化配置失败: {}", e); + } + + logging!(info, Type::Setup, true, "初始化资源..."); + if let Err(e) = utils::init::init_resources() { + logging!(error, Type::Setup, true, "初始化资源失败: {}", e); + } + + logging!(info, Type::Setup, true, "初始化完成,继续执行"); Ok(()) }) .invoke_handler(tauri::generate_handler![ @@ -184,8 +219,9 @@ pub fn run() { cmd::get_system_hostname, cmd::restart_core, cmd::restart_app, - // 添加新的命令 + // 启动命令 cmd::notify_ui_ready, + cmd::update_ui_stage, cmd::reset_ui_ready_state, cmd::get_running_mode, cmd::get_app_uptime, @@ -279,6 +315,7 @@ pub fn run() { app.run(|app_handle, e| match e { tauri::RunEvent::Ready | tauri::RunEvent::Resumed => { + logging!(info, Type::System, true, "应用就绪或恢复"); AppHandleManager::global().init(app_handle.clone()); #[cfg(target_os = "macos")] { @@ -286,6 +323,7 @@ pub fn run() { .get_handle() .get_webview_window("main") { + logging!(info, Type::Window, true, "设置macOS窗口标题"); let _ = window.set_title("Clash Verge"); } } @@ -323,8 +361,11 @@ pub fn run() { } println!("closing window..."); api.prevent_close(); - let window = core::handle::Handle::global().get_window().unwrap(); - let _ = window.hide(); + if let Some(window) = core::handle::Handle::global().get_window() { + let _ = window.hide(); + } else { + logging!(warn, Type::Window, true, "尝试隐藏窗口但窗口不存在"); + } } tauri::WindowEvent::Focused(true) => { #[cfg(target_os = "macos")] diff --git a/clash-verge-rev/src-tauri/src/module/lightweight.rs b/clash-verge-rev/src-tauri/src/module/lightweight.rs index 690a2ad1e7..d8033f17ba 100644 --- a/clash-verge-rev/src-tauri/src/module/lightweight.rs +++ b/clash-verge-rev/src-tauri/src/module/lightweight.rs @@ -16,8 +16,6 @@ use std::{ }; use tauri::{Listener, Manager}; -pub static AUTO_LIGHT_WEIGHT_MODE_INIT: OnceCell<()> = OnceCell::new(); - const LIGHT_WEIGHT_TASK_UID: &str = "light_weight_task"; // 轻量模式状态标志 @@ -217,19 +215,3 @@ fn cancel_light_weight_timer() -> Result<()> { Ok(()) } - -pub fn run_once_auto_lightweight() { - AUTO_LIGHT_WEIGHT_MODE_INIT.get_or_init(|| { - let is_silent_start = { Config::verge().data().enable_silent_start }.unwrap_or(false); - let enable_auto = { Config::verge().data().enable_auto_light_weight_mode }.unwrap_or(false); - if enable_auto && is_silent_start { - logging!( - info, - Type::Lightweight, - true, - "Add timer listener when creating window in silent start mode" - ); - enable_auto_light_weight_mode(); - } - }); -} diff --git a/clash-verge-rev/src-tauri/src/utils/dirs.rs b/clash-verge-rev/src-tauri/src/utils/dirs.rs index ec54b37c8a..5669a5dbdb 100644 --- a/clash-verge-rev/src-tauri/src/utils/dirs.rs +++ b/clash-verge-rev/src-tauri/src/utils/dirs.rs @@ -49,12 +49,60 @@ pub fn app_home_dir() -> Result { .ok_or(anyhow::anyhow!("failed to get the portable app dir"))?; return Ok(PathBuf::from(app_dir).join(".config").join(APP_ID)); } - let app_handle = handle::Handle::global().app_handle().unwrap(); + + // 避免在Handle未初始化时崩溃 + let app_handle = match handle::Handle::global().app_handle() { + Some(handle) => handle, + None => { + log::warn!(target: "app", "app_handle not initialized, using default path"); + // 使用可执行文件目录作为备用 + let exe_path = tauri::utils::platform::current_exe()?; + let exe_dir = exe_path + .parent() + .ok_or(anyhow::anyhow!("failed to get executable directory"))?; + + // 使用系统临时目录 + 应用ID + #[cfg(target_os = "windows")] + { + if let Some(local_app_data) = std::env::var_os("LOCALAPPDATA") { + let path = PathBuf::from(local_app_data).join(APP_ID); + return Ok(path); + } + } + + #[cfg(target_os = "macos")] + { + if let Some(home) = std::env::var_os("HOME") { + let path = PathBuf::from(home) + .join("Library") + .join("Application Support") + .join(APP_ID); + return Ok(path); + } + } + + #[cfg(target_os = "linux")] + { + if let Some(home) = std::env::var_os("HOME") { + let path = PathBuf::from(home) + .join(".local") + .join("share") + .join(APP_ID); + return Ok(path); + } + } + + // 如果无法获取系统目录,则回退到可执行文件目录 + let fallback_dir = PathBuf::from(exe_dir).join(".config").join(APP_ID); + log::warn!(target: "app", "Using fallback data directory: {:?}", fallback_dir); + return Ok(fallback_dir); + } + }; match app_handle.path().data_dir() { Ok(dir) => Ok(dir.join(APP_ID)), Err(e) => { - log::error!(target:"app", "Failed to get the app home directory: {}", e); + log::error!(target: "app", "Failed to get the app home directory: {}", e); Err(anyhow::anyhow!("Failed to get the app homedirectory")) } } @@ -62,11 +110,24 @@ pub fn app_home_dir() -> Result { /// get the resources dir pub fn app_resources_dir() -> Result { - let app_handle = handle::Handle::global().app_handle().unwrap(); + // 避免在Handle未初始化时崩溃 + let app_handle = match handle::Handle::global().app_handle() { + Some(handle) => handle, + None => { + log::warn!(target: "app", "app_handle not initialized in app_resources_dir, using fallback"); + // 使用可执行文件目录作为备用 + let exe_dir = tauri::utils::platform::current_exe()? + .parent() + .ok_or(anyhow::anyhow!("failed to get executable directory"))? + .to_path_buf(); + return Ok(exe_dir.join("resources")); + } + }; + match app_handle.path().resource_dir() { Ok(dir) => Ok(dir.join("resources")), Err(e) => { - log::error!(target:"app", "Failed to get the resource directory: {}", e); + log::error!(target: "app", "Failed to get the resource directory: {}", e); Err(anyhow::anyhow!("Failed to get the resource directory")) } } @@ -126,12 +187,14 @@ pub fn profiles_path() -> Result { #[cfg(target_os = "macos")] pub fn service_path() -> Result { - Ok(app_resources_dir()?.join("clash-verge-service")) + let res_dir = app_resources_dir()?; + Ok(res_dir.join("clash-verge-service")) } #[cfg(windows)] pub fn service_path() -> Result { - Ok(app_resources_dir()?.join("clash-verge-service.exe")) + let res_dir = app_resources_dir()?; + Ok(res_dir.join("clash-verge-service.exe")) } pub fn service_log_file() -> Result { diff --git a/clash-verge-rev/src-tauri/src/utils/error.rs b/clash-verge-rev/src-tauri/src/utils/error.rs deleted file mode 100644 index d661b6099c..0000000000 --- a/clash-verge-rev/src-tauri/src/utils/error.rs +++ /dev/null @@ -1,40 +0,0 @@ -use crate::log_err; -use anyhow; -use std::{ - backtrace::{Backtrace, BacktraceStatus}, - thread, -}; - -pub fn redirect_panic_to_log() { - std::panic::set_hook(Box::new(move |panic_info| { - let thread = thread::current(); - let thread_name = thread.name().unwrap_or(""); - let payload = panic_info.payload(); - - let payload = if let Some(s) = payload.downcast_ref::<&str>() { - &**s - } else if let Some(s) = payload.downcast_ref::() { - s - } else { - &format!("{:?}", payload) - }; - - let location = panic_info - .location() - .map(|l| l.to_string()) - .unwrap_or("unknown location".to_string()); - - let backtrace = Backtrace::capture(); - let backtrace = if backtrace.status() == BacktraceStatus::Captured { - &format!("stack backtrace:\n{}", backtrace) - } else { - "note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace" - }; - - let err: Result<(), anyhow::Error> = Err(anyhow::anyhow!(format!( - "thread '{}' panicked at {}:\n{}\n{}", - thread_name, location, payload, backtrace - ))); - log_err!(err); - })); -} diff --git a/clash-verge-rev/src-tauri/src/utils/mod.rs b/clash-verge-rev/src-tauri/src/utils/mod.rs index 698b499a9d..6a0a09fb53 100644 --- a/clash-verge-rev/src-tauri/src/utils/mod.rs +++ b/clash-verge-rev/src-tauri/src/utils/mod.rs @@ -1,6 +1,5 @@ pub mod autostart; pub mod dirs; -pub mod error; pub mod help; pub mod i18n; pub mod init; diff --git a/clash-verge-rev/src-tauri/src/utils/network.rs b/clash-verge-rev/src-tauri/src/utils/network.rs index 9a4cce3815..542e2ef9e1 100644 --- a/clash-verge-rev/src-tauri/src/utils/network.rs +++ b/clash-verge-rev/src-tauri/src/utils/network.rs @@ -128,118 +128,118 @@ impl NetworkManager { *error_count = 0; } } + /* + /// 获取或创建自代理客户端 + fn get_or_create_self_proxy_client(&self) -> Client { + if self.should_reset_clients() { + self.reset_clients(); + } - /// 获取或创建自代理客户端 - fn get_or_create_self_proxy_client(&self) -> Client { - if self.should_reset_clients() { - self.reset_clients(); - } + let mut client_guard = self.self_proxy_client.lock().unwrap(); - let mut client_guard = self.self_proxy_client.lock().unwrap(); + if client_guard.is_none() { + let port = Config::verge() + .latest() + .verge_mixed_port + .unwrap_or(Config::clash().data().get_mixed_port()); - if client_guard.is_none() { - let port = Config::verge() - .latest() - .verge_mixed_port - .unwrap_or(Config::clash().data().get_mixed_port()); + let proxy_scheme = format!("http://127.0.0.1:{port}"); - let proxy_scheme = format!("http://127.0.0.1:{port}"); + let mut builder = ClientBuilder::new() + .use_rustls_tls() + .pool_max_idle_per_host(POOL_MAX_IDLE_PER_HOST) + .pool_idle_timeout(POOL_IDLE_TIMEOUT) + .connect_timeout(DEFAULT_CONNECT_TIMEOUT) + .timeout(DEFAULT_REQUEST_TIMEOUT) + .http2_initial_stream_window_size(H2_STREAM_WINDOW_SIZE) + .http2_initial_connection_window_size(H2_CONNECTION_WINDOW_SIZE) + .http2_adaptive_window(true) + .http2_keep_alive_interval(Some(H2_KEEP_ALIVE_INTERVAL)) + .http2_keep_alive_timeout(H2_KEEP_ALIVE_TIMEOUT) + .http2_max_frame_size(H2_MAX_FRAME_SIZE) + .tcp_keepalive(Some(Duration::from_secs(10))) + .http2_prior_knowledge() + .http2_max_header_list_size(16 * 1024); - let mut builder = ClientBuilder::new() - .use_rustls_tls() - .pool_max_idle_per_host(POOL_MAX_IDLE_PER_HOST) - .pool_idle_timeout(POOL_IDLE_TIMEOUT) - .connect_timeout(DEFAULT_CONNECT_TIMEOUT) - .timeout(DEFAULT_REQUEST_TIMEOUT) - .http2_initial_stream_window_size(H2_STREAM_WINDOW_SIZE) - .http2_initial_connection_window_size(H2_CONNECTION_WINDOW_SIZE) - .http2_adaptive_window(true) - .http2_keep_alive_interval(Some(H2_KEEP_ALIVE_INTERVAL)) - .http2_keep_alive_timeout(H2_KEEP_ALIVE_TIMEOUT) - .http2_max_frame_size(H2_MAX_FRAME_SIZE) - .tcp_keepalive(Some(Duration::from_secs(10))) - .http2_prior_knowledge() - .http2_max_header_list_size(16 * 1024); + if let Ok(proxy) = Proxy::http(&proxy_scheme) { + builder = builder.proxy(proxy); + } + if let Ok(proxy) = Proxy::https(&proxy_scheme) { + builder = builder.proxy(proxy); + } + if let Ok(proxy) = Proxy::all(&proxy_scheme) { + builder = builder.proxy(proxy); + } - if let Ok(proxy) = Proxy::http(&proxy_scheme) { - builder = builder.proxy(proxy); - } - if let Ok(proxy) = Proxy::https(&proxy_scheme) { - builder = builder.proxy(proxy); - } - if let Ok(proxy) = Proxy::all(&proxy_scheme) { - builder = builder.proxy(proxy); - } + let client = builder.build().expect("Failed to build self_proxy client"); + *client_guard = Some(client); + } - let client = builder.build().expect("Failed to build self_proxy client"); - *client_guard = Some(client); - } + client_guard.as_ref().unwrap().clone() + } - client_guard.as_ref().unwrap().clone() - } + /// 获取或创建系统代理客户端 + fn get_or_create_system_proxy_client(&self) -> Client { + if self.should_reset_clients() { + self.reset_clients(); + } - /// 获取或创建系统代理客户端 - fn get_or_create_system_proxy_client(&self) -> Client { - if self.should_reset_clients() { - self.reset_clients(); - } + let mut client_guard = self.system_proxy_client.lock().unwrap(); - let mut client_guard = self.system_proxy_client.lock().unwrap(); + if client_guard.is_none() { + use sysproxy::Sysproxy; - if client_guard.is_none() { - use sysproxy::Sysproxy; + let mut builder = ClientBuilder::new() + .use_rustls_tls() + .pool_max_idle_per_host(POOL_MAX_IDLE_PER_HOST) + .pool_idle_timeout(POOL_IDLE_TIMEOUT) + .connect_timeout(DEFAULT_CONNECT_TIMEOUT) + .timeout(DEFAULT_REQUEST_TIMEOUT) + .http2_initial_stream_window_size(H2_STREAM_WINDOW_SIZE) + .http2_initial_connection_window_size(H2_CONNECTION_WINDOW_SIZE) + .http2_adaptive_window(true) + .http2_keep_alive_interval(Some(H2_KEEP_ALIVE_INTERVAL)) + .http2_keep_alive_timeout(H2_KEEP_ALIVE_TIMEOUT) + .http2_max_frame_size(H2_MAX_FRAME_SIZE) + .tcp_keepalive(Some(Duration::from_secs(10))) + .http2_prior_knowledge() + .http2_max_header_list_size(16 * 1024); - let mut builder = ClientBuilder::new() - .use_rustls_tls() - .pool_max_idle_per_host(POOL_MAX_IDLE_PER_HOST) - .pool_idle_timeout(POOL_IDLE_TIMEOUT) - .connect_timeout(DEFAULT_CONNECT_TIMEOUT) - .timeout(DEFAULT_REQUEST_TIMEOUT) - .http2_initial_stream_window_size(H2_STREAM_WINDOW_SIZE) - .http2_initial_connection_window_size(H2_CONNECTION_WINDOW_SIZE) - .http2_adaptive_window(true) - .http2_keep_alive_interval(Some(H2_KEEP_ALIVE_INTERVAL)) - .http2_keep_alive_timeout(H2_KEEP_ALIVE_TIMEOUT) - .http2_max_frame_size(H2_MAX_FRAME_SIZE) - .tcp_keepalive(Some(Duration::from_secs(10))) - .http2_prior_knowledge() - .http2_max_header_list_size(16 * 1024); + if let Ok(p @ Sysproxy { enable: true, .. }) = Sysproxy::get_system_proxy() { + let proxy_scheme = format!("http://{}:{}", p.host, p.port); - if let Ok(p @ Sysproxy { enable: true, .. }) = Sysproxy::get_system_proxy() { - let proxy_scheme = format!("http://{}:{}", p.host, p.port); + if let Ok(proxy) = Proxy::http(&proxy_scheme) { + builder = builder.proxy(proxy); + } + if let Ok(proxy) = Proxy::https(&proxy_scheme) { + builder = builder.proxy(proxy); + } + if let Ok(proxy) = Proxy::all(&proxy_scheme) { + builder = builder.proxy(proxy); + } + } - if let Ok(proxy) = Proxy::http(&proxy_scheme) { - builder = builder.proxy(proxy); - } - if let Ok(proxy) = Proxy::https(&proxy_scheme) { - builder = builder.proxy(proxy); - } - if let Ok(proxy) = Proxy::all(&proxy_scheme) { - builder = builder.proxy(proxy); - } - } + let client = builder + .build() + .expect("Failed to build system_proxy client"); + *client_guard = Some(client); + } - let client = builder - .build() - .expect("Failed to build system_proxy client"); - *client_guard = Some(client); - } - - client_guard.as_ref().unwrap().clone() - } - - /// 根据代理设置选择合适的客户端 - pub fn get_client(&self, proxy_type: ProxyType) -> Client { - match proxy_type { - ProxyType::NoProxy => { - let client_guard = self.no_proxy_client.lock().unwrap(); - client_guard.as_ref().unwrap().clone() - } - ProxyType::SelfProxy => self.get_or_create_self_proxy_client(), - ProxyType::SystemProxy => self.get_or_create_system_proxy_client(), - } - } + client_guard.as_ref().unwrap().clone() + } + /// 根据代理设置选择合适的客户端 + pub fn get_client(&self, proxy_type: ProxyType) -> Client { + match proxy_type { + ProxyType::NoProxy => { + let client_guard = self.no_proxy_client.lock().unwrap(); + client_guard.as_ref().unwrap().clone() + } + ProxyType::SelfProxy => self.get_or_create_self_proxy_client(), + ProxyType::SystemProxy => self.get_or_create_system_proxy_client(), + } + } + */ /// 创建带有自定义选项的HTTP请求 pub fn create_request( &self, @@ -335,7 +335,7 @@ impl NetworkManager { client.get(url) } - /// 执行GET请求,添加错误跟踪 + /* /// 执行GET请求,添加错误跟踪 pub async fn get( &self, url: &str, @@ -370,7 +370,7 @@ impl NetworkManager { )) } } - } + } */ pub async fn get_with_interrupt( &self, diff --git a/clash-verge-rev/src-tauri/src/utils/resolve.rs b/clash-verge-rev/src-tauri/src/utils/resolve.rs index 1bb9b4a33e..71d9f937d6 100644 --- a/clash-verge-rev/src-tauri/src/utils/resolve.rs +++ b/clash-verge-rev/src-tauri/src/utils/resolve.rs @@ -1,12 +1,10 @@ -#[cfg(target_os = "macos")] -use crate::AppHandleManager; use crate::{ config::{Config, IVerge, PrfItem}, core::*, logging, logging_error, module::lightweight, process::AsyncHandler, - utils::{dirs, error, init, logging::Type, server}, + utils::{init, logging::Type, server}, wrap_err, }; use anyhow::{bail, Result}; @@ -14,14 +12,13 @@ use once_cell::sync::OnceCell; use parking_lot::{Mutex, RwLock}; use percent_encoding::percent_decode_str; use serde::{Deserialize, Serialize}; -use serde_json; use serde_yaml::Mapping; use std::{ net::TcpListener, sync::Arc, time::{Duration, Instant}, }; -use tauri::{App, Emitter, Manager}; +use tauri::{AppHandle, Emitter, Manager}; use tauri::Url; //#[cfg(not(target_os = "linux"))] @@ -29,10 +26,6 @@ use tauri::Url; pub static VERSION: OnceCell = OnceCell::new(); -// 窗口状态文件中的尺寸 -static STATE_WIDTH: OnceCell = OnceCell::new(); -static STATE_HEIGHT: OnceCell = OnceCell::new(); - // 定义默认窗口尺寸常量 const DEFAULT_WIDTH: u32 = 900; const DEFAULT_HEIGHT: u32 = 700; @@ -43,6 +36,35 @@ static UI_READY: OnceCell>> = OnceCell::new(); // 窗口创建锁,防止并发创建窗口 static WINDOW_CREATING: OnceCell> = OnceCell::new(); +// UI就绪阶段状态枚举 +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum UiReadyStage { + NotStarted, + Loading, + DomReady, + ResourcesLoaded, + Ready, +} + +// UI就绪详细状态 +#[derive(Debug)] +struct UiReadyState { + stage: RwLock, + last_update: RwLock, +} + +impl Default for UiReadyState { + fn default() -> Self { + Self { + stage: RwLock::new(UiReadyStage::NotStarted), + last_update: RwLock::new(Instant::now()), + } + } +} + +// 获取UI就绪状态细节 +static UI_READY_STATE: OnceCell> = OnceCell::new(); + // 定义窗口状态结构体 #[derive(Debug, Serialize, Deserialize)] struct WindowState { @@ -58,16 +80,54 @@ fn get_ui_ready() -> &'static Arc> { UI_READY.get_or_init(|| Arc::new(RwLock::new(false))) } +fn get_ui_ready_state() -> &'static Arc { + UI_READY_STATE.get_or_init(|| Arc::new(UiReadyState::default())) +} + +// 更新UI准备阶段 +pub fn update_ui_ready_stage(stage: UiReadyStage) { + let state = get_ui_ready_state(); + let mut stage_lock = state.stage.write(); + let mut time_lock = state.last_update.write(); + + *stage_lock = stage; + *time_lock = Instant::now(); + + logging!( + info, + Type::Window, + true, + "UI准备阶段更新: {:?}, 耗时: {:?}ms", + stage, + time_lock.elapsed().as_millis() + ); + + // 如果是最终阶段,标记UI完全就绪 + if stage == UiReadyStage::Ready { + mark_ui_ready(); + } +} + // 标记UI已准备就绪 pub fn mark_ui_ready() { let mut ready = get_ui_ready().write(); *ready = true; + logging!(info, Type::Window, true, "UI已标记为完全就绪"); } // 重置UI就绪状态 pub fn reset_ui_ready() { - let mut ready = get_ui_ready().write(); - *ready = false; + { + let mut ready = get_ui_ready().write(); + *ready = false; + } + { + let state = get_ui_ready_state(); + let mut stage = state.stage.write(); + let mut time = state.last_update.write(); + *stage = UiReadyStage::NotStarted; + *time = Instant::now(); + } logging!(info, Type::Window, true, "UI就绪状态已重置"); } @@ -88,54 +148,53 @@ pub fn find_unused_port() -> Result { } } -/// handle something when start app -pub async fn resolve_setup(app: &mut App) { - error::redirect_panic_to_log(); - #[cfg(target_os = "macos")] - { - AppHandleManager::global().init(app.app_handle().clone()); - AppHandleManager::global().set_activation_policy_accessory(); +/// 异步方式处理启动后的额外任务 +pub async fn resolve_setup_async(app_handle: &AppHandle) { + logging!(info, Type::Setup, true, "执行异步设置任务..."); + + if VERSION.get().is_none() { + let version = app_handle.package_info().version.to_string(); + VERSION.get_or_init(|| { + logging!(info, Type::Setup, true, "初始化版本信息: {}", version); + version.clone() + }); } - let version = app.package_info().version.to_string(); - handle::Handle::global().init(app.app_handle()); - VERSION.get_or_init(|| version.clone()); - - logging_error!(Type::Config, true, init::init_config()); - logging_error!(Type::Setup, true, init::init_resources()); logging_error!(Type::Setup, true, init::init_scheme()); + logging_error!(Type::Setup, true, init::startup_script().await); - // 诊断服务状态 - /* logging!(info, Type::Service, true, "执行服务状态诊断"); - { - match crate::core::service::diagnose_service().await { - Ok(_) => { - logging!(info, Type::Service, true, "服务诊断完成"); - }, - Err(e) => { - logging!(error, Type::Service, true, "服务诊断出错: {}", e); - }, - } - } */ - - // 处理随机端口 logging_error!(Type::System, true, resolve_random_port_config()); - // 启动核心 - logging!(trace, Type::Config, true, "Initial config"); + + logging!(trace, Type::Config, true, "初始化配置..."); logging_error!(Type::Config, true, Config::init_config().await); - logging!(trace, Type::Core, "Starting CoreManager"); + logging!(trace, Type::Core, true, "启动核心管理器..."); logging_error!(Type::Core, true, CoreManager::global().init().await); - // setup a simple http server for singleton - log::trace!(target: "app", "launch embed server"); + log::trace!(target: "app", "启动内嵌服务器..."); server::embed_server(); - log::trace!(target: "app", "Initial system tray"); logging_error!(Type::Tray, true, tray::Tray::global().init()); - logging_error!(Type::Tray, true, tray::Tray::global().create_systray(app)); + if let Some(app_handle) = handle::Handle::global().app_handle() { + logging!(info, Type::Tray, true, "创建系统托盘..."); + let result = tray::Tray::global().create_tray_from_handle(&app_handle); + if result.is_ok() { + logging!(info, Type::Tray, true, "系统托盘创建成功"); + } else if let Err(e) = result { + logging!(error, Type::Tray, true, "系统托盘创建失败: {}", e); + } + } else { + logging!( + error, + Type::Tray, + true, + "无法创建系统托盘: app_handle不存在" + ); + } + + // 更新系统代理 logging_error!( Type::System, true, @@ -147,11 +206,14 @@ pub async fn resolve_setup(app: &mut App) { sysopt::Sysopt::global().init_guard_sysproxy() ); + // 创建窗口 let is_silent_start = { Config::verge().data().enable_silent_start }.unwrap_or(false); create_window(!is_silent_start); + // 初始化定时器 logging_error!(Type::System, true, timer::Timer::global().init()); + // 自动进入轻量模式 let enable_auto_light_weight_mode = { Config::verge().data().enable_auto_light_weight_mode }.unwrap_or(false); if enable_auto_light_weight_mode && !is_silent_start { @@ -160,12 +222,13 @@ pub async fn resolve_setup(app: &mut App) { logging_error!(Type::Tray, true, tray::Tray::global().update_part()); - // 初始化热键 - logging!(trace, Type::System, true, "Initial hotkeys"); + logging!(trace, Type::System, true, "初始化热键..."); logging_error!(Type::System, true, hotkey::Hotkey::global().init()); + + logging!(info, Type::Setup, true, "异步设置任务完成"); } -/// reset system proxy (异步版) +/// reset system proxy (异步) pub async fn resolve_reset_async() { #[cfg(target_os = "macos")] logging!(info, Type::Tray, true, "Unsubscribing from traffic updates"); @@ -185,321 +248,135 @@ pub async fn resolve_reset_async() { } } -/// 窗口创建锁守卫 -struct WindowCreateGuard; +/// Create the main window +pub fn create_window(is_show: bool) -> bool { + logging!( + info, + Type::Window, + true, + "开始创建主窗口, is_show={}", + is_show + ); -impl Drop for WindowCreateGuard { - fn drop(&mut self) { - let mut lock = get_window_creating_lock().lock(); - lock.0 = false; - logging!(info, Type::Window, true, "窗口创建过程已完成,释放锁"); - } -} + let creating_lock = get_window_creating_lock(); + let mut creating = creating_lock.lock(); -/// create main window -pub fn create_window(is_showup: bool) { - // 尝试获取窗口创建锁 - let mut creating_lock = get_window_creating_lock().lock(); - let (is_creating, last_create_time) = *creating_lock; - let now = Instant::now(); + let (is_creating, last_time) = *creating; + let elapsed = last_time.elapsed(); - // 检查是否有其他线程正在创建窗口,防止短时间内多次创建窗口导致竞态条件 - if is_creating && now.duration_since(last_create_time) < Duration::from_secs(2) { + if is_creating && elapsed < Duration::from_secs(2) { logging!( - warn, + info, Type::Window, true, - "另一个窗口创建过程正在进行中,跳过本次创建请求" + "窗口创建请求被忽略,因为最近创建过 ({:?}ms)", + elapsed.as_millis() ); - return; + return false; } - *creating_lock = (true, now); - drop(creating_lock); + *creating = (true, Instant::now()); - // 创建窗口锁守卫结束时自动释放锁 - let _guard = WindowCreateGuard; - - // 打印 .window-state.json 文件路径 - let window_state_file = dirs::app_home_dir() - .ok() - .map(|dir| dir.join(".window-state.json")); - logging!( - info, - Type::Window, - true, - "窗口状态文件路径: {:?}", - window_state_file - ); - - // 从文件加载窗口状态 - if let Some(window_state_file_path) = window_state_file { - if window_state_file_path.exists() { - match std::fs::read_to_string(&window_state_file_path) { - Ok(content) => { - logging!( - debug, - Type::Window, - true, - "读取窗口状态文件内容成功: {} 字节", - content.len() - ); - - match serde_json::from_str::(&content) { - Ok(window_state) => { - logging!( - info, - Type::Window, - true, - "成功解析窗口状态: width={:?}, height={:?}", - window_state.width, - window_state.height - ); - - // 存储窗口状态以供后续使用 - if let Some(width) = window_state.width { - STATE_WIDTH.set(width).ok(); - } - if let Some(height) = window_state.height { - STATE_HEIGHT.set(height).ok(); - } - } - Err(e) => { - logging!(error, Type::Window, true, "解析窗口状态文件失败: {:?}", e); - } - } - } - Err(e) => { - logging!(error, Type::Window, true, "读取窗口状态文件失败: {:?}", e); - } - } - } else { - logging!( - info, - Type::Window, - true, - "窗口状态文件不存在,将使用默认设置" - ); - } - } - - if !is_showup { - logging!(info, Type::Window, "Not to display create window"); - return; - } - - logging!(info, Type::Window, true, "Creating window"); - - let app_handle = handle::Handle::global().app_handle().unwrap(); - #[cfg(target_os = "macos")] - AppHandleManager::global().set_activation_policy_regular(); - - // 检查是否从轻量模式恢复 - let from_lightweight = crate::module::lightweight::is_in_lightweight_mode(); - if from_lightweight { - logging!(info, Type::Window, true, "从轻量模式恢复窗口"); - crate::module::lightweight::exit_lightweight_mode(); - } - - if let Some(window) = handle::Handle::global().get_window() { - logging!(info, Type::Window, true, "Found existing window"); - - if window.is_minimized().unwrap_or(false) { - let _ = window.unminimize(); - } - - if from_lightweight { - // 从轻量模式恢复需要销毁旧窗口以重建 - logging!(info, Type::Window, true, "销毁旧窗口以重建新窗口"); - let _ = window.close(); - - // 添加短暂延迟确保窗口正确关闭 - std::thread::sleep(std::time::Duration::from_millis(100)); - } else { - // 普通情况直接显示窗口 - let _ = window.show(); - let _ = window.set_focus(); - return; - } - } - - let width = STATE_WIDTH.get().copied().unwrap_or(DEFAULT_WIDTH); - let height = STATE_HEIGHT.get().copied().unwrap_or(DEFAULT_HEIGHT); - - logging!( - info, - Type::Window, - true, - "Initializing new window with size: {}x{}", - width, - height - ); - - // 根据不同平台创建不同配置的窗口 - #[cfg(target_os = "macos")] - let win_builder = { - // 基本配置 - let builder = tauri::WebviewWindowBuilder::new( - &app_handle, - "main", - tauri::WebviewUrl::App("index.html".into()), - ) - .title("Clash Verge") - .center() - .decorations(true) - .hidden_title(true) // 隐藏标题文本 - .fullscreen(false) - .inner_size(width as f64, height as f64) - .min_inner_size(520.0, 520.0) - .visible(false); - - // 尝试设置标题栏样式 - // 注意:根据Tauri版本不同,此API可能有变化 - // 如果编译出错,请注释掉下面这行 - let builder = builder.title_bar_style(tauri::TitleBarStyle::Overlay); - - builder - }; - - #[cfg(not(target_os = "macos"))] - let win_builder = tauri::WebviewWindowBuilder::new( - &app_handle, - "main", + match tauri::WebviewWindowBuilder::new( + &handle::Handle::global().app_handle().unwrap(), + "main", /* the unique window label */ tauri::WebviewUrl::App("index.html".into()), ) .title("Clash Verge") .center() + .decorations(true) .fullscreen(false) - .inner_size(width as f64, height as f64) + .inner_size(DEFAULT_WIDTH as f64, DEFAULT_HEIGHT as f64) .min_inner_size(520.0, 520.0) .visible(false) - .decorations(false); + .build() + { + Ok(_) => { + logging!(info, Type::Window, true, "主窗口创建成功"); - let window = win_builder.build(); + *creating = (false, Instant::now()); - match window { - Ok(window) => { - logging!(info, Type::Window, true, "Window created successfully"); - - // 静默启动模式等窗口初始化再启动自动进入轻量模式的计时监听器,防止初始化的时候找不到窗口对象导致监听器挂载失败 - lightweight::run_once_auto_lightweight(); - - // 标记前端UI已准备就绪,向前端发送启动完成事件 - let app_handle_clone = app_handle.clone(); - - // 获取窗口创建后的初始大小 - if let Ok(size) = window.inner_size() { - let state_width = STATE_WIDTH.get().copied().unwrap_or(DEFAULT_WIDTH); - let state_height = STATE_HEIGHT.get().copied().unwrap_or(DEFAULT_HEIGHT); - - // 输出所有尺寸信息 - logging!( - info, - Type::Window, - true, - "API报告的窗口尺寸: {}x{}, 状态文件尺寸: {}x{}, 默认尺寸: {}x{}", - size.width, - size.height, - state_width, - state_height, - DEFAULT_WIDTH, - DEFAULT_HEIGHT - ); - - // 优化窗口大小设置 - if size.width < state_width || size.height < state_height { - logging!( - info, - Type::Window, - true, - "强制设置窗口尺寸: {}x{}", - state_width, - state_height - ); - - // 尝试不同的方式设置窗口大小 - let _ = window.set_size(tauri::PhysicalSize { - width: state_width, - height: state_height, - }); - - // 关键:等待短暂时间让窗口尺寸生效 - std::thread::sleep(std::time::Duration::from_millis(50)); - - // 再次检查窗口尺寸 - if let Ok(new_size) = window.inner_size() { - logging!( - info, - Type::Window, - true, - "设置后API报告的窗口尺寸: {}x{}", - new_size.width, - new_size.height - ); - } - } - } - - // 标记此窗口是否从轻量模式恢复 - let was_from_lightweight = from_lightweight; + update_ui_ready_stage(UiReadyStage::NotStarted); AsyncHandler::spawn(move || async move { - // 处理启动完成 handle::Handle::global().mark_startup_completed(); + logging!(info, Type::Window, true, "标记启动完成"); - if let Some(window) = app_handle_clone.get_webview_window("main") { - // 发送启动完成事件 - let _ = window.emit("verge://startup-completed", ()); + if let Some(app_handle) = handle::Handle::global().app_handle() { + if let Some(window) = app_handle.get_webview_window("main") { + let _ = window.emit("verge://startup-completed", ()); + logging!(info, Type::Window, true, "已发送启动完成事件"); - if is_showup { - let window_clone = window.clone(); + if is_show { + let window_clone = window.clone(); - // 从轻量模式恢复时使用较短的超时,避免卡死 - let timeout_seconds = if was_from_lightweight { - // 从轻量模式恢复只等待2秒,确保不会卡死 - 2 - } else { - 5 - }; + let timeout_seconds = + if crate::module::lightweight::is_in_lightweight_mode() { + 2 + } else { + 5 + }; - // 使用普通的等待方式替代事件监听,简化实现 - let wait_result = - tokio::time::timeout(Duration::from_secs(timeout_seconds), async { - while !*get_ui_ready().read() { - tokio::time::sleep(Duration::from_millis(100)).await; + logging!( + info, + Type::Window, + true, + "等待UI就绪,最多{}秒", + timeout_seconds + ); + + let wait_result = + tokio::time::timeout(Duration::from_secs(timeout_seconds), async { + let mut check_count = 0; + while !*get_ui_ready().read() { + check_count += 1; + if check_count % 10 == 0 { + let state = get_ui_ready_state(); + let stage = *state.stage.read(); + logging!( + info, + Type::Window, + true, + "等待UI就绪中... 当前阶段: {:?}, 已等待: {}ms", + stage, + check_count * 100 + ); + } + tokio::time::sleep(Duration::from_millis(100)).await; + } + }) + .await; + + match wait_result { + Ok(_) => { + logging!(info, Type::Window, true, "UI就绪,显示窗口"); } - }) - .await; + Err(_) => { + logging!( + warn, + Type::Window, + true, + "等待UI就绪超时({}秒),强制显示窗口", + timeout_seconds + ); - // 根据结果处理 - match wait_result { - Ok(_) => { - logging!(info, Type::Window, true, "UI就绪,显示窗口"); - } - Err(_) => { - logging!( - warn, - Type::Window, - true, - "等待UI就绪超时({}秒),强制显示窗口", - timeout_seconds - ); - // 强制设置UI就绪状态 - *get_ui_ready().write() = true; + *get_ui_ready().write() = true; + } } + + let _ = window_clone.show(); + let _ = window_clone.set_focus(); + + logging!(info, Type::Window, true, "窗口创建和显示流程已完成"); } - - // 显示窗口 - let _ = window_clone.show(); - let _ = window_clone.set_focus(); - - logging!(info, Type::Window, true, "窗口创建和显示流程已完成"); } } }); + true } Err(e) => { logging!(error, Type::Window, true, "Failed to create window: {}", e); + false } } } @@ -529,7 +406,6 @@ pub async fn resolve_scheme(param: String) -> Result<()> { .find(|(key, _)| key == "name") .map(|(_, value)| value.into_owned()); - // 通过直接获取查询部分并解析特定参数来避免 URL 转义问题 let url_param = if let Some(query) = link_parsed.query() { let prefix = "url="; if let Some(pos) = query.find(prefix) { diff --git a/clash-verge-rev/src/pages/_layout.tsx b/clash-verge-rev/src/pages/_layout.tsx index ee8aa321c8..44f73e0fe0 100644 --- a/clash-verge-rev/src/pages/_layout.tsx +++ b/clash-verge-rev/src/pages/_layout.tsx @@ -165,7 +165,6 @@ const Layout = () => { useEffect(() => { if (clashInfo) { const { server = "", secret = "" } = clashInfo; - // 使用本地存储中的enableLog值初始化全局日志服务 initGlobalLogService(server, secret, enableLog, "info"); } }, [clashInfo, enableLog]); @@ -173,7 +172,6 @@ const Layout = () => { // 设置监听器 useEffect(() => { const listeners = [ - // 配置更新监听 addListener("verge://refresh-clash-config", async () => { await getAxios(true); mutate("getProxies"); @@ -182,21 +180,17 @@ const Layout = () => { mutate("getProxyProviders"); }), - // verge 配置更新监听 addListener("verge://refresh-verge-config", () => { mutate("getVergeConfig"); - // 添加对系统代理状态的刷新 mutate("getSystemProxy"); mutate("getAutotemProxy"); }), - // 通知消息监听 addListener("verge://notice-message", ({ payload }) => handleNotice(payload as [string, string]), ), ]; - // 设置窗口显示/隐藏监听 const setupWindowListeners = async () => { const [hideUnlisten, showUnlisten] = await Promise.all([ listen("verge://hide-window", () => appWindow.hide()), @@ -209,29 +203,51 @@ const Layout = () => { }; }; - // 初始化 setupCloseListener(); const cleanupWindow = setupWindowListeners(); - // 清理函数 return () => { - // 清理主要监听器 listeners.forEach((listener) => { if (typeof listener.then === "function") { listener.then((unlisten) => unlisten()); } }); - // 清理窗口监听器 cleanupWindow.then((cleanup) => cleanup()); }; }, [handleNotice]); - // 监听启动完成事件并通知UI已加载 useEffect(() => { + const notifyUiStage = async (stage: string) => { + try { + console.log(`UI加载阶段: ${stage}`); + await invoke("update_ui_stage", { stage }); + } catch (err) { + console.error(`通知UI加载阶段(${stage})失败:`, err); + } + }; + + const notifyUiCoreReady = async () => { + try { + console.log("核心组件已加载,通知后端"); + await invoke("update_ui_stage", { stage: "DomReady" }); + } catch (err) { + console.error("通知核心组件加载完成失败:", err); + } + }; + + const notifyUiResourcesLoaded = async () => { + try { + console.log("所有资源已加载,通知后端"); + await invoke("update_ui_stage", { stage: "ResourcesLoaded" }); + } catch (err) { + console.error("通知资源加载完成失败:", err); + } + }; + const notifyUiReady = async () => { try { + console.log("UI完全准备就绪,通知后端"); await invoke("notify_ui_ready"); - console.log("已通知后端UI准备就绪"); } catch (err) { console.error("通知UI准备就绪失败:", err); } @@ -240,6 +256,7 @@ const Layout = () => { // 监听后端发送的启动完成事件 const listenStartupCompleted = async () => { try { + console.log("开始监听启动完成事件"); const unlisten = await listen("verge://startup-completed", () => { console.log("收到启动完成事件,开始通知UI就绪"); notifyUiReady(); @@ -251,9 +268,21 @@ const Layout = () => { } }; - // 初始加载时也通知一次 - console.log("页面初始加载,通知UI就绪"); - notifyUiReady(); + // 初始阶段 - 开始加载 + notifyUiStage("Loading"); + + setTimeout(() => { + notifyUiCoreReady(); + + setTimeout(() => { + notifyUiResourcesLoaded(); + setTimeout(() => { + notifyUiReady(); + }, 100); + }, 100); + }, 100); + + // 启动监听器 const unlistenPromise = listenStartupCompleted(); return () => { diff --git a/lede/include/image-commands.mk b/lede/include/image-commands.mk index 6afb76ef8a..b3f679d16d 100644 --- a/lede/include/image-commands.mk +++ b/lede/include/image-commands.mk @@ -106,7 +106,7 @@ endef define Build/append-squashfs-fakeroot-be rm -rf $@.fakefs $@.fakesquashfs mkdir $@.fakefs - $(STAGING_DIR_HOST)/bin/mksquashfs-lzma \ + $(STAGING_DIR_HOST)/bin/mksquashfs3-lzma \ $@.fakefs $@.fakesquashfs \ -noappend -root-owned -be -nopad -b 65536 \ $(if $(SOURCE_DATE_EPOCH),-fixed-time $(SOURCE_DATE_EPOCH)) diff --git a/lede/include/kernel-5.15 b/lede/include/kernel-5.15 index 09e76b7f10..421678da59 100644 --- a/lede/include/kernel-5.15 +++ b/lede/include/kernel-5.15 @@ -1,2 +1,2 @@ -LINUX_VERSION-5.15 = .181 -LINUX_KERNEL_HASH-5.15.181 = 3346436d9efae810195b40922c6b73001d1a4dd7e5eeb5a7e8ed85e63960da38 +LINUX_VERSION-5.15 = .182 +LINUX_KERNEL_HASH-5.15.182 = b6abfa53315a04e459070b927c58beb41f085433117d58756504d68b67f6a31e diff --git a/lede/include/kernel-5.4 b/lede/include/kernel-5.4 index 744fca5639..3fc3689c3d 100644 --- a/lede/include/kernel-5.4 +++ b/lede/include/kernel-5.4 @@ -1,2 +1,2 @@ LINUX_VERSION-5.4 = .293 - LINUX_KERNEL_HASH-5.4.293 = 34589340c7d76c0de91965e5242f61e9f9f3bacd03e8e34239e5d4660d45372d +LINUX_KERNEL_HASH-5.4.293 = 34589340c7d76c0de91965e5242f61e9f9f3bacd03e8e34239e5d4660d45372d diff --git a/lede/include/kernel-6.1 b/lede/include/kernel-6.1 index cc5f329700..866fc534a3 100644 --- a/lede/include/kernel-6.1 +++ b/lede/include/kernel-6.1 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.1 = .137 -LINUX_KERNEL_HASH-6.1.137 = 59ac8fce0c12706b225eda7c838c41f4637d4fd3317b90a2b9d266b4a8711041 +LINUX_VERSION-6.1 = .138 +LINUX_KERNEL_HASH-6.1.138 = e319a5bb9049ba9fb8cbc08cba4874716e8985bd10f7971f2573ea802c257911 diff --git a/lede/include/kernel-6.12 b/lede/include/kernel-6.12 index f17e5a1410..70a35aa2ae 100644 --- a/lede/include/kernel-6.12 +++ b/lede/include/kernel-6.12 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.12 = .27 -LINUX_KERNEL_HASH-6.12.27 = 8f4655a4cc7f93d72f515bbca54756de26ddaf5949790da6a17f766e3c33dc79 +LINUX_VERSION-6.12 = .28 +LINUX_KERNEL_HASH-6.12.28 = e8a099182562aecff781de72ce769461e706d97af42d740dff20eb450dd5771e diff --git a/lede/include/kernel-6.6 b/lede/include/kernel-6.6 index 72007af264..e4ac53448d 100644 --- a/lede/include/kernel-6.6 +++ b/lede/include/kernel-6.6 @@ -1,2 +1,2 @@ -LINUX_VERSION-6.6 = .89 - LINUX_KERNEL_HASH-6.6.89 = c21af7d36068e4ac0704c242eac8459212e6bf4a5d09df941b9b4d17dc1eba00 +LINUX_VERSION-6.6 = .90 +LINUX_KERNEL_HASH-6.6.90 = ff856748671629c1fefef219099e0b4b81131c2d325e768cb0806e204157014e diff --git a/lede/package/kernel/linux/modules/usb.mk b/lede/package/kernel/linux/modules/usb.mk index 58446e870d..ce194b768a 100644 --- a/lede/package/kernel/linux/modules/usb.mk +++ b/lede/package/kernel/linux/modules/usb.mk @@ -1439,11 +1439,11 @@ $(eval $(call KernelPackage,usb-net-rtl8150)) define KernelPackage/usb-net-rtl8152 TITLE:=Kernel module for USB-to-Ethernet Realtek convertors - DEPENDS:=+r8152-firmware +kmod-crypto-sha256 +kmod-mii + DEPENDS:=+r8152-firmware +kmod-crypto-sha256 +kmod-mii +kmod-usb-net-cdc-ncm KCONFIG:=CONFIG_USB_RTL8152 FILES:=$(LINUX_DIR)/drivers/$(USBNET_DIR)/r8152.ko AUTOLOAD:=$(call AutoProbe,r8152) - $(call AddDepends/usb, +LINUX_5_10:kmod-crypto-hash) + $(call AddDepends/usb-net, +LINUX_5_10:kmod-crypto-hash) endef define KernelPackage/usb-net-rtl8152/description diff --git a/lede/package/network/utils/iw/Makefile b/lede/package/network/utils/iw/Makefile index 3f10031c19..1734062471 100644 --- a/lede/package/network/utils/iw/Makefile +++ b/lede/package/network/utils/iw/Makefile @@ -8,15 +8,16 @@ include $(TOPDIR)/rules.mk PKG_NAME:=iw -PKG_VERSION:=5.19 -PKG_RELEASE:=1 - +PKG_VERSION:=6.9 +PKG_RELEASE:=4 + PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@KERNEL/software/network/iw -PKG_HASH:=f167bbe947dd53bb9ebc0c1dcef5db6ad73ac1d6084f2c6f9376c5c360cc4d4e +PKG_HASH:=3f2db22ad41c675242b98ae3942dbf3112548c60a42ff739210f2de4e98e4894 PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=GPL-2.0 +PKG_CPE_ID:=cpe:/a:kernel:iw PKG_BUILD_FLAGS:=gc-sections lto diff --git a/lede/package/network/utils/iw/patches/001-nl80211_h_sync.patch b/lede/package/network/utils/iw/patches/001-nl80211_h_sync.patch index afe27d6f23..f48c083575 100644 --- a/lede/package/network/utils/iw/patches/001-nl80211_h_sync.patch +++ b/lede/package/network/utils/iw/patches/001-nl80211_h_sync.patch @@ -1,259 +1,98 @@ --- a/nl80211.h +++ b/nl80211.h -@@ -324,6 +324,17 @@ - */ - - /** -+ * DOC: Multi-Link Operation +@@ -2061,6 +2061,10 @@ enum nl80211_commands { + * @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported + * interface combinations. In each nested item, it contains attributes + * defined in &enum nl80211_if_combination_attrs. ++ * If the wiphy uses multiple radios (@NL80211_ATTR_WIPHY_RADIOS is set), ++ * this attribute contains the interface combinations of the first radio. ++ * See @NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS for the global wiphy ++ * combinations for the sum of all radios. + * @NL80211_ATTR_SOFTWARE_IFTYPES: Nested attribute (just like + * %NL80211_ATTR_SUPPORTED_IFTYPES) containing the interface types that + * are managed in software: interfaces of these types aren't subject to +@@ -2856,6 +2860,17 @@ enum nl80211_commands { + * %NL80211_CMD_ASSOCIATE indicating the SPP A-MSDUs + * are used on this connection + * ++ * @NL80211_ATTR_WIPHY_RADIOS: Nested attribute describing physical radios ++ * belonging to this wiphy. See &enum nl80211_wiphy_radio_attrs. + * -+ * In Multi-Link Operation, a connection between to MLDs utilizes multiple -+ * links. To use this in nl80211, various commands and responses now need -+ * to or will include the new %NL80211_ATTR_MLO_LINKS attribute. -+ * Additionally, various commands that need to operate on a specific link -+ * now need to be given the %NL80211_ATTR_MLO_LINK_ID attribute, e.g. to -+ * use %NL80211_CMD_START_AP or similar functions. -+ */ -+ -+/** - * enum nl80211_commands - supported nl80211 commands - * - * @NL80211_CMD_UNSPEC: unspecified command to catch errors -@@ -366,14 +377,22 @@ - * the non-transmitting interfaces are deleted as well. - * - * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified -- * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. -+ * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. %NL80211_ATTR_MAC -+ * represents peer's MLD address for MLO pairwise key. For MLO group key, -+ * the link is identified by %NL80211_ATTR_MLO_LINK_ID. - * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT, - * %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD. -+ * For MLO connection, the link to set default key is identified by -+ * %NL80211_ATTR_MLO_LINK_ID. - * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA, - * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC, %NL80211_ATTR_KEY_CIPHER, -- * and %NL80211_ATTR_KEY_SEQ attributes. -+ * and %NL80211_ATTR_KEY_SEQ attributes. %NL80211_ATTR_MAC represents -+ * peer's MLD address for MLO pairwise key. The link to add MLO -+ * group key is identified by %NL80211_ATTR_MLO_LINK_ID. - * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX -- * or %NL80211_ATTR_MAC. -+ * or %NL80211_ATTR_MAC. %NL80211_ATTR_MAC represents peer's MLD address -+ * for MLO pairwise key. The link to delete group key is identified by -+ * %NL80211_ATTR_MLO_LINK_ID. - * - * @NL80211_CMD_GET_BEACON: (not used) - * @NL80211_CMD_SET_BEACON: change the beacon on an access point interface -@@ -753,6 +772,13 @@ - * %NL80211_ATTR_CSA_C_OFFSETS_TX is an array of offsets to CSA - * counters which will be updated to the current value. This attribute - * is used during CSA period. -+ * For TX on an MLD, the frequency can be omitted and the link ID be -+ * specified, or if transmitting to a known peer MLD (with MLD addresses -+ * in the frame) both can be omitted and the link will be selected by -+ * lower layers. -+ * For RX notification, %NL80211_ATTR_RX_HW_TIMESTAMP may be included to -+ * indicate the frame RX timestamp and %NL80211_ATTR_TX_HW_TIMESTAMP may -+ * be included to indicate the ack TX timestamp. - * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this - * command may be used with the corresponding cookie to cancel the wait - * time if it is known that it is no longer necessary. This command is -@@ -763,7 +789,9 @@ - * transmitted with %NL80211_CMD_FRAME. %NL80211_ATTR_COOKIE identifies - * the TX command and %NL80211_ATTR_FRAME includes the contents of the - * frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged -- * the frame. -+ * the frame. %NL80211_ATTR_TX_HW_TIMESTAMP may be included to indicate the -+ * tx timestamp and %NL80211_ATTR_RX_HW_TIMESTAMP may be included to -+ * indicate the ack RX timestamp. - * @NL80211_CMD_ACTION_TX_STATUS: Alias for @NL80211_CMD_FRAME_TX_STATUS for - * backward compatibility. - * -@@ -1108,6 +1136,12 @@ - * has been received. %NL80211_ATTR_FRAME is used to specify the - * frame contents. The frame is the raw EAPoL data, without ethernet or - * 802.11 headers. -+ * For an MLD transmitter, the %NL80211_ATTR_MLO_LINK_ID may be given and -+ * its effect will depend on the destination: If the destination is known -+ * to be an MLD, this will be used as a hint to select the link to transmit -+ * the frame on. If the destination is not an MLD, this will select both -+ * the link to transmit on and the source address will be set to the link -+ * address of that link. - * When used as an event indication %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, - * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT and %NL80211_ATTR_MAC are added - * indicating the protocol type of the received frame; whether the frame -@@ -1237,6 +1271,16 @@ - * to describe the BSSID address of the AP and %NL80211_ATTR_TIMEOUT to - * specify the timeout value. - * -+ * @NL80211_CMD_ADD_LINK: Add a new link to an interface. The -+ * %NL80211_ATTR_MLO_LINK_ID attribute is used for the new link. -+ * @NL80211_CMD_REMOVE_LINK: Remove a link from an interface. This may come -+ * without %NL80211_ATTR_MLO_LINK_ID as an easy way to remove all links -+ * in preparation for e.g. roaming to a regular (non-MLO) AP. ++ * @NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS: Nested attribute listing the ++ * supported interface combinations for all radios combined. In each ++ * nested item, it contains attributes defined in ++ * &enum nl80211_if_combination_attrs. + * -+ * @NL80211_CMD_ADD_LINK_STA: Add a link to an MLD station -+ * @NL80211_CMD_MODIFY_LINK_STA: Modify a link of an MLD station -+ * @NL80211_CMD_REMOVE_LINK_STA: Remove a link of an MLD station -+ * - * @NL80211_CMD_MAX: highest used command number - * @__NL80211_CMD_AFTER_LAST: internal use - */ -@@ -1481,6 +1525,13 @@ enum nl80211_commands { - - NL80211_CMD_ASSOC_COMEBACK, - -+ NL80211_CMD_ADD_LINK, -+ NL80211_CMD_REMOVE_LINK, -+ -+ NL80211_CMD_ADD_LINK_STA, -+ NL80211_CMD_MODIFY_LINK_STA, -+ NL80211_CMD_REMOVE_LINK_STA, -+ - /* add new commands above here */ - - /* used to define NL80211_CMD_MAX below */ -@@ -2340,8 +2391,10 @@ enum nl80211_commands { - * - * @NL80211_ATTR_IFTYPE_EXT_CAPA: Nested attribute of the following attributes: - * %NL80211_ATTR_IFTYPE, %NL80211_ATTR_EXT_CAPA, -- * %NL80211_ATTR_EXT_CAPA_MASK, to specify the extended capabilities per -- * interface type. -+ * %NL80211_ATTR_EXT_CAPA_MASK, to specify the extended capabilities and -+ * other interface-type specific capabilities per interface type. For MLO, -+ * %NL80211_ATTR_EML_CAPABILITY and %NL80211_ATTR_MLD_CAPA_AND_OPS are -+ * present. - * - * @NL80211_ATTR_MU_MIMO_GROUP_DATA: array of 24 bytes that defines a MU-MIMO - * groupID for monitor mode. -@@ -2663,6 +2716,44 @@ enum nl80211_commands { - * association request when used with NL80211_CMD_NEW_STATION). Can be set - * only if %NL80211_STA_FLAG_WME is set. - * -+ * @NL80211_ATTR_MLO_LINK_ID: A (u8) link ID for use with MLO, to be used with -+ * various commands that need a link ID to operate. -+ * @NL80211_ATTR_MLO_LINKS: A nested array of links, each containing some -+ * per-link information and a link ID. -+ * @NL80211_ATTR_MLD_ADDR: An MLD address, used with various commands such as -+ * authenticate/associate. -+ * -+ * @NL80211_ATTR_MLO_SUPPORT: Flag attribute to indicate user space supports MLO -+ * connection. Used with %NL80211_CMD_CONNECT. If this attribute is not -+ * included in NL80211_CMD_CONNECT drivers must not perform MLO connection. -+ * -+ * @NL80211_ATTR_MAX_NUM_AKM_SUITES: U16 attribute. Indicates maximum number of -+ * AKM suites allowed for %NL80211_CMD_CONNECT, %NL80211_CMD_ASSOCIATE and -+ * %NL80211_CMD_START_AP in %NL80211_CMD_GET_WIPHY response. If this -+ * attribute is not present userspace shall consider maximum number of AKM -+ * suites allowed as %NL80211_MAX_NR_AKM_SUITES which is the legacy maximum -+ * number prior to the introduction of this attribute. -+ * -+ * @NL80211_ATTR_EML_CAPABILITY: EML Capability information (u16) -+ * @NL80211_ATTR_MLD_CAPA_AND_OPS: MLD Capabilities and Operations (u16) -+ * -+ * @NL80211_ATTR_TX_HW_TIMESTAMP: Hardware timestamp for TX operation in -+ * nanoseconds (u64). This is the device clock timestamp so it will -+ * probably reset when the device is stopped or the firmware is reset. -+ * When used with %NL80211_CMD_FRAME_TX_STATUS, indicates the frame TX -+ * timestamp. When used with %NL80211_CMD_FRAME RX notification, indicates -+ * the ack TX timestamp. -+ * @NL80211_ATTR_RX_HW_TIMESTAMP: Hardware timestamp for RX operation in -+ * nanoseconds (u64). This is the device clock timestamp so it will -+ * probably reset when the device is stopped or the firmware is reset. -+ * When used with %NL80211_CMD_FRAME_TX_STATUS, indicates the ack RX -+ * timestamp. When used with %NL80211_CMD_FRAME RX notification, indicates -+ * the incoming frame RX timestamp. -+ * @NL80211_ATTR_TD_BITMAP: Transition Disable bitmap, for subsequent -+ * (re)associations. -+ * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce -+ * transmit power to stay within regulatory limits. u32, dBi. ++ * @NL80211_ATTR_VIF_RADIO_MASK: Bitmask of allowed radios (u32). ++ * A value of 0 means all radios. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use -@@ -3177,6 +3268,23 @@ enum nl80211_attrs { +@@ -3401,6 +3416,11 @@ enum nl80211_attrs { - NL80211_ATTR_DISABLE_EHT, + NL80211_ATTR_ASSOC_SPP_AMSDU, -+ NL80211_ATTR_MLO_LINKS, -+ NL80211_ATTR_MLO_LINK_ID, -+ NL80211_ATTR_MLD_ADDR, ++ NL80211_ATTR_WIPHY_RADIOS, ++ NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS, + -+ NL80211_ATTR_MLO_SUPPORT, -+ -+ NL80211_ATTR_MAX_NUM_AKM_SUITES, -+ -+ NL80211_ATTR_EML_CAPABILITY, -+ NL80211_ATTR_MLD_CAPA_AND_OPS, -+ -+ NL80211_ATTR_TX_HW_TIMESTAMP, -+ NL80211_ATTR_RX_HW_TIMESTAMP, -+ NL80211_ATTR_TD_BITMAP, -+ -+ NL80211_ATTR_WIPHY_ANTENNA_GAIN, ++ NL80211_ATTR_VIF_RADIO_MASK, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, -@@ -3231,6 +3339,11 @@ enum nl80211_attrs { - #define NL80211_HE_MIN_CAPABILITY_LEN 16 - #define NL80211_HE_MAX_CAPABILITY_LEN 54 - #define NL80211_MAX_NR_CIPHER_SUITES 5 -+ -+/* -+ * NL80211_MAX_NR_AKM_SUITES is obsolete when %NL80211_ATTR_MAX_NUM_AKM_SUITES -+ * present in %NL80211_CMD_GET_WIPHY response. -+ */ - #define NL80211_MAX_NR_AKM_SUITES 2 - #define NL80211_EHT_MIN_CAPABILITY_LEN 13 - #define NL80211_EHT_MAX_CAPABILITY_LEN 51 -@@ -4853,6 +4966,8 @@ enum nl80211_bss_scan_width { - * Contains a nested array of signal strength attributes (u8, dBm), - * using the nesting index as the antenna number. - * @NL80211_BSS_FREQUENCY_OFFSET: frequency offset in KHz -+ * @NL80211_BSS_MLO_LINK_ID: MLO link ID of the BSS (u8). -+ * @NL80211_BSS_MLD_ADDR: MLD address of this BSS if connected to it. - * @__NL80211_BSS_AFTER_LAST: internal - * @NL80211_BSS_MAX: highest BSS attribute - */ -@@ -4878,6 +4993,8 @@ enum nl80211_bss { - NL80211_BSS_PARENT_BSSID, - NL80211_BSS_CHAIN_SIGNAL, - NL80211_BSS_FREQUENCY_OFFSET, -+ NL80211_BSS_MLO_LINK_ID, -+ NL80211_BSS_MLD_ADDR, +@@ -7987,4 +8007,54 @@ enum nl80211_ap_settings_flags { + NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT = 1 << 1, + }; - /* keep last */ - __NL80211_BSS_AFTER_LAST, -@@ -5874,7 +5991,7 @@ enum nl80211_ap_sme_features { - * @NL80211_FEATURE_INACTIVITY_TIMER: This driver takes care of freeing up - * the connected inactive stations in AP mode. - * @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested -- * to work properly to suppport receiving regulatory hints from -+ * to work properly to support receiving regulatory hints from - * cellular base stations. - * @NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL: (no longer available, only - * here to reserve the value for API/ABI compatibility) -@@ -6174,6 +6291,14 @@ enum nl80211_feature_flags { - * @NL80211_EXT_FEATURE_RADAR_BACKGROUND: Device supports background radar/CAC - * detection. - * -+ * @NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE: Device can perform a MAC address -+ * change without having to bring the underlying network device down -+ * first. For example, in station mode this can be used to vary the -+ * origin MAC address prior to a connection to a new AP for privacy -+ * or other reasons. Note that certain driver specific restrictions -+ * might apply, e.g. no scans in progress, no offchannel operations -+ * in progress, and no active connections. ++/** ++ * enum nl80211_wiphy_radio_attrs - wiphy radio attributes + * - * @NUM_NL80211_EXT_FEATURES: number of extended features. - * @MAX_NL80211_EXT_FEATURES: highest extended feature index. - */ -@@ -6241,6 +6366,7 @@ enum nl80211_ext_feature_index { - NL80211_EXT_FEATURE_BSS_COLOR, - NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD, - NL80211_EXT_FEATURE_RADAR_BACKGROUND, -+ NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE, - - /* add new features before the definition below */ - NUM_NL80211_EXT_FEATURES, ++ * @__NL80211_WIPHY_RADIO_ATTR_INVALID: Invalid ++ * ++ * @NL80211_WIPHY_RADIO_ATTR_INDEX: Index of this radio (u32) ++ * @NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE: Frequency range supported by this ++ * radio. Attribute may be present multiple times. ++ * @NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION: Supported interface ++ * combination for this radio. Attribute may be present multiple times ++ * and contains attributes defined in &enum nl80211_if_combination_attrs. ++ * ++ * @__NL80211_WIPHY_RADIO_ATTR_LAST: Internal ++ * @NL80211_WIPHY_RADIO_ATTR_MAX: Highest attribute ++ */ ++enum nl80211_wiphy_radio_attrs { ++ __NL80211_WIPHY_RADIO_ATTR_INVALID, ++ ++ NL80211_WIPHY_RADIO_ATTR_INDEX, ++ NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE, ++ NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION, ++ ++ /* keep last */ ++ __NL80211_WIPHY_RADIO_ATTR_LAST, ++ NL80211_WIPHY_RADIO_ATTR_MAX = __NL80211_WIPHY_RADIO_ATTR_LAST - 1, ++}; ++ ++/** ++ * enum nl80211_wiphy_radio_freq_range - wiphy radio frequency range ++ * ++ * @__NL80211_WIPHY_RADIO_FREQ_ATTR_INVALID: Invalid ++ * ++ * @NL80211_WIPHY_RADIO_FREQ_ATTR_START: Frequency range start (u32). ++ * The unit is kHz. ++ * @NL80211_WIPHY_RADIO_FREQ_ATTR_END: Frequency range end (u32). ++ * The unit is kHz. ++ * ++ * @__NL80211_WIPHY_RADIO_FREQ_ATTR_LAST: Internal ++ * @NL80211_WIPHY_RADIO_FREQ_ATTR_MAX: Highest attribute ++ */ ++enum nl80211_wiphy_radio_freq_range { ++ __NL80211_WIPHY_RADIO_FREQ_ATTR_INVALID, ++ ++ NL80211_WIPHY_RADIO_FREQ_ATTR_START, ++ NL80211_WIPHY_RADIO_FREQ_ATTR_END, ++ ++ __NL80211_WIPHY_RADIO_FREQ_ATTR_LAST, ++ NL80211_WIPHY_RADIO_FREQ_ATTR_MAX = __NL80211_WIPHY_RADIO_FREQ_ATTR_LAST - 1, ++}; ++ + #endif /* __LINUX_NL80211_H */ diff --git a/lede/package/network/utils/iw/patches/010-Revert-iw-allow-specifying-CFLAGS-LIBS-externally.patch b/lede/package/network/utils/iw/patches/010-Revert-iw-allow-specifying-CFLAGS-LIBS-externally.patch index 1254efa9c7..1c93f00900 100644 --- a/lede/package/network/utils/iw/patches/010-Revert-iw-allow-specifying-CFLAGS-LIBS-externally.patch +++ b/lede/package/network/utils/iw/patches/010-Revert-iw-allow-specifying-CFLAGS-LIBS-externally.patch @@ -16,7 +16,7 @@ Signed-off-by: Hauke Mehrtens --- a/Makefile +++ b/Makefile -@@ -45,30 +45,30 @@ NLLIBNAME = libnl-1 +@@ -46,30 +46,30 @@ NLLIBNAME = libnl-1 endif ifeq ($(NL2FOUND),Y) @@ -55,7 +55,7 @@ Signed-off-by: Hauke Mehrtens NLLIBNAME = libnl-3.1 endif -@@ -76,8 +76,8 @@ ifeq ($(NLLIBNAME),) +@@ -77,8 +77,8 @@ ifeq ($(NLLIBNAME),) $(error Cannot find development files for any supported version of libnl) endif diff --git a/lede/package/network/utils/iw/patches/100-scan-Add-printing-of-HE-Operation-Element.patch b/lede/package/network/utils/iw/patches/100-scan-Add-printing-of-HE-Operation-Element.patch new file mode 100644 index 0000000000..a251ceea37 --- /dev/null +++ b/lede/package/network/utils/iw/patches/100-scan-Add-printing-of-HE-Operation-Element.patch @@ -0,0 +1,153 @@ +From 422419e06d55a7c852d1f6f054a094e285ebaa27 Mon Sep 17 00:00:00 2001 +From: Christopher A Wills +Date: Tue, 30 Jul 2024 16:27:36 -0700 +Subject: [PATCH] scan: Add printing of HE Operation Element + +Signed-off-by: Christopher A Wills +--- + iw.h | 1 + + scan.c | 8 +++++ + util.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 112 insertions(+) + +--- a/iw.h ++++ b/iw.h +@@ -222,6 +222,7 @@ void print_ampdu_spacing(__u8 spacing); + void print_ht_capability(__u16 cap); + void print_vht_info(__u32 capa, const __u8 *mcs); + void print_he_capability(const uint8_t *ie, int len); ++void print_he_operation(const uint8_t *ie, int len); + void print_he_info(struct nlattr *nl_iftype); + void print_eht_info(struct nlattr *nl_iftype, int band); + void print_s1g_capability(const uint8_t *caps); +--- a/scan.c ++++ b/scan.c +@@ -2384,8 +2384,16 @@ static void print_he_capa(const uint8_t + print_he_capability(data, len); + } + ++static void print_he_oper(const uint8_t type, uint8_t len, const uint8_t *data, ++ const struct print_ies_data *ie_buffer) ++{ ++ printf("\n"); ++ print_he_operation(data, len); ++} ++ + static const struct ie_print ext_printers[] = { + [35] = { "HE capabilities", print_he_capa, 21, 54, BIT(PRINT_SCAN), }, ++ [36] = { "HE Operation", print_he_oper, 6, 15, BIT(PRINT_SCAN), }, + }; + + static void print_extension(unsigned char len, unsigned char *ie, +--- a/util.c ++++ b/util.c +@@ -1733,6 +1733,109 @@ void print_he_capability(const uint8_t * + __print_he_capa(mac_cap, phy_cap - 1, mcs_set, mcs_len, NULL, 0, false); + } + ++void print_he_operation(const uint8_t *ie, int len) ++{ ++ uint8_t oper_parameters[3] = {ie[0], ie[1], ie[2] }; ++ uint8_t bss_color = ie[3]; ++ uint16_t nss_mcs_set = *(uint16_t*)(&ie[4]); ++ uint8_t vht_oper_present = oper_parameters[1] & 0x40; ++ uint8_t co_hosted_bss_present = oper_parameters[1] & 0x80; ++ uint8_t uhb_operation_info_present = oper_parameters[2] & 0x02; ++ uint8_t offset = 6; ++ ++ printf("\t\tHE Operation Parameters: (0x%02x%02x%02x)\n", ++ oper_parameters[2], oper_parameters[1], oper_parameters[0]); ++ printf("\t\t\tDefault PE Duration: %hhu\n", oper_parameters[0] & 0x07); ++ if (oper_parameters[0] & 0x08) ++ printf("\t\t\tTWT Required\n"); ++ ++ printf("\t\t\tTXOP Duration RTS Threshold: %hu\n", ++ (*(uint16_t*)(oper_parameters)) >> 4 & 0x03ff); ++ if (oper_parameters[1] & 0x40) ++ printf("\t\t\tVHT Operation Information Present\n"); ++ ++ if (oper_parameters[1] & 0x80) ++ printf("\t\t\tCo-Hosted BSS\n"); ++ ++ if (oper_parameters[2] & 0x01) ++ printf("\t\t\tER SU Disable\n"); ++ ++ if (oper_parameters[2] & 0x02) ++ printf("\t\t\t6 GHz Operation Information Present\n"); ++ ++ printf("\t\tBSS Color: %hhu\n", bss_color & 0x3F); ++ if (bss_color & 0x40) ++ printf("\t\tPartial BSS Color\n"); ++ ++ if (bss_color & 0x80) ++ printf("\t\tBSS Color Disabled\n"); ++ ++ printf("\t\tBasic HE-MCS NSS Set: 0x%04x\n", nss_mcs_set); ++ for (int k = 0; k < 8; k++) { ++ __u16 mcs = nss_mcs_set; ++ ++ mcs >>= k * 2; ++ mcs &= 0x3; ++ printf("\t\t\t%d streams: ", k + 1); ++ if (mcs == 3) ++ printf("not supported\n"); ++ else ++ printf("MCS 0-%d\n", 7 + (mcs * 2)); ++ } ++ ++ if (vht_oper_present) { ++ if (len - offset < 3) { ++ printf("\t\tVHT Operation Info: Invalid\n"); ++ return; ++ } ++ ++ printf("\t\tVHT Operation Info: 0x%02x%02x%02x\n", ++ ie[offset + 2], ie[offset + 1], ie[offset + 0]); ++ offset += 3; ++ } ++ ++ if (co_hosted_bss_present) { ++ if (len - offset < 1) { ++ printf("\t\tMax Co-Hosted BSSID: Invalid\n"); ++ return; ++ } ++ ++ printf("\t\tMax Co-Hosted BSSID: %hhu\n", ie[offset]); ++ offset += 1; ++ } ++ ++ if (uhb_operation_info_present) { ++ if (len - offset < 5) { ++ printf("\t\t6 GHz Operation Info: Invalid\n"); ++ return; ++ } else { ++ const uint8_t control = ie[offset + 1]; ++ ++ printf("\t\t6 Ghz Operation Information: 0x"); ++ for (uint8_t i = 0; i < 5; i++) ++ printf("%02x", ie[offset + i]); ++ ++ printf("\n"); ++ printf("\t\t\tPrimary Channel: %hhu\n", ie[offset]); ++ printf("\t\t\tChannel Width: "); ++ switch (control & 0x3) { ++ case 0: printf("20 MHz\n"); break; ++ case 1: printf("40 MHz\n"); break; ++ case 2: printf("80 MHz\n"); break; ++ case 3: printf("80+80 or 160 MHz\n"); break; ++ } ++ ++ if (control & 0x4) ++ printf("\t\t\tDuplicate Beacon: True\n"); ++ ++ printf("\t\t\tRegulatory Info: %hhu\n", (control >> 3) & 0xf); ++ printf("\t\t\tCenter Frequency Segment 0: %hhu\n", ie[offset+2]); ++ printf("\t\t\tCenter Frequency Segment 1: %hhu\n", ie[offset+3]); ++ printf("\t\t\tMinimum Rate: %hhu\n", ie[offset+4]); ++ } ++ } ++} ++ + void iw_hexdump(const char *prefix, const __u8 *buf, size_t size) + { + size_t i; diff --git a/lede/package/network/utils/iw/patches/101-iw-fix-HE-capabilities-on-Big-Endian-platforms.patch b/lede/package/network/utils/iw/patches/101-iw-fix-HE-capabilities-on-Big-Endian-platforms.patch new file mode 100644 index 0000000000..a4abc14aba --- /dev/null +++ b/lede/package/network/utils/iw/patches/101-iw-fix-HE-capabilities-on-Big-Endian-platforms.patch @@ -0,0 +1,77 @@ +From c41971e27a8359f88122593a2700f270f58cb2fa Mon Sep 17 00:00:00 2001 +From: Aleksander Jan Bajkowski +Date: Sat, 5 Apr 2025 20:48:05 +0200 +Subject: [PATCH 1/2] iw: fix HE capabilities on Big Endian platforms + +IE fields are encoded in Little Endian and are not correctly +printed on Big Endian platforms. + +Fixes: c741be9f6ca3 ("iw: print HE capabilities") +Signed-off-by: Aleksander Jan Bajkowski +Link: https://patch.msgid.link/20250405184807.701728-2-olek2@wp.pl +Signed-off-by: Johannes Berg +--- + util.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +--- a/util.c ++++ b/util.c +@@ -1245,14 +1245,15 @@ static void __print_he_capa(const __u16 + + #define PRINT_HE_CAP(_var, _idx, _bit, _str) \ + do { \ +- if (_var[_idx] & BIT(_bit)) \ ++ if (le16toh(_var[_idx]) & BIT(_bit)) \ + printf("%s\t\t\t" _str "\n", pre); \ + } while (0) + + #define PRINT_HE_CAP_MASK(_var, _idx, _shift, _mask, _str) \ + do { \ +- if ((_var[_idx] >> _shift) & _mask) \ +- printf("%s\t\t\t" _str ": %d\n", pre, (_var[_idx] >> _shift) & _mask); \ ++ if ((le16toh(_var[_idx]) >> _shift) & _mask) \ ++ printf("%s\t\t\t" _str ": %d\n", pre, \ ++ (le16toh(_var[_idx]) >> _shift) & _mask); \ + } while (0) + + #define PRINT_HE_MAC_CAP(...) PRINT_HE_CAP(mac_cap, __VA_ARGS__) +@@ -1263,7 +1264,7 @@ static void __print_he_capa(const __u16 + + printf("%s\t\tHE MAC Capabilities (0x", pre); + for (i = 0; i < 3; i++) +- printf("%04x", mac_cap[i]); ++ printf("%04x", le16toh(mac_cap[i])); + printf("):\n"); + + PRINT_HE_MAC_CAP(0, 0, "+HTC HE Supported"); +@@ -1377,18 +1378,18 @@ static void __print_he_capa(const __u16 + char *bw[] = { "<= 80", "160", "80+80" }; + int j; + +- if ((phy_cap[0] & (phy_cap_support[i] << 8)) == 0) ++ if ((le16toh(phy_cap[0]) & (phy_cap_support[i] << 8)) == 0) + continue; + + /* Supports more, but overflow? Abort. */ +- if ((i * 2 + 2) * sizeof(mcs_set[0]) >= mcs_len) ++ if ((i * 2 + 2) * sizeof(le16toh(mcs_set[0])) >= mcs_len) + return; + + for (j = 0; j < 2; j++) { + int k; + printf("%s\t\tHE %s MCS and NSS set %s MHz\n", pre, j ? "TX" : "RX", bw[i]); + for (k = 0; k < 8; k++) { +- __u16 mcs = mcs_set[(i * 2) + j]; ++ __u16 mcs = le16toh(mcs_set[(i * 2) + j]); + mcs >>= k * 2; + mcs &= 0x3; + printf("%s\t\t\t%d streams: ", pre, k + 1); +@@ -1411,7 +1412,7 @@ static void __print_he_capa(const __u16 + ppet_len = 0; + } + +- if (ppet_len && (phy_cap[3] & BIT(15))) { ++ if (ppet_len && (le16toh(phy_cap[3]) & BIT(15))) { + printf("%s\t\tPPE Threshold ", pre); + for (i = 0; i < ppet_len; i++) + if (ppet[i]) diff --git a/lede/package/network/utils/iw/patches/102-iw-fix-HE-operation-on-Big-Endian-platforms.patch b/lede/package/network/utils/iw/patches/102-iw-fix-HE-operation-on-Big-Endian-platforms.patch new file mode 100644 index 0000000000..0cb943c688 --- /dev/null +++ b/lede/package/network/utils/iw/patches/102-iw-fix-HE-operation-on-Big-Endian-platforms.patch @@ -0,0 +1,36 @@ +From 41a07a818090da424ddd24bf07f468cf5725cdc6 Mon Sep 17 00:00:00 2001 +From: Aleksander Jan Bajkowski +Date: Sat, 5 Apr 2025 20:48:06 +0200 +Subject: [PATCH 2/2] iw: fix HE operation on Big Endian platforms + +IE fields are encoded in Little Endian and are not correctly +printed on Big Endian platforms. + +Fixes: 422419e06d55 ("scan: Add printing of HE Operation Element") +Signed-off-by: Aleksander Jan Bajkowski +Link: https://patch.msgid.link/20250405184807.701728-3-olek2@wp.pl +Signed-off-by: Johannes Berg +--- + util.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/util.c ++++ b/util.c +@@ -1738,7 +1738,7 @@ void print_he_operation(const uint8_t *i + { + uint8_t oper_parameters[3] = {ie[0], ie[1], ie[2] }; + uint8_t bss_color = ie[3]; +- uint16_t nss_mcs_set = *(uint16_t*)(&ie[4]); ++ uint16_t nss_mcs_set = le16toh(*(uint16_t *)(&ie[4])); + uint8_t vht_oper_present = oper_parameters[1] & 0x40; + uint8_t co_hosted_bss_present = oper_parameters[1] & 0x80; + uint8_t uhb_operation_info_present = oper_parameters[2] & 0x02; +@@ -1751,7 +1751,7 @@ void print_he_operation(const uint8_t *i + printf("\t\t\tTWT Required\n"); + + printf("\t\t\tTXOP Duration RTS Threshold: %hu\n", +- (*(uint16_t*)(oper_parameters)) >> 4 & 0x03ff); ++ le16toh((*(uint16_t *)(oper_parameters))) >> 4 & 0x03ff); + if (oper_parameters[1] & 0x40) + printf("\t\t\tVHT Operation Information Present\n"); + diff --git a/lede/package/network/utils/iw/patches/103-iw-scan-add-enum-for-element-IDs.patch b/lede/package/network/utils/iw/patches/103-iw-scan-add-enum-for-element-IDs.patch new file mode 100644 index 0000000000..abf699f2ff --- /dev/null +++ b/lede/package/network/utils/iw/patches/103-iw-scan-add-enum-for-element-IDs.patch @@ -0,0 +1,170 @@ +From 966c590bc4dcbd9a69fdf8fe9f41cec00e72e376 Mon Sep 17 00:00:00 2001 +From: Dylan Eskew +Date: Mon, 30 Sep 2024 11:11:43 -0700 +Subject: [PATCH] iw: scan: add enum for element IDs + +Formerly, element IDs were hardcoded. Improve readability by using +element ID names. + +Signed-off-by: Dylan Eskew +Link: https://patch.msgid.link/20240930181145.1043048-2-dylan.eskew@candelatech.com +Signed-off-by: Johannes Berg +--- + ieee80211.h | 43 +++++++++++++++++++++++++++ + scan.c | 86 +++++++++++++++++++++++++++++++---------------------- + 2 files changed, 93 insertions(+), 36 deletions(-) + +--- a/ieee80211.h ++++ b/ieee80211.h +@@ -58,6 +58,49 @@ struct ieee80211_vht_cap { + struct ieee80211_vht_mcs_info mcs; + } __attribute__ ((packed)); + ++enum elem_id { ++ EID_SSID = 0, ++ EID_SUPP_RATES = 1, ++ EID_DS_PARAMS = 3, ++ EID_TIM = 5, ++ EID_IBSS_TIM_PARAMS = 6, ++ EID_COUNTRY = 7, ++ EID_BSS_LOAD = 11, ++ EID_POWER_CONSTRAINT = 32, ++ EID_TPC_REPORT = 35, ++ EID_ERP_INFO = 42, ++ EID_HT_CAPABILITY = 45, ++ EID_ERP_D4_0 = 47, ++ EID_RSN = 48, ++ EID_EXT_SUPP_RATES = 50, ++ EID_AP_CHAN_REPORT = 51, ++ EID_SUPP_OP_CLASSES = 59, ++ EID_HT_OPERATION = 61, ++ EID_SECONDARY_CH_OFFSET = 62, ++ EID_MEASUREMENT_PILOT_TX = 66, ++ EID_RM_ENABLED_CAPABILITIES = 70, ++ EID_OVERLAP_BSS_SCAN_PARAM = 74, ++ EID_INTERWORKING = 107, ++ EID_ADVERTISEMENT = 108, ++ EID_ROAMING_CONSORTIUM = 111, ++ EID_MESH_CONFIG = 113, ++ EID_MESH_ID = 114, ++ EID_EXT_CAPABILITY = 127, ++ EID_VHT_CAPABILITY = 191, ++ EID_VHT_OPERATION = 192, ++ EID_TRANSMIT_POWER_ENVELOPE = 195, ++ EID_SHORT_BEACON_INTERVAL = 214, ++ EID_S1G_CAPABILITY = 217, ++ EID_VENDOR = 221, ++ EID_S1G_OPERATION = 232, ++ EID_EXTENSION = 255, ++}; ++ ++enum elem_id_ext { ++ EID_EXT_HE_CAPABILITY = 35, ++ EID_EXT_HE_OPERATION = 36, ++}; ++ + #define SUITE(oui, id) (((oui) << 8) | (id)) + + /* cipher suite selectors */ +--- a/scan.c ++++ b/scan.c +@@ -1816,40 +1816,54 @@ static void print_ie(const struct ie_pri + } + + static const struct ie_print ieprinters[] = { +- [0] = { "SSID", print_ssid, 0, 32, +- BIT(PRINT_SCAN) | BIT(PRINT_LINK) | BIT(PRINT_LINK_MLO_MLD), }, +- [1] = { "Supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), }, +- [3] = { "DS Parameter set", print_ds, 1, 1, BIT(PRINT_SCAN), }, +- [5] = { "TIM", print_tim, 4, 255, BIT(PRINT_SCAN), }, +- [6] = { "IBSS ATIM window", print_ibssatim, 2, 2, BIT(PRINT_SCAN), }, +- [7] = { "Country", print_country, 3, 255, BIT(PRINT_SCAN), }, +- [11] = { "BSS Load", print_bss_load, 5, 5, BIT(PRINT_SCAN), }, +- [32] = { "Power constraint", print_powerconstraint, 1, 1, BIT(PRINT_SCAN), }, +- [35] = { "TPC report", print_tpcreport, 2, 2, BIT(PRINT_SCAN), }, +- [42] = { "ERP", print_erp, 1, 255, BIT(PRINT_SCAN), }, +- [45] = { "HT capabilities", print_ht_capa, 26, 26, BIT(PRINT_SCAN), }, +- [47] = { "ERP D4.0", print_erp, 1, 255, BIT(PRINT_SCAN), }, +- [51] = { "AP Channel Report", print_ap_channel_report, 1, 255, BIT(PRINT_SCAN), }, +- [59] = { "Supported operating classes", print_supp_op_classes, 1, 255, BIT(PRINT_SCAN), }, +- [66] = { "Measurement Pilot Transmission", print_measurement_pilot_tx, 1, 255, BIT(PRINT_SCAN), }, +- [74] = { "Overlapping BSS scan params", print_obss_scan_params, 14, 255, BIT(PRINT_SCAN), }, +- [61] = { "HT operation", print_ht_op, 22, 22, BIT(PRINT_SCAN), }, +- [62] = { "Secondary Channel Offset", print_secchan_offs, 1, 1, BIT(PRINT_SCAN), }, +- [191] = { "VHT capabilities", print_vht_capa, 12, 255, BIT(PRINT_SCAN), }, +- [192] = { "VHT operation", print_vht_oper, 5, 255, BIT(PRINT_SCAN), }, +- [48] = { "RSN", print_rsn, 2, 255, BIT(PRINT_SCAN), }, +- [50] = { "Extended supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), }, +- [70] = { "RM enabled capabilities", print_rm_enabled_capabilities, 5, 5, BIT(PRINT_SCAN), }, +- [113] = { "MESH Configuration", print_mesh_conf, 7, 7, BIT(PRINT_SCAN), }, +- [114] = { "MESH ID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), }, +- [127] = { "Extended capabilities", print_capabilities, 0, 255, BIT(PRINT_SCAN), }, +- [107] = { "802.11u Interworking", print_interworking, 0, 255, BIT(PRINT_SCAN), }, +- [108] = { "802.11u Advertisement", print_11u_advert, 0, 255, BIT(PRINT_SCAN), }, +- [111] = { "802.11u Roaming Consortium", print_11u_rcon, 2, 255, BIT(PRINT_SCAN), }, +- [195] = { "Transmit Power Envelope", print_tx_power_envelope, 2, 5, BIT(PRINT_SCAN), }, +- [214] = { "Short beacon interval", print_short_beacon_int, 2, 2, BIT(PRINT_SCAN), }, +- [217] = { "S1G capabilities", print_s1g_capa, 15, 15, BIT(PRINT_SCAN), }, +- [232] = { "S1G operation", print_s1g_oper, 6, 6, BIT(PRINT_SCAN), }, ++ [EID_SSID] = { "SSID", print_ssid, 0, 32, ++ BIT(PRINT_SCAN) | BIT(PRINT_LINK) | BIT(PRINT_LINK_MLO_MLD), }, ++ [EID_SUPP_RATES] = { "Supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), }, ++ [EID_DS_PARAMS] = { "DS Parameter set", print_ds, 1, 1, BIT(PRINT_SCAN), }, ++ [EID_TIM] = { "TIM", print_tim, 4, 255, BIT(PRINT_SCAN), }, ++ [EID_IBSS_TIM_PARAMS] = { "IBSS ATIM window", print_ibssatim, 2, 2, BIT(PRINT_SCAN), }, ++ [EID_COUNTRY] = { "Country", print_country, 3, 255, BIT(PRINT_SCAN), }, ++ [EID_BSS_LOAD] = { "BSS Load", print_bss_load, 5, 5, BIT(PRINT_SCAN), }, ++ [EID_POWER_CONSTRAINT] = { "Power constraint", print_powerconstraint, ++ 1, 1, BIT(PRINT_SCAN), }, ++ [EID_TPC_REPORT] = { "TPC report", print_tpcreport, 2, 2, BIT(PRINT_SCAN), }, ++ [EID_ERP_INFO] = { "ERP", print_erp, 1, 255, BIT(PRINT_SCAN), }, ++ [EID_HT_CAPABILITY] = { "HT capabilities", print_ht_capa, 26, 26, BIT(PRINT_SCAN), }, ++ [EID_ERP_D4_0] = { "ERP D4.0", print_erp, 1, 255, BIT(PRINT_SCAN), }, ++ [EID_AP_CHAN_REPORT] = { "AP Channel Report", print_ap_channel_report, ++ 1, 255, BIT(PRINT_SCAN), }, ++ [EID_SUPP_OP_CLASSES] = { "Supported operating classes", ++ print_supp_op_classes, 1, 255, BIT(PRINT_SCAN), }, ++ [EID_MEASUREMENT_PILOT_TX] = { "Measurement Pilot Transmission", ++ print_measurement_pilot_tx, 1, 255, BIT(PRINT_SCAN), }, ++ [EID_OVERLAP_BSS_SCAN_PARAM] = { "Overlapping BSS scan params", ++ print_obss_scan_params, 14, 255, BIT(PRINT_SCAN), }, ++ [EID_HT_OPERATION] = { "HT operation", print_ht_op, 22, 22, BIT(PRINT_SCAN), }, ++ [EID_SECONDARY_CH_OFFSET] = { "Secondary Channel Offset", ++ print_secchan_offs, 1, 1, BIT(PRINT_SCAN), }, ++ [EID_VHT_CAPABILITY] = { "VHT capabilities", print_vht_capa, 12, 255, BIT(PRINT_SCAN), }, ++ [EID_VHT_OPERATION] = { "VHT operation", print_vht_oper, 5, 255, BIT(PRINT_SCAN), }, ++ [EID_RSN] = { "RSN", print_rsn, 2, 255, BIT(PRINT_SCAN), }, ++ [EID_EXT_SUPP_RATES] = { "Extended supported rates", print_supprates, ++ 0, 255, BIT(PRINT_SCAN), }, ++ [EID_RM_ENABLED_CAPABILITIES] = { "RM enabled capabilities", ++ print_rm_enabled_capabilities, 5, 5, BIT(PRINT_SCAN), }, ++ [EID_MESH_CONFIG] = { "MESH Configuration", print_mesh_conf, 7, 7, BIT(PRINT_SCAN), }, ++ [EID_MESH_ID] = { "MESH ID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), }, ++ [EID_EXT_CAPABILITY] = { "Extended capabilities", print_capabilities, ++ 0, 255, BIT(PRINT_SCAN), }, ++ [EID_INTERWORKING] = { "802.11u Interworking", print_interworking, ++ 0, 255, BIT(PRINT_SCAN), }, ++ [EID_ADVERTISEMENT] = { "802.11u Advertisement", print_11u_advert, ++ 0, 255, BIT(PRINT_SCAN), }, ++ [EID_ROAMING_CONSORTIUM] = { "802.11u Roaming Consortium", ++ print_11u_rcon, 2, 255, BIT(PRINT_SCAN), }, ++ [EID_TRANSMIT_POWER_ENVELOPE] = { "Transmit Power Envelope", ++ print_tx_power_envelope, 2, 5, BIT(PRINT_SCAN), }, ++ [EID_SHORT_BEACON_INTERVAL] = { "Short beacon interval", ++ print_short_beacon_int, 2, 2, BIT(PRINT_SCAN), }, ++ [EID_S1G_CAPABILITY] = { "S1G capabilities", print_s1g_capa, 15, 15, BIT(PRINT_SCAN), }, ++ [EID_S1G_OPERATION] = { "S1G operation", print_s1g_oper, 6, 6, BIT(PRINT_SCAN), }, + }; + + static void print_wifi_wpa(const uint8_t type, uint8_t len, const uint8_t *data, +@@ -2392,8 +2406,8 @@ static void print_he_oper(const uint8_t + } + + static const struct ie_print ext_printers[] = { +- [35] = { "HE capabilities", print_he_capa, 21, 54, BIT(PRINT_SCAN), }, +- [36] = { "HE Operation", print_he_oper, 6, 15, BIT(PRINT_SCAN), }, ++ [EID_EXT_HE_CAPABILITY] = { "HE capabilities", print_he_capa, 21, 54, BIT(PRINT_SCAN), }, ++ [EID_EXT_HE_OPERATION] = { "HE Operation", print_he_oper, 6, 15, BIT(PRINT_SCAN), }, + }; + + static void print_extension(unsigned char len, unsigned char *ie, diff --git a/lede/package/network/utils/iw/patches/104-iw-scan-replace-passed-ie-buffer-with-ie-context.patch b/lede/package/network/utils/iw/patches/104-iw-scan-replace-passed-ie-buffer-with-ie-context.patch new file mode 100644 index 0000000000..aa8b8b16a0 --- /dev/null +++ b/lede/package/network/utils/iw/patches/104-iw-scan-replace-passed-ie-buffer-with-ie-context.patch @@ -0,0 +1,482 @@ +From a0a7ddef29fc412cee7e3ca027905218b145a40f Mon Sep 17 00:00:00 2001 +From: Dylan Eskew +Date: Fri, 22 Nov 2024 08:18:51 -0800 +Subject: [PATCH] iw: scan: replace passed ie buffer with ie context + +Since some ies require references to other ies, parse +the ie list once before to create a context and prevent +parsing more than the two times required. + +Signed-off-by: Dylan Eskew +Link: https://patch.msgid.link/20241122161851.647214-1-dylan.eskew@candelatech.com +[cleanups] +Signed-off-by: Johannes Berg +--- + scan.c | 141 +++++++++++++++++++++++++++++++-------------------------- + 1 file changed, 76 insertions(+), 65 deletions(-) + +--- a/scan.c ++++ b/scan.c +@@ -554,13 +554,12 @@ static void tab_on_first(bool *first) + *first = false; + } + +-struct print_ies_data { +- unsigned char *ie; +- int ielen; ++struct ie_context { ++ bool is_vht_cap; + }; + + static void print_ssid(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf(" "); + print_ssid_escaped(len, data); +@@ -572,7 +571,7 @@ static void print_ssid(const uint8_t typ + + static void print_supprates(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + int i; + +@@ -595,7 +594,7 @@ static void print_supprates(const uint8_ + + static void print_rm_enabled_capabilities(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + __u64 capa = ((__u64) data[0]) | + ((__u64) data[1]) << 8 | +@@ -649,7 +648,7 @@ static void print_rm_enabled_capabilitie + } + + static void print_ds(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf(" channel %d\n", data[0]); + } +@@ -669,7 +668,7 @@ static const char *country_env_str(char + } + + static void print_country(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf(" %.*s", 2, data); + +@@ -716,21 +715,21 @@ static void print_country(const uint8_t + + static void print_powerconstraint(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf(" %d dB\n", data[0]); + } + + static void print_tpcreport(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf(" TX power: %d dBm\n", data[0]); + /* printf(" Link Margin (%d dB) is reserved in Beacons\n", data[1]); */ + } + + static void print_erp(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + if (data[0] == 0x00) + printf(" "); +@@ -744,7 +743,7 @@ static void print_erp(const uint8_t type + } + + static void print_ap_channel_report(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + uint8_t oper_class = data[0]; + int i; +@@ -1084,13 +1083,13 @@ static void print_osen_ie(const char *de + } + + static void print_rsn(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + print_rsn_ie("CCMP", "IEEE 802.1X", len, data); + } + + static void print_ht_capa(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf("\n"); + print_ht_capability(data[0] | (data[1] << 8)); +@@ -1135,7 +1134,7 @@ static const char* vgroup_11u(uint8_t t) + + static void print_interworking(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + /* See Section 7.3.2.92 in the 802.11u spec. */ + printf("\n"); +@@ -1168,7 +1167,7 @@ static void print_interworking(const uin + + static void print_11u_advert(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + /* See Section 7.3.2.93 in the 802.11u spec. */ + /* TODO: This code below does not decode private protocol IDs */ +@@ -1201,7 +1200,7 @@ static void print_11u_advert(const uint8 + } + + static void print_11u_rcon(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + /* See Section 7.3.2.96 in the 802.11u spec. */ + int idx = 0; +@@ -1254,7 +1253,7 @@ static void print_11u_rcon(const uint8_t + + static void print_tx_power_envelope(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + const uint8_t local_max_tx_power_count = data[0] & 7; + const uint8_t local_max_tx_power_unit_interp = (data[0] >> 3) & 7; +@@ -1290,7 +1289,7 @@ static const char *ht_secondary_offset[4 + }; + + static void print_ht_op(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + static const char *protection[4] = { + "no", +@@ -1322,21 +1321,10 @@ static void print_ht_op(const uint8_t ty + + static void print_capabilities(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + int i, base, bit, si_duration = 0, max_amsdu = 0; +- bool s_psmp_support = false, is_vht_cap = false; +- unsigned char *ie = ie_buffer->ie; +- int ielen = ie_buffer->ielen; +- +- while (ielen >= 2 && ielen >= ie[1]) { +- if (ie[0] == 191) { +- is_vht_cap = true; +- break; +- } +- ielen -= ie[1] + 2; +- ie += ie[1] + 2; +- } ++ bool s_psmp_support = false; + + for (i = 0; i < len; i++) { + base = i * 8; +@@ -1432,8 +1420,8 @@ static void print_capabilities(const uin + CAPA(61, "TDLS Wider Bandwidth"); + CAPA(62, "Operating Mode Notification"); + +- ADD_BIT_VAL(63, is_vht_cap, max_amsdu, 1); +- ADD_BIT_VAL(64, is_vht_cap, max_amsdu, 2); ++ ADD_BIT_VAL(63, ctx->is_vht_cap, max_amsdu, 1); ++ ADD_BIT_VAL(64, ctx->is_vht_cap, max_amsdu, 2); + + CAPA(65, "Channel Schedule Management"); + CAPA(66, "Geodatabase Inband Enabling Signal"); +@@ -1462,7 +1450,7 @@ static void print_capabilities(const uin + printf("\n\t\t * Service Interval Granularity is %d ms", + (si_duration + 1) * 5); + +- if (is_vht_cap) { ++ if (ctx->is_vht_cap) { + printf("\n\t\t * Max Number Of MSDUs In A-MSDU is "); + switch (max_amsdu) { + case 0: +@@ -1486,7 +1474,7 @@ static void print_capabilities(const uin + } + + static void print_tim(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf(" DTIM Count %u DTIM Period %u Bitmap Control 0x%x " + "Bitmap[0] 0x%x", +@@ -1497,13 +1485,13 @@ static void print_tim(const uint8_t type + } + + static void print_ibssatim(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf(" %d TUs\n", (data[1] << 8) + data[0]); + } + + static void print_vht_capa(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf("\n"); + print_vht_info((__u32) data[0] | ((__u32)data[1] << 8) | +@@ -1512,7 +1500,7 @@ static void print_vht_capa(const uint8_t + } + + static void print_vht_oper(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + const char *chandwidths[] = { + [0] = "20 or 40 MHz", +@@ -1531,7 +1519,7 @@ static void print_vht_oper(const uint8_t + + static void print_supp_op_classes(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + uint8_t *p = (uint8_t*) data; + const uint8_t *next_data = p + len; +@@ -1565,7 +1553,7 @@ static void print_supp_op_classes(const + + static void print_measurement_pilot_tx(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + uint8_t *p, len_remaining; + +@@ -1614,7 +1602,7 @@ static void print_measurement_pilot_tx(c + + static void print_obss_scan_params(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf("\n"); + printf("\t\t * passive dwell: %d TUs\n", (data[1] << 8) | data[0]); +@@ -1629,7 +1617,7 @@ static void print_obss_scan_params(const + + static void print_secchan_offs(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + if (data[0] < ARRAY_SIZE(ht_secondary_offset)) + printf(" %s (%d)\n", ht_secondary_offset[data[0]], data[0]); +@@ -1638,7 +1626,7 @@ static void print_secchan_offs(const uin + } + + static void print_bss_load(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf("\n"); + printf("\t\t * station count: %d\n", (data[1] << 8) | data[0]); +@@ -1648,7 +1636,7 @@ static void print_bss_load(const uint8_t + + static void print_mesh_conf(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf("\n"); + printf("\t\t * Active Path Selection Protocol ID: %d\n", data[0]); +@@ -1681,7 +1669,7 @@ static void print_mesh_conf(const uint8_ + + static void print_s1g_capa(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf("\n"); + print_s1g_capability(data); +@@ -1689,14 +1677,14 @@ static void print_s1g_capa(const uint8_t + + static void print_short_beacon_int(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf(" %d\n", (data[1] << 8) | data[0]); + } + + static void print_s1g_oper(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + int oper_ch_width, prim_ch_width; + int prim_ch_width_subfield = data[0] & 0x1; +@@ -1777,14 +1765,14 @@ static void print_s1g_oper(const uint8_t + struct ie_print { + const char *name; + void (*print)(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer); ++ const struct ie_context *ctx); + uint8_t minlen, maxlen; + uint8_t flags; + }; + + static void print_ie(const struct ie_print *p, const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + int i; + +@@ -1805,7 +1793,7 @@ static void print_ie(const struct ie_pri + return; + } + +- p->print(type, len, data, ie_buffer); ++ p->print(type, len, data, ctx); + } + + #define PRINT_IGN { \ +@@ -1867,14 +1855,14 @@ static const struct ie_print ieprinters[ + }; + + static void print_wifi_wpa(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + print_rsn_ie("TKIP", "IEEE 802.1X", len, data); + } + + static void print_wifi_osen(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + print_osen_ie("OSEN", "OSEN", len, data); + } +@@ -1922,7 +1910,7 @@ static bool print_wifi_wmm_param(const u + } + + static void print_wifi_wmm(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + int i; + +@@ -1965,7 +1953,7 @@ static const char * wifi_wps_dev_passwd_ + } + + static void print_wifi_wps(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + bool first = true; + __u16 subtype, sublen; +@@ -2205,7 +2193,7 @@ static const struct ie_print wifiprinter + + static inline void print_p2p(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + bool first = true; + __u8 subtype; +@@ -2287,7 +2275,7 @@ static inline void print_p2p(const uint8 + + static inline void print_hs20_ind(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + /* I can't find the spec for this...just going off what wireshark uses. */ + printf("\n"); +@@ -2299,7 +2287,7 @@ static inline void print_hs20_ind(const + + static void print_wifi_owe_tarns(const uint8_t type, uint8_t len, + const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + char mac_addr[20]; + int ssid_len; +@@ -2392,14 +2380,14 @@ static void print_vendor(unsigned char l + } + + static void print_he_capa(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf("\n"); + print_he_capability(data, len); + } + + static void print_he_oper(const uint8_t type, uint8_t len, const uint8_t *data, +- const struct print_ies_data *ie_buffer) ++ const struct ie_context *ctx) + { + printf("\n"); + print_he_operation(data, len); +@@ -2437,23 +2425,46 @@ static void print_extension(unsigned cha + } + } + ++static void init_context(struct ie_context *ctx, ++ unsigned char *ie, int ielen) ++{ ++ unsigned char *pos = ie; ++ int remaining = ielen; ++ ++ memset(ctx, 0, sizeof(*ctx)); ++ ++ if (!ie || !ielen) ++ return; ++ ++ while (remaining >= 2 && remaining - 2 >= pos[1]) { ++ switch (pos[0]) { ++ case EID_VHT_CAPABILITY: ++ ctx->is_vht_cap = true; ++ break; ++ } ++ ++ remaining -= pos[1] + 2; ++ pos += pos[1] + 2; ++ } ++} ++ + void print_ies(unsigned char *ie, int ielen, bool unknown, + enum print_ie_type ptype) + { +- struct print_ies_data ie_buffer = { +- .ie = ie, +- .ielen = ielen }; ++ struct ie_context ctx; + +- if (ie == NULL || ielen < 0) ++ if (!ie) + return; + ++ init_context(&ctx, ie, ielen); ++ + while (ielen >= 2 && ielen - 2 >= ie[1]) { + if (ie[0] < ARRAY_SIZE(ieprinters) && + ieprinters[ie[0]].name && + ieprinters[ie[0]].flags & BIT(ptype) && + ie[1] > 0) { + print_ie(&ieprinters[ie[0]], +- ie[0], ie[1], ie + 2, &ie_buffer); ++ ie[0], ie[1], ie + 2, &ctx); + } else if (ie[0] == 221 /* vendor */) { + print_vendor(ie[1], ie + 2, unknown, ptype); + } else if (ie[0] == 255 /* extension */) { diff --git a/lede/package/network/utils/iw/patches/105-iw-util-update-and-clean-up-eht-capa-printing.patch b/lede/package/network/utils/iw/patches/105-iw-util-update-and-clean-up-eht-capa-printing.patch new file mode 100644 index 0000000000..3970677d74 --- /dev/null +++ b/lede/package/network/utils/iw/patches/105-iw-util-update-and-clean-up-eht-capa-printing.patch @@ -0,0 +1,207 @@ +From 4c859917316b69e66ba241d85b4da6ee01292a11 Mon Sep 17 00:00:00 2001 +From: Dylan Eskew +Date: Wed, 19 Mar 2025 11:39:17 -0700 +Subject: [PATCH] iw: util: update and clean up eht capa printing + +A number of fields were either missing or incorrect, so +update to more aligned with 802.11be spec. Also clean up +printout formatting. + +Signed-off-by: Dylan Eskew +Link: https://patch.msgid.link/20250319183918.1215853-2-dylan.eskew@candelatech.com +Signed-off-by: Johannes Berg +--- + iw.h | 2 + + util.c | 124 ++++++++++++++++++++++++++++++++++++++++++++------------- + 2 files changed, 99 insertions(+), 27 deletions(-) + +--- a/iw.h ++++ b/iw.h +@@ -224,6 +224,8 @@ void print_vht_info(__u32 capa, const __ + void print_he_capability(const uint8_t *ie, int len); + void print_he_operation(const uint8_t *ie, int len); + void print_he_info(struct nlattr *nl_iftype); ++void print_eht_capability(const uint8_t *ie, int len, const uint8_t *he_cap, ++ bool from_ap); + void print_eht_info(struct nlattr *nl_iftype, int band); + void print_s1g_capability(const uint8_t *caps); + +--- a/util.c ++++ b/util.c +@@ -1515,11 +1515,11 @@ static void __print_eht_capa(int band, + const __u8 *mcs_set, size_t mcs_len, + const __u8 *ppet, size_t ppet_len, + const __u16 *he_phy_cap, ++ bool from_ap, + bool indent) + { + unsigned int i; + const char *pre = indent ? "\t" : ""; +- const char *mcs[] = { "0-7", "8-9", "10-11", "12-13"}; + + #define PRINT_EHT_CAP(_var, _idx, _bit, _str) \ + do { \ +@@ -1534,6 +1534,7 @@ static void __print_eht_capa(int band, + } while (0) + + #define PRINT_EHT_MAC_CAP(...) PRINT_EHT_CAP(mac_cap, __VA_ARGS__) ++ #define PRINT_EHT_MAC_CAP_MASK(...) PRINT_EHT_CAP_MASK(mac_cap, __VA_ARGS__) + #define PRINT_EHT_PHY_CAP(...) PRINT_EHT_CAP(phy_cap, __VA_ARGS__) + #define PRINT_EHT_PHY_CAP_MASK(...) PRINT_EHT_CAP_MASK(phy_cap, __VA_ARGS__) + +@@ -1542,13 +1543,22 @@ static void __print_eht_capa(int band, + printf("%02x", mac_cap[i]); + printf("):\n"); + +- PRINT_EHT_MAC_CAP(0, 0, "NSEP priority access Supported"); ++ PRINT_EHT_MAC_CAP(0, 0, "EPCS Priority Access Supported"); + PRINT_EHT_MAC_CAP(0, 1, "EHT OM Control Supported"); +- PRINT_EHT_MAC_CAP(0, 2, "Triggered TXOP Sharing Supported"); +- PRINT_EHT_MAC_CAP(0, 3, "ARR Supported"); ++ PRINT_EHT_MAC_CAP(0, 2, "Triggered TXOP Sharing Mode 1 Supported"); ++ PRINT_EHT_MAC_CAP(0, 3, "Triggered TXOP Sharing Mode 2 Supported"); ++ PRINT_EHT_MAC_CAP(0, 4, "Restricted TWP Supported"); ++ PRINT_EHT_MAC_CAP(0, 5, "SCS Traffic Description Supported"); ++ PRINT_EHT_MAC_CAP_MASK(0, 6, 0x3, "Maximum MPDU Length"); ++ ++ PRINT_EHT_MAC_CAP(1, 1, "Maximum A_MPDU Length Exponent Extension"); ++ PRINT_EHT_MAC_CAP(1, 2, "EHT TRS Supported"); ++ PRINT_EHT_MAC_CAP(1, 3, "TXOP Return In TXOP Sharing Mode 2 Supported"); ++ PRINT_EHT_MAC_CAP(1, 4, "Two BQRs Supported"); ++ PRINT_EHT_MAC_CAP_MASK(1, 5, 0x3, "EHT Link Adaptation Supported"); + +- printf("%s\t\tEHT PHY Capabilities: (0x", pre); +- for (i = 0; i < 8; i++) ++ printf("%s\t\tEHT PHY Capabilities (0x", pre); ++ for (i = 0; i < 9; i++) + printf("%02x", ((__u8 *)phy_cap)[i]); + printf("):\n"); + +@@ -1594,39 +1604,77 @@ static void __print_eht_capa(int band, + PRINT_EHT_PHY_CAP(1, 28, "MU Beamformer (80MHz)"); + PRINT_EHT_PHY_CAP(1, 29, "MU Beamformer (160MHz)"); + PRINT_EHT_PHY_CAP(1, 30, "MU Beamformer (320MHz)"); ++ PRINT_EHT_PHY_CAP(1, 31, "TB Sounding Feedback Rate Limit"); + +- printf("%s\t\tEHT MCS/NSS: (0x", pre); +- for (i = 0; i < mcs_len; i++) +- printf("%02x", ((__u8 *)mcs_set)[i]); +- printf("):\n"); ++ PRINT_EHT_PHY_CAP(2, 0, "Rx 1024-QAM In Wider Bandwidth DL OFDMA Supported"); ++ PRINT_EHT_PHY_CAP(2, 1, "Rx 4096-QAM In Wider Bandwidth DL OFDMA Supported"); + +- if (!(he_phy_cap[0] & ((BIT(2) | BIT(3) | BIT(4)) << 8))){ +- for (i = 0; i < 4; i++) +- printf("%s\t\tEHT bw=20 MHz, max NSS for MCS %s: Rx=%u, Tx=%u\n", +- pre, mcs[i], +- mcs_set[i] & 0xf, mcs_set[i] >> 4); ++ if (!from_ap && ++ !(he_phy_cap[0] & ((BIT(1) | BIT(2) | BIT(3) | BIT(4)) << 8))) { ++ static const char * const mcs[] = { "0-7", "8-9", "10-11", "12-13" }; ++ ++ printf("%s\t\tEHT-MCS Map (20 Mhz Non-AP STA) (0x", pre); ++ for (i = 0; i < mcs_len; i++) ++ printf("%02x", ((__u8 *)mcs_set)[i]); ++ printf("):\n"); ++ ++ for (i = 0; i < 4; i++) { ++ printf("%s\t\t\tRx Max NSS for MCS %s: %u\n", ++ pre, mcs[i], mcs_set[i] & 0xf); ++ printf("%s\t\t\tTx Max NSS for MCS %s: %u\n", ++ pre, mcs[i], mcs_set[i] >> 4); ++ } + } else { +- if (he_phy_cap[0] & (BIT(2) << 8)) { ++ static const char * const mcs[] = { "0-9", "10-11", "12-13"}; ++ ++ /* Bit 1 corresponds to 2.4Ghz 40Mhz support ++ * Bit 2 corresponds to 5/6Ghz 40 and 80Mhz support ++ * If no Channel Width bits are set, but we are an AP, we use ++ * this MCS logic also. ++ */ ++ if (he_phy_cap[0] & ((BIT(1) | BIT(2)) << 8) || ++ (from_ap && !(he_phy_cap[0] & ((BIT(1) | BIT(2) | BIT(3) | BIT(4)) << 8)))) { ++ printf("%s\t\tEHT-MCS Map (BW <= 80) (0x", pre); + for (i = 0; i < 3; i++) +- printf("%s\t\tEHT bw <= 80 MHz, max NSS for MCS %s: Rx=%u, Tx=%u\n", +- pre, mcs[i + 1], +- mcs_set[i] & 0xf, mcs_set[i] >> 4); ++ printf("%02x", ((__u8 *)mcs_set)[i]); ++ printf("):\n"); ++ ++ for (i = 0; i < 3; i++) { ++ printf("%s\t\t\tRx Max NSS for MCS %s: %u\n", ++ pre, mcs[i], mcs_set[i] & 0xf); ++ printf("%s\t\t\tTx Max NSS for MCS %s: %u\n", ++ pre, mcs[i], mcs_set[i] >> 4); ++ } + } + mcs_set += 3; + + if (he_phy_cap[0] & (BIT(3) << 8)) { ++ printf("%s\t\tEHT-MCS Map (BW = 160) (0x", pre); + for (i = 0; i < 3; i++) +- printf("%s\t\tEHT bw=160 MHz, max NSS for MCS %s: Rx=%u, Tx=%u\n", +- pre, mcs[i + 1], +- mcs_set[i] & 0xf, mcs_set[i] >> 4); ++ printf("%02x", ((__u8 *)mcs_set)[i]); ++ printf("):\n"); ++ ++ for (i = 0; i < 3; i++) { ++ printf("%s\t\t\tRx Max NSS for MCS %s: %u\n", ++ pre, mcs[i], mcs_set[i] & 0xf); ++ printf("%s\t\t\tTx Max NSS for MCS %s: %u\n", ++ pre, mcs[i], mcs_set[i] >> 4); ++ } + } + + mcs_set += 3; + if (band == NL80211_BAND_6GHZ && (phy_cap[0] & BIT(1))) { ++ printf("%s\t\tEHT-MCS Map (BW = 320) (0x", pre); + for (i = 0; i < 3; i++) +- printf("%s\t\tEHT bw=320 MHz, max NSS for MCS %s: Rx=%u, Tx=%u\n", +- pre, mcs[i + 1], +- mcs_set[i] & 0xf, mcs_set[i] >> 4); ++ printf("%02x", ((__u8 *)mcs_set)[i]); ++ printf("):\n"); ++ ++ for (i = 0; i < 3; i++) { ++ printf("%s\t\t\tRx Max NSS for MCS %s: %u\n", ++ pre, mcs[i], mcs_set[i] & 0xf); ++ printf("%s\t\t\tTx Max NSS for MCS %s: %u\n", ++ pre, mcs[i], mcs_set[i] >> 4); ++ } + } + } + +@@ -1713,7 +1761,29 @@ void print_eht_info(struct nlattr *nl_if + } + + __print_eht_capa(band, mac_cap, phy_cap, mcs_set, mcs_len, ppet, ppet_len, +- he_phy_cap, true); ++ he_phy_cap, false, true); ++} ++ ++void print_eht_capability(const uint8_t *ie, int len, const uint8_t *he_cap, ++ bool from_ap) ++{ ++ const void *mac_cap, *phy_cap, *mcs_set, *he_phy_cap; ++ int mcs_len; ++ int i = 0; ++ ++ mac_cap = &ie[i]; ++ i += 2; ++ ++ phy_cap = &ie[i]; ++ i += 9; ++ ++ mcs_set = &ie[i]; ++ mcs_len = len - i; ++ ++ he_phy_cap = &he_cap[6]; ++ ++ __print_eht_capa(NL80211_BAND_6GHZ, mac_cap, phy_cap, mcs_set, mcs_len, ++ NULL, 0, he_phy_cap - 1, from_ap, false); + } + + void print_he_capability(const uint8_t *ie, int len) diff --git a/lede/package/network/utils/iw/patches/106-iw-scan-add-eht-capability-parsing.patch b/lede/package/network/utils/iw/patches/106-iw-scan-add-eht-capability-parsing.patch new file mode 100644 index 0000000000..ff8a323d34 --- /dev/null +++ b/lede/package/network/utils/iw/patches/106-iw-scan-add-eht-capability-parsing.patch @@ -0,0 +1,175 @@ +From a6ad3f11ead18d1812c7d3759991dc22b20d90da Mon Sep 17 00:00:00 2001 +From: Dylan Eskew +Date: Wed, 19 Mar 2025 11:39:18 -0700 +Subject: [PATCH] iw: scan: add eht capability parsing + +Add ability to print out EHT capabilities from +AP beacons. + +Signed-off-by: Dylan Eskew +Link: https://patch.msgid.link/20250319183918.1215853-3-dylan.eskew@candelatech.com +Signed-off-by: Johannes Berg +--- + ieee80211.h | 1 + + iw.h | 2 +- + link.c | 5 +++-- + scan.c | 34 +++++++++++++++++++++++++++------- + 4 files changed, 32 insertions(+), 10 deletions(-) + +--- a/ieee80211.h ++++ b/ieee80211.h +@@ -99,6 +99,7 @@ enum elem_id { + enum elem_id_ext { + EID_EXT_HE_CAPABILITY = 35, + EID_EXT_HE_OPERATION = 36, ++ EID_EXT_EHT_CAPABILITY = 108, + }; + + #define SUITE(oui, id) (((oui) << 8) | (id)) +--- a/iw.h ++++ b/iw.h +@@ -256,7 +256,7 @@ enum print_ie_type { + #define BIT(x) (1ULL<<(x)) + + void print_ies(unsigned char *ie, int ielen, bool unknown, +- enum print_ie_type ptype); ++ enum print_ie_type ptype, bool from_ap); + + void parse_bitrate(struct nlattr *bitrate_attr, char *buf, int buflen); + void iw_hexdump(const char *prefix, const __u8 *data, size_t len); +--- a/link.c ++++ b/link.c +@@ -93,7 +93,7 @@ static int link_bss_handler(struct nl_ms + if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) + print_ies(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]), + nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]), +- false, PRINT_LINK_MLO_MLD); ++ false, PRINT_LINK_MLO_MLD, false); + } + } else { + memcpy(result->sta_addr, nla_data(bss[NL80211_BSS_BSSID]), 6); +@@ -121,7 +121,8 @@ static int link_bss_handler(struct nl_ms + if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) + print_ies(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]), + nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]), +- false, result->mld ? PRINT_LINK_MLO_LINK : PRINT_LINK); ++ false, result->mld ? PRINT_LINK_MLO_LINK : PRINT_LINK, ++ false); + + if (bss[NL80211_BSS_FREQUENCY_OFFSET]) + freq_offset = nla_get_u32(bss[NL80211_BSS_FREQUENCY_OFFSET]); +--- a/scan.c ++++ b/scan.c +@@ -555,7 +555,9 @@ static void tab_on_first(bool *first) + } + + struct ie_context { ++ bool from_ap; + bool is_vht_cap; ++ const uint8_t *he_cap; + }; + + static void print_ssid(const uint8_t type, uint8_t len, const uint8_t *data, +@@ -2393,12 +2395,21 @@ static void print_he_oper(const uint8_t + print_he_operation(data, len); + } + ++static void print_eht_capa(const uint8_t type, uint8_t len, ++ const uint8_t *data, const struct ie_context *ctx) ++{ ++ printf("\n"); ++ print_eht_capability(data, len, ctx->he_cap, ctx->from_ap); ++} ++ + static const struct ie_print ext_printers[] = { + [EID_EXT_HE_CAPABILITY] = { "HE capabilities", print_he_capa, 21, 54, BIT(PRINT_SCAN), }, + [EID_EXT_HE_OPERATION] = { "HE Operation", print_he_oper, 6, 15, BIT(PRINT_SCAN), }, ++ [EID_EXT_EHT_CAPABILITY] = { "EHT capabilities", print_eht_capa, 13, 30, BIT(PRINT_SCAN), }, + }; + + static void print_extension(unsigned char len, unsigned char *ie, ++ const struct ie_context *ctx, + bool unknown, enum print_ie_type ptype) + { + unsigned char tag; +@@ -2411,7 +2422,7 @@ static void print_extension(unsigned cha + tag = ie[0]; + if (tag < ARRAY_SIZE(ext_printers) && ext_printers[tag].name && + ext_printers[tag].flags & BIT(ptype)) { +- print_ie(&ext_printers[tag], tag, len - 1, ie + 1, NULL); ++ print_ie(&ext_printers[tag], tag, len - 1, ie + 1, ctx); + return; + } + +@@ -2426,7 +2437,7 @@ static void print_extension(unsigned cha + } + + static void init_context(struct ie_context *ctx, +- unsigned char *ie, int ielen) ++ unsigned char *ie, int ielen, bool from_ap) + { + unsigned char *pos = ie; + int remaining = ielen; +@@ -2436,11 +2447,20 @@ static void init_context(struct ie_conte + if (!ie || !ielen) + return; + ++ ctx->from_ap = from_ap; ++ + while (remaining >= 2 && remaining - 2 >= pos[1]) { + switch (pos[0]) { + case EID_VHT_CAPABILITY: + ctx->is_vht_cap = true; + break; ++ case EID_EXTENSION: ++ switch (pos[2]) { ++ case EID_EXT_HE_CAPABILITY: ++ ctx->he_cap = pos + 3; ++ break; ++ } ++ break; + } + + remaining -= pos[1] + 2; +@@ -2449,14 +2469,14 @@ static void init_context(struct ie_conte + } + + void print_ies(unsigned char *ie, int ielen, bool unknown, +- enum print_ie_type ptype) ++ enum print_ie_type ptype, bool from_ap) + { + struct ie_context ctx; + + if (!ie) + return; + +- init_context(&ctx, ie, ielen); ++ init_context(&ctx, ie, ielen, from_ap); + + while (ielen >= 2 && ielen - 2 >= ie[1]) { + if (ie[0] < ARRAY_SIZE(ieprinters) && +@@ -2468,7 +2488,7 @@ void print_ies(unsigned char *ie, int ie + } else if (ie[0] == 221 /* vendor */) { + print_vendor(ie[1], ie + 2, unknown, ptype); + } else if (ie[0] == 255 /* extension */) { +- print_extension(ie[1], ie + 2, unknown, ptype); ++ print_extension(ie[1], ie + 2, &ctx, unknown, ptype); + } else if (unknown) { + int i; + +@@ -2673,13 +2693,13 @@ static int print_bss_handler(struct nl_m + printf("\tInformation elements from Probe Response " + "frame:\n"); + print_ies(nla_data(ies), nla_len(ies), +- params->unknown, params->type); ++ params->unknown, params->type, true); + } + if (bss[NL80211_BSS_BEACON_IES] && show--) { + printf("\tInformation elements from Beacon frame:\n"); + print_ies(nla_data(bss[NL80211_BSS_BEACON_IES]), + nla_len(bss[NL80211_BSS_BEACON_IES]), +- params->unknown, params->type); ++ params->unknown, params->type, true); + } + + return NL_SKIP; diff --git a/lede/package/network/utils/iw/patches/107-iw-fix-EHT-capabilities-on-Big-Endian-platforms.patch b/lede/package/network/utils/iw/patches/107-iw-fix-EHT-capabilities-on-Big-Endian-platforms.patch new file mode 100644 index 0000000000..d0f15eaec5 --- /dev/null +++ b/lede/package/network/utils/iw/patches/107-iw-fix-EHT-capabilities-on-Big-Endian-platforms.patch @@ -0,0 +1,107 @@ +From 59660a349cf35903e951f99bdd8a74df063c912e Mon Sep 17 00:00:00 2001 +From: Aleksander Jan Bajkowski +Date: Fri, 2 May 2025 21:44:05 +0200 +Subject: [PATCH] iw: fix EHT capabilities on Big Endian platforms + +IE fields are encoded in Little Endian and are not correctly +printed on Big Endian platforms. + +Fixes: 5a71b722270c ("iw: Print local EHT capabilities") +Signed-off-by: Aleksander Jan Bajkowski +Link: https://patch.msgid.link/20250502194405.3489240-1-olek2@wp.pl +Signed-off-by: Johannes Berg +--- + util.c | 40 +++++++++++++++++++++++++--------------- + 1 file changed, 25 insertions(+), 15 deletions(-) + +--- a/util.c ++++ b/util.c +@@ -1521,22 +1521,31 @@ static void __print_eht_capa(int band, + unsigned int i; + const char *pre = indent ? "\t" : ""; + +- #define PRINT_EHT_CAP(_var, _idx, _bit, _str) \ ++ #define PRINT_EHT_MAC_CAP(_idx, _bit, _str) \ + do { \ +- if (_var[_idx] & BIT(_bit)) \ ++ if (mac_cap[_idx] & BIT(_bit)) \ + printf("%s\t\t\t" _str "\n", pre); \ + } while (0) + +- #define PRINT_EHT_CAP_MASK(_var, _idx, _shift, _mask, _str) \ ++ #define PRINT_EHT_MAC_CAP_MASK(_idx, _shift, _mask, _str) \ + do { \ +- if ((_var[_idx] >> _shift) & _mask) \ +- printf("%s\t\t\t" _str ": %d\n", pre, (_var[_idx] >> _shift) & _mask); \ ++ if ((mac_cap[_idx] >> _shift) & _mask) \ ++ printf("%s\t\t\t" _str ": %d\n", pre, \ ++ (mac_cap[_idx] >> _shift) & _mask); \ + } while (0) + +- #define PRINT_EHT_MAC_CAP(...) PRINT_EHT_CAP(mac_cap, __VA_ARGS__) +- #define PRINT_EHT_MAC_CAP_MASK(...) PRINT_EHT_CAP_MASK(mac_cap, __VA_ARGS__) +- #define PRINT_EHT_PHY_CAP(...) PRINT_EHT_CAP(phy_cap, __VA_ARGS__) +- #define PRINT_EHT_PHY_CAP_MASK(...) PRINT_EHT_CAP_MASK(phy_cap, __VA_ARGS__) ++ #define PRINT_EHT_PHY_CAP(_idx, _bit, _str) \ ++ do { \ ++ if (le32toh(phy_cap[_idx]) & BIT(_bit)) \ ++ printf("%s\t\t\t" _str "\n", pre); \ ++ } while (0) ++ ++ #define PRINT_EHT_PHY_CAP_MASK(_idx, _shift, _mask, _str) \ ++ do { \ ++ if ((le32toh(phy_cap[_idx]) >> _shift) & _mask) \ ++ printf("%s\t\t\t" _str ": %d\n", pre, \ ++ (le32toh(phy_cap[_idx]) >> _shift) & _mask); \ ++ } while (0) + + printf("%s\t\tEHT MAC Capabilities (0x", pre); + for (i = 0; i < 2; i++) +@@ -1610,7 +1619,7 @@ static void __print_eht_capa(int band, + PRINT_EHT_PHY_CAP(2, 1, "Rx 4096-QAM In Wider Bandwidth DL OFDMA Supported"); + + if (!from_ap && +- !(he_phy_cap[0] & ((BIT(1) | BIT(2) | BIT(3) | BIT(4)) << 8))) { ++ !(le16toh(he_phy_cap[0]) & ((BIT(1) | BIT(2) | BIT(3) | BIT(4)) << 8))) { + static const char * const mcs[] = { "0-7", "8-9", "10-11", "12-13" }; + + printf("%s\t\tEHT-MCS Map (20 Mhz Non-AP STA) (0x", pre); +@@ -1632,8 +1641,9 @@ static void __print_eht_capa(int band, + * If no Channel Width bits are set, but we are an AP, we use + * this MCS logic also. + */ +- if (he_phy_cap[0] & ((BIT(1) | BIT(2)) << 8) || +- (from_ap && !(he_phy_cap[0] & ((BIT(1) | BIT(2) | BIT(3) | BIT(4)) << 8)))) { ++ if (le16toh(he_phy_cap[0]) & ((BIT(1) | BIT(2)) << 8) || ++ (from_ap && !(le16toh(he_phy_cap[0]) & ++ ((BIT(1) | BIT(2) | BIT(3) | BIT(4)) << 8)))) { + printf("%s\t\tEHT-MCS Map (BW <= 80) (0x", pre); + for (i = 0; i < 3; i++) + printf("%02x", ((__u8 *)mcs_set)[i]); +@@ -1648,7 +1658,7 @@ static void __print_eht_capa(int band, + } + mcs_set += 3; + +- if (he_phy_cap[0] & (BIT(3) << 8)) { ++ if (le16toh(he_phy_cap[0]) & (BIT(3) << 8)) { + printf("%s\t\tEHT-MCS Map (BW = 160) (0x", pre); + for (i = 0; i < 3; i++) + printf("%02x", ((__u8 *)mcs_set)[i]); +@@ -1663,7 +1673,7 @@ static void __print_eht_capa(int band, + } + + mcs_set += 3; +- if (band == NL80211_BAND_6GHZ && (phy_cap[0] & BIT(1))) { ++ if (band == NL80211_BAND_6GHZ && (le32toh(phy_cap[0]) & BIT(1))) { + printf("%s\t\tEHT-MCS Map (BW = 320) (0x", pre); + for (i = 0; i < 3; i++) + printf("%02x", ((__u8 *)mcs_set)[i]); +@@ -1678,7 +1688,7 @@ static void __print_eht_capa(int band, + } + } + +- if (ppet && ppet_len && (phy_cap[1] & BIT(11))) { ++ if (ppet && ppet_len && (le32toh(phy_cap[1]) & BIT(11))) { + printf("%s\t\tEHT PPE Thresholds ", pre); + for (i = 0; i < ppet_len; i++) + if (ppet[i]) diff --git a/lede/package/network/utils/iw/patches/108-iw-scan-Add-printing-of-EHT-Operation-Element.patch b/lede/package/network/utils/iw/patches/108-iw-scan-Add-printing-of-EHT-Operation-Element.patch new file mode 100644 index 0000000000..81b1def031 --- /dev/null +++ b/lede/package/network/utils/iw/patches/108-iw-scan-Add-printing-of-EHT-Operation-Element.patch @@ -0,0 +1,131 @@ +From 8ea80d378ce5f727e69493533a666278c6a568a7 Mon Sep 17 00:00:00 2001 +From: Aleksander Jan Bajkowski +Date: Fri, 2 May 2025 12:03:53 +0200 +Subject: [PATCH] iw: scan: Add printing of EHT Operation Element + +Add ability to print out EHT capabilities from AP beacons. + +Signed-off-by: Aleksander Jan Bajkowski +Link: https://patch.msgid.link/20250502100353.3149470-1-olek2@wp.pl +[add default case to bandwidth switch] +Signed-off-by: Johannes Berg +--- + ieee80211.h | 1 + + iw.h | 1 + + scan.c | 8 +++++++ + util.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 73 insertions(+) + +--- a/ieee80211.h ++++ b/ieee80211.h +@@ -99,6 +99,7 @@ enum elem_id { + enum elem_id_ext { + EID_EXT_HE_CAPABILITY = 35, + EID_EXT_HE_OPERATION = 36, ++ EID_EXT_EHT_OPERATION = 106, + EID_EXT_EHT_CAPABILITY = 108, + }; + +--- a/iw.h ++++ b/iw.h +@@ -226,6 +226,7 @@ void print_he_operation(const uint8_t *i + void print_he_info(struct nlattr *nl_iftype); + void print_eht_capability(const uint8_t *ie, int len, const uint8_t *he_cap, + bool from_ap); ++void print_eht_operation(const uint8_t *ie, int len); + void print_eht_info(struct nlattr *nl_iftype, int band); + void print_s1g_capability(const uint8_t *caps); + +--- a/scan.c ++++ b/scan.c +@@ -2402,10 +2402,18 @@ static void print_eht_capa(const uint8_t + print_eht_capability(data, len, ctx->he_cap, ctx->from_ap); + } + ++static void print_eht_oper(const uint8_t type, uint8_t len, const uint8_t *data, ++ const struct ie_context *ctx) ++{ ++ printf("\n"); ++ print_eht_operation(data, len); ++} ++ + static const struct ie_print ext_printers[] = { + [EID_EXT_HE_CAPABILITY] = { "HE capabilities", print_he_capa, 21, 54, BIT(PRINT_SCAN), }, + [EID_EXT_HE_OPERATION] = { "HE Operation", print_he_oper, 6, 15, BIT(PRINT_SCAN), }, + [EID_EXT_EHT_CAPABILITY] = { "EHT capabilities", print_eht_capa, 13, 30, BIT(PRINT_SCAN), }, ++ [EID_EXT_EHT_OPERATION] = { "EHT Operation", print_eht_oper, 5, 10, BIT(PRINT_SCAN), }, + }; + + static void print_extension(unsigned char len, unsigned char *ie, +--- a/util.c ++++ b/util.c +@@ -1917,6 +1917,69 @@ void print_he_operation(const uint8_t *i + } + } + ++void print_eht_operation(const uint8_t *ie, int len) ++{ ++ uint8_t oper_parameters = ie[0]; ++ uint8_t disabled_subchannel_info_present = oper_parameters & 0x02; ++ uint8_t eht_operation_info_present = oper_parameters & 0x01; ++ ++ printf("\t\tEHT Operation Parameters: (0x%02x)\n", ++ oper_parameters); ++ ++ if (oper_parameters & 0x04) ++ printf("\t\t\tEHT Default PE Duration\n"); ++ ++ if (oper_parameters & 0x08) ++ printf("\t\t\tGroup Addressed BU Indication Limit\n"); ++ ++ printf("\t\t\tGroup Addressed BU Indication Exponent: 0x%01x\n", ++ (oper_parameters >> 4 & 3)); ++ ++ printf("\t\tBasic EHT-MCS And Nss Set: 0x"); ++ for (uint8_t i = 0; i < 4; i++) ++ printf("%02x", ie[1 + i]); ++ ++ printf("\n"); ++ ++ if (eht_operation_info_present) { ++ uint8_t offset = 5; ++ const uint8_t control = ie[offset]; ++ uint8_t eht_operation_info_len = 3; ++ ++ if (disabled_subchannel_info_present) ++ eht_operation_info_len += 2; ++ ++ if (len - offset < eht_operation_info_len) { ++ printf("\t\tEHT Operation Info: Invalid\n"); ++ return; ++ } ++ ++ printf("\t\tEHT Operation Info: 0x"); ++ for (uint8_t i = 0; i < eht_operation_info_len; i++) ++ printf("%02x", ie[offset + i]); ++ ++ printf("\n"); ++ printf("\t\t\tChannel Width: "); ++ switch (control & 0x7) { ++ case 0: printf("20 MHz\n"); break; ++ case 1: printf("40 MHz\n"); break; ++ case 2: printf("80 MHz\n"); break; ++ case 3: printf("160 MHz\n"); break; ++ case 4: printf("320 MHz\n"); break; ++ default: printf("invalid bandwidth (%d)\n", control & 0x7); break; ++ } ++ ++ printf("\t\t\tCenter Frequency Segment 0: %hhu\n", ++ ie[offset + 1]); ++ printf("\t\t\tCenter Frequency Segment 1: %hhu\n", ++ ie[offset + 2]); ++ ++ if (disabled_subchannel_info_present) ++ printf("\t\t\tDisabled Subchannel Bitmap: 0x%02x%02x\n", ++ ie[offset + 3], ie[offset + 4]); ++ } ++} ++ + void iw_hexdump(const char *prefix, const __u8 *buf, size_t size) + { + size_t i; diff --git a/lede/package/network/utils/iw/patches/120-antenna_gain.patch b/lede/package/network/utils/iw/patches/120-antenna_gain.patch deleted file mode 100644 index f8d537fe1e..0000000000 --- a/lede/package/network/utils/iw/patches/120-antenna_gain.patch +++ /dev/null @@ -1,33 +0,0 @@ ---- a/phy.c -+++ b/phy.c -@@ -855,3 +855,30 @@ static int handle_get_txq(struct nl80211 - COMMAND(get, txq, "", - NL80211_CMD_GET_WIPHY, 0, CIB_PHY, handle_get_txq, - "Get TXQ parameters."); -+ -+static int handle_antenna_gain(struct nl80211_state *state, -+ struct nl_msg *msg, -+ int argc, char **argv, -+ enum id_input id) -+{ -+ char *endptr; -+ int dbm; -+ -+ /* get the required args */ -+ if (argc != 1) -+ return 1; -+ -+ dbm = strtol(argv[0], &endptr, 10); -+ if (*endptr) -+ return 2; -+ -+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_GAIN, dbm); -+ -+ return 0; -+ -+ nla_put_failure: -+ return -ENOBUFS; -+} -+COMMAND(set, antenna_gain, "", -+ NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_antenna_gain, -+ "Specify antenna gain."); diff --git a/lede/package/network/utils/iw/patches/200-reduce_size.patch b/lede/package/network/utils/iw/patches/200-reduce_size.patch index 8621994524..40ca57209d 100644 --- a/lede/package/network/utils/iw/patches/200-reduce_size.patch +++ b/lede/package/network/utils/iw/patches/200-reduce_size.patch @@ -1,6 +1,6 @@ --- a/event.c +++ b/event.c -@@ -971,6 +971,7 @@ static int print_event(struct nl_msg *ms +@@ -973,6 +973,7 @@ static int print_event(struct nl_msg *ms } switch (gnlh->cmd) { @@ -8,7 +8,7 @@ case NL80211_CMD_NEW_WIPHY: printf("renamed to %s\n", nla_get_string(tb[NL80211_ATTR_WIPHY_NAME])); break; -@@ -1006,6 +1007,7 @@ static int print_event(struct nl_msg *ms +@@ -1008,6 +1009,7 @@ static int print_event(struct nl_msg *ms case NL80211_CMD_SCHED_SCAN_RESULTS: printf("got scheduled scan results\n"); break; @@ -16,7 +16,7 @@ case NL80211_CMD_WIPHY_REG_CHANGE: case NL80211_CMD_REG_CHANGE: if (gnlh->cmd == NL80211_CMD_WIPHY_REG_CHANGE) -@@ -1088,6 +1090,7 @@ static int print_event(struct nl_msg *ms +@@ -1090,6 +1092,7 @@ static int print_event(struct nl_msg *ms mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC])); printf("del station %s\n", macbuf); break; @@ -24,7 +24,7 @@ case NL80211_CMD_JOIN_IBSS: mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC])); printf("IBSS %s joined\n", macbuf); -@@ -1295,9 +1298,9 @@ static int print_event(struct nl_msg *ms +@@ -1297,9 +1300,9 @@ static int print_event(struct nl_msg *ms case NL80211_CMD_ASSOC_COMEBACK: /* 147 */ parse_assoc_comeback(tb, gnlh->cmd); break; @@ -38,7 +38,7 @@ --- a/info.c +++ b/info.c -@@ -309,6 +309,7 @@ next: +@@ -446,6 +446,7 @@ next: } } @@ -46,7 +46,7 @@ if (tb_band[NL80211_BAND_ATTR_RATES]) { printf("\t\tBitrates (non-HT):\n"); nla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) { -@@ -325,6 +326,7 @@ next: +@@ -462,6 +463,7 @@ next: printf("\n"); } } @@ -54,7 +54,7 @@ } } -@@ -390,6 +392,7 @@ next: +@@ -527,6 +529,7 @@ next: printf("\tCoverage class: %d (up to %dm)\n", coverage, 450 * coverage); } @@ -62,7 +62,7 @@ if (tb_msg[NL80211_ATTR_CIPHER_SUITES]) { int num = nla_len(tb_msg[NL80211_ATTR_CIPHER_SUITES]) / sizeof(__u32); int i; -@@ -401,6 +404,7 @@ next: +@@ -538,6 +541,7 @@ next: cipher_name(ciphers[i])); } } @@ -70,7 +70,7 @@ if (tb_msg[NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX] && tb_msg[NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX]) -@@ -418,9 +422,11 @@ next: +@@ -555,9 +559,11 @@ next: print_iftype_list("\tSupported interface modes", "\t\t", tb_msg[NL80211_ATTR_SUPPORTED_IFTYPES]); @@ -82,7 +82,7 @@ if (tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS]) { struct nlattr *nl_combi; -@@ -510,6 +516,7 @@ broken_combination: +@@ -647,6 +653,7 @@ broken_combination: printf("\tinterface combinations are not supported\n"); } @@ -90,7 +90,7 @@ if (tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS]) { printf("\tSupported commands:\n"); nla_for_each_nested(nl_cmd, tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS], rem_cmd) -@@ -607,6 +614,7 @@ broken_combination: +@@ -744,6 +751,7 @@ broken_combination: printf("\t\t * wake up on TCP connection\n"); } } @@ -98,7 +98,7 @@ if (tb_msg[NL80211_ATTR_ROAM_SUPPORT]) printf("\tDevice supports roaming.\n"); -@@ -645,6 +653,7 @@ broken_combination: +@@ -782,6 +790,7 @@ broken_combination: } } @@ -106,7 +106,7 @@ if (tb_msg[NL80211_ATTR_FEATURE_FLAGS]) { unsigned int features = nla_get_u32(tb_msg[NL80211_ATTR_FEATURE_FLAGS]); -@@ -709,6 +718,7 @@ broken_combination: +@@ -846,6 +855,7 @@ broken_combination: if (features & NL80211_FEATURE_ND_RANDOM_MAC_ADDR) printf("\tDevice supports randomizing MAC-addr in net-detect scans.\n"); } @@ -114,7 +114,7 @@ if (tb_msg[NL80211_ATTR_TDLS_SUPPORT]) printf("\tDevice supports T-DLS.\n"); -@@ -774,6 +784,7 @@ TOPLEVEL(list, NULL, NL80211_CMD_GET_WIP +@@ -914,6 +924,7 @@ TOPLEVEL(list, NULL, NL80211_CMD_GET_WIP "List all wireless devices and their capabilities."); TOPLEVEL(phy, NULL, NL80211_CMD_GET_WIPHY, NLM_F_DUMP, CIB_NONE, handle_info, NULL); @@ -122,7 +122,7 @@ static int handle_commands(struct nl80211_state *state, struct nl_msg *msg, int argc, char **argv, enum id_input id) { -@@ -785,6 +796,7 @@ static int handle_commands(struct nl8021 +@@ -925,6 +936,7 @@ static int handle_commands(struct nl8021 } TOPLEVEL(commands, NULL, NL80211_CMD_GET_WIPHY, 0, CIB_NONE, handle_commands, "list all known commands and their decimal & hex value"); @@ -132,7 +132,7 @@ { --- a/scan.c +++ b/scan.c -@@ -1306,6 +1306,9 @@ static void print_ht_op(const uint8_t ty +@@ -1309,6 +1309,9 @@ static void print_ht_op(const uint8_t ty printf("\t\t * secondary channel offset: %s\n", ht_secondary_offset[data[1] & 0x3]); printf("\t\t * STA channel width: %s\n", sta_chan_width[(data[1] & 0x4)>>2]); @@ -142,50 +142,62 @@ printf("\t\t * RIFS: %d\n", (data[1] & 0x8)>>3); printf("\t\t * HT protection: %s\n", protection[data[2] & 0x3]); printf("\t\t * non-GF present: %d\n", (data[2] & 0x4) >> 2); -@@ -1716,6 +1719,14 @@ static void print_ie(const struct ie_pri - +@@ -1808,17 +1811,25 @@ static void print_ie(const struct ie_pri static const struct ie_print ieprinters[] = { - [0] = { "SSID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), }, -+ [45] = { "HT capabilities", print_ht_capa, 26, 26, BIT(PRINT_SCAN), }, -+ [48] = { "RSN", print_rsn, 2, 255, BIT(PRINT_SCAN), }, -+ [61] = { "HT operation", print_ht_op, 22, 22, BIT(PRINT_SCAN), }, -+ [62] = { "Secondary Channel Offset", print_secchan_offs, 1, 1, BIT(PRINT_SCAN), }, -+ [114] = { "MESH ID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), }, -+ [191] = { "VHT capabilities", print_vht_capa, 12, 255, BIT(PRINT_SCAN), }, -+ [192] = { "VHT operation", print_vht_oper, 5, 255, BIT(PRINT_SCAN), }, + [EID_SSID] = { "SSID", print_ssid, 0, 32, + BIT(PRINT_SCAN) | BIT(PRINT_LINK) | BIT(PRINT_LINK_MLO_MLD), }, ++ [EID_BSS_LOAD] = { "BSS Load", print_bss_load, 5, 5, BIT(PRINT_SCAN), }, ++ [EID_HT_CAPABILITY] = { "HT capabilities", print_ht_capa, 26, 26, BIT(PRINT_SCAN), }, ++ [EID_RSN] = { "RSN", print_rsn, 2, 255, BIT(PRINT_SCAN), }, ++ [EID_HT_OPERATION] = { "HT operation", print_ht_op, 22, 22, BIT(PRINT_SCAN), }, ++ [EID_SECONDARY_CH_OFFSET] = { "Secondary Channel Offset", ++ print_secchan_offs, 1, 1, BIT(PRINT_SCAN), }, ++ [EID_MESH_ID] = { "MESH ID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), }, ++ [EID_VHT_CAPABILITY] = { "VHT capabilities", print_vht_capa, 12, 255, BIT(PRINT_SCAN), }, ++ [EID_VHT_OPERATION] = { "VHT operation", print_vht_oper, 5, 255, BIT(PRINT_SCAN), }, +#ifdef IW_FULL - [1] = { "Supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), }, - [3] = { "DS Parameter set", print_ds, 1, 1, BIT(PRINT_SCAN), }, - [5] = { "TIM", print_tim, 4, 255, BIT(PRINT_SCAN), }, -@@ -1725,26 +1736,20 @@ static const struct ie_print ieprinters[ - [32] = { "Power constraint", print_powerconstraint, 1, 1, BIT(PRINT_SCAN), }, - [35] = { "TPC report", print_tpcreport, 2, 2, BIT(PRINT_SCAN), }, - [42] = { "ERP", print_erp, 1, 255, BIT(PRINT_SCAN), }, -- [45] = { "HT capabilities", print_ht_capa, 26, 26, BIT(PRINT_SCAN), }, - [47] = { "ERP D4.0", print_erp, 1, 255, BIT(PRINT_SCAN), }, - [51] = { "AP Channel Report", print_ap_channel_report, 1, 255, BIT(PRINT_SCAN), }, - [59] = { "Supported operating classes", print_supp_op_classes, 1, 255, BIT(PRINT_SCAN), }, - [66] = { "Measurement Pilot Transmission", print_measurement_pilot_tx, 1, 255, BIT(PRINT_SCAN), }, - [74] = { "Overlapping BSS scan params", print_obss_scan_params, 14, 255, BIT(PRINT_SCAN), }, -- [61] = { "HT operation", print_ht_op, 22, 22, BIT(PRINT_SCAN), }, -- [62] = { "Secondary Channel Offset", print_secchan_offs, 1, 1, BIT(PRINT_SCAN), }, -- [191] = { "VHT capabilities", print_vht_capa, 12, 255, BIT(PRINT_SCAN), }, -- [192] = { "VHT operation", print_vht_oper, 5, 255, BIT(PRINT_SCAN), }, -- [48] = { "RSN", print_rsn, 2, 255, BIT(PRINT_SCAN), }, - [50] = { "Extended supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), }, - [70] = { "RM enabled capabilities", print_rm_enabled_capabilities, 5, 5, BIT(PRINT_SCAN), }, - [113] = { "MESH Configuration", print_mesh_conf, 7, 7, BIT(PRINT_SCAN), }, -- [114] = { "MESH ID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), }, - [127] = { "Extended capabilities", print_capabilities, 0, 255, BIT(PRINT_SCAN), }, - [107] = { "802.11u Interworking", print_interworking, 0, 255, BIT(PRINT_SCAN), }, - [108] = { "802.11u Advertisement", print_11u_advert, 0, 255, BIT(PRINT_SCAN), }, - [111] = { "802.11u Roaming Consortium", print_11u_rcon, 2, 255, BIT(PRINT_SCAN), }, - [195] = { "Transmit Power Envelope", print_tx_power_envelope, 2, 5, BIT(PRINT_SCAN), }, + [EID_SUPP_RATES] = { "Supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), }, + [EID_DS_PARAMS] = { "DS Parameter set", print_ds, 1, 1, BIT(PRINT_SCAN), }, + [EID_TIM] = { "TIM", print_tim, 4, 255, BIT(PRINT_SCAN), }, + [EID_IBSS_TIM_PARAMS] = { "IBSS ATIM window", print_ibssatim, 2, 2, BIT(PRINT_SCAN), }, + [EID_COUNTRY] = { "Country", print_country, 3, 255, BIT(PRINT_SCAN), }, +- [EID_BSS_LOAD] = { "BSS Load", print_bss_load, 5, 5, BIT(PRINT_SCAN), }, + [EID_POWER_CONSTRAINT] = { "Power constraint", print_powerconstraint, + 1, 1, BIT(PRINT_SCAN), }, + [EID_TPC_REPORT] = { "TPC report", print_tpcreport, 2, 2, BIT(PRINT_SCAN), }, + [EID_ERP_INFO] = { "ERP", print_erp, 1, 255, BIT(PRINT_SCAN), }, +- [EID_HT_CAPABILITY] = { "HT capabilities", print_ht_capa, 26, 26, BIT(PRINT_SCAN), }, + [EID_ERP_D4_0] = { "ERP D4.0", print_erp, 1, 255, BIT(PRINT_SCAN), }, + [EID_AP_CHAN_REPORT] = { "AP Channel Report", print_ap_channel_report, + 1, 255, BIT(PRINT_SCAN), }, +@@ -1828,18 +1839,11 @@ static const struct ie_print ieprinters[ + print_measurement_pilot_tx, 1, 255, BIT(PRINT_SCAN), }, + [EID_OVERLAP_BSS_SCAN_PARAM] = { "Overlapping BSS scan params", + print_obss_scan_params, 14, 255, BIT(PRINT_SCAN), }, +- [EID_HT_OPERATION] = { "HT operation", print_ht_op, 22, 22, BIT(PRINT_SCAN), }, +- [EID_SECONDARY_CH_OFFSET] = { "Secondary Channel Offset", +- print_secchan_offs, 1, 1, BIT(PRINT_SCAN), }, +- [EID_VHT_CAPABILITY] = { "VHT capabilities", print_vht_capa, 12, 255, BIT(PRINT_SCAN), }, +- [EID_VHT_OPERATION] = { "VHT operation", print_vht_oper, 5, 255, BIT(PRINT_SCAN), }, +- [EID_RSN] = { "RSN", print_rsn, 2, 255, BIT(PRINT_SCAN), }, + [EID_EXT_SUPP_RATES] = { "Extended supported rates", print_supprates, + 0, 255, BIT(PRINT_SCAN), }, + [EID_RM_ENABLED_CAPABILITIES] = { "RM enabled capabilities", + print_rm_enabled_capabilities, 5, 5, BIT(PRINT_SCAN), }, + [EID_MESH_CONFIG] = { "MESH Configuration", print_mesh_conf, 7, 7, BIT(PRINT_SCAN), }, +- [EID_MESH_ID] = { "MESH ID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), }, + [EID_EXT_CAPABILITY] = { "Extended capabilities", print_capabilities, + 0, 255, BIT(PRINT_SCAN), }, + [EID_INTERWORKING] = { "802.11u Interworking", print_interworking, +@@ -1854,6 +1858,7 @@ static const struct ie_print ieprinters[ + print_short_beacon_int, 2, 2, BIT(PRINT_SCAN), }, + [EID_S1G_CAPABILITY] = { "S1G capabilities", print_s1g_capa, 15, 15, BIT(PRINT_SCAN), }, + [EID_S1G_OPERATION] = { "S1G operation", print_s1g_oper, 6, 6, BIT(PRINT_SCAN), }, +#endif }; static void print_wifi_wpa(const uint8_t type, uint8_t len, const uint8_t *data, -@@ -2080,8 +2085,10 @@ static void print_wifi_wps(const uint8_t +@@ -2189,8 +2194,10 @@ static void print_wifi_wps(const uint8_t static const struct ie_print wifiprinters[] = { [1] = { "WPA", print_wifi_wpa, 2, 255, BIT(PRINT_SCAN), }, @@ -196,7 +208,7 @@ }; static inline void print_p2p(const uint8_t type, uint8_t len, -@@ -2244,6 +2251,10 @@ static void print_vendor(unsigned char l +@@ -2353,6 +2360,10 @@ static void print_vendor(unsigned char l return; } @@ -207,7 +219,7 @@ if (len >= 4 && memcmp(data, wfa_oui, 3) == 0) { if (data[3] < ARRAY_SIZE(wfa_printers) && wfa_printers[data[3]].name && -@@ -2377,6 +2388,7 @@ static void print_capa_non_dmg(__u16 cap +@@ -2544,6 +2555,7 @@ static void print_capa_non_dmg(__u16 cap printf(" ESS"); if (capa & WLAN_CAPABILITY_IBSS) printf(" IBSS"); @@ -215,7 +227,7 @@ if (capa & WLAN_CAPABILITY_CF_POLLABLE) printf(" CfPollable"); if (capa & WLAN_CAPABILITY_CF_POLL_REQUEST) -@@ -2405,6 +2417,7 @@ static void print_capa_non_dmg(__u16 cap +@@ -2572,6 +2584,7 @@ static void print_capa_non_dmg(__u16 cap printf(" DelayedBACK"); if (capa & WLAN_CAPABILITY_IMM_BACK) printf(" ImmediateBACK"); @@ -223,10 +235,10 @@ } static int print_bss_handler(struct nl_msg *msg, void *arg) -@@ -2489,8 +2502,10 @@ static int print_bss_handler(struct nl_m - if (bss[NL80211_BSS_FREQUENCY]) { - int freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]); - printf("\tfreq: %d\n", freq); +@@ -2662,8 +2675,10 @@ static int print_bss_handler(struct nl_m + else + printf("\tfreq: %d\n", freq); + +#ifdef IW_FULL if (freq > 45000) is_dmg = true; @@ -234,7 +246,7 @@ } if (bss[NL80211_BSS_BEACON_INTERVAL]) printf("\tbeacon interval: %d TUs\n", -@@ -2684,6 +2699,7 @@ static int handle_stop_sched_scan(struct +@@ -2857,6 +2872,7 @@ static int handle_stop_sched_scan(struct return 0; } @@ -242,7 +254,7 @@ COMMAND(scan, sched_start, SCHED_SCAN_OPTIONS, NL80211_CMD_START_SCHED_SCAN, 0, CIB_NETDEV, handle_start_sched_scan, -@@ -2694,3 +2710,4 @@ COMMAND(scan, sched_start, +@@ -2867,3 +2883,4 @@ COMMAND(scan, sched_start, COMMAND(scan, sched_stop, "", NL80211_CMD_STOP_SCHED_SCAN, 0, CIB_NETDEV, handle_stop_sched_scan, "Stop an ongoing scheduled scan."); @@ -265,7 +277,7 @@ int ieee80211_channel_to_frequency(int chan, enum nl80211_band band) { -@@ -311,6 +313,9 @@ int parse_keys(struct nl_msg *msg, char +@@ -313,6 +315,9 @@ int parse_keys(struct nl_msg *msg, char char keybuf[13]; int pos = 0; @@ -277,7 +289,7 @@ --- a/Makefile +++ b/Makefile -@@ -23,6 +23,12 @@ _OBJS := $(sort $(patsubst %.c,%.o,$(wil +@@ -24,6 +24,12 @@ _OBJS := $(sort $(patsubst %.c,%.o,$(wil VERSION_OBJS := $(filter-out version.o, $(_OBJS)) OBJS := $(VERSION_OBJS) version.o @@ -292,7 +304,7 @@ ifeq ($(NO_PKG_CONFIG),) --- a/station.c +++ b/station.c -@@ -791,10 +791,12 @@ static int handle_station_set_plink(stru +@@ -801,10 +801,12 @@ static int handle_station_set_plink(stru nla_put_failure: return -ENOBUFS; } @@ -305,7 +317,7 @@ static int handle_station_set_vlan(struct nl80211_state *state, struct nl_msg *msg, -@@ -889,11 +891,13 @@ static int handle_station_set_mesh_power +@@ -899,11 +901,13 @@ static int handle_station_set_mesh_power nla_put_failure: return -ENOBUFS; } @@ -321,7 +333,7 @@ struct nl_msg *msg, --- a/interface.c +++ b/interface.c -@@ -629,9 +629,11 @@ static int handle_interface_wds_peer(str +@@ -668,9 +668,11 @@ static int handle_interface_wds_peer(str nla_put_failure: return -ENOBUFS; } @@ -333,7 +345,7 @@ static int set_mcast_rate(struct nl80211_state *state, struct nl_msg *msg, -@@ -721,6 +723,7 @@ static int handle_chan(struct nl80211_st +@@ -760,6 +762,7 @@ static int handle_chan(struct nl80211_st return handle_chanfreq(state, msg, true, argc, argv, id); } @@ -341,14 +353,14 @@ SECTION(switch); COMMAND(switch, freq, " [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz] [beacons ] [block-tx]\n" -@@ -992,3 +995,4 @@ COMMAND(set, tidconf, "[peer [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n" "freq [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n" "freq [5|10|20|40|80|80+80|160] [ []]", -@@ -380,6 +381,7 @@ COMMAND(cac, trigger, - NL80211_CMD_RADAR_DETECT, 0, CIB_NETDEV, handle_cac_trigger, - "Start or trigger a channel availability check (CAC) looking to look for\n" +@@ -422,6 +423,7 @@ COMMAND(cac, background, + NL80211_CMD_RADAR_DETECT, 0, CIB_NETDEV, handle_cac_background, + "Start background channel availability check (CAC) looking to look for\n" "radars on the given channel."); +#endif diff --git a/lede/package/network/utils/iw/patches/300-wiphy_radios.patch b/lede/package/network/utils/iw/patches/300-wiphy_radios.patch new file mode 100644 index 0000000000..534addf897 --- /dev/null +++ b/lede/package/network/utils/iw/patches/300-wiphy_radios.patch @@ -0,0 +1,252 @@ +--- a/info.c ++++ b/info.c +@@ -295,6 +295,151 @@ static void print_pmsr_capabilities(stru + } + } + ++static void print_interface_combinations(struct nlattr *ifcomb, bool radio) ++{ ++ const char *indent = radio ? "\t" : ""; ++ struct nlattr *nl_combi; ++ bool have_combinations = false; ++ int rem; ++ ++ nla_for_each_nested(nl_combi, ifcomb, rem) { ++ static struct nla_policy iface_combination_policy[NUM_NL80211_IFACE_COMB] = { ++ [NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED }, ++ [NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 }, ++ [NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG }, ++ [NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 }, ++ [NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS] = { .type = NLA_U32 }, ++ }; ++ struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB]; ++ static struct nla_policy iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = { ++ [NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED }, ++ [NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 }, ++ }; ++ struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT]; ++ struct nlattr *nl_limit; ++ int err, rem_limit; ++ bool comma = false; ++ ++ if (radio && nla_type(nl_combi) != ++ NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION) ++ continue; ++ ++ if (!have_combinations) { ++ printf("\t%svalid interface combinations:\n", indent); ++ have_combinations = true; ++ } ++ ++ printf("\t\t%s * ", indent); ++ ++ err = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB, ++ nl_combi, iface_combination_policy); ++ if (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] || ++ !tb_comb[NL80211_IFACE_COMB_MAXNUM] || ++ !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]) { ++ printf(" \n"); ++ goto broken_combination; ++ } ++ ++ nla_for_each_nested(nl_limit, tb_comb[NL80211_IFACE_COMB_LIMITS], rem_limit) { ++ err = nla_parse_nested(tb_limit, MAX_NL80211_IFACE_LIMIT, ++ nl_limit, iface_limit_policy); ++ if (err || !tb_limit[NL80211_IFACE_LIMIT_TYPES]) { ++ printf("\n"); ++ goto broken_combination; ++ } ++ ++ if (comma) ++ printf(", "); ++ comma = true; ++ printf("#{ "); ++ print_iftype_line(tb_limit[NL80211_IFACE_LIMIT_TYPES]); ++ printf(" } <= %u", nla_get_u32(tb_limit[NL80211_IFACE_LIMIT_MAX])); ++ } ++ printf(",\n\t\t%s ", indent); ++ ++ printf("total <= %d, #channels <= %d%s", ++ nla_get_u32(tb_comb[NL80211_IFACE_COMB_MAXNUM]), ++ nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]), ++ tb_comb[NL80211_IFACE_COMB_STA_AP_BI_MATCH] ? ++ ", STA/AP BI must match" : ""); ++ if (tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS]) { ++ unsigned long widths = nla_get_u32(tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS]); ++ ++ if (widths) { ++ int width; ++ bool first = true; ++ ++ printf(", radar detect widths: {"); ++ for (width = 0; width < 32; width++) ++ if (widths & (1 << width)) { ++ printf("%s %s", ++ first ? "":",", ++ channel_width_name(width)); ++ first = false; ++ } ++ printf(" }\n"); ++ } ++ } ++ printf("\n"); ++broken_combination: ++ ; ++ } ++ ++ if (!have_combinations) ++ printf("\t%sinterface combinations are not supported\n", indent); ++} ++ ++static void print_radio_freq(struct nlattr *freqs) ++{ ++ struct nlattr *freq; ++ int rem; ++ ++ nla_for_each_nested(freq, freqs, rem) { ++ static struct nla_policy freq_policy[NL80211_WIPHY_RADIO_FREQ_ATTR_MAX + 1] = { ++ [NL80211_WIPHY_RADIO_FREQ_ATTR_START] = { .type = NLA_U32 }, ++ [NL80211_WIPHY_RADIO_FREQ_ATTR_END] = { .type = NLA_U32 }, ++ }; ++ struct nlattr *tb[NL80211_WIPHY_RADIO_FREQ_ATTR_MAX + 1]; ++ uint32_t start, end; ++ ++ if (nla_type(freq) != NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE) ++ continue; ++ ++ if (nla_parse_nested(tb, NL80211_WIPHY_RADIO_ATTR_MAX + 1, ++ freq, freq_policy) || ++ !tb[NL80211_WIPHY_RADIO_FREQ_ATTR_START] || ++ !tb[NL80211_WIPHY_RADIO_FREQ_ATTR_END]) ++ continue; ++ ++ start = nla_get_u32(tb[NL80211_WIPHY_RADIO_FREQ_ATTR_START]); ++ end = nla_get_u32(tb[NL80211_WIPHY_RADIO_FREQ_ATTR_END]); ++ ++ printf("\t\tfreq range: %.1f MHz - %.1f MHz\n", (float)start / 1000, (float)end / 1000); ++ } ++} ++ ++static void print_radios(struct nlattr *radios) ++{ ++ struct nlattr *radio; ++ int rem, idx = 0; ++ ++ nla_for_each_nested(radio, radios, rem) { ++ static struct nla_policy radio_policy[NL80211_WIPHY_RADIO_ATTR_MAX + 1] = { ++ [NL80211_WIPHY_RADIO_ATTR_INDEX] = { .type = NLA_U32 }, ++ }; ++ struct nlattr *tb[NL80211_WIPHY_RADIO_ATTR_MAX + 1]; ++ ++ if (nla_parse_nested(tb, NL80211_WIPHY_RADIO_ATTR_MAX + 1, ++ radio, radio_policy) || ++ !tb[NL80211_WIPHY_RADIO_ATTR_INDEX]) ++ continue; ++ ++ printf("\twiphy radio %d:\n", nla_get_u32(tb[NL80211_WIPHY_RADIO_ATTR_INDEX])); ++ print_radio_freq(radio); ++ print_interface_combinations(radio, true); ++ } ++} ++ + static int print_phy_handler(struct nl_msg *msg, void *arg) + { + struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; +@@ -565,93 +710,11 @@ next: + "\t\t", tb_msg[NL80211_ATTR_SOFTWARE_IFTYPES]); + #endif + +- if (tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS]) { +- struct nlattr *nl_combi; +- int rem_combi; +- bool have_combinations = false; +- +- nla_for_each_nested(nl_combi, tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS], rem_combi) { +- static struct nla_policy iface_combination_policy[NUM_NL80211_IFACE_COMB] = { +- [NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED }, +- [NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 }, +- [NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG }, +- [NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 }, +- [NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS] = { .type = NLA_U32 }, +- }; +- struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB]; +- static struct nla_policy iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = { +- [NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED }, +- [NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 }, +- }; +- struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT]; +- struct nlattr *nl_limit; +- int err, rem_limit; +- bool comma = false; +- +- if (!have_combinations) { +- printf("\tvalid interface combinations:\n"); +- have_combinations = true; +- } +- +- printf("\t\t * "); ++ if (tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS]) ++ print_interface_combinations(tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS], false); + +- err = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB, +- nl_combi, iface_combination_policy); +- if (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] || +- !tb_comb[NL80211_IFACE_COMB_MAXNUM] || +- !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]) { +- printf(" \n"); +- goto broken_combination; +- } +- +- nla_for_each_nested(nl_limit, tb_comb[NL80211_IFACE_COMB_LIMITS], rem_limit) { +- err = nla_parse_nested(tb_limit, MAX_NL80211_IFACE_LIMIT, +- nl_limit, iface_limit_policy); +- if (err || !tb_limit[NL80211_IFACE_LIMIT_TYPES]) { +- printf("\n"); +- goto broken_combination; +- } +- +- if (comma) +- printf(", "); +- comma = true; +- printf("#{ "); +- print_iftype_line(tb_limit[NL80211_IFACE_LIMIT_TYPES]); +- printf(" } <= %u", nla_get_u32(tb_limit[NL80211_IFACE_LIMIT_MAX])); +- } +- printf(",\n\t\t "); +- +- printf("total <= %d, #channels <= %d%s", +- nla_get_u32(tb_comb[NL80211_IFACE_COMB_MAXNUM]), +- nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]), +- tb_comb[NL80211_IFACE_COMB_STA_AP_BI_MATCH] ? +- ", STA/AP BI must match" : ""); +- if (tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS]) { +- unsigned long widths = nla_get_u32(tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS]); +- +- if (widths) { +- int width; +- bool first = true; +- +- printf(", radar detect widths: {"); +- for (width = 0; width < 32; width++) +- if (widths & (1 << width)) { +- printf("%s %s", +- first ? "":",", +- channel_width_name(width)); +- first = false; +- } +- printf(" }\n"); +- } +- } +- printf("\n"); +-broken_combination: +- ; +- } +- +- if (!have_combinations) +- printf("\tinterface combinations are not supported\n"); +- } ++ if (tb_msg[NL80211_ATTR_WIPHY_RADIOS]) ++ print_radios(tb_msg[NL80211_ATTR_WIPHY_RADIOS]); + + #ifdef IW_FULL + if (tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS]) { diff --git a/lede/package/network/utils/iw/patches/310-vif_radio_mask.patch b/lede/package/network/utils/iw/patches/310-vif_radio_mask.patch new file mode 100644 index 0000000000..724f71cdad --- /dev/null +++ b/lede/package/network/utils/iw/patches/310-vif_radio_mask.patch @@ -0,0 +1,99 @@ +--- a/interface.c ++++ b/interface.c +@@ -226,6 +226,43 @@ nla_put_failure: + return 1; + } + ++static int parse_radio_list(char *str, struct nl_msg *msg) ++{ ++ unsigned int mask = 0; ++ unsigned long id; ++ char *end; ++ ++ if (!str) ++ return 1; ++ ++ if (!strcmp(str, "all")) ++ goto out; ++ ++ while (1) { ++ if (!*str) ++ return 1; ++ ++ id = strtoul(str, &end, 0); ++ if (id > 31) ++ return 1; ++ ++ mask |= 1 << id; ++ if (!*end) ++ break; ++ ++ if (end == str || *end != ',') ++ return 1; ++ ++ str = end + 1; ++ } ++ ++out: ++ NLA_PUT_U32(msg, NL80211_ATTR_VIF_RADIO_MASK, mask); ++ return 0; ++nla_put_failure: ++ return 1; ++} ++ + static int handle_interface_add(struct nl80211_state *state, + struct nl_msg *msg, + int argc, char **argv, +@@ -287,6 +324,15 @@ try_another: + fprintf(stderr, "flags error\n"); + return 2; + } ++ } else if (strcmp(argv[0], "radios") == 0) { ++ argc--; ++ argv++; ++ if (parse_radio_list(argv[0], msg)) { ++ fprintf(stderr, "Invalid radio list\n"); ++ return 2; ++ } ++ argc--; ++ argv++; + } else { + return 1; + } +@@ -306,14 +352,14 @@ try_another: + nla_put_failure: + return -ENOBUFS; + } +-COMMAND(interface, add, " type [mesh_id ] [4addr on|off] [flags *] [addr ]", ++COMMAND(interface, add, " type [mesh_id ] [4addr on|off] [flags *] [addr ] [radios all|[,...]]", + NL80211_CMD_NEW_INTERFACE, 0, CIB_PHY, handle_interface_add, + "Add a new virtual interface with the given configuration.\n" + IFACE_TYPES "\n\n" + "The flags are only used for monitor interfaces, valid flags are:\n" + VALID_FLAGS "\n\n" + "The mesh_id is used only for mesh mode."); +-COMMAND(interface, add, " type [mesh_id ] [4addr on|off] [flags *] [addr ]", ++COMMAND(interface, add, " type [mesh_id ] [4addr on|off] [flags *] [addr ] [radios all|[,...]]", + NL80211_CMD_NEW_INTERFACE, 0, CIB_NETDEV, handle_interface_add, NULL); + + static int handle_interface_del(struct nl80211_state *state, +@@ -493,6 +539,19 @@ static int print_iface_handler(struct nl + printf("\n"); + } + } ++ ++ if (tb_msg[NL80211_ATTR_VIF_RADIO_MASK]) { ++ uint32_t mask = nla_get_u32(tb_msg[NL80211_ATTR_VIF_RADIO_MASK]); ++ int i; ++ ++ if (mask) { ++ printf("%s\tRadios:", indent); ++ for (i = 0; mask; i++, mask >>= 1) ++ if (mask & 1) ++ printf(" %d", i); ++ printf("\n"); ++ } ++ } + + return NL_SKIP; + } diff --git a/lede/target/linux/ath79/Makefile b/lede/target/linux/ath79/Makefile index dd57d9fed9..18009ff9e1 100644 --- a/lede/target/linux/ath79/Makefile +++ b/lede/target/linux/ath79/Makefile @@ -8,7 +8,8 @@ SUBTARGETS:=generic mikrotik nand tiny FEATURES:=ramdisk squashfs usbgadget -KERNEL_PATCHVER:=5.10 +KERNEL_PATCHVER:=6.6 +KERNEL_TESTING_PATCHVER:=5.15 include $(INCLUDE_DIR)/target.mk diff --git a/lede/target/linux/ath79/config-6.6 b/lede/target/linux/ath79/config-6.6 new file mode 100644 index 0000000000..c43dbfd719 --- /dev/null +++ b/lede/target/linux/ath79/config-6.6 @@ -0,0 +1,222 @@ +# CONFIG_AG71XX is not set +CONFIG_AG71XX_LEGACY=y +# CONFIG_AG71XX_LEGACY_DEBUG is not set +CONFIG_AG71XX_LEGACY_DEBUG_FS=y +CONFIG_AR8216_PHY=y +CONFIG_AR8216_PHY_LEDS=y +CONFIG_ARCH_32BIT_OFF_T=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MMAP_RND_BITS_MAX=15 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_AT803X_PHY=y +CONFIG_ATH79=y +CONFIG_ATH79_WDT=y +CONFIG_BLK_MQ_PCI=y +CONFIG_CEVT_R4K=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMDLINE="rootfstype=squashfs,jffs2" +CONFIG_CMDLINE_BOOL=y +# CONFIG_CMDLINE_OVERRIDE is not set +CONFIG_COMMON_CLK=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_CPU_BIG_ENDIAN=y +CONFIG_CPU_GENERIC_DUMP_TLB=y +CONFIG_CPU_HAS_DIEI=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_RIXI=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_CPU_MIPS32=y +CONFIG_CPU_MIPS32_R2=y +CONFIG_CPU_MIPSR2=y +CONFIG_CPU_MITIGATIONS=y +CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y +CONFIG_CPU_R4K_CACHE_TLB=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_CPU_SUPPORTS_MSA=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2 +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CSRC_R4K=y +CONFIG_DEBUG_INFO=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_DTC=y +CONFIG_EARLY_PRINTK=y +CONFIG_ETHERNET_PACKET_MANGLE=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_FIXED_PHY=y +CONFIG_FORCE_NR_CPUS=y +CONFIG_FS_IOMAP=y +CONFIG_FUNCTION_ALIGNMENT=0 +CONFIG_FWNODE_MDIO=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=y +CONFIG_GENERIC_ATOMIC64=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_LIB_ASHLDI3=y +CONFIG_GENERIC_LIB_ASHRDI3=y +CONFIG_GENERIC_LIB_CMPDI2=y +CONFIG_GENERIC_LIB_LSHRDI3=y +CONFIG_GENERIC_LIB_UCMPDI2=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_TIME_VSYSCALL=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_74X164=y +CONFIG_GPIO_ATH79=y +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_GENERIC=y +# CONFIG_GPIO_LATCH_MIKROTIK is not set +# CONFIG_GPIO_RB91X_KEY is not set +CONFIG_HARDWARE_WATCHPOINTS=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HZ_PERIODIC=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_MIPS_CPU=y +CONFIG_IRQ_WORK=y +CONFIG_LEDS_GPIO=y +# CONFIG_LEDS_RESET is not set +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_MDIO_BITBANG=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y +CONFIG_MDIO_GPIO=y +# CONFIG_MFD_RB4XX_CPLD is not set +CONFIG_MFD_SYSCON=y +CONFIG_MIGRATION=y +CONFIG_MIPS=y +CONFIG_MIPS_ASID_BITS=8 +CONFIG_MIPS_ASID_SHIFT=0 +CONFIG_MIPS_CLOCK_VSYSCALL=y +# CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set +# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set +CONFIG_MIPS_CMDLINE_FROM_DTB=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_MIPS_NO_APPENDED_DTB is not set +CONFIG_MIPS_RAW_APPENDED_DTB=y +CONFIG_MIPS_SPRAM=y +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_GEOMETRY=y +# CONFIG_MTD_CFI_I2 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set +CONFIG_MTD_PARSER_CYBERTAN=y +# CONFIG_MTD_PARSER_TPLINK_SAFELOADER is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_ELF_FW=y +CONFIG_MTD_SPLIT_LZMA_FW=y +CONFIG_MTD_SPLIT_SEAMA_FW=y +CONFIG_MTD_SPLIT_TPLINK_FW=y +CONFIG_MTD_SPLIT_UIMAGE_FW=y +CONFIG_MTD_SPLIT_WRGG_FW=y +CONFIG_MTD_VIRT_CONCAT=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_PER_CPU_KM=y +CONFIG_NET_EGRESS=y +CONFIG_NET_INGRESS=y +CONFIG_NET_SELFTESTS=y +CONFIG_NET_XGRESS=y +CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y +CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=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_PCI=y +CONFIG_PCI_AR71XX=y +CONFIG_PCI_AR724X=y +CONFIG_PCI_DISABLE_COMMON_QUIRKS=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DRIVERS_LEGACY=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHYLIB=y +CONFIG_PHYLIB_LEDS=y +# CONFIG_PHY_AR7100_USB is not set +# CONFIG_PHY_AR7200_USB is not set +# CONFIG_PHY_ATH79_USB is not set +CONFIG_PINCTRL=y +CONFIG_PREEMPT_NONE_BUILD=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_QCOM_NET_PHYLIB=y +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RATIONAL=y +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGULATOR=y +CONFIG_RESET_ATH79=y +CONFIG_RESET_CONTROLLER=y +CONFIG_SERIAL_8250_NR_UARTS=1 +CONFIG_SERIAL_8250_RUNTIME_UARTS=1 +CONFIG_SERIAL_AR933X=y +CONFIG_SERIAL_AR933X_CONSOLE=y +CONFIG_SERIAL_AR933X_NR_UARTS=2 +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SPI=y +CONFIG_SPI_AR934X=y +CONFIG_SPI_ATH79=y +CONFIG_SPI_BITBANG=y +CONFIG_SPI_GPIO=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +# CONFIG_SPI_RB4XX is not set +# CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI_PERCPU is not set +CONFIG_SQUASHFS_COMPILE_DECOMP_SINGLE=y +CONFIG_SQUASHFS_DECOMP_SINGLE=y +CONFIG_SWCONFIG=y +CONFIG_SWCONFIG_LEDS=y +CONFIG_SWPHY=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_SYS_HAS_CPU_MIPS32_R2=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y +CONFIG_SYS_SUPPORTS_MIPS16=y +CONFIG_SYS_SUPPORTS_ZBOOT=y +CONFIG_SYS_SUPPORTS_ZBOOT_UART_PROM=y +CONFIG_TARGET_ISA_REV=2 +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TINY_SRCU=y +CONFIG_USB_SUPPORT=y +CONFIG_USE_OF=y +CONFIG_ZBOOT_LOAD_ADDRESS=0x0 diff --git a/lede/target/linux/ath79/image/common-netgear.mk b/lede/target/linux/ath79/image/common-netgear.mk index 5a61caf1f6..c3b20cf1dc 100644 --- a/lede/target/linux/ath79/image/common-netgear.mk +++ b/lede/target/linux/ath79/image/common-netgear.mk @@ -12,7 +12,7 @@ define Build/netgear-squashfs rm -rf $@.fs $@.squashfs mkdir -p $@.fs/image cp $@ $@.fs/image/uImage - $(STAGING_DIR_HOST)/bin/mksquashfs-lzma \ + $(STAGING_DIR_HOST)/bin/mksquashfs3-lzma \ $@.fs $@.squashfs -be \ -noappend -root-owned -b 65536 \ $(if $(SOURCE_DATE_EPOCH),-fixed-time $(SOURCE_DATE_EPOCH)) diff --git a/lede/target/linux/ath79/patches-6.6/001-v6.11-gpio-ath79-convert-to-dynamic-GPIO-base-allocation.patch b/lede/target/linux/ath79/patches-6.6/001-v6.11-gpio-ath79-convert-to-dynamic-GPIO-base-allocation.patch new file mode 100644 index 0000000000..4222639d4d --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/001-v6.11-gpio-ath79-convert-to-dynamic-GPIO-base-allocation.patch @@ -0,0 +1,32 @@ +From 9a473c2a093e0d1c466bf86073230e2c8b658977 Mon Sep 17 00:00:00 2001 +From: Shiji Yang +Date: Wed, 26 Jun 2024 08:33:18 +0800 +Subject: gpio: ath79: convert to dynamic GPIO base allocation + +ath79 target has already been converted to device tree based platform. +Use dynamic GPIO numberspace base to suppress the warning: + +gpio gpiochip0: Static allocation of GPIO base is deprecated, use dynamic allocation. + +Tested on Atheros AR7241 and AR9344. + +Signed-off-by: Shiji Yang +Suggested-by: Jonas Gorski +Link: https://lore.kernel.org/r/TYCP286MB089598EA71E964BD8AB9EFD3BCD62@TYCP286MB0895.JPNP286.PROD.OUTLOOK.COM +[Bartosz: tweaked the commit message] +Signed-off-by: Bartosz Golaszewski +--- + drivers/gpio/gpio-ath79.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/gpio/gpio-ath79.c ++++ b/drivers/gpio/gpio-ath79.c +@@ -273,8 +273,6 @@ static int ath79_gpio_probe(struct platf + dev_err(dev, "bgpio_init failed\n"); + return err; + } +- /* Use base 0 to stay compatible with legacy platforms */ +- ctrl->gc.base = 0; + + /* Optional interrupt setup */ + if (!np || of_property_read_bool(np, "interrupt-controller")) { diff --git a/lede/target/linux/ath79/patches-6.6/100-reset-ath79-read-back-reset-register.patch b/lede/target/linux/ath79/patches-6.6/100-reset-ath79-read-back-reset-register.patch new file mode 100644 index 0000000000..7aa501514d --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/100-reset-ath79-read-back-reset-register.patch @@ -0,0 +1,33 @@ +From 661edfc3dab943a67c8821353b63cc23057f7ce9 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Tue, 9 Jan 2024 20:48:46 +0100 +Subject: [PATCH] reset: ath79: read back reset register + +Read back the reset register in order to flush the cache. This fixes +spurious reboot hangs on TP-Link TL-WDR3600 and TL-WDR4300 with Zentel +DRAM chips. + +This issue was fixed in the past, but switching to the reset-driver +specific implementation removed the old fix. + +Link: https://github.com/freifunk-gluon/gluon/issues/2904 +Link: https://github.com/openwrt/openwrt/issues/13043 +Link: https://dev.archive.openwrt.org/ticket/17839 +Link: f8a7bfe1cb2c ("MIPS: ath79: fix system restart") + +Signed-off-by: David Bauer +--- + drivers/reset/reset-ath79.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/reset/reset-ath79.c ++++ b/drivers/reset/reset-ath79.c +@@ -37,6 +37,8 @@ static int ath79_reset_update(struct res + else + val &= ~BIT(id); + writel(val, ath79_reset->base); ++ /* Flush cache */ ++ readl(ath79_reset->base); + spin_unlock_irqrestore(&ath79_reset->lock, flags); + + return 0; diff --git a/lede/target/linux/ath79/patches-6.6/101-reset-ath79-reset-ETH-switch-for-AR9344.patch b/lede/target/linux/ath79/patches-6.6/101-reset-ath79-reset-ETH-switch-for-AR9344.patch new file mode 100644 index 0000000000..5d9daf1c1c --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/101-reset-ath79-reset-ETH-switch-for-AR9344.patch @@ -0,0 +1,105 @@ +From: David Bauer +Date: Tue, 2 Jan 2025 19:22:40 +0100 +Subject: [PATCH] reset: ath79: reset ETH switch for AR9344 + +According to datasheet, on AR9344 the switch and switch analog need to +be reset first before initiating a full reset. + +Resetting these systems fixes spurious reset hangs on Atheros AR9344 +SoCs. + +Link: https://github.com/freifunk-gluon/gluon/issues/2904 + +Signed-off-by: David Bauer + +--- a/drivers/reset/reset-ath79.c ++++ b/drivers/reset/reset-ath79.c +@@ -12,8 +12,11 @@ + #include + #include + #include ++#include ++#include + + struct ath79_reset { ++ struct platform_device *pdev; + struct reset_controller_dev rcdev; + struct notifier_block restart_nb; + void __iomem *base; +@@ -21,16 +24,13 @@ struct ath79_reset { + }; + + #define FULL_CHIP_RESET 24 ++#define ETH_SWITCH_RESET 8 ++#define ETH_SWITCH_ARESET 12 + +-static int ath79_reset_update(struct reset_controller_dev *rcdev, ++static void __ath79_reset_update_unlocked(struct ath79_reset *ath79_reset, + unsigned long id, bool assert) + { +- struct ath79_reset *ath79_reset = +- container_of(rcdev, struct ath79_reset, rcdev); +- unsigned long flags; + u32 val; +- +- spin_lock_irqsave(&ath79_reset->lock, flags); + val = readl(ath79_reset->base); + if (assert) + val |= BIT(id); +@@ -39,6 +39,17 @@ static int ath79_reset_update(struct res + writel(val, ath79_reset->base); + /* Flush cache */ + readl(ath79_reset->base); ++} ++ ++static int ath79_reset_update(struct reset_controller_dev *rcdev, ++ unsigned long id, bool assert) ++{ ++ struct ath79_reset *ath79_reset = ++ container_of(rcdev, struct ath79_reset, rcdev); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ath79_reset->lock, flags); ++ __ath79_reset_update_unlocked(ath79_reset, id, assert); + spin_unlock_irqrestore(&ath79_reset->lock, flags); + + return 0; +@@ -79,8 +90,28 @@ static int ath79_reset_restart_handler(s + { + struct ath79_reset *ath79_reset = + container_of(nb, struct ath79_reset, restart_nb); ++ unsigned long flags; + +- ath79_reset_assert(&ath79_reset->rcdev, FULL_CHIP_RESET); ++ spin_lock_irqsave(&ath79_reset->lock, flags); ++ ++ if (of_device_is_compatible(ath79_reset->pdev->dev.of_node, "qca,ar9340-reset")) { ++ /** ++ * AR9344 has been observed to hang on reboot in rare cases. ++ * ++ * Datasheet states to reset the ETH switch systems before asserting ++ * full chip reset. See page 111 of the AR9344 datasheet. ++ */ ++ __ath79_reset_update_unlocked(ath79_reset, ETH_SWITCH_RESET, true); ++ mdelay(1); ++ __ath79_reset_update_unlocked(ath79_reset, ETH_SWITCH_ARESET, true); ++ mdelay(1); ++ __ath79_reset_update_unlocked(ath79_reset, FULL_CHIP_RESET, true); ++ mdelay(10); ++ } else { ++ __ath79_reset_update_unlocked(ath79_reset, FULL_CHIP_RESET, true); ++ } ++ ++ spin_unlock_irqrestore(&ath79_reset->lock, flags); + + return NOTIFY_DONE; + } +@@ -95,6 +126,8 @@ static int ath79_reset_probe(struct plat + if (!ath79_reset) + return -ENOMEM; + ++ ath79_reset->pdev = pdev; ++ + ath79_reset->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(ath79_reset->base)) + return PTR_ERR(ath79_reset->base); diff --git a/lede/target/linux/ath79/patches-6.6/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch b/lede/target/linux/ath79/patches-6.6/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch new file mode 100644 index 0000000000..ceda511c21 --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/300-irqchip-irq-ath79-intc-add-irq-cascade-driver-for-QC.patch @@ -0,0 +1,168 @@ +From f3eacff2310a60348a755c50a8da6fc251fc8587 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Tue, 6 Mar 2018 09:55:13 +0100 +Subject: [PATCH 07/33] irqchip/irq-ath79-intc: add irq cascade driver for + QCA9556 SoCs + +Signed-off-by: John Crispin +--- + drivers/irqchip/Makefile | 1 + + drivers/irqchip/irq-ath79-intc.c | 142 +++++++++++++++++++++++++++++++++++++++ + 2 files changed, 143 insertions(+) + create mode 100644 drivers/irqchip/irq-ath79-intc.c + +--- a/drivers/irqchip/Makefile ++++ b/drivers/irqchip/Makefile +@@ -4,6 +4,7 @@ obj-$(CONFIG_IRQCHIP) += irqchip.o + obj-$(CONFIG_AL_FIC) += irq-al-fic.o + obj-$(CONFIG_ALPINE_MSI) += irq-alpine-msi.o + obj-$(CONFIG_ATH79) += irq-ath79-cpu.o ++obj-$(CONFIG_ATH79) += irq-ath79-intc.o + obj-$(CONFIG_ATH79) += irq-ath79-misc.o + obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o + obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o +--- /dev/null ++++ b/drivers/irqchip/irq-ath79-intc.c +@@ -0,0 +1,142 @@ ++/* ++ * Atheros AR71xx/AR724x/AR913x specific interrupt handling ++ * ++ * Copyright (C) 2018 John Crispin ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#define ATH79_MAX_INTC_CASCADE 3 ++ ++struct ath79_intc { ++ struct irq_chip chip; ++ u32 irq; ++ u32 pending_mask; ++ u32 int_status; ++ u32 irq_mask[ATH79_MAX_INTC_CASCADE]; ++ u32 irq_wb_chan[ATH79_MAX_INTC_CASCADE]; ++}; ++ ++static void ath79_intc_irq_handler(struct irq_desc *desc) ++{ ++ struct irq_domain *domain = irq_desc_get_handler_data(desc); ++ struct ath79_intc *intc = domain->host_data; ++ u32 pending; ++ ++ pending = ath79_reset_rr(intc->int_status); ++ pending &= intc->pending_mask; ++ ++ if (pending) { ++ int i; ++ ++ for (i = 0; i < domain->hwirq_max; i++) ++ if (pending & intc->irq_mask[i]) { ++ if (intc->irq_wb_chan[i] != 0xffffffff) ++ ath79_ddr_wb_flush(intc->irq_wb_chan[i]); ++ generic_handle_irq(irq_find_mapping(domain, i)); ++ } ++ } else { ++ spurious_interrupt(); ++ } ++} ++ ++static void ath79_intc_irq_enable(struct irq_data *d) ++{ ++ struct ath79_intc *intc = d->domain->host_data; ++ enable_irq(intc->irq); ++} ++ ++static void ath79_intc_irq_disable(struct irq_data *d) ++{ ++ struct ath79_intc *intc = d->domain->host_data; ++ disable_irq(intc->irq); ++} ++ ++static int ath79_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) ++{ ++ struct ath79_intc *intc = d->host_data; ++ ++ irq_set_chip_and_handler(irq, &intc->chip, handle_level_irq); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops ath79_irq_domain_ops = { ++ .xlate = irq_domain_xlate_onecell, ++ .map = ath79_intc_map, ++}; ++ ++static int __init ath79_intc_of_init( ++ struct device_node *node, struct device_node *parent) ++{ ++ struct irq_domain *domain; ++ struct ath79_intc *intc; ++ int cnt, cntwb, i, err; ++ ++ cnt = of_property_count_u32_elems(node, "qca,pending-bits"); ++ if (cnt > ATH79_MAX_INTC_CASCADE) ++ panic("Too many INTC pending bits\n"); ++ ++ intc = kzalloc(sizeof(*intc), GFP_KERNEL); ++ if (!intc) ++ panic("Failed to allocate INTC memory\n"); ++ intc->chip = dummy_irq_chip; ++ intc->chip.name = "INTC"; ++ intc->chip.irq_disable = ath79_intc_irq_disable; ++ intc->chip.irq_enable = ath79_intc_irq_enable; ++ ++ if (of_property_read_u32(node, "qca,int-status-addr", &intc->int_status) < 0) { ++ panic("Missing address of interrupt status register\n"); ++ } ++ ++ of_property_read_u32_array(node, "qca,pending-bits", intc->irq_mask, cnt); ++ for (i = 0; i < cnt; i++) { ++ intc->pending_mask |= intc->irq_mask[i]; ++ intc->irq_wb_chan[i] = 0xffffffff; ++ } ++ ++ cntwb = of_count_phandle_with_args( ++ node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells"); ++ ++ for (i = 0; i < cntwb; i++) { ++ struct of_phandle_args args; ++ u32 irq = i; ++ ++ of_property_read_u32_index( ++ node, "qca,ddr-wb-channel-interrupts", i, &irq); ++ if (irq >= ATH79_MAX_INTC_CASCADE) ++ continue; ++ ++ err = of_parse_phandle_with_args( ++ node, "qca,ddr-wb-channels", ++ "#qca,ddr-wb-channel-cells", ++ i, &args); ++ if (err) ++ return err; ++ ++ intc->irq_wb_chan[irq] = args.args[0]; ++ } ++ ++ intc->irq = irq_of_parse_and_map(node, 0); ++ if (!intc->irq) ++ panic("Failed to get INTC IRQ"); ++ ++ domain = irq_domain_add_linear(node, cnt, &ath79_irq_domain_ops, intc); ++ irq_set_chained_handler_and_data(intc->irq, ath79_intc_irq_handler, domain); ++ ++ return 0; ++} ++IRQCHIP_DECLARE(ath79_intc, "qca,ar9340-intc", ++ ath79_intc_of_init); diff --git a/lede/target/linux/ath79/patches-6.6/301-irqchip-irq-ath79-cpu-drop-OF-init-helper.patch b/lede/target/linux/ath79/patches-6.6/301-irqchip-irq-ath79-cpu-drop-OF-init-helper.patch new file mode 100644 index 0000000000..13117d9a8e --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/301-irqchip-irq-ath79-cpu-drop-OF-init-helper.patch @@ -0,0 +1,23 @@ +From e029f998594f151008ecbfa024e2957edd2a5189 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Tue, 6 Mar 2018 09:58:19 +0100 +Subject: [PATCH 08/33] irqchip/irq-ath79-cpu: drop !OF init helper + +Signed-off-by: John Crispin +--- + drivers/irqchip/irq-ath79-cpu.c | 7 ------- + 1 file changed, 7 deletions(-) + +--- a/drivers/irqchip/irq-ath79-cpu.c ++++ b/drivers/irqchip/irq-ath79-cpu.c +@@ -85,10 +85,3 @@ static int __init ar79_cpu_intc_of_init( + } + IRQCHIP_DECLARE(ar79_cpu_intc, "qca,ar7100-cpu-intc", + ar79_cpu_intc_of_init); +- +-void __init ath79_cpu_irq_init(unsigned irq_wb_chan2, unsigned irq_wb_chan3) +-{ +- irq_wb_chan[2] = irq_wb_chan2; +- irq_wb_chan[3] = irq_wb_chan3; +- mips_cpu_irq_init(); +-} diff --git a/lede/target/linux/ath79/patches-6.6/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch b/lede/target/linux/ath79/patches-6.6/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch new file mode 100644 index 0000000000..cf0a75c791 --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/310-dt-bindings-PCI-qcom-ar7100-adds-binding-doc.patch @@ -0,0 +1,57 @@ +From 4a4f869ec58ed8910b9b2e68d0eee50957e9bb20 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 25 Jun 2018 15:52:10 +0200 +Subject: [PATCH 17/33] dt-bindings: PCI: qcom,ar7100: adds binding doc + +With the driver being converted from platform_data to pure OF, we need to +also add some docs. + +Cc: Rob Herring +Cc: devicetree@vger.kernel.org +Signed-off-by: John Crispin +--- + .../devicetree/bindings/pci/qcom,ar7100-pci.txt | 38 ++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + create mode 100644 Documentation/devicetree/bindings/pci/qcom,ar7100-pci.txt + +--- /dev/null ++++ b/Documentation/devicetree/bindings/pci/qcom,ar7100-pci.txt +@@ -0,0 +1,38 @@ ++* Qualcomm Atheros AR7100 PCI express root complex ++ ++Required properties: ++- compatible: should contain "qcom,ar7100-pci" to identify the core. ++- reg: Should contain the register ranges as listed in the reg-names property. ++- reg-names: Definition: Must include the following entries ++ - "cfg_base" IO Memory ++- #address-cells: set to <3> ++- #size-cells: set to <2> ++- ranges: ranges for the PCI memory and I/O regions ++- interrupt-map-mask and interrupt-map: standard PCI ++ properties to define the mapping of the PCIe interface to interrupt ++ numbers. ++- #interrupt-cells: set to <1> ++- interrupt-controller: define to enable the builtin IRQ cascade. ++ ++Optional properties: ++- interrupt-parent: phandle to the MIPS IRQ controller ++ ++* Example for ar7100 ++ pcie@180c0000 { ++ compatible = "qca,ar7100-pci"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ bus-range = <0x0 0x0>; ++ reg = <0x17010000 0x100>; ++ reg-names = "cfg_base"; ++ ranges = <0x2000000 0 0x10000000 0x10000000 0 0x07000000 ++ 0x1000000 0 0x00000000 0x00000000 0 0x00000001>; ++ interrupt-parent = <&cpuintc>; ++ interrupts = <2>; ++ ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ ++ interrupt-map-mask = <0 0 0 1>; ++ interrupt-map = <0 0 0 0 &pcie0 0>; ++ }; diff --git a/lede/target/linux/ath79/patches-6.6/311-MIPS-pci-ar71xx-convert-to-OF.patch b/lede/target/linux/ath79/patches-6.6/311-MIPS-pci-ar71xx-convert-to-OF.patch new file mode 100644 index 0000000000..9a315aed0b --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/311-MIPS-pci-ar71xx-convert-to-OF.patch @@ -0,0 +1,206 @@ +From 1855ab6b1d27f5b38a648baf57ff6a534afec26d Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sat, 23 Jun 2018 15:07:23 +0200 +Subject: [PATCH 18/33] MIPS: pci-ar71xx: convert to OF + +With the ath79 target getting converted to pure OF, we can drop all the +platform data code and add the missing OF bits to the driver. We also add +a irq domain for the PCI/e controllers cascade, thus making it usable from +dts files. + +Signed-off-by: John Crispin +--- + arch/mips/pci/pci-ar71xx.c | 82 +++++++++++++++++++++++----------------------- + 1 file changed, 41 insertions(+), 41 deletions(-) + +--- a/arch/mips/pci/pci-ar71xx.c ++++ b/arch/mips/pci/pci-ar71xx.c +@@ -15,8 +15,11 @@ + #include + #include + #include ++#include + #include + #include ++#include ++#include + + #include + #include +@@ -46,12 +49,13 @@ + #define AR71XX_PCI_IRQ_COUNT 5 + + struct ar71xx_pci_controller { ++ struct device_node *np; + void __iomem *cfg_base; + int irq; +- int irq_base; + struct pci_controller pci_ctrl; + struct resource io_res; + struct resource mem_res; ++ struct irq_domain *domain; + }; + + /* Byte lane enable bits */ +@@ -225,29 +229,30 @@ static struct pci_ops ar71xx_pci_ops = { + + static void ar71xx_pci_irq_handler(struct irq_desc *desc) + { +- struct ar71xx_pci_controller *apc; + void __iomem *base = ath79_reset_base; ++ struct irq_chip *chip = irq_desc_get_chip(desc); ++ struct ar71xx_pci_controller *apc = irq_desc_get_handler_data(desc); + u32 pending; + +- apc = irq_desc_get_handler_data(desc); +- ++ chained_irq_enter(chip, desc); + pending = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_STATUS) & + __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); + + if (pending & AR71XX_PCI_INT_DEV0) +- generic_handle_irq(apc->irq_base + 0); ++ generic_handle_irq(irq_linear_revmap(apc->domain, 1)); + + else if (pending & AR71XX_PCI_INT_DEV1) +- generic_handle_irq(apc->irq_base + 1); ++ generic_handle_irq(irq_linear_revmap(apc->domain, 2)); + + else if (pending & AR71XX_PCI_INT_DEV2) +- generic_handle_irq(apc->irq_base + 2); ++ generic_handle_irq(irq_linear_revmap(apc->domain, 3)); + + else if (pending & AR71XX_PCI_INT_CORE) +- generic_handle_irq(apc->irq_base + 4); ++ generic_handle_irq(irq_linear_revmap(apc->domain, 4)); + + else + spurious_interrupt(); ++ chained_irq_exit(chip, desc); + } + + static void ar71xx_pci_irq_unmask(struct irq_data *d) +@@ -258,7 +263,7 @@ static void ar71xx_pci_irq_unmask(struct + u32 t; + + apc = irq_data_get_irq_chip_data(d); +- irq = d->irq - apc->irq_base; ++ irq = irq_linear_revmap(apc->domain, d->irq); + + t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); + __raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); +@@ -275,7 +280,7 @@ static void ar71xx_pci_irq_mask(struct i + u32 t; + + apc = irq_data_get_irq_chip_data(d); +- irq = d->irq - apc->irq_base; ++ irq = irq_linear_revmap(apc->domain, d->irq); + + t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); + __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); +@@ -291,24 +296,31 @@ static struct irq_chip ar71xx_pci_irq_ch + .irq_mask_ack = ar71xx_pci_irq_mask, + }; + ++static int ar71xx_pci_irq_map(struct irq_domain *d, ++ unsigned int irq, irq_hw_number_t hw) ++{ ++ struct ar71xx_pci_controller *apc = d->host_data; ++ ++ irq_set_chip_and_handler(irq, &ar71xx_pci_irq_chip, handle_level_irq); ++ irq_set_chip_data(irq, apc); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops ar71xx_pci_domain_ops = { ++ .xlate = irq_domain_xlate_onecell, ++ .map = ar71xx_pci_irq_map, ++}; ++ + static void ar71xx_pci_irq_init(struct ar71xx_pci_controller *apc) + { + void __iomem *base = ath79_reset_base; +- int i; + + __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_ENABLE); + __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_STATUS); + +- BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR71XX_PCI_IRQ_COUNT); +- +- apc->irq_base = ATH79_PCI_IRQ_BASE; +- for (i = apc->irq_base; +- i < apc->irq_base + AR71XX_PCI_IRQ_COUNT; i++) { +- irq_set_chip_and_handler(i, &ar71xx_pci_irq_chip, +- handle_level_irq); +- irq_set_chip_data(i, apc); +- } +- ++ apc->domain = irq_domain_add_linear(apc->np, AR71XX_PCI_IRQ_COUNT, ++ &ar71xx_pci_domain_ops, apc); + irq_set_chained_handler_and_data(apc->irq, ar71xx_pci_irq_handler, + apc); + } +@@ -325,10 +337,14 @@ static void ar71xx_pci_reset(void) + mdelay(100); + } + ++static const struct of_device_id ar71xx_pci_ids[] = { ++ { .compatible = "qca,ar7100-pci" }, ++ {}, ++}; ++ + static int ar71xx_pci_probe(struct platform_device *pdev) + { + struct ar71xx_pci_controller *apc; +- struct resource *res; + u32 t; + + apc = devm_kzalloc(&pdev->dev, sizeof(struct ar71xx_pci_controller), +@@ -345,26 +361,6 @@ static int ar71xx_pci_probe(struct platf + if (apc->irq < 0) + return -EINVAL; + +- res = platform_get_resource_byname(pdev, IORESOURCE_IO, "io_base"); +- if (!res) +- return -EINVAL; +- +- apc->io_res.parent = res; +- apc->io_res.name = "PCI IO space"; +- apc->io_res.start = res->start; +- apc->io_res.end = res->end; +- apc->io_res.flags = IORESOURCE_IO; +- +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem_base"); +- if (!res) +- return -EINVAL; +- +- apc->mem_res.parent = res; +- apc->mem_res.name = "PCI memory space"; +- apc->mem_res.start = res->start; +- apc->mem_res.end = res->end; +- apc->mem_res.flags = IORESOURCE_MEM; +- + ar71xx_pci_reset(); + + /* setup COMMAND register */ +@@ -377,9 +373,11 @@ static int ar71xx_pci_probe(struct platf + + ar71xx_pci_irq_init(apc); + ++ apc->np = pdev->dev.of_node; + apc->pci_ctrl.pci_ops = &ar71xx_pci_ops; + apc->pci_ctrl.mem_resource = &apc->mem_res; + apc->pci_ctrl.io_resource = &apc->io_res; ++ pci_load_of_ranges(&apc->pci_ctrl, pdev->dev.of_node); + + register_pci_controller(&apc->pci_ctrl); + +@@ -390,6 +388,7 @@ static struct platform_driver ar71xx_pci + .probe = ar71xx_pci_probe, + .driver = { + .name = "ar71xx-pci", ++ .of_match_table = of_match_ptr(ar71xx_pci_ids), + }, + }; + diff --git a/lede/target/linux/ath79/patches-6.6/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch b/lede/target/linux/ath79/patches-6.6/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch new file mode 100644 index 0000000000..a32c9bdcde --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/312-dt-bindings-PCI-qcom-ar7240-adds-binding-doc.patch @@ -0,0 +1,61 @@ +From ea27764bc3ef2a05decf3ae05edffc289cd0d93c Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Mon, 25 Jun 2018 15:52:02 +0200 +Subject: [PATCH 19/33] dt-bindings: PCI: qcom,ar7240: adds binding doc + +With the driver being converted from platform_data to pure OF, we need to +also add some docs. + +Cc: Rob Herring +Cc: devicetree@vger.kernel.org +Signed-off-by: John Crispin +--- + .../devicetree/bindings/pci/qcom,ar7240-pci.txt | 42 ++++++++++++++++++++++ + 1 file changed, 42 insertions(+) + create mode 100644 Documentation/devicetree/bindings/pci/qcom,ar7240-pci.txt + +--- /dev/null ++++ b/Documentation/devicetree/bindings/pci/qcom,ar7240-pci.txt +@@ -0,0 +1,42 @@ ++* Qualcomm Atheros AR724X PCI express root complex ++ ++Required properties: ++- compatible: should contain "qcom,ar7240-pci" to identify the core. ++- reg: Should contain the register ranges as listed in the reg-names property. ++- reg-names: Definition: Must include the following entries ++ - "crp_base" Configuration registers ++ - "ctrl_base" Control registers ++ - "cfg_base" IO Memory ++- #address-cells: set to <3> ++- #size-cells: set to <2> ++- ranges: ranges for the PCI memory and I/O regions ++- interrupt-map-mask and interrupt-map: standard PCI ++ properties to define the mapping of the PCIe interface to interrupt ++ numbers. ++- #interrupt-cells: set to <1> ++- interrupt-parent: phandle to the MIPS IRQ controller ++ ++Optional properties: ++- interrupt-controller: define to enable the builtin IRQ cascade. ++ ++* Example for qca9557 ++ pcie@180c0000 { ++ compatible = "qcom,ar7240-pci"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ bus-range = <0x0 0x0>; ++ reg = <0x180c0000 0x1000>, ++ <0x180f0000 0x100>, ++ <0x14000000 0x1000>; ++ reg-names = "crp_base", "ctrl_base", "cfg_base"; ++ ranges = <0x2000000 0 0x10000000 0x10000000 0 0x04000000 ++ 0x1000000 0 0x00000000 0x00000000 0 0x00000001>; ++ interrupt-parent = <&intc2>; ++ interrupts = <1>; ++ ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ ++ interrupt-map-mask = <0 0 0 1>; ++ interrupt-map = <0 0 0 0 &pcie0 0>; ++ }; diff --git a/lede/target/linux/ath79/patches-6.6/313-MIPS-pci-ar724x-convert-to-OF.patch b/lede/target/linux/ath79/patches-6.6/313-MIPS-pci-ar724x-convert-to-OF.patch new file mode 100644 index 0000000000..7927c1cbf5 --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/313-MIPS-pci-ar724x-convert-to-OF.patch @@ -0,0 +1,213 @@ +From a522ee0199d5d3ea114ca2e211f6ac398d3e8e0b Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sat, 23 Jun 2018 15:07:37 +0200 +Subject: [PATCH 20/33] MIPS: pci-ar724x: convert to OF + +With the ath79 target getting converted to pure OF, we can drop all the +platform data code and add the missing OF bits to the driver. We also add +a irq domain for the PCI/e controllers cascade, thus making it usable from +dts files. + +Signed-off-by: John Crispin +--- + arch/mips/pci/pci-ar724x.c | 88 ++++++++++++++++++++++------------------------ + 1 file changed, 42 insertions(+), 46 deletions(-) + +--- a/arch/mips/pci/pci-ar724x.c ++++ b/arch/mips/pci/pci-ar724x.c +@@ -11,8 +11,11 @@ + #include + #include + #include ++#include + #include + #include ++#include ++#include + + #define AR724X_PCI_REG_APP 0x00 + #define AR724X_PCI_REG_RESET 0x18 +@@ -42,17 +45,20 @@ struct ar724x_pci_controller { + void __iomem *crp_base; + + int irq; +- int irq_base; + + bool link_up; + bool bar0_is_cached; + u32 bar0_value; + ++ struct device_node *np; + struct pci_controller pci_controller; ++ struct irq_domain *domain; + struct resource io_res; + struct resource mem_res; + }; + ++static struct irq_chip ar724x_pci_irq_chip; ++ + static inline bool ar724x_pci_check_link(struct ar724x_pci_controller *apc) + { + u32 reset; +@@ -228,35 +234,31 @@ static struct pci_ops ar724x_pci_ops = { + + static void ar724x_pci_irq_handler(struct irq_desc *desc) + { +- struct ar724x_pci_controller *apc; +- void __iomem *base; ++ struct irq_chip *chip = irq_desc_get_chip(desc); ++ struct ar724x_pci_controller *apc = irq_desc_get_handler_data(desc); + u32 pending; + +- apc = irq_desc_get_handler_data(desc); +- base = apc->ctrl_base; +- +- pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) & +- __raw_readl(base + AR724X_PCI_REG_INT_MASK); ++ chained_irq_enter(chip, desc); ++ pending = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_INT_STATUS) & ++ __raw_readl(apc->ctrl_base + AR724X_PCI_REG_INT_MASK); + + if (pending & AR724X_PCI_INT_DEV0) +- generic_handle_irq(apc->irq_base + 0); +- ++ generic_handle_irq(irq_linear_revmap(apc->domain, 1)); + else + spurious_interrupt(); ++ chained_irq_exit(chip, desc); + } + + static void ar724x_pci_irq_unmask(struct irq_data *d) + { + struct ar724x_pci_controller *apc; + void __iomem *base; +- int offset; + u32 t; + + apc = irq_data_get_irq_chip_data(d); + base = apc->ctrl_base; +- offset = apc->irq_base - d->irq; + +- switch (offset) { ++ switch (irq_linear_revmap(apc->domain, d->irq)) { + case 0: + t = __raw_readl(base + AR724X_PCI_REG_INT_MASK); + __raw_writel(t | AR724X_PCI_INT_DEV0, +@@ -270,14 +272,12 @@ static void ar724x_pci_irq_mask(struct i + { + struct ar724x_pci_controller *apc; + void __iomem *base; +- int offset; + u32 t; + + apc = irq_data_get_irq_chip_data(d); + base = apc->ctrl_base; +- offset = apc->irq_base - d->irq; + +- switch (offset) { ++ switch (irq_linear_revmap(apc->domain, d->irq)) { + case 0: + t = __raw_readl(base + AR724X_PCI_REG_INT_MASK); + __raw_writel(t & ~AR724X_PCI_INT_DEV0, +@@ -302,26 +302,34 @@ static struct irq_chip ar724x_pci_irq_ch + .irq_mask_ack = ar724x_pci_irq_mask, + }; + ++static int ar724x_pci_irq_map(struct irq_domain *d, ++ unsigned int irq, irq_hw_number_t hw) ++{ ++ struct ar724x_pci_controller *apc = d->host_data; ++ ++ irq_set_chip_and_handler(irq, &ar724x_pci_irq_chip, handle_level_irq); ++ irq_set_chip_data(irq, apc); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops ar724x_pci_domain_ops = { ++ .xlate = irq_domain_xlate_onecell, ++ .map = ar724x_pci_irq_map, ++}; ++ + static void ar724x_pci_irq_init(struct ar724x_pci_controller *apc, + int id) + { + void __iomem *base; +- int i; + + base = apc->ctrl_base; + + __raw_writel(0, base + AR724X_PCI_REG_INT_MASK); + __raw_writel(0, base + AR724X_PCI_REG_INT_STATUS); + +- apc->irq_base = ATH79_PCI_IRQ_BASE + (id * AR724X_PCI_IRQ_COUNT); +- +- for (i = apc->irq_base; +- i < apc->irq_base + AR724X_PCI_IRQ_COUNT; i++) { +- irq_set_chip_and_handler(i, &ar724x_pci_irq_chip, +- handle_level_irq); +- irq_set_chip_data(i, apc); +- } +- ++ apc->domain = irq_domain_add_linear(apc->np, 2, ++ &ar724x_pci_domain_ops, apc); + irq_set_chained_handler_and_data(apc->irq, ar724x_pci_irq_handler, + apc); + } +@@ -360,7 +368,6 @@ static void ar724x_pci_hw_init(struct ar + static int ar724x_pci_probe(struct platform_device *pdev) + { + struct ar724x_pci_controller *apc; +- struct resource *res; + int id; + + id = pdev->id; +@@ -388,29 +395,11 @@ static int ar724x_pci_probe(struct platf + if (apc->irq < 0) + return -EINVAL; + +- res = platform_get_resource_byname(pdev, IORESOURCE_IO, "io_base"); +- if (!res) +- return -EINVAL; +- +- apc->io_res.parent = res; +- apc->io_res.name = "PCI IO space"; +- apc->io_res.start = res->start; +- apc->io_res.end = res->end; +- apc->io_res.flags = IORESOURCE_IO; +- +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem_base"); +- if (!res) +- return -EINVAL; +- +- apc->mem_res.parent = res; +- apc->mem_res.name = "PCI memory space"; +- apc->mem_res.start = res->start; +- apc->mem_res.end = res->end; +- apc->mem_res.flags = IORESOURCE_MEM; +- ++ apc->np = pdev->dev.of_node; + apc->pci_controller.pci_ops = &ar724x_pci_ops; + apc->pci_controller.io_resource = &apc->io_res; + apc->pci_controller.mem_resource = &apc->mem_res; ++ pci_load_of_ranges(&apc->pci_controller, pdev->dev.of_node); + + /* + * Do the full PCIE Root Complex Initialization Sequence if the PCIe +@@ -432,10 +421,16 @@ static int ar724x_pci_probe(struct platf + return 0; + } + ++static const struct of_device_id ar724x_pci_ids[] = { ++ { .compatible = "qcom,ar7240-pci" }, ++ {}, ++}; ++ + static struct platform_driver ar724x_pci_driver = { + .probe = ar724x_pci_probe, + .driver = { + .name = "ar724x-pci", ++ .of_match_table = of_match_ptr(ar724x_pci_ids), + }, + }; + diff --git a/lede/target/linux/ath79/patches-6.6/314-MIPS-ath79-remove-irq-code-from-pci.patch b/lede/target/linux/ath79/patches-6.6/314-MIPS-ath79-remove-irq-code-from-pci.patch new file mode 100644 index 0000000000..01549eec68 --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/314-MIPS-ath79-remove-irq-code-from-pci.patch @@ -0,0 +1,149 @@ +From: John Crispin +Subject: ath79: fix remove irq code from pci driver patch + +This patch got mangled in the void while rebasing it. + +Submitted-by: John Crispin +--- + arch/mips/pci/pci-ar71xx.c | 107 ------------------ + 1 file changed, 141 deletions(-) + +--- a/arch/mips/pci/pci-ar71xx.c ++++ b/arch/mips/pci/pci-ar71xx.c +@@ -51,11 +51,9 @@ + struct ar71xx_pci_controller { + struct device_node *np; + void __iomem *cfg_base; +- int irq; + struct pci_controller pci_ctrl; + struct resource io_res; + struct resource mem_res; +- struct irq_domain *domain; + }; + + /* Byte lane enable bits */ +@@ -227,104 +225,6 @@ static struct pci_ops ar71xx_pci_ops = { + .write = ar71xx_pci_write_config, + }; + +-static void ar71xx_pci_irq_handler(struct irq_desc *desc) +-{ +- void __iomem *base = ath79_reset_base; +- struct irq_chip *chip = irq_desc_get_chip(desc); +- struct ar71xx_pci_controller *apc = irq_desc_get_handler_data(desc); +- u32 pending; +- +- chained_irq_enter(chip, desc); +- pending = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_STATUS) & +- __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); +- +- if (pending & AR71XX_PCI_INT_DEV0) +- generic_handle_irq(irq_linear_revmap(apc->domain, 1)); +- +- else if (pending & AR71XX_PCI_INT_DEV1) +- generic_handle_irq(irq_linear_revmap(apc->domain, 2)); +- +- else if (pending & AR71XX_PCI_INT_DEV2) +- generic_handle_irq(irq_linear_revmap(apc->domain, 3)); +- +- else if (pending & AR71XX_PCI_INT_CORE) +- generic_handle_irq(irq_linear_revmap(apc->domain, 4)); +- +- else +- spurious_interrupt(); +- chained_irq_exit(chip, desc); +-} +- +-static void ar71xx_pci_irq_unmask(struct irq_data *d) +-{ +- struct ar71xx_pci_controller *apc; +- unsigned int irq; +- void __iomem *base = ath79_reset_base; +- u32 t; +- +- apc = irq_data_get_irq_chip_data(d); +- irq = irq_linear_revmap(apc->domain, d->irq); +- +- t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); +- __raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); +- +- /* flush write */ +- __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); +-} +- +-static void ar71xx_pci_irq_mask(struct irq_data *d) +-{ +- struct ar71xx_pci_controller *apc; +- unsigned int irq; +- void __iomem *base = ath79_reset_base; +- u32 t; +- +- apc = irq_data_get_irq_chip_data(d); +- irq = irq_linear_revmap(apc->domain, d->irq); +- +- t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); +- __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); +- +- /* flush write */ +- __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); +-} +- +-static struct irq_chip ar71xx_pci_irq_chip = { +- .name = "AR71XX PCI", +- .irq_mask = ar71xx_pci_irq_mask, +- .irq_unmask = ar71xx_pci_irq_unmask, +- .irq_mask_ack = ar71xx_pci_irq_mask, +-}; +- +-static int ar71xx_pci_irq_map(struct irq_domain *d, +- unsigned int irq, irq_hw_number_t hw) +-{ +- struct ar71xx_pci_controller *apc = d->host_data; +- +- irq_set_chip_and_handler(irq, &ar71xx_pci_irq_chip, handle_level_irq); +- irq_set_chip_data(irq, apc); +- +- return 0; +-} +- +-static const struct irq_domain_ops ar71xx_pci_domain_ops = { +- .xlate = irq_domain_xlate_onecell, +- .map = ar71xx_pci_irq_map, +-}; +- +-static void ar71xx_pci_irq_init(struct ar71xx_pci_controller *apc) +-{ +- void __iomem *base = ath79_reset_base; +- +- __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_ENABLE); +- __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_STATUS); +- +- apc->domain = irq_domain_add_linear(apc->np, AR71XX_PCI_IRQ_COUNT, +- &ar71xx_pci_domain_ops, apc); +- irq_set_chained_handler_and_data(apc->irq, ar71xx_pci_irq_handler, +- apc); +-} +- + static void ar71xx_pci_reset(void) + { + ath79_device_reset_set(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE); +@@ -357,10 +257,6 @@ static int ar71xx_pci_probe(struct platf + if (IS_ERR(apc->cfg_base)) + return PTR_ERR(apc->cfg_base); + +- apc->irq = platform_get_irq(pdev, 0); +- if (apc->irq < 0) +- return -EINVAL; +- + ar71xx_pci_reset(); + + /* setup COMMAND register */ +@@ -371,8 +267,6 @@ static int ar71xx_pci_probe(struct platf + /* clear bus errors */ + ar71xx_pci_check_error(apc, 1); + +- ar71xx_pci_irq_init(apc); +- + apc->np = pdev->dev.of_node; + apc->pci_ctrl.pci_ops = &ar71xx_pci_ops; + apc->pci_ctrl.mem_resource = &apc->mem_res; diff --git a/lede/target/linux/ath79/patches-6.6/315-MIPS-pci-ar724x-add-QCA9550-reset-sequence.patch b/lede/target/linux/ath79/patches-6.6/315-MIPS-pci-ar724x-add-QCA9550-reset-sequence.patch new file mode 100644 index 0000000000..375dec8ba2 --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/315-MIPS-pci-ar724x-add-QCA9550-reset-sequence.patch @@ -0,0 +1,130 @@ +From: David Bauer +Date: Sat, 11 Apr 2020 14:03:12 +0200 +Subject: MIPS: pci-ar724x: add QCA9550 reset sequence + +The QCA9550 family of SoCs have a slightly different reset +sequence compared to older chips. + +Normally the bootloader performs this sequence, however +some bootloader implementation expect the operating system +to clear the reset. + +Also get the resets from OF to support handling of the second +PCIe root-complex on the QCA9558. + +Signed-off-by: David Bauer + +--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h ++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +@@ -390,6 +390,7 @@ + #define QCA955X_PLL_CPU_CONFIG_REG 0x00 + #define QCA955X_PLL_DDR_CONFIG_REG 0x04 + #define QCA955X_PLL_CLK_CTRL_REG 0x08 ++#define QCA955X_PLL_PCIE_CONFIG_REG 0x0c + #define QCA955X_PLL_ETH_XMII_CONTROL_REG 0x28 + #define QCA955X_PLL_ETH_SGMII_CONTROL_REG 0x48 + #define QCA955X_PLL_ETH_SGMII_SERDES_REG 0x4c +@@ -475,6 +476,9 @@ + #define QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL BIT(21) + #define QCA956X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) + ++#define QCA955X_PLL_PCIE_CONFIG_PLL_PWD BIT(30) ++#define QCA955X_PLL_PCIE_CONFIG_PLL_BYPASS BIT(16) ++ + #define QCA956X_PLL_SWITCH_CLOCK_SPARE_I2C_CLK_SELB BIT(5) + #define QCA956X_PLL_SWITCH_CLOCK_SPARE_MDIO_CLK_SEL0_1 BIT(6) + #define QCA956X_PLL_SWITCH_CLOCK_SPARE_UART1_CLK_SEL BIT(7) +--- a/arch/mips/pci/pci-ar724x.c ++++ b/arch/mips/pci/pci-ar724x.c +@@ -8,6 +8,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -55,6 +56,9 @@ struct ar724x_pci_controller { + struct irq_domain *domain; + struct resource io_res; + struct resource mem_res; ++ ++ struct reset_control *hc_reset; ++ struct reset_control *phy_reset; + }; + + static struct irq_chip ar724x_pci_irq_chip; +@@ -340,18 +344,30 @@ static void ar724x_pci_hw_init(struct ar + int wait = 0; + + /* deassert PCIe host controller and PCIe PHY reset */ +- ath79_device_reset_clear(AR724X_RESET_PCIE); +- ath79_device_reset_clear(AR724X_RESET_PCIE_PHY); ++ reset_control_deassert(apc->hc_reset); ++ reset_control_deassert(apc->phy_reset); + +- /* remove the reset of the PCIE PLL */ +- ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG); +- ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_RESET; +- ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl); +- +- /* deassert bypass for the PCIE PLL */ +- ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG); +- ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_BYPASS; +- ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl); ++ if (of_device_is_compatible(apc->np, "qcom,qca9550-pci")) { ++ /* remove the reset of the PCIE PLL */ ++ ppl = ath79_pll_rr(QCA955X_PLL_PCIE_CONFIG_REG); ++ ppl &= ~QCA955X_PLL_PCIE_CONFIG_PLL_PWD; ++ ath79_pll_wr(QCA955X_PLL_PCIE_CONFIG_REG, ppl); ++ ++ /* deassert bypass for the PCIE PLL */ ++ ppl = ath79_pll_rr(QCA955X_PLL_PCIE_CONFIG_REG); ++ ppl &= ~QCA955X_PLL_PCIE_CONFIG_PLL_BYPASS; ++ ath79_pll_wr(QCA955X_PLL_PCIE_CONFIG_REG, ppl); ++ } else { ++ /* remove the reset of the PCIE PLL */ ++ ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG); ++ ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_RESET; ++ ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl); ++ ++ /* deassert bypass for the PCIE PLL */ ++ ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG); ++ ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_BYPASS; ++ ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl); ++ } + + /* set PCIE Application Control to ready */ + app = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_APP); +@@ -395,6 +411,14 @@ static int ar724x_pci_probe(struct platf + if (apc->irq < 0) + return -EINVAL; + ++ apc->hc_reset = devm_reset_control_get_exclusive(&pdev->dev, "hc"); ++ if (IS_ERR(apc->hc_reset)) ++ return PTR_ERR(apc->hc_reset); ++ ++ apc->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, "phy"); ++ if (IS_ERR(apc->phy_reset)) ++ return PTR_ERR(apc->phy_reset); ++ + apc->np = pdev->dev.of_node; + apc->pci_controller.pci_ops = &ar724x_pci_ops; + apc->pci_controller.io_resource = &apc->io_res; +@@ -405,7 +429,7 @@ static int ar724x_pci_probe(struct platf + * Do the full PCIE Root Complex Initialization Sequence if the PCIe + * host controller is in reset. + */ +- if (ath79_reset_rr(AR724X_RESET_REG_RESET_MODULE) & AR724X_RESET_PCIE) ++ if (reset_control_status(apc->hc_reset)) + ar724x_pci_hw_init(apc); + + apc->link_up = ar724x_pci_check_link(apc); +@@ -423,6 +447,7 @@ static int ar724x_pci_probe(struct platf + + static const struct of_device_id ar724x_pci_ids[] = { + { .compatible = "qcom,ar7240-pci" }, ++ { .compatible = "qcom,qca9550-pci" }, + {}, + }; + diff --git a/lede/target/linux/ath79/patches-6.6/316-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch b/lede/target/linux/ath79/patches-6.6/316-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch new file mode 100644 index 0000000000..1e2715b84c --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/316-MIPS-ath79-swizzle-pci-address-for-ar71xx.patch @@ -0,0 +1,109 @@ +From: Gabor Juhos +Subject: [PATCH] ar71xx: swizzle address for PCI byte/word access on AR71xx + +Closes #11683. + +SVN-Revision: 32639 +--- + .../mips/include/asm/mach-ath79/mangle-port.h | 111 ++++++++++++++++++ + 1 file changed, 111 insertions(+) + create mode 100644 arch/mips/include/asm/mach-ath79/mangle-port.h + +--- /dev/null ++++ b/arch/mips/include/asm/mach-ath79/mangle-port.h +@@ -0,0 +1,37 @@ ++/* ++ * Copyright (C) 2012 Gabor Juhos ++ * ++ * This file was derived from: inlude/asm-mips/mach-generic/mangle-port.h ++ * Copyright (C) 2003, 2004 Ralf Baechle ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef __ASM_MACH_ATH79_MANGLE_PORT_H ++#define __ASM_MACH_ATH79_MANGLE_PORT_H ++ ++#ifdef CONFIG_PCI_AR71XX ++extern unsigned long (ath79_pci_swizzle_b)(unsigned long port); ++extern unsigned long (ath79_pci_swizzle_w)(unsigned long port); ++#else ++#define ath79_pci_swizzle_b(port) (port) ++#define ath79_pci_swizzle_w(port) (port) ++#endif ++ ++#define __swizzle_addr_b(port) ath79_pci_swizzle_b(port) ++#define __swizzle_addr_w(port) ath79_pci_swizzle_w(port) ++#define __swizzle_addr_l(port) (port) ++#define __swizzle_addr_q(port) (port) ++ ++# define ioswabb(a, x) (x) ++# define __mem_ioswabb(a, x) (x) ++# define ioswabw(a, x) (x) ++# define __mem_ioswabw(a, x) cpu_to_le16(x) ++# define ioswabl(a, x) (x) ++# define __mem_ioswabl(a, x) cpu_to_le32(x) ++# define ioswabq(a, x) (x) ++# define __mem_ioswabq(a, x) cpu_to_le64(x) ++ ++#endif /* __ASM_MACH_ATH79_MANGLE_PORT_H */ +--- a/arch/mips/pci/pci-ar71xx.c ++++ b/arch/mips/pci/pci-ar71xx.c +@@ -68,6 +68,45 @@ static const u32 ar71xx_pci_read_mask[8] + 0, 0xff, 0xffff, 0, 0xffffffff, 0, 0, 0 + }; + ++static unsigned long (*__ath79_pci_swizzle_b)(unsigned long port); ++static unsigned long (*__ath79_pci_swizzle_w)(unsigned long port); ++ ++static inline bool ar71xx_is_pci_addr(unsigned long port) ++{ ++ unsigned long phys = CPHYSADDR(port); ++ ++ return (phys >= AR71XX_PCI_MEM_BASE && ++ phys < AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE); ++} ++ ++static unsigned long ar71xx_pci_swizzle_b(unsigned long port) ++{ ++ return ar71xx_is_pci_addr(port) ? port ^ 3 : port; ++} ++ ++static unsigned long ar71xx_pci_swizzle_w(unsigned long port) ++{ ++ return ar71xx_is_pci_addr(port) ? port ^ 2 : port; ++} ++ ++unsigned long ath79_pci_swizzle_b(unsigned long port) ++{ ++ if (__ath79_pci_swizzle_b) ++ return __ath79_pci_swizzle_b(port); ++ ++ return port; ++} ++EXPORT_SYMBOL(ath79_pci_swizzle_b); ++ ++unsigned long ath79_pci_swizzle_w(unsigned long port) ++{ ++ if (__ath79_pci_swizzle_w) ++ return __ath79_pci_swizzle_w(port); ++ ++ return port; ++} ++EXPORT_SYMBOL(ath79_pci_swizzle_w); ++ + static inline u32 ar71xx_pci_get_ble(int where, int size, int local) + { + u32 t; +@@ -275,6 +314,9 @@ static int ar71xx_pci_probe(struct platf + + register_pci_controller(&apc->pci_ctrl); + ++ __ath79_pci_swizzle_b = ar71xx_pci_swizzle_b; ++ __ath79_pci_swizzle_w = ar71xx_pci_swizzle_w; ++ + return 0; + } + diff --git a/lede/target/linux/ath79/patches-6.6/317-MIPS-pci-ar724x-clear-power-down-of-pll-on-AR934x.patch b/lede/target/linux/ath79/patches-6.6/317-MIPS-pci-ar724x-clear-power-down-of-pll-on-AR934x.patch new file mode 100644 index 0000000000..dfb7e483a7 --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/317-MIPS-pci-ar724x-clear-power-down-of-pll-on-AR934x.patch @@ -0,0 +1,34 @@ +From f2ca10b22ace3ce53b4e3f189bf1dd53a4482475 Mon Sep 17 00:00:00 2001 +From: INAGAKI Hiroshi +Date: Fri, 26 Apr 2024 23:53:58 +0900 +Subject: [PATCH 1/2] MIPS: pci-ar724x: clear power down of pll on AR934x + +Fix PCIe initialization on AR934x by clearing PLL_PWD bit in addition to +PPL_RESET bit of AR724x. + +Signed-off-by: INAGAKI Hiroshi +--- + +--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h ++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +@@ -347,6 +347,8 @@ + #define AR934X_PLL_CPU_DDR_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21) + #define AR934X_PLL_CPU_DDR_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) + ++#define AR934X_PLL_PCIE_CONFIG_PLL_PWD BIT(30) ++ + #define AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL BIT(6) + + #define QCA953X_PLL_CPU_CONFIG_REG 0x00 +--- a/arch/mips/pci/pci-ar724x.c ++++ b/arch/mips/pci/pci-ar724x.c +@@ -360,7 +360,8 @@ static void ar724x_pci_hw_init(struct ar + } else { + /* remove the reset of the PCIE PLL */ + ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG); +- ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_RESET; ++ ppl &= ~(AR934X_PLL_PCIE_CONFIG_PLL_PWD | ++ AR724X_PLL_REG_PCIE_CONFIG_PPL_RESET); + ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl); + + /* deassert bypass for the PCIE PLL */ diff --git a/lede/target/linux/ath79/patches-6.6/318-MIPS-pci-ar724x-deassert-the-reset-of-PCIe-endpoint.patch b/lede/target/linux/ath79/patches-6.6/318-MIPS-pci-ar724x-deassert-the-reset-of-PCIe-endpoint.patch new file mode 100644 index 0000000000..c906bdbbb6 --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/318-MIPS-pci-ar724x-deassert-the-reset-of-PCIe-endpoint.patch @@ -0,0 +1,41 @@ +From 859c93981a8994ffa69967b44b247d2e7d6a01f1 Mon Sep 17 00:00:00 2001 +From: INAGAKI Hiroshi +Date: Fri, 26 Apr 2024 23:54:57 +0900 +Subject: [PATCH 2/2] MIPS: pci-ar724x: deassert the reset of PCIe endpoint + +Fix PCIe initialization by de-assertion of PCIe endpoint reset. + +Signed-off-by: INAGAKI Hiroshi +--- + +--- a/arch/mips/pci/pci-ar724x.c ++++ b/arch/mips/pci/pci-ar724x.c +@@ -25,6 +25,7 @@ + + #define AR724X_PCI_APP_LTSSM_ENABLE BIT(0) + ++#define AR724X_PCI_RESET_EP_RESET_L BIT(2) + #define AR724X_PCI_RESET_LINK_UP BIT(0) + + #define AR724X_PCI_INT_DEV0 BIT(14) +@@ -340,7 +341,7 @@ static void ar724x_pci_irq_init(struct a + + static void ar724x_pci_hw_init(struct ar724x_pci_controller *apc) + { +- u32 ppl, app; ++ u32 ppl, rst, app; + int wait = 0; + + /* deassert PCIe host controller and PCIe PHY reset */ +@@ -370,6 +371,11 @@ static void ar724x_pci_hw_init(struct ar + ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl); + } + ++ /* deassert the reset state of the PCIE endpoint */ ++ rst = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_RESET); ++ rst |= AR724X_PCI_RESET_EP_RESET_L; ++ __raw_writel(rst, apc->ctrl_base + AR724X_PCI_REG_RESET); ++ + /* set PCIE Application Control to ready */ + app = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_APP); + app |= AR724X_PCI_APP_LTSSM_ENABLE; diff --git a/lede/target/linux/ath79/patches-6.6/330-missing-registers.patch b/lede/target/linux/ath79/patches-6.6/330-missing-registers.patch new file mode 100644 index 0000000000..d05e741c7e --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/330-missing-registers.patch @@ -0,0 +1,20 @@ +From: Christian Lamparter +Subject: [PATCH] ath79: gmac: add parsers for rxd(v)- and tx(d|en)-delay for + + ath79: gmac: add parsers for rxd(v)- and tx(d|en)-delay for AR9344 + + Signed-off-by: Christian Lamparter + +--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h ++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +@@ -1233,6 +1233,10 @@ + #define AR934X_ETH_CFG_RDV_DELAY BIT(16) + #define AR934X_ETH_CFG_RDV_DELAY_MASK 0x3 + #define AR934X_ETH_CFG_RDV_DELAY_SHIFT 16 ++#define AR934X_ETH_CFG_TXD_DELAY_MASK 0x3 ++#define AR934X_ETH_CFG_TXD_DELAY_SHIFT 18 ++#define AR934X_ETH_CFG_TXE_DELAY_MASK 0x3 ++#define AR934X_ETH_CFG_TXE_DELAY_SHIFT 20 + + /* + * QCA953X GMAC Interface diff --git a/lede/target/linux/ath79/patches-6.6/331-MIPS-ath79-add-missing-QCA955x-GMAC-registers.patch b/lede/target/linux/ath79/patches-6.6/331-MIPS-ath79-add-missing-QCA955x-GMAC-registers.patch new file mode 100644 index 0000000000..5d9c77c69f --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/331-MIPS-ath79-add-missing-QCA955x-GMAC-registers.patch @@ -0,0 +1,90 @@ +From 60efe35257b063ce584968f9f80b437030ce6ba6 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Mon, 18 Mar 2019 00:54:06 +0100 +Subject: [PATCH] MIPS: ath79: add missing QCA955x GMAC registers + +This adds missing GMAC register definitions for the Qualcomm Atheros +QCA955X series MIPS SoCs. + +They originate from the platforms U-Boot code and the AVM FRITZ!WLAN +Repeater 450E's GPL tarball. + +Signed-off-by: David Bauer +--- + .../mips/include/asm/mach-ath79/ar71xx_regs.h | 54 +++++++++++++++++++ + 1 file changed, 54 insertions(+) + +--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h ++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +@@ -1253,7 +1253,12 @@ + */ + + #define QCA955X_GMAC_REG_ETH_CFG 0x00 ++#define QCA955X_GMAC_REG_SGMII_RESET 0x14 + #define QCA955X_GMAC_REG_SGMII_SERDES 0x18 ++#define QCA955X_GMAC_REG_MR_AN_CONTROL 0x1c ++#define QCA955X_GMAC_REG_MR_AN_STATUS 0x20 ++#define QCA955X_GMAC_REG_SGMII_CONFIG 0x34 ++#define QCA955X_GMAC_REG_SGMII_DEBUG 0x58 + + #define QCA955X_ETH_CFG_RGMII_EN BIT(0) + #define QCA955X_ETH_CFG_MII_GE0 BIT(1) +@@ -1275,9 +1280,58 @@ + #define QCA955X_ETH_CFG_TXE_DELAY_MASK 0x3 + #define QCA955X_ETH_CFG_TXE_DELAY_SHIFT 20 + ++#define QCA955X_SGMII_RESET_RX_CLK_N_RESET 0 ++#define QCA955X_SGMII_RESET_RX_CLK_N BIT(0) ++#define QCA955X_SGMII_RESET_TX_CLK_N BIT(1) ++#define QCA955X_SGMII_RESET_RX_125M_N BIT(2) ++#define QCA955X_SGMII_RESET_TX_125M_N BIT(3) ++#define QCA955X_SGMII_RESET_HW_RX_125M_N BIT(4) ++ + #define QCA955X_SGMII_SERDES_LOCK_DETECT_STATUS BIT(15) + #define QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT 23 + #define QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK 0xf ++ ++#define QCA955X_MR_AN_CONTROL_SPEED_SEL1 BIT(6) ++#define QCA955X_MR_AN_CONTROL_DUPLEX_MODE BIT(8) ++#define QCA955X_MR_AN_CONTROL_RESTART_AN BIT(9) ++#define QCA955X_MR_AN_CONTROL_POWER_DOWN BIT(11) ++#define QCA955X_MR_AN_CONTROL_AN_ENABLE BIT(12) ++#define QCA955X_MR_AN_CONTROL_SPEED_SEL0 BIT(13) ++#define QCA955X_MR_AN_CONTROL_LOOPBACK BIT(14) ++#define QCA955X_MR_AN_CONTROL_PHY_RESET BIT(15) ++ ++#define QCA955X_MR_AN_STATUS_EXT_CAP BIT(0) ++#define QCA955X_MR_AN_STATUS_LINK_UP BIT(2) ++#define QCA955X_MR_AN_STATUS_AN_ABILITY BIT(3) ++#define QCA955X_MR_AN_STATUS_REMOTE_FAULT BIT(4) ++#define QCA955X_MR_AN_STATUS_AN_COMPLETE BIT(5) ++#define QCA955X_MR_AN_STATUS_NO_PREAMBLE BIT(6) ++#define QCA955X_MR_AN_STATUS_BASE_PAGE BIT(7) ++ ++#define QCA955X_SGMII_CONFIG_MODE_CTRL_SHIFT 0 ++#define QCA955X_SGMII_CONFIG_MODE_CTRL_MASK 0x7 ++#define QCA955X_SGMII_CONFIG_ENABLE_SGMII_TX_PAUSE BIT(3) ++#define QCA955X_SGMII_CONFIG_MR_REG4_CHANGED BIT(4) ++#define QCA955X_SGMII_CONFIG_FORCE_SPEED BIT(5) ++#define QCA955X_SGMII_CONFIG_SPEED_SHIFT 6 ++#define QCA955X_SGMII_CONFIG_SPEED_MASK 0xc0 ++#define QCA955X_SGMII_CONFIG_REMOTE_PHY_LOOPBACK BIT(8) ++#define QCA955X_SGMII_CONFIG_NEXT_PAGE_LOADED BIT(9) ++#define QCA955X_SGMII_CONFIG_MDIO_ENABLE BIT(10) ++#define QCA955X_SGMII_CONFIG_MDIO_PULSE BIT(11) ++#define QCA955X_SGMII_CONFIG_MDIO_COMPLETE BIT(12) ++#define QCA955X_SGMII_CONFIG_PRBS_ENABLE BIT(13) ++#define QCA955X_SGMII_CONFIG_BERT_ENABLE BIT(14) ++ ++#define QCA955X_SGMII_DEBUG_TX_STATE_MASK 0xff ++#define QCA955X_SGMII_DEBUG_TX_STATE_SHIFT 0 ++#define QCA955X_SGMII_DEBUG_RX_STATE_MASK 0xff00 ++#define QCA955X_SGMII_DEBUG_RX_STATE_SHIFT 8 ++#define QCA955X_SGMII_DEBUG_RX_SYNC_STATE_MASK 0xff0000 ++#define QCA955X_SGMII_DEBUG_RX_SYNC_STATE_SHIFT 16 ++#define QCA955X_SGMII_DEBUG_ARB_STATE_MASK 0xf000000 ++#define QCA955X_SGMII_DEBUG_ARB_STATE_SHIFT 24 ++ + /* + * QCA956X GMAC Interface + */ diff --git a/lede/target/linux/ath79/patches-6.6/332-ath79-sgmii-config.patch b/lede/target/linux/ath79/patches-6.6/332-ath79-sgmii-config.patch new file mode 100644 index 0000000000..6f6217ce75 --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/332-ath79-sgmii-config.patch @@ -0,0 +1,30 @@ +From: David Bauer +Subject: [PATCH] ath79: force SGMII SerDes mode to MAC operation + +The mode on the SGMII SerDes on the QCA9563 is 1000 Base-X by default. +This only allows for 1000 Mbit/s links, however when used with an SGMII +PHY in 100 Mbit/s link mode, the link remains dead. + +This strictly has nothing to do with the SerDes calibration, however it +is done at the same point in the QCA reference U-Boot which is the +blueprint for everything happening here. As the current state is more or +less a hack, this should be fine. + +This fixes the issues outlined above on a TP-Link EAP-225 Outdoor. + +Reported-by: Tom Herbers +Tested-by: Tom Herbers +Submitted-by: David Bauer +--- + arch/mips/include/asm/mach-ath79/ar71xx_regs.h | 1 + + 1 files changed, 1 insertion(+) + +--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h ++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +@@ -1382,5 +1382,6 @@ + + #define QCA956X_SGMII_CONFIG_MODE_CTRL_SHIFT 0 + #define QCA956X_SGMII_CONFIG_MODE_CTRL_MASK 0x7 ++#define QCA956X_SGMII_CONFIG_MODE_CTRL_SGMII_MAC 0x2 + + #endif /* __ASM_MACH_AR71XX_REGS_H */ diff --git a/lede/target/linux/ath79/patches-6.6/340-register_gpio_driver_earlier.patch b/lede/target/linux/ath79/patches-6.6/340-register_gpio_driver_earlier.patch new file mode 100644 index 0000000000..a3bdf890c4 --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/340-register_gpio_driver_earlier.patch @@ -0,0 +1,26 @@ +From: John Crispin +Subject: ath79: Register GPIO driver earlier + +HACK: register the GPIO driver earlier to ensure that gpio_request calls +from mach files succeed. + +Submitted-by: John Crispin +--- + drivers/gpio/gpio-ath79.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/gpio/gpio-ath79.c ++++ b/drivers/gpio/gpio-ath79.c +@@ -300,7 +300,11 @@ static struct platform_driver ath79_gpio + .probe = ath79_gpio_probe, + }; + +-module_platform_driver(ath79_gpio_driver); ++static int __init ath79_gpio_init(void) ++{ ++ return platform_driver_register(&ath79_gpio_driver); ++} ++postcore_initcall(ath79_gpio_init); + + MODULE_DESCRIPTION("Atheros AR71XX/AR724X/AR913X GPIO API support"); + MODULE_LICENSE("GPL v2"); diff --git a/lede/target/linux/ath79/patches-6.6/341-wifi-ath9k-obtain-system-gpios.patch b/lede/target/linux/ath79/patches-6.6/341-wifi-ath9k-obtain-system-gpios.patch new file mode 100644 index 0000000000..a43e3537e6 --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/341-wifi-ath9k-obtain-system-gpios.patch @@ -0,0 +1,233 @@ +From patchwork Tue Apr 23 12:12:33 2024 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Linus Walleij +X-Patchwork-Id: 1926515 +Return-Path: + +X-Original-To: incoming@patchwork.ozlabs.org +Delivered-To: patchwork-incoming@legolas.ozlabs.org +Authentication-Results: legolas.ozlabs.org; + dkim=pass (2048-bit key; + unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 + header.s=google header.b=qX99TQMM; + dkim-atps=neutral +Authentication-Results: legolas.ozlabs.org; + spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org + (client-ip=2604:1380:45e3:2400::1; helo=sv.mirrors.kernel.org; + envelope-from=linux-gpio+bounces-5755-incoming=patchwork.ozlabs.org@vger.kernel.org; + receiver=patchwork.ozlabs.org) +Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org + [IPv6:2604:1380:45e3:2400::1]) + (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) + key-exchange X25519 server-signature ECDSA (secp384r1)) + (No client certificate requested) + by legolas.ozlabs.org (Postfix) with ESMTPS id 4VP1Gc6RZKz1yZP + for ; Tue, 23 Apr 2024 22:12:56 +1000 (AEST) +Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org + [52.25.139.140]) + (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) + (No client certificate requested) + by sv.mirrors.kernel.org (Postfix) with ESMTPS id 5BB9C28522A + for ; Tue, 23 Apr 2024 12:12:55 +0000 (UTC) +Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) + by smtp.subspace.kernel.org (Postfix) with ESMTP id 2F83B8563D; + Tue, 23 Apr 2024 12:12:41 +0000 (UTC) +Authentication-Results: smtp.subspace.kernel.org; + dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org + header.b="qX99TQMM" +X-Original-To: linux-gpio@vger.kernel.org +Received: from mail-lj1-f179.google.com (mail-lj1-f179.google.com + [209.85.208.179]) + (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) + (No client certificate requested) + by smtp.subspace.kernel.org (Postfix) with ESMTPS id A8F3C82865 + for ; Tue, 23 Apr 2024 12:12:37 +0000 (UTC) +Authentication-Results: smtp.subspace.kernel.org; + arc=none smtp.client-ip=209.85.208.179 +ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; + t=1713874361; cv=none; + b=d6RcvcAu8hBYAK8Io489ZHQpJVXPwuokP6iMcAkbvElCerbXD6jAdqdi+RjDlo5C49GHGO4FQ19UwQn/VE//qSwiK1ulTSBp3OkvAmyb7yYAFnDs9AVNWRw+5/NxeFNn3fj5PyvqVymIbaJKabfrOVNwkz/5JMHxEIJtr6Crmog= +ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; + s=arc-20240116; t=1713874361; c=relaxed/simple; + bh=0eXJ5AIjzz1TBGZ8SlshIPrEHZaZwZfYEdof+dSpu4Y=; + h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; + b=EfFtruUxRIGy+jylEiJ2rPEyPCjGCc8ptT9FVxe6s0O/kW38Y6196xVQeiSV2tSKVCEOIO+9HoqmpgdKsJE7gU9++EcrasP96MYpsklYpc2zsWW3b8QEhfxfZ9Ai/idyYihE2u9dQ7a143P/Ij/twDrZTt24wO/mtHDrE5XcCFI= +ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=linaro.org; + spf=pass smtp.mailfrom=linaro.org; + dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org + header.b=qX99TQMM; arc=none smtp.client-ip=209.85.208.179 +Authentication-Results: smtp.subspace.kernel.org; + dmarc=pass (p=none dis=none) header.from=linaro.org +Authentication-Results: smtp.subspace.kernel.org; + spf=pass smtp.mailfrom=linaro.org +Received: by mail-lj1-f179.google.com with SMTP id + 38308e7fff4ca-2dd041acff1so40839131fa.1 + for ; + Tue, 23 Apr 2024 05:12:37 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=linaro.org; s=google; t=1713874356; x=1714479156; + darn=vger.kernel.org; + h=cc:to:message-id:content-transfer-encoding:mime-version:subject + :date:from:from:to:cc:subject:date:message-id:reply-to; + bh=vysJsMiH5IVqdTs4yMwZxZ7nUmt2aG7eBhkn8qm8hvI=; + b=qX99TQMMdHbskFYUaw8c93sIJsUhKmj/WPdyahHcupUhwn5wol4aVoPczkOKYwJZhE + eoInxzjAHIl3UNKyvPPrD4MrbLcSoFT6mTFMsgRQYUghsLattmGcqIebu9XT556dBhsf + DydmpqGgnTOIa+IEknFxg24mo8Xn2LVmDC7LSGEYykUy1xLHd1NSq56YEaYXC7641xeZ + 9TOL0rZszeGld5cCS3013EmEeXQGCC3lAP83Eb48vbFXjPojkN0s40rZ2s8YpVsGT0iP + LeLVtP/E8XJqi4YipKryKSgbgOvQ1Bclle5+s+2qcJQNnSEjekMwR59BIRs3OZH2SRfN + gQdQ== +X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=1e100.net; s=20230601; t=1713874356; x=1714479156; + h=cc:to:message-id:content-transfer-encoding:mime-version:subject + :date:from:x-gm-message-state:from:to:cc:subject:date:message-id + :reply-to; + bh=vysJsMiH5IVqdTs4yMwZxZ7nUmt2aG7eBhkn8qm8hvI=; + b=jEBH4NQ7SzFi2tnb1lgL06IchnBJoscNgKesjlorvou6X/9wDE/VbgxNFKR0zWwdTk + BEjG/ifFJxLmM9jdaCKu5cJc4yiDNXp7yZd48D71V34zJ4aINAGAx4hcOKqf95neFknx + nsFPpBFnTYFEpCLF0TebVoL6h6ehPzSojmkArzsrMppNvW2cwJ5gDlkqy2y4SezLanmM + 6iU0ksnwE0bb2iLkahhgo00Ejt33yqxwa+3xBfhOe9oYKSSZYnY7qVq055SSwt9IAq+H + REGyJN+GrvupTHagiioYe3LPXDPdOui9ZixXXDllw1t1yGUy+TkJu8xSqtvHEfg81FHP + AxtA== +X-Forwarded-Encrypted: i=1; + AJvYcCUbxzPklfPYrLgyY1I0ycuj7Dh04dcGVonYocA2mzxzlAEV107o0ELlFqr3O9Td+tV/t0eV9ly9YAbTY6n1XPnFXS5dsYYAZw6RHw== +X-Gm-Message-State: AOJu0YxsC7zdakTzntbiRFnN2A7yTrR0x+IpR6ce6eGn5kHeqIBi1km+ + zTVpRulbch3JsmzVDbCbbAAYoBkNgEA568YL6zdjVARnvFwNz1cqatOrR1AXUm0= +X-Google-Smtp-Source: + AGHT+IHBRMGvaJM98f86Z6m/RfVhK2XejjNGF3EvcRq/4x3oGM0DKpd2PbeCJdgmzHjLPVVbdsNzJg== +X-Received: by 2002:a2e:9852:0:b0:2d8:a98d:18e with SMTP id + e18-20020a2e9852000000b002d8a98d018emr7955886ljj.8.1713874355700; + Tue, 23 Apr 2024 05:12:35 -0700 (PDT) +Received: from [192.168.1.140] ([85.235.12.238]) + by smtp.gmail.com with ESMTPSA id + x6-20020a2e7c06000000b002da179d8d25sm1628982ljc.64.2024.04.23.05.12.33 + (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); + Tue, 23 Apr 2024 05:12:35 -0700 (PDT) +From: Linus Walleij +Date: Tue, 23 Apr 2024 14:12:33 +0200 +Subject: [PATCH v2] wifi: ath9k: Obtain system GPIOS from descriptors +Precedence: bulk +X-Mailing-List: linux-gpio@vger.kernel.org +List-Id: +List-Subscribe: +List-Unsubscribe: +MIME-Version: 1.0 +Message-Id: <20240423-descriptors-wireless-v2-1-6d1d03b30bfa@linaro.org> +X-B4-Tracking: v=1; b=H4sIALClJ2YC/22Nyw6CMBBFf4XM2hpanrLyPwyL0o4wCaFkxqCG9 + N+txKXLc5Nz7g6CTCjQZTswbiQUlgTmlIGb7DKiIp8YTG7KXBujPIpjWh+BRT2JcUYRNbTeXir + v7FBUkNSV8U6vI3vrE08kSXgfL5v+rr9gof8HN61yhdo1rvJ125T1dabFcjgHHqGPMX4Ao4iiN + LkAAAA= +To: Kalle Valo , + Andy Shevchenko , + Arnd Bergmann , Alban Bedel , + Bartosz Golaszewski , =?utf-8?q?Toke_H=C3=B8iland-J=C3=B8rg?= + =?utf-8?q?ensen?= +Cc: linux-wireless@vger.kernel.org, brcm80211-dev-list.pdl@broadcom.com, + linux-gpio@vger.kernel.org, Linus Walleij +X-Mailer: b4 0.13.0 + +The ath9k has an odd use of system-wide GPIOs: if the chip +does not have internal GPIO capability, it will try to obtain a +GPIO line from the system GPIO controller: + + if (BIT(gpio) & ah->caps.gpio_mask) + ath9k_hw_gpio_cfg_wmac(...); + else if (AR_SREV_SOC(ah)) + ath9k_hw_gpio_cfg_soc(ah, gpio, out, label); + +Where ath9k_hw_gpio_cfg_soc() will attempt to issue +gpio_request_one() passing the local GPIO number of the controller +(0..31) to gpio_request_one(). + +This is somewhat peculiar and possibly even dangerous: there is +nowadays no guarantee of the numbering of these system-wide +GPIOs, and assuming that GPIO 0..31 as used by ath9k would +correspond to GPIOs 0..31 on the system as a whole seems a bit +wild. + +Register all 32 GPIOs at index 0..31 directly in the ATH79K +GPIO driver and associate with WIFI if and only if we are probing +ATH79K wifi from the AHB bus (used for SoCs). + +Signed-off-by: Linus Walleij +--- +Changes in v2: +- Define all the descriptors directly in the ATH79K + GPIO driver in case the driver want to request them directly. +- Link to v1: https://lore.kernel.org/r/20240131-descriptors-wireless-v1-0-e1c7c5d68746@linaro.org +--- + drivers/gpio/gpio-ath79.c | 47 ++++++++++++++++++++++++++++++++++++- + drivers/net/wireless/ath/ath9k/hw.c | 29 ++++++++++++----------- + drivers/net/wireless/ath/ath9k/hw.h | 3 ++- + 3 files changed, 63 insertions(+), 16 deletions(-) + + +--- +base-commit: 4cece764965020c22cff7665b18a012006359095 +change-id: 20240122-descriptors-wireless-b8da95dcab35 + +Best regards, + +--- a/drivers/gpio/gpio-ath79.c ++++ b/drivers/gpio/gpio-ath79.c +@@ -9,6 +9,7 @@ + */ + + #include ++#include /* For WLAN GPIOs */ + #include + #include + #include +@@ -222,6 +223,37 @@ static const struct of_device_id ath79_g + }; + MODULE_DEVICE_TABLE(of, ath79_gpio_of_match); + ++/* ++ * This registers all of the ath79k GPIOs as descriptors to be picked ++ * directly from the ATH79K wifi driver if the two are jitted together ++ * in the same SoC. ++ */ ++#define ATH79K_WIFI_DESCS 32 ++static int ath79_gpio_register_wifi_descriptors(struct device *dev, ++ const char *label) ++{ ++ struct gpiod_lookup_table *lookup; ++ int i; ++ ++ /* Create a gpiod lookup using gpiochip-local offsets + 1 for NULL */ ++ lookup = devm_kzalloc(dev, ++ struct_size(lookup, table, ATH79K_WIFI_DESCS + 1), ++ GFP_KERNEL); ++ ++ if (!lookup) ++ return -ENOMEM; ++ ++ for (i = 0; i < ATH79K_WIFI_DESCS; i++) { ++ lookup->table[i] = (struct gpiod_lookup) ++ GPIO_LOOKUP_IDX(label, i, "ath9k", i, ++ GPIO_ACTIVE_HIGH); ++ } ++ ++ gpiod_add_lookup_table(lookup); ++ ++ return 0; ++} ++ + static int ath79_gpio_probe(struct platform_device *pdev) + { + struct ath79_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev); +@@ -289,7 +321,11 @@ static int ath79_gpio_probe(struct platf + girq->handler = handle_simple_irq; + } + +- return devm_gpiochip_add_data(dev, &ctrl->gc, ctrl); ++ err = devm_gpiochip_add_data(dev, &ctrl->gc, ctrl); ++ if (err) ++ return err; ++ ++ return ath79_gpio_register_wifi_descriptors(dev, ctrl->gc.label); + } + + static struct platform_driver ath79_gpio_driver = { diff --git a/lede/target/linux/ath79/patches-6.6/350-MIPS-ath79-ath9k-exports.patch b/lede/target/linux/ath79/patches-6.6/350-MIPS-ath79-ath9k-exports.patch new file mode 100644 index 0000000000..e460fe58f3 --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/350-MIPS-ath79-ath9k-exports.patch @@ -0,0 +1,36 @@ +From: John Crispin +Subject: [PATCH] ath79: make ahb wifi work + +Submitted-by: John Crispin +--- + arch/mips/ath79/common.c | 3 +++ + mips/include/asm/mach-ath79/ath79.h | 1+ + 1 file changed, 4 insertions(+) + +--- a/arch/mips/ath79/common.c ++++ b/arch/mips/ath79/common.c +@@ -31,11 +31,13 @@ EXPORT_SYMBOL_GPL(ath79_ddr_freq); + + enum ath79_soc_type ath79_soc; + unsigned int ath79_soc_rev; ++EXPORT_SYMBOL_GPL(ath79_soc_rev); + + void __iomem *ath79_pll_base; + void __iomem *ath79_reset_base; + EXPORT_SYMBOL_GPL(ath79_reset_base); +-static void __iomem *ath79_ddr_base; ++void __iomem *ath79_ddr_base; ++EXPORT_SYMBOL_GPL(ath79_ddr_base); + static void __iomem *ath79_ddr_wb_flush_base; + static void __iomem *ath79_ddr_pci_win_base; + +--- a/arch/mips/include/asm/mach-ath79/ath79.h ++++ b/arch/mips/include/asm/mach-ath79/ath79.h +@@ -149,6 +149,7 @@ void ath79_ddr_wb_flush(unsigned int reg + void ath79_ddr_set_pci_windows(void); + + extern void __iomem *ath79_pll_base; ++extern void __iomem *ath79_ddr_base; + extern void __iomem *ath79_reset_base; + + static inline void ath79_pll_wr(unsigned reg, u32 val) diff --git a/lede/target/linux/ath79/patches-6.6/351-MIPS-ath79-common-exports.patch b/lede/target/linux/ath79/patches-6.6/351-MIPS-ath79-common-exports.patch new file mode 100644 index 0000000000..befcf2d50f --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/351-MIPS-ath79-common-exports.patch @@ -0,0 +1,26 @@ +From: Luiz Angelo Daros de Luca +Subject: [PATCH] ath79: export ath79_pll_base + +This symbol is declared as extern but nobody exported it. +Any module including arch/mips/include/asm/mach-ath79/ath79.h +will not build. Without this export, ag71xx.ko will not build +as a module and the build will fail like this: + +ERROR: modpost: "ath79_pll_base" [drivers/net/ethernet/atheros/ag71xx/ag71xx.ko] undefined! + +The ath79_pll_base symbol is accessed in the ath79_pll_wr() inline function. + +--- + arch/mips/ath79/common.c | 1 + + 1 file changed, 1 insertions(+) + +--- a/arch/mips/ath79/common.c ++++ b/arch/mips/ath79/common.c +@@ -34,6 +34,7 @@ unsigned int ath79_soc_rev; + EXPORT_SYMBOL_GPL(ath79_soc_rev); + + void __iomem *ath79_pll_base; ++EXPORT_SYMBOL_GPL(ath79_pll_base); + void __iomem *ath79_reset_base; + EXPORT_SYMBOL_GPL(ath79_reset_base); + void __iomem *ath79_ddr_base; diff --git a/lede/target/linux/ath79/patches-6.6/360-MIPS-ath79-export-UART1-reference-clock.patch b/lede/target/linux/ath79/patches-6.6/360-MIPS-ath79-export-UART1-reference-clock.patch new file mode 100644 index 0000000000..ae2f5aa0cd --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/360-MIPS-ath79-export-UART1-reference-clock.patch @@ -0,0 +1,67 @@ +From: Daniel Golle +Subject: [PATCH] ath79: add support for Atheros AR934x HS UART + +AR934x chips also got the 'old' qca,ar9330-uart in addition to the +'new' ns16550a compatible one. Add support for UART1 clock selector as +well as device-tree bindings in ar934x.dtsi to make use of that uart. + +Reported-by: Piotr Dymacz +Submitted-by: Daniel Golle +--- + arch/mips/ath79/clock.c | 7 +++++++ + .../mips/include/asm/mach-ath79/ar71xx_regs.h | 1 + + include/dt-bindings/clock/ath79-clk.h | 3 ++- + 3 files changed, 10 insertions(+), 1 deletion(-) + +--- a/arch/mips/ath79/clock.c ++++ b/arch/mips/ath79/clock.c +@@ -40,6 +40,7 @@ static const char * const clk_names[ATH7 + [ATH79_CLK_AHB] = "ahb", + [ATH79_CLK_REF] = "ref", + [ATH79_CLK_MDIO] = "mdio", ++ [ATH79_CLK_UART1] = "uart1", + }; + + static const char * __init ath79_clk_name(int type) +@@ -344,6 +345,9 @@ static void __init ar934x_clocks_init(vo + if (clk_ctrl & AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL) + ath79_set_clk(ATH79_CLK_MDIO, 100 * 1000 * 1000); + ++ if (clk_ctrl & AR934X_PLL_SWITCH_CLOCK_CONTROL_UART1_CLK_SEL) ++ ath79_set_clk(ATH79_CLK_UART1, 100 * 1000 * 1000); ++ + iounmap(dpll_base); + } + +@@ -649,6 +653,9 @@ static void __init ath79_clocks_init_dt( + if (!clks[ATH79_CLK_MDIO]) + clks[ATH79_CLK_MDIO] = clks[ATH79_CLK_REF]; + ++ if (!clks[ATH79_CLK_UART1]) ++ clks[ATH79_CLK_UART1] = clks[ATH79_CLK_REF]; ++ + if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data)) { + pr_err("%pOF: could not register clk provider\n", np); + goto err_iounmap; +--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h ++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +@@ -350,6 +350,7 @@ + #define AR934X_PLL_PCIE_CONFIG_PLL_PWD BIT(30) + + #define AR934X_PLL_SWITCH_CLOCK_CONTROL_MDIO_CLK_SEL BIT(6) ++#define AR934X_PLL_SWITCH_CLOCK_CONTROL_UART1_CLK_SEL BIT(7) + + #define QCA953X_PLL_CPU_CONFIG_REG 0x00 + #define QCA953X_PLL_DDR_CONFIG_REG 0x04 +--- a/include/dt-bindings/clock/ath79-clk.h ++++ b/include/dt-bindings/clock/ath79-clk.h +@@ -11,7 +11,8 @@ + #define ATH79_CLK_AHB 2 + #define ATH79_CLK_REF 3 + #define ATH79_CLK_MDIO 4 ++#define ATH79_CLK_UART1 5 + +-#define ATH79_CLK_END 5 ++#define ATH79_CLK_END 6 + + #endif /* __DT_BINDINGS_ATH79_CLK_H */ diff --git a/lede/target/linux/ath79/patches-6.6/370-MIPS-ath79-sanitize-symbols.patch b/lede/target/linux/ath79/patches-6.6/370-MIPS-ath79-sanitize-symbols.patch new file mode 100644 index 0000000000..e6aeef5115 --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/370-MIPS-ath79-sanitize-symbols.patch @@ -0,0 +1,77 @@ +From 3fc8585cf76022dba7496627074d42af88c30718 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Sat, 23 Jun 2018 15:16:55 +0200 +Subject: [PATCH 32/33] MIPS: ath79: sanitize symbols + +We no longer need to select which SoCs are supported as the whole arch +code is always built. So lets drop all the SoC symbols + +Signed-off-by: John Crispin +--- + arch/mips/Kconfig | 2 ++ + arch/mips/ath79/Kconfig | 44 +++++--------------------------------------- + arch/mips/pci/Makefile | 2 +- + 3 files changed, 8 insertions(+), 40 deletions(-) + +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -255,6 +255,8 @@ config ATH79 + select SYS_SUPPORTS_BIG_ENDIAN + select SYS_SUPPORTS_MIPS16 + select SYS_SUPPORTS_ZBOOT_UART_PROM ++ select HAVE_PCI ++ select USB_ARCH_HAS_EHCI + select USE_OF + select USB_EHCI_ROOT_HUB_TT if USB_EHCI_HCD_PLATFORM + help +--- a/arch/mips/ath79/Kconfig ++++ b/arch/mips/ath79/Kconfig +@@ -1,32 +1,14 @@ + # SPDX-License-Identifier: GPL-2.0 + if ATH79 + +-config SOC_AR71XX +- select HAVE_PCI +- def_bool n +- +-config SOC_AR724X +- select HAVE_PCI +- select PCI_AR724X if PCI +- def_bool n +- +-config SOC_AR913X +- def_bool n +- +-config SOC_AR933X +- def_bool n +- +-config SOC_AR934X +- select HAVE_PCI +- select PCI_AR724X if PCI +- def_bool n +- +-config SOC_QCA955X +- select HAVE_PCI +- select PCI_AR724X if PCI ++config PCI_AR71XX ++ bool "PCI support for AR7100 type SoCs" ++ depends on PCI + def_bool n + + config PCI_AR724X ++ bool "PCI support for AR724x type SoCs" ++ depends on PCI + def_bool n + + endif +--- a/arch/mips/pci/Makefile ++++ b/arch/mips/pci/Makefile +@@ -19,7 +19,7 @@ obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o + ops-bcm63xx.o + obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o + obj-$(CONFIG_PCI_AR2315) += pci-ar2315.o +-obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o ++obj-$(CONFIG_PCI_AR71XX) += pci-ar71xx.o + obj-$(CONFIG_PCI_AR724X) += pci-ar724x.o + obj-$(CONFIG_PCI_XTALK_BRIDGE) += pci-xtalk-bridge.o + # diff --git a/lede/target/linux/ath79/patches-6.6/400-mtd-nor-support-mtd-name-from-device-tree.patch b/lede/target/linux/ath79/patches-6.6/400-mtd-nor-support-mtd-name-from-device-tree.patch new file mode 100644 index 0000000000..62d402625d --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/400-mtd-nor-support-mtd-name-from-device-tree.patch @@ -0,0 +1,53 @@ +From f32bc2aa01edcba2f2ed5db151cf183eac9ef919 Mon Sep 17 00:00:00 2001 +From: Abhimanyu Vishwakarma +Date: Sat, 25 Feb 2017 16:42:50 +0000 +Subject: mtd: nor: support mtd name from device tree + +Signed-off-by: Abhimanyu Vishwakarma +--- + drivers/mtd/spi-nor/spi-nor.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/mtd/spi-nor/core.c ++++ b/drivers/mtd/spi-nor/core.c +@@ -3420,12 +3420,19 @@ static void spi_nor_set_mtd_info(struct + { + struct mtd_info *mtd = &nor->mtd; + struct device *dev = nor->dev; ++ struct device_node *np = spi_nor_get_flash_node(nor); ++ const char __maybe_unused *of_mtd_name = NULL; + + spi_nor_set_mtd_locking_ops(nor); + spi_nor_set_mtd_otp_ops(nor); + + mtd->dev.parent = dev; +- if (!mtd->name) ++#ifdef CONFIG_MTD_OF_PARTS ++ of_property_read_string(np, "linux,mtd-name", &of_mtd_name); ++#endif ++ if (of_mtd_name) ++ mtd->name = of_mtd_name; ++ else if (!mtd->name) + mtd->name = dev_name(dev); + mtd->type = MTD_NORFLASH; + mtd->flags = MTD_CAP_NORFLASH; +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -870,6 +870,17 @@ out_error: + */ + static void mtd_set_dev_defaults(struct mtd_info *mtd) + { ++#ifdef CONFIG_MTD_OF_PARTS ++ const char __maybe_unused *of_mtd_name = NULL; ++ struct device_node *np; ++ ++ np = mtd_get_of_node(mtd); ++ if (np && !mtd->name) { ++ of_property_read_string(np, "linux,mtd-name", &of_mtd_name); ++ if (of_mtd_name) ++ mtd->name = of_mtd_name; ++ } else ++#endif + if (mtd->dev.parent) { + if (!mtd->owner && mtd->dev.parent->driver) + mtd->owner = mtd->dev.parent->driver->owner; diff --git a/lede/target/linux/ath79/patches-6.6/410-mtd-cybertan-trx-parser.patch b/lede/target/linux/ath79/patches-6.6/410-mtd-cybertan-trx-parser.patch new file mode 100644 index 0000000000..d0e8aec0d5 --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/410-mtd-cybertan-trx-parser.patch @@ -0,0 +1,45 @@ +From: Christian Lamparter +Subject: [PATCH] ath79: port cybertan_part from ar71xx + +This patch ports the cybertan_part code from ar71xx and converts the +driver to a DT-supported mtd parser. As a result, it will no longer +add the u-boot, nvram and art partitions, which were never part of +the special Cybertan header. + +Instead these partitions have to be specified in the DT, which has the +upside of making it possible to add properties (i.e.: read-only), labels +and references to these important partitions. + +Submitted-by: Christian Lamparter +--- + drivers/mtd/parsers/Makefile | 1 + + drivers/mtd/parsers/Kconfig | 8 ++++++++ + 2 files changed, 9 insertions(+) + +--- a/drivers/mtd/parsers/Makefile ++++ b/drivers/mtd/parsers/Makefile +@@ -9,6 +9,7 @@ obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o + ofpart-y += ofpart_core.o + ofpart-$(CONFIG_MTD_OF_PARTS_BCM4908) += ofpart_bcm4908.o + ofpart-$(CONFIG_MTD_OF_PARTS_LINKSYS_NS)+= ofpart_linksys_ns.o ++obj-$(CONFIG_MTD_PARSER_CYBERTAN) += parser_cybertan.o + obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o + obj-$(CONFIG_MTD_AFS_PARTS) += afs.o + obj-$(CONFIG_MTD_PARSER_TPLINK_SAFELOADER) += tplink_safeloader.o +--- a/drivers/mtd/parsers/Kconfig ++++ b/drivers/mtd/parsers/Kconfig +@@ -112,6 +112,14 @@ config MTD_OF_PARTS_LINKSYS_NS + two "firmware" partitions. Currently used firmware has to be detected + using CFE environment variable. + ++config MTD_PARSER_CYBERTAN ++ tristate "Parser for Cybertan format partitions" ++ depends on MTD && (ATH79 || COMPILE_TEST) ++ help ++ Cybertan has a proprietory header than encompasses a Broadcom trx ++ header. This driver will parse the header and take care of the ++ special offsets that result in the extra headers. ++ + config MTD_PARSER_IMAGETAG + tristate "Parser for BCM963XX Image Tag format partitions" + depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST diff --git a/lede/target/linux/ath79/patches-6.6/430-mtd-ar934x-nand-driver.patch b/lede/target/linux/ath79/patches-6.6/430-mtd-ar934x-nand-driver.patch new file mode 100644 index 0000000000..fc4c3804a7 --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/430-mtd-ar934x-nand-driver.patch @@ -0,0 +1,34 @@ +From: Gabor Juhos +Subject: ar71xx: ar934x_nfc: experimental NAND Flash Controller driver for AR934x + +SVN-Revision: 33385 +--- + drivers/mtd/nand/raw/Kconfig | 8 ++++++++ + drivers/mtd/nand/raw/Makefile | 1 + + 2 files changed, 9 insertions(+) + +--- a/drivers/mtd/nand/raw/Kconfig ++++ b/drivers/mtd/nand/raw/Kconfig +@@ -542,4 +542,12 @@ config MTD_NAND_DISKONCHIP_BBTWRITE + load time (assuming you build diskonchip as a module) with the module + parameter "inftl_bbt_write=1". + ++config MTD_NAND_AR934X ++ tristate "Support for NAND controller on Qualcomm Atheros AR934x/QCA955x SoCs" ++ depends on ATH79 || COMPILE_TEST ++ depends on HAS_IOMEM ++ help ++ Enables support for NAND controller on Qualcomm Atheros SoCs. ++ This controller is found on AR934x and QCA955x SoCs. ++ + endif # MTD_RAW_NAND +--- a/drivers/mtd/nand/raw/Makefile ++++ b/drivers/mtd/nand/raw/Makefile +@@ -57,6 +57,7 @@ obj-$(CONFIG_MTD_NAND_INTEL_LGM) += inte + obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip-nand-controller.o + obj-$(CONFIG_MTD_NAND_PL35X) += pl35x-nand-controller.o + obj-$(CONFIG_MTD_NAND_RENESAS) += renesas-nand-controller.o ++obj-$(CONFIG_MTD_NAND_AR934X) += ar934x_nand.o + + nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o + nand-objs += nand_onfi.o diff --git a/lede/target/linux/ath79/patches-6.6/700-phy-add-ath79-usb-phys.patch b/lede/target/linux/ath79/patches-6.6/700-phy-add-ath79-usb-phys.patch new file mode 100644 index 0000000000..1c1b2f2ca1 --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/700-phy-add-ath79-usb-phys.patch @@ -0,0 +1,285 @@ +From 08c9d6ceef01893678a5d2e8a15517c745417f21 Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Tue, 6 Mar 2018 10:04:05 +0100 +Subject: [PATCH 04/27] phy: add ath79 usb phys + +Signed-off-by: John Crispin +--- + drivers/phy/Kconfig | 16 ++++++ + drivers/phy/Makefile | 2 + + drivers/phy/phy-ar7100-usb.c | 124 +++++++++++++++++++++++++++++++++++++++++++ + drivers/phy/phy-ar7200-usb.c | 108 +++++++++++++++++++++++++++++++++++++ + 4 files changed, 250 insertions(+) + create mode 100644 drivers/phy/phy-ar7100-usb.c + create mode 100644 drivers/phy/phy-ar7200-usb.c + +--- a/drivers/phy/Kconfig ++++ b/drivers/phy/Kconfig +@@ -25,6 +25,22 @@ config GENERIC_PHY_MIPI_DPHY + Provides a number of helpers a core functions for MIPI D-PHY + drivers to us. + ++config PHY_AR7100_USB ++ tristate "Atheros AR7100 USB PHY driver" ++ depends on ATH79 || COMPILE_TEST ++ default y if USB_EHCI_HCD_PLATFORM ++ select GENERIC_PHY ++ help ++ Enable this to support the USB PHY on Atheros AR7100 SoCs. ++ ++config PHY_AR7200_USB ++ tristate "Atheros AR7200 USB PHY driver" ++ depends on ATH79 || COMPILE_TEST ++ default y if USB_EHCI_HCD_PLATFORM ++ select GENERIC_PHY ++ help ++ Enable this to support the USB PHY on Atheros AR7200 SoCs. ++ + config PHY_LPC18XX_USB_OTG + tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver" + depends on OF && (ARCH_LPC18XX || COMPILE_TEST) +--- a/drivers/phy/Makefile ++++ b/drivers/phy/Makefile +@@ -4,6 +4,8 @@ + # + + obj-$(CONFIG_GENERIC_PHY) += phy-core.o ++obj-$(CONFIG_PHY_AR7100_USB) += phy-ar7100-usb.o ++obj-$(CONFIG_PHY_AR7200_USB) += phy-ar7200-usb.o + obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY) += phy-core-mipi-dphy.o + obj-$(CONFIG_PHY_CAN_TRANSCEIVER) += phy-can-transceiver.o + obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o +--- /dev/null ++++ b/drivers/phy/phy-ar7100-usb.c +@@ -0,0 +1,117 @@ ++/* ++ * Copyright (C) 2018 John Crispin ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++struct ar7100_usb_phy { ++ struct reset_control *rst_phy; ++ struct reset_control *rst_host; ++ struct reset_control *rst_ohci_dll; ++ void __iomem *io_base; ++ struct phy *phy; ++ int gpio; ++}; ++ ++static int ar7100_usb_phy_power_off(struct phy *phy) ++{ ++ struct ar7100_usb_phy *priv = phy_get_drvdata(phy); ++ int err = 0; ++ ++ err |= reset_control_assert(priv->rst_host); ++ err |= reset_control_assert(priv->rst_phy); ++ err |= reset_control_assert(priv->rst_ohci_dll); ++ ++ return err; ++} ++ ++static int ar7100_usb_phy_power_on(struct phy *phy) ++{ ++ struct ar7100_usb_phy *priv = phy_get_drvdata(phy); ++ int err = 0; ++ ++ err |= ar7100_usb_phy_power_off(phy); ++ mdelay(100); ++ err |= reset_control_deassert(priv->rst_ohci_dll); ++ err |= reset_control_deassert(priv->rst_phy); ++ err |= reset_control_deassert(priv->rst_host); ++ mdelay(500); ++ iowrite32(0xf0000, priv->io_base + AR71XX_USB_CTRL_REG_CONFIG); ++ iowrite32(0x20c00, priv->io_base + AR71XX_USB_CTRL_REG_FLADJ); ++ ++ return err; ++} ++ ++static const struct phy_ops ar7100_usb_phy_ops = { ++ .power_on = ar7100_usb_phy_power_on, ++ .power_off = ar7100_usb_phy_power_off, ++ .owner = THIS_MODULE, ++}; ++ ++static int ar7100_usb_phy_probe(struct platform_device *pdev) ++{ ++ struct phy_provider *phy_provider; ++ struct ar7100_usb_phy *priv; ++ ++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->io_base = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(priv->io_base)) ++ return PTR_ERR(priv->io_base); ++ ++ priv->rst_phy = devm_reset_control_get(&pdev->dev, "phy"); ++ if (IS_ERR(priv->rst_phy)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(priv->rst_phy), "phy reset is missing"); ++ ++ priv->rst_host = devm_reset_control_get(&pdev->dev, "host"); ++ if (IS_ERR(priv->rst_host)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(priv->rst_host), "host reset is missing"); ++ ++ priv->rst_ohci_dll = devm_reset_control_get(&pdev->dev, "usb-ohci-dll"); ++ if (IS_ERR(priv->rst_ohci_dll)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(priv->rst_host), "ohci-dll reset is missing"); ++ ++ priv->phy = devm_phy_create(&pdev->dev, NULL, &ar7100_usb_phy_ops); ++ if (IS_ERR(priv->phy)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(priv->phy), "failed to create PHY"); ++ ++ phy_set_drvdata(priv->phy, priv); ++ ++ phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate); ++ ++ return PTR_ERR_OR_ZERO(phy_provider); ++} ++ ++static const struct of_device_id ar7100_usb_phy_of_match[] = { ++ { .compatible = "qca,ar7100-usb-phy" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, ar7100_usb_phy_of_match); ++ ++static struct platform_driver ar7100_usb_phy_driver = { ++ .probe = ar7100_usb_phy_probe, ++ .driver = { ++ .of_match_table = ar7100_usb_phy_of_match, ++ .name = "ar7100-usb-phy", ++ } ++}; ++module_platform_driver(ar7100_usb_phy_driver); ++ ++MODULE_DESCRIPTION("ATH79 USB PHY driver"); ++MODULE_AUTHOR("Alban Bedel "); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/phy/phy-ar7200-usb.c +@@ -0,0 +1,111 @@ ++/* ++ * Copyright (C) 2015 Alban Bedel ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++struct ar7200_usb_phy { ++ struct reset_control *rst_phy; ++ struct reset_control *rst_phy_analog; ++ struct reset_control *suspend_override; ++ struct phy *phy; ++ int gpio; ++}; ++ ++static int ar7200_usb_phy_power_on(struct phy *phy) ++{ ++ struct ar7200_usb_phy *priv = phy_get_drvdata(phy); ++ int err = 0; ++ ++ if (priv->suspend_override) ++ err = reset_control_assert(priv->suspend_override); ++ if (priv->rst_phy) ++ err |= reset_control_deassert(priv->rst_phy); ++ if (priv->rst_phy_analog) ++ err |= reset_control_deassert(priv->rst_phy_analog); ++ ++ return err; ++} ++ ++static int ar7200_usb_phy_power_off(struct phy *phy) ++{ ++ struct ar7200_usb_phy *priv = phy_get_drvdata(phy); ++ int err = 0; ++ ++ if (priv->suspend_override) ++ err = reset_control_deassert(priv->suspend_override); ++ if (priv->rst_phy) ++ err |= reset_control_assert(priv->rst_phy); ++ if (priv->rst_phy_analog) ++ err |= reset_control_assert(priv->rst_phy_analog); ++ ++ return err; ++} ++ ++static const struct phy_ops ar7200_usb_phy_ops = { ++ .power_on = ar7200_usb_phy_power_on, ++ .power_off = ar7200_usb_phy_power_off, ++ .owner = THIS_MODULE, ++}; ++ ++static int ar7200_usb_phy_probe(struct platform_device *pdev) ++{ ++ struct phy_provider *phy_provider; ++ struct ar7200_usb_phy *priv; ++ ++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->rst_phy = devm_reset_control_get(&pdev->dev, "phy"); ++ if (IS_ERR(priv->rst_phy)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(priv->rst_phy), "phy reset is missing"); ++ ++ priv->rst_phy_analog = devm_reset_control_get_optional( ++ &pdev->dev, "phy-analog"); ++ if (IS_ERR(priv->rst_phy_analog)) ++ return PTR_ERR(priv->rst_phy_analog); ++ ++ priv->suspend_override = devm_reset_control_get_optional( ++ &pdev->dev, "suspend-override"); ++ if (IS_ERR(priv->suspend_override)) ++ return PTR_ERR(priv->suspend_override); ++ ++ priv->phy = devm_phy_create(&pdev->dev, NULL, &ar7200_usb_phy_ops); ++ if (IS_ERR(priv->phy)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(priv->phy), "failed to create PHY"); ++ ++ phy_set_drvdata(priv->phy, priv); ++ ++ phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate); ++ ++ return PTR_ERR_OR_ZERO(phy_provider); ++} ++ ++static const struct of_device_id ar7200_usb_phy_of_match[] = { ++ { .compatible = "qca,ar7200-usb-phy" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, ar7200_usb_phy_of_match); ++ ++static struct platform_driver ar7200_usb_phy_driver = { ++ .probe = ar7200_usb_phy_probe, ++ .driver = { ++ .of_match_table = ar7200_usb_phy_of_match, ++ .name = "ar7200-usb-phy", ++ } ++}; ++module_platform_driver(ar7200_usb_phy_driver); ++ ++MODULE_DESCRIPTION("ATH79 USB PHY driver"); ++MODULE_AUTHOR("Alban Bedel "); ++MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/ath79/patches-6.6/701-usb-add-more-OF-quirk-properties.patch b/lede/target/linux/ath79/patches-6.6/701-usb-add-more-OF-quirk-properties.patch new file mode 100644 index 0000000000..293a359884 --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/701-usb-add-more-OF-quirk-properties.patch @@ -0,0 +1,24 @@ +From 2201818e5bd33f389beceb3943fdfcf5a698fc5b Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Tue, 6 Mar 2018 10:01:43 +0100 +Subject: [PATCH 05/27] usb: add more OF/quirk properties + +Signed-off-by: John Crispin +--- + drivers/usb/host/ehci-platform.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/usb/host/ehci-platform.c ++++ b/drivers/usb/host/ehci-platform.c +@@ -274,6 +274,11 @@ static int ehci_platform_probe(struct pl + ehci = hcd_to_ehci(hcd); + + if (pdata == &ehci_platform_defaults && dev->dev.of_node) { ++ of_property_read_u32(dev->dev.of_node, "caps-offset", &pdata->caps_offset); ++ ++ if (of_property_read_bool(dev->dev.of_node, "has-synopsys-hc-bug")) ++ pdata->has_synopsys_hc_bug = 1; ++ + if (of_property_read_bool(dev->dev.of_node, "big-endian-regs")) + ehci->big_endian_mmio = 1; + diff --git a/lede/target/linux/ath79/patches-6.6/710-net-use-downstream-ag71xx.patch b/lede/target/linux/ath79/patches-6.6/710-net-use-downstream-ag71xx.patch new file mode 100644 index 0000000000..0997aa1ab8 --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/710-net-use-downstream-ag71xx.patch @@ -0,0 +1,34 @@ +From: John Crispin +Subject: [PATCH] ath79: add new OF only target for QCA MIPS silicon + +This target aims to replace ar71xx mid-term. The big part that is still +missing is making the MMIO/AHB wifi work using OF. NAND and mikrotik +subtargets will follow. + +Submitted-by: John Crispin +--- + drivers/net/ethernet/atheros/Kconfig | 8 +------- + drivers/net/ethernet/atheros/Makefile | 2 +- + 2 files changed, 2 insertions(+), 8 deletions(-) + +--- a/drivers/net/ethernet/atheros/Kconfig ++++ b/drivers/net/ethernet/atheros/Kconfig +@@ -26,6 +26,8 @@ config AG71XX + If you wish to compile a kernel for AR7XXX/91XXX and enable + ethernet support, then you should always answer Y to this. + ++source "drivers/net/ethernet/atheros/ag71xx/Kconfig" ++ + config ATL2 + tristate "Atheros L2 Fast Ethernet support" + depends on PCI +--- a/drivers/net/ethernet/atheros/Makefile ++++ b/drivers/net/ethernet/atheros/Makefile +@@ -4,6 +4,7 @@ + # + + obj-$(CONFIG_AG71XX) += ag71xx.o ++obj-$(CONFIG_AG71XX_LEGACY) += ag71xx/ + obj-$(CONFIG_ATL1) += atlx/ + obj-$(CONFIG_ATL2) += atlx/ + obj-$(CONFIG_ATL1E) += atl1e/ diff --git a/lede/target/linux/ath79/patches-6.6/720-mdio_bitbang_ignore_ta_value.patch b/lede/target/linux/ath79/patches-6.6/720-mdio_bitbang_ignore_ta_value.patch new file mode 100644 index 0000000000..ce6b16c34e --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/720-mdio_bitbang_ignore_ta_value.patch @@ -0,0 +1,40 @@ +From: Jonas Gorski +Subject: ar71xx: add a workaround for ar8316 not always driving the TA bit to low + +AR8316 behind a GPIO bitbanged MDIO bus fails to drive the turnaround bit +to low despite returning a valid value. Ignore it and just use the +returned value anyway. + +SVN-Revision: 28422 +--- + drivers/net/mdio/mdio-bitbang.c | 16 ++----------------- + 1 file changed, 2 insertions(+), 14 deletions(-) + +--- a/drivers/net/mdio/mdio-bitbang.c ++++ b/drivers/net/mdio/mdio-bitbang.c +@@ -148,23 +148,11 @@ static void mdiobb_cmd_addr(struct mdiob + static int mdiobb_read_common(struct mii_bus *bus, int phy) + { + struct mdiobb_ctrl *ctrl = bus->priv; +- int ret, i; ++ int ret; + + ctrl->ops->set_mdio_dir(ctrl, 0); + +- /* check the turnaround bit: the PHY should be driving it to zero, if this +- * PHY is listed in phy_ignore_ta_mask as having broken TA, skip that +- */ +- if (mdiobb_get_bit(ctrl) != 0 && +- !(bus->phy_ignore_ta_mask & (1 << phy))) { +- /* PHY didn't drive TA low -- flush any bits it +- * may be trying to send. +- */ +- for (i = 0; i < 32; i++) +- mdiobb_get_bit(ctrl); +- +- return 0xffff; +- } ++ mdiobb_get_bit(ctrl); + + ret = mdiobb_get_num(ctrl, 16); + mdiobb_get_bit(ctrl); diff --git a/lede/target/linux/ath79/patches-6.6/721-phy-mdio-bitbang-prevent-rescheduling-during-command.patch b/lede/target/linux/ath79/patches-6.6/721-phy-mdio-bitbang-prevent-rescheduling-during-command.patch new file mode 100644 index 0000000000..26c40e132b --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/721-phy-mdio-bitbang-prevent-rescheduling-during-command.patch @@ -0,0 +1,94 @@ +From 66e584435ac0de6e0abeb6d7166fe4fe25d6bb73 Mon Sep 17 00:00:00 2001 +From: Jonas Gorski +Date: Tue, 16 Jun 2015 13:15:08 +0200 +Subject: [PATCH] phy/mdio-bitbang: prevent rescheduling during command + +It seems some phys have some maximum timings for accessing the MDIO line, +resulting in bit errors under cpu stress. Prevent this from happening by +disabling interrupts when sending commands. + +Signed-off-by: Jonas Gorski +--- + drivers/net/mdio/mdio-bitbang.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/net/mdio/mdio-bitbang.c ++++ b/drivers/net/mdio/mdio-bitbang.c +@@ -14,6 +14,7 @@ + * Vitaly Bordug + */ + ++#include + #include + #include + #include +@@ -161,22 +162,32 @@ static int mdiobb_read_common(struct mii + + int mdiobb_read_c22(struct mii_bus *bus, int phy, int reg) + { ++ int ret; ++ unsigned long flags; + struct mdiobb_ctrl *ctrl = bus->priv; + ++ local_irq_save(flags); + mdiobb_cmd(ctrl, ctrl->op_c22_read, phy, reg); + +- return mdiobb_read_common(bus, phy); ++ ret = mdiobb_read_common(bus, phy); ++ local_irq_restore(flags); ++ return ret; + } + EXPORT_SYMBOL(mdiobb_read_c22); + + int mdiobb_read_c45(struct mii_bus *bus, int phy, int devad, int reg) + { ++ int ret; ++ unsigned long flags; + struct mdiobb_ctrl *ctrl = bus->priv; + ++ local_irq_save(flags); + mdiobb_cmd_addr(ctrl, phy, devad, reg); + mdiobb_cmd(ctrl, MDIO_C45_READ, phy, devad); + +- return mdiobb_read_common(bus, phy); ++ ret = mdiobb_read_common(bus, phy); ++ local_irq_restore(flags); ++ return ret; + } + EXPORT_SYMBOL(mdiobb_read_c45); + +@@ -197,22 +208,32 @@ static int mdiobb_write_common(struct mi + + int mdiobb_write_c22(struct mii_bus *bus, int phy, int reg, u16 val) + { ++ int ret; ++ unsigned long flags; + struct mdiobb_ctrl *ctrl = bus->priv; + ++ local_irq_save(flags); + mdiobb_cmd(ctrl, ctrl->op_c22_write, phy, reg); + +- return mdiobb_write_common(bus, val); ++ ret = mdiobb_write_common(bus, val); ++ local_irq_restore(flags); ++ return ret; + } + EXPORT_SYMBOL(mdiobb_write_c22); + + int mdiobb_write_c45(struct mii_bus *bus, int phy, int devad, int reg, u16 val) + { ++ int ret; ++ unsigned long flags; + struct mdiobb_ctrl *ctrl = bus->priv; + ++ local_irq_save(flags); + mdiobb_cmd_addr(ctrl, phy, devad, reg); + mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, devad); + +- return mdiobb_write_common(bus, val); ++ ret = mdiobb_write_common(bus, val); ++ local_irq_restore(flags); ++ return ret; + } + EXPORT_SYMBOL(mdiobb_write_c45); + diff --git a/lede/target/linux/ath79/patches-6.6/730-ar8216-make-reg-access-atomic.patch b/lede/target/linux/ath79/patches-6.6/730-ar8216-make-reg-access-atomic.patch new file mode 100644 index 0000000000..16d9005699 --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/730-ar8216-make-reg-access-atomic.patch @@ -0,0 +1,59 @@ +From b3797d1a92afe97c173b00fdb7824cedba24eef0 Mon Sep 17 00:00:00 2001 +From: Chuanhong Guo +Date: Sun, 20 Sep 2020 01:00:45 +0800 +Subject: [PATCH] ath79: ar8216: make switch register access atomic + +due to some unknown reason these register accesses sometimes fail +on the integrated switch without this patch. + +THIS ONLY WORKS ON ATH79 AND MAY BREAK THE DRIVER ON OTHER PLATFORMS! +The mdio bus on ath79 works in polling mode and doesn't rely on +any interrupt. This patch breaks the driver on any mdio master +with interrupts used. + +--- +--- a/drivers/net/phy/ar8216.c ++++ b/drivers/net/phy/ar8216.c +@@ -251,6 +251,7 @@ ar8xxx_mii_write32(struct ar8xxx_priv *p + u32 + ar8xxx_read(struct ar8xxx_priv *priv, int reg) + { ++ unsigned long flags; + struct mii_bus *bus = priv->mii_bus; + u16 r1, r2, page; + u32 val; +@@ -258,11 +259,13 @@ ar8xxx_read(struct ar8xxx_priv *priv, in + split_addr((u32) reg, &r1, &r2, &page); + + mutex_lock(&bus->mdio_lock); ++ local_irq_save(flags); + + bus->write(bus, 0x18, 0, page); + wait_for_page_switch(); + val = ar8xxx_mii_read32(priv, 0x10 | r2, r1); + ++ local_irq_restore(flags); + mutex_unlock(&bus->mdio_lock); + + return val; +@@ -271,17 +274,20 @@ ar8xxx_read(struct ar8xxx_priv *priv, in + void + ar8xxx_write(struct ar8xxx_priv *priv, int reg, u32 val) + { ++ unsigned long flags; + struct mii_bus *bus = priv->mii_bus; + u16 r1, r2, page; + + split_addr((u32) reg, &r1, &r2, &page); + + mutex_lock(&bus->mdio_lock); ++ local_irq_save(flags); + + bus->write(bus, 0x18, 0, page); + wait_for_page_switch(); + ar8xxx_mii_write32(priv, 0x10 | r2, r1, val); + ++ local_irq_restore(flags); + mutex_unlock(&bus->mdio_lock); + } + diff --git a/lede/target/linux/ath79/patches-6.6/800-leds-add-reset-controller-based-driver.patch b/lede/target/linux/ath79/patches-6.6/800-leds-add-reset-controller-based-driver.patch new file mode 100644 index 0000000000..e84cc00f4b --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/800-leds-add-reset-controller-based-driver.patch @@ -0,0 +1,186 @@ +From ecbd9c87f073f097d9fe56390353e64e963e866a Mon Sep 17 00:00:00 2001 +From: John Crispin +Date: Tue, 6 Mar 2018 10:03:03 +0100 +Subject: [PATCH 03/27] leds: add reset-controller based driver + +Signed-off-by: John Crispin +--- + drivers/leds/Kconfig | 11 ++++ + drivers/leds/Makefile | 1 + + drivers/leds/leds-reset.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 149 insertions(+) + create mode 100644 drivers/leds/leds-reset.c + +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -911,6 +911,17 @@ source "drivers/leds/flash/Kconfig" + comment "RGB LED drivers" + source "drivers/leds/rgb/Kconfig" + ++config LEDS_RESET ++ tristate "LED support for reset-controller API" ++ depends on LEDS_CLASS ++ depends on RESET_CONTROLLER ++ help ++ This option enables support for LEDs connected to pins driven by reset ++ controllers. Yes, DNI actual built HW like that. ++ ++ To compile this driver as a module, choose M here: the module ++ will be called leds-reset. ++ + comment "LED Triggers" + source "drivers/leds/trigger/Kconfig" + +--- /dev/null ++++ b/drivers/leds/leds-reset.c +@@ -0,0 +1,140 @@ ++/* ++ * Copyright (C) 2018 John Crispin ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct reset_led_data { ++ struct led_classdev cdev; ++ struct reset_control *rst; ++}; ++ ++static inline struct reset_led_data * ++ cdev_to_reset_led_data(struct led_classdev *led_cdev) ++{ ++ return container_of(led_cdev, struct reset_led_data, cdev); ++} ++ ++static void reset_led_set(struct led_classdev *led_cdev, ++ enum led_brightness value) ++{ ++ struct reset_led_data *led_dat = cdev_to_reset_led_data(led_cdev); ++ ++ if (value == LED_OFF) ++ reset_control_assert(led_dat->rst); ++ else ++ reset_control_deassert(led_dat->rst); ++} ++ ++struct reset_leds_priv { ++ int num_leds; ++ struct reset_led_data leds[]; ++}; ++ ++static inline int sizeof_reset_leds_priv(int num_leds) ++{ ++ return sizeof(struct reset_leds_priv) + ++ (sizeof(struct reset_led_data) * num_leds); ++} ++ ++static struct reset_leds_priv *reset_leds_create(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct fwnode_handle *child; ++ struct reset_leds_priv *priv; ++ int count, ret; ++ ++ count = device_get_child_node_count(dev); ++ if (!count) ++ return ERR_PTR(-ENODEV); ++ ++ priv = devm_kzalloc(dev, sizeof_reset_leds_priv(count), GFP_KERNEL); ++ if (!priv) ++ return ERR_PTR(-ENOMEM); ++ ++ device_for_each_child_node(dev, child) { ++ struct reset_led_data *led = &priv->leds[priv->num_leds]; ++ struct device_node *np = to_of_node(child); ++ ++ ret = fwnode_property_read_string(child, "label", &led->cdev.name); ++ if (!led->cdev.name) { ++ fwnode_handle_put(child); ++ return ERR_PTR(-EINVAL); ++ } ++ led->rst = __of_reset_control_get(np, NULL, 0, 0, 0, true); ++ if (IS_ERR(led->rst)) ++ return ERR_PTR(-EINVAL); ++ ++ fwnode_property_read_string(child, "linux,default-trigger", ++ &led->cdev.default_trigger); ++ ++ led->cdev.brightness_set = reset_led_set; ++ ret = devm_led_classdev_register(&pdev->dev, &led->cdev); ++ if (ret < 0) ++ return ERR_PTR(ret); ++ led->cdev.dev->of_node = np; ++ priv->num_leds++; ++ } ++ ++ return priv; ++} ++ ++static const struct of_device_id of_reset_leds_match[] = { ++ { .compatible = "reset-leds", }, ++ {}, ++}; ++ ++MODULE_DEVICE_TABLE(of, of_reset_leds_match); ++ ++static int reset_led_probe(struct platform_device *pdev) ++{ ++ struct reset_leds_priv *priv; ++ ++ priv = reset_leds_create(pdev); ++ if (IS_ERR(priv)) ++ return PTR_ERR(priv); ++ ++ platform_set_drvdata(pdev, priv); ++ ++ return 0; ++} ++ ++static void reset_led_shutdown(struct platform_device *pdev) ++{ ++ struct reset_leds_priv *priv = platform_get_drvdata(pdev); ++ int i; ++ ++ for (i = 0; i < priv->num_leds; i++) { ++ struct reset_led_data *led = &priv->leds[i]; ++ ++ if (!(led->cdev.flags & LED_RETAIN_AT_SHUTDOWN)) ++ reset_led_set(&led->cdev, LED_OFF); ++ } ++} ++ ++static struct platform_driver reset_led_driver = { ++ .probe = reset_led_probe, ++ .shutdown = reset_led_shutdown, ++ .driver = { ++ .name = "leds-reset", ++ .of_match_table = of_reset_leds_match, ++ }, ++}; ++ ++module_platform_driver(reset_led_driver); ++ ++MODULE_AUTHOR("John Crispin "); ++MODULE_DESCRIPTION("reset controller LED driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:leds-reset"); +--- a/drivers/leds/Makefile ++++ b/drivers/leds/Makefile +@@ -89,6 +89,7 @@ obj-$(CONFIG_LEDS_TURRIS_OMNIA) += leds + obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o + obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o + obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o ++obj-$(CONFIG_LEDS_RESET) += leds-reset.o + + # LED SPI Drivers + obj-$(CONFIG_LEDS_CR0014114) += leds-cr0014114.o diff --git a/lede/target/linux/ath79/patches-6.6/810-ath79-ignore-the-abused-interrupt-map-on-pcie-node.patch b/lede/target/linux/ath79/patches-6.6/810-ath79-ignore-the-abused-interrupt-map-on-pcie-node.patch new file mode 100644 index 0000000000..b53461e37f --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/810-ath79-ignore-the-abused-interrupt-map-on-pcie-node.patch @@ -0,0 +1,33 @@ +From: Shiji Yang +Date: Wed, 31 May 2023 00:15:23 +0000 +Subject: [PATCH] ath79: ignore the abused interrupt-map on pcie node + +ath79 PCIe interrupt controller has stopped working correctly. This +is because the DT exposing a non-sensical interrupt-map property, +and their drivers relying on the kernel ignoring this property[1]. + +This patch fix the pcie init error: +ath9k 0000:00:00.0: of_irq_parse_pci: failed with rc=-14 + +Notice: +This is just a workaround, not a fix. PCIe driver and related dts +node need to be rewritten. + +[1] https://lore.kernel.org/all/20211201114102.13446-1-maz@kernel.org/ + +Signed-off-by: Shiji Yang +--- + drivers/of/irq.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/of/irq.c ++++ b/drivers/of/irq.c +@@ -94,6 +94,8 @@ EXPORT_SYMBOL_GPL(of_irq_find_parent); + * drawing board. + */ + static const char * const of_irq_imap_abusers[] = { ++ "qca,ar7100-pci", ++ "qcom,ar7240-pci", + "CBEA,platform-spider-pic", + "sti,platform-spider-pic", + "realtek,rtl-intc", diff --git a/lede/target/linux/ath79/patches-6.6/820-mfd-syscon-support-skip-reset-control-for-syscon-devices.patch b/lede/target/linux/ath79/patches-6.6/820-mfd-syscon-support-skip-reset-control-for-syscon-devices.patch new file mode 100644 index 0000000000..3bdc2faf3f --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/820-mfd-syscon-support-skip-reset-control-for-syscon-devices.patch @@ -0,0 +1,37 @@ +From: Shiji Yang +Date: Wed, 13 Mar 2024 22:36:31 +0800 +Subject: [PATCH] mfd: syscon: support skip reset control for syscon devices + +Some platform device drivers(e.g. ag71xx) expect exclusive reset +control. Fetching reset controller for syscon[1] will break these +drivers. This patch introduces a new property 'syscon-no-reset' +to skip it. + +[1] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit?id=7d1e3bd94828ad9fc86f55253cd6fec8edd65394 + +Signed-off-by: Shiji Yang +--- + drivers/mfd/syscon.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/mfd/syscon.c ++++ b/drivers/mfd/syscon.c +@@ -53,7 +53,7 @@ static struct syscon *of_syscon_register + int ret; + struct regmap_config syscon_config = syscon_regmap_config; + struct resource res; +- struct reset_control *reset; ++ struct reset_control *reset = NULL; + + WARN_ON(!mutex_is_locked(&syscon_list_lock)); + +@@ -133,7 +133,8 @@ static struct syscon *of_syscon_register + goto err_attach_clk; + } + +- reset = of_reset_control_get_optional_exclusive(np, NULL); ++ if (!of_property_read_bool(np, "syscon-no-reset")) ++ reset = of_reset_control_get_optional_exclusive(np, NULL); + if (IS_ERR(reset)) { + ret = PTR_ERR(reset); + goto err_attach_clk; diff --git a/lede/target/linux/ath79/patches-6.6/900-unaligned_access_hacks.patch b/lede/target/linux/ath79/patches-6.6/900-unaligned_access_hacks.patch new file mode 100644 index 0000000000..ce260b031e --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/900-unaligned_access_hacks.patch @@ -0,0 +1,900 @@ +From: Felix Fietkau +Subject: [PATCH] ar71xx: fix unaligned access in a few more places + +SVN-Revision: 35130 +--- + arch/mips/include/asm/checksum.h | 83 +++--------------- + include/uapi/linux/ip.h | 2 +- + include/uapi/linux/ipv6.h | 2 +- + include/uapi/linux/tcp.h | 4 ++-- + include/uapi/linux/udp.h | 2 +- + net/netfilter/nf_conntrack_core.c | 4 ++-- + include/uapi/linux/icmp.h | 2 +- + include/uapi/linux/in6.h | 2 +- + net/ipv6/tcp_ipv6.c | 9 +++-- + net/ipv6/datagram.c | 6 ++-- + net/ipv6/exthdrs.c | 2 +- + include/linux/types.h | 5 +++ + net/ipv4/af_inet.c | 4 ++-- + net/ipv4/tcp_output.c | 69 +++++++++-------- + include/uapi/linux/igmp.h | 8 +++--- + net/core/flow_dissector.c | 2 +- + include/uapi/linux/icmpv6.h | 2 +- + include/net/ndisc.h | 10 ++++---- + net/sched/cls_u32.c | 6 +++--- + net/ipv6/ip6_offload.c | 2 +- + include/net/addrconf.h | 2 +- + include/net/inet_ecn.h | 4 ++-- + include/net/ipv6.h | 23 +++++---- + include/net/secure_seq.h | 1 + + include/uapi/linux/in.h | 2 +- + net/ipv6/ip6_fib.h | 2 +- + net/netfilter/nf_conntrack_proto_tcp.c | 2 +- + net/xfrm/xfrm_input.c | 4 ++-- + net/ipv4/tcp_input.c | 12 ++++--- + include/uapi/linux/if_pppox.h | 1 + + net/ipv6/netfilter/nf_log_ipv6.c | 4 ++-- + include/net/neighbour.h | 6 +++-- + include/uapi/linux/netfilter_arp/arp_tables.h | 2 +- + net/core/utils.c | 10 +++++-- + include/linux/etherdevice.h | 11 ++++--- + net/ipv4/tcp_offload.c | 6 +++--- + net/ipv6/netfilter/ip6table_mangle.c | 4 ++-- + 37 file changed, 171 insertions(+), 141 deletions(-) + +--- a/arch/mips/include/asm/checksum.h ++++ b/arch/mips/include/asm/checksum.h +@@ -100,26 +100,30 @@ static inline __sum16 ip_fast_csum(const + const unsigned int *stop = word + ihl; + unsigned int csum; + int carry; ++ unsigned int w; + +- csum = word[0]; +- csum += word[1]; +- carry = (csum < word[1]); ++ csum = net_hdr_word(word++); ++ ++ w = net_hdr_word(word++); ++ csum += w; ++ carry = (csum < w); + csum += carry; + +- csum += word[2]; +- carry = (csum < word[2]); ++ w = net_hdr_word(word++); ++ csum += w; ++ carry = (csum < w); + csum += carry; + +- csum += word[3]; +- carry = (csum < word[3]); ++ w = net_hdr_word(word++); ++ csum += w; ++ carry = (csum < w); + csum += carry; + +- word += 4; + do { +- csum += *word; +- carry = (csum < *word); ++ w = net_hdr_word(word++); ++ csum += w; ++ carry = (csum < w); + csum += carry; +- word++; + } while (word != stop); + + return csum_fold(csum); +@@ -179,74 +183,6 @@ static inline __sum16 ip_compute_csum(co + return csum_fold(csum_partial(buff, len, 0)); + } + +-#define _HAVE_ARCH_IPV6_CSUM +-static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, +- const struct in6_addr *daddr, +- __u32 len, __u8 proto, +- __wsum sum) +-{ +- __wsum tmp; +- +- __asm__( +- " .set push # csum_ipv6_magic\n" +- " .set noreorder \n" +- " .set noat \n" +- " addu %0, %5 # proto (long in network byte order)\n" +- " sltu $1, %0, %5 \n" +- " addu %0, $1 \n" +- +- " addu %0, %6 # csum\n" +- " sltu $1, %0, %6 \n" +- " lw %1, 0(%2) # four words source address\n" +- " addu %0, $1 \n" +- " addu %0, %1 \n" +- " sltu $1, %0, %1 \n" +- +- " lw %1, 4(%2) \n" +- " addu %0, $1 \n" +- " addu %0, %1 \n" +- " sltu $1, %0, %1 \n" +- +- " lw %1, 8(%2) \n" +- " addu %0, $1 \n" +- " addu %0, %1 \n" +- " sltu $1, %0, %1 \n" +- +- " lw %1, 12(%2) \n" +- " addu %0, $1 \n" +- " addu %0, %1 \n" +- " sltu $1, %0, %1 \n" +- +- " lw %1, 0(%3) \n" +- " addu %0, $1 \n" +- " addu %0, %1 \n" +- " sltu $1, %0, %1 \n" +- +- " lw %1, 4(%3) \n" +- " addu %0, $1 \n" +- " addu %0, %1 \n" +- " sltu $1, %0, %1 \n" +- +- " lw %1, 8(%3) \n" +- " addu %0, $1 \n" +- " addu %0, %1 \n" +- " sltu $1, %0, %1 \n" +- +- " lw %1, 12(%3) \n" +- " addu %0, $1 \n" +- " addu %0, %1 \n" +- " sltu $1, %0, %1 \n" +- +- " addu %0, $1 # Add final carry\n" +- " .set pop" +- : "=&r" (sum), "=&r" (tmp) +- : "r" (saddr), "r" (daddr), +- "0" (htonl(len)), "r" (htonl(proto)), "r" (sum) +- : "memory"); +- +- return csum_fold(sum); +-} +- + #include + #endif /* CONFIG_GENERIC_CSUM */ + +--- a/include/uapi/linux/ip.h ++++ b/include/uapi/linux/ip.h +@@ -106,7 +106,7 @@ struct iphdr { + __be32 daddr; + ); + /*The options start here. */ +-}; ++} __attribute__((packed, aligned(2))); + + + struct ip_auth_hdr { +--- a/include/uapi/linux/ipv6.h ++++ b/include/uapi/linux/ipv6.h +@@ -135,7 +135,7 @@ struct ipv6hdr { + struct in6_addr saddr; + struct in6_addr daddr; + ); +-}; ++} __attribute__((packed, aligned(2))); + + + /* index values for the variables in ipv6_devconf */ +--- a/include/uapi/linux/tcp.h ++++ b/include/uapi/linux/tcp.h +@@ -55,7 +55,7 @@ struct tcphdr { + __be16 window; + __sum16 check; + __be16 urg_ptr; +-}; ++} __attribute__((packed, aligned(2))); + + /* + * The union cast uses a gcc extension to avoid aliasing problems +@@ -65,7 +65,7 @@ struct tcphdr { + union tcp_word_hdr { + struct tcphdr hdr; + __be32 words[5]; +-}; ++} __attribute__((packed, aligned(2))); + + #define tcp_flag_word(tp) (((union tcp_word_hdr *)(tp))->words[3]) + +--- a/include/uapi/linux/udp.h ++++ b/include/uapi/linux/udp.h +@@ -25,7 +25,7 @@ struct udphdr { + __be16 dest; + __be16 len; + __sum16 check; +-}; ++} __attribute__((packed, aligned(2))); + + /* UDP socket options */ + #define UDP_CORK 1 /* Never send partially complete segments */ +--- a/net/netfilter/nf_conntrack_core.c ++++ b/net/netfilter/nf_conntrack_core.c +@@ -298,8 +298,8 @@ nf_ct_get_tuple(const struct sk_buff *sk + + switch (l3num) { + case NFPROTO_IPV4: +- tuple->src.u3.ip = ap[0]; +- tuple->dst.u3.ip = ap[1]; ++ tuple->src.u3.ip = net_hdr_word(ap++); ++ tuple->dst.u3.ip = net_hdr_word(ap); + break; + case NFPROTO_IPV6: + memcpy(tuple->src.u3.ip6, ap, sizeof(tuple->src.u3.ip6)); +--- a/include/uapi/linux/icmp.h ++++ b/include/uapi/linux/icmp.h +@@ -102,7 +102,7 @@ struct icmphdr { + } frag; + __u8 reserved[4]; + } un; +-}; ++} __attribute__((packed, aligned(2))); + + + /* +--- a/include/uapi/linux/in6.h ++++ b/include/uapi/linux/in6.h +@@ -43,7 +43,7 @@ struct in6_addr { + #define s6_addr16 in6_u.u6_addr16 + #define s6_addr32 in6_u.u6_addr32 + #endif +-}; ++} __attribute__((packed, aligned(2))); + #endif /* __UAPI_DEF_IN6_ADDR */ + + #if __UAPI_DEF_SOCKADDR_IN6 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -891,10 +892,10 @@ static void tcp_v6_send_response(const s + topt = (__be32 *)(t1 + 1); + + if (tsecr) { +- *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | +- (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); +- *topt++ = htonl(tsval); +- *topt++ = htonl(tsecr); ++ put_unaligned_be32((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | ++ (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP, topt++); ++ put_unaligned_be32(tsval, topt++); ++ put_unaligned_be32(tsecr, topt++); + } + + if (mrst) +--- a/include/linux/ipv6.h ++++ b/include/linux/ipv6.h +@@ -6,6 +6,7 @@ + + #define ipv6_optlen(p) (((p)->hdrlen+1) << 3) + #define ipv6_authlen(p) (((p)->hdrlen+2) << 2) ++ + /* + * This structure contains configuration options per IPv6 link. + */ +--- a/net/ipv6/datagram.c ++++ b/net/ipv6/datagram.c +@@ -499,7 +499,7 @@ int ipv6_recv_error(struct sock *sk, str + ipv6_iface_scope_id(&sin->sin6_addr, + IP6CB(skb)->iif); + } else { +- ipv6_addr_set_v4mapped(*(__be32 *)(nh + serr->addr_offset), ++ ipv6_addr_set_v4mapped(net_hdr_word(nh + serr->addr_offset), + &sin->sin6_addr); + sin->sin6_scope_id = 0; + } +@@ -853,12 +853,12 @@ int ip6_datagram_send_ctl(struct net *ne + } + + if (fl6->flowlabel&IPV6_FLOWINFO_MASK) { +- if ((fl6->flowlabel^*(__be32 *)CMSG_DATA(cmsg))&~IPV6_FLOWINFO_MASK) { ++ if ((fl6->flowlabel^net_hdr_word(CMSG_DATA(cmsg)))&~IPV6_FLOWINFO_MASK) { + err = -EINVAL; + goto exit_f; + } + } +- fl6->flowlabel = IPV6_FLOWINFO_MASK & *(__be32 *)CMSG_DATA(cmsg); ++ fl6->flowlabel = IPV6_FLOWINFO_MASK & net_hdr_word(CMSG_DATA(cmsg)); + break; + + case IPV6_2292HOPOPTS: +--- a/net/ipv6/exthdrs.c ++++ b/net/ipv6/exthdrs.c +@@ -982,7 +982,7 @@ static bool ipv6_hop_jumbo(struct sk_buf + goto drop; + } + +- pkt_len = ntohl(*(__be32 *)(nh + optoff + 2)); ++ pkt_len = ntohl(net_hdr_word(nh + optoff + 2)); + if (pkt_len <= IPV6_MAXPLEN) { + icmpv6_param_prob_reason(skb, ICMPV6_HDR_FIELD, optoff + 2, + SKB_DROP_REASON_IP_INHDR); +--- a/include/linux/types.h ++++ b/include/linux/types.h +@@ -244,5 +244,11 @@ typedef void (*swap_func_t)(void *a, voi + typedef int (*cmp_r_func_t)(const void *a, const void *b, const void *priv); + typedef int (*cmp_func_t)(const void *a, const void *b); + ++struct net_hdr_word { ++ u32 words[1]; ++} __attribute__((packed, aligned(2))); ++ ++#define net_hdr_word(_p) (((struct net_hdr_word *) (_p))->words[0]) ++ + #endif /* __ASSEMBLY__ */ + #endif /* _LINUX_TYPES_H */ +--- a/net/ipv4/af_inet.c ++++ b/net/ipv4/af_inet.c +@@ -1506,8 +1506,8 @@ struct sk_buff *inet_gro_receive(struct + goto out; + + NAPI_GRO_CB(skb)->proto = proto; +- id = ntohl(*(__be32 *)&iph->id); +- flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id & ~IP_DF)); ++ id = ntohl(net_hdr_word(&iph->id)); ++ flush = (u16)((ntohl(net_hdr_word(iph)) ^ skb_gro_len(skb)) | (id & ~IP_DF)); + id >>= 16; + + list_for_each_entry(p, head, list) { +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -625,48 +625,53 @@ static void tcp_options_write(struct tcp + u16 options = opts->options; /* mungable copy */ + + if (unlikely(OPTION_MD5 & options)) { +- *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | +- (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG); ++ net_hdr_word(ptr++) = ++ htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | ++ (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG); + /* overload cookie hash location */ + opts->hash_location = (__u8 *)ptr; + ptr += 4; + } + + if (unlikely(opts->mss)) { +- *ptr++ = htonl((TCPOPT_MSS << 24) | +- (TCPOLEN_MSS << 16) | +- opts->mss); ++ net_hdr_word(ptr++) = ++ htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | ++ opts->mss); + } + + if (likely(OPTION_TS & options)) { + if (unlikely(OPTION_SACK_ADVERTISE & options)) { +- *ptr++ = htonl((TCPOPT_SACK_PERM << 24) | +- (TCPOLEN_SACK_PERM << 16) | +- (TCPOPT_TIMESTAMP << 8) | +- TCPOLEN_TIMESTAMP); ++ net_hdr_word(ptr++) = ++ htonl((TCPOPT_SACK_PERM << 24) | ++ (TCPOLEN_SACK_PERM << 16) | ++ (TCPOPT_TIMESTAMP << 8) | ++ TCPOLEN_TIMESTAMP); + options &= ~OPTION_SACK_ADVERTISE; + } else { +- *ptr++ = htonl((TCPOPT_NOP << 24) | +- (TCPOPT_NOP << 16) | +- (TCPOPT_TIMESTAMP << 8) | +- TCPOLEN_TIMESTAMP); ++ net_hdr_word(ptr++) = ++ htonl((TCPOPT_NOP << 24) | ++ (TCPOPT_NOP << 16) | ++ (TCPOPT_TIMESTAMP << 8) | ++ TCPOLEN_TIMESTAMP); + } +- *ptr++ = htonl(opts->tsval); +- *ptr++ = htonl(opts->tsecr); ++ net_hdr_word(ptr++) = htonl(opts->tsval); ++ net_hdr_word(ptr++) = htonl(opts->tsecr); + } + + if (unlikely(OPTION_SACK_ADVERTISE & options)) { +- *ptr++ = htonl((TCPOPT_NOP << 24) | +- (TCPOPT_NOP << 16) | +- (TCPOPT_SACK_PERM << 8) | +- TCPOLEN_SACK_PERM); ++ net_hdr_word(ptr++) = ++ htonl((TCPOPT_NOP << 24) | ++ (TCPOPT_NOP << 16) | ++ (TCPOPT_SACK_PERM << 8) | ++ TCPOLEN_SACK_PERM); + } + + if (unlikely(OPTION_WSCALE & options)) { +- *ptr++ = htonl((TCPOPT_NOP << 24) | +- (TCPOPT_WINDOW << 16) | +- (TCPOLEN_WINDOW << 8) | +- opts->ws); ++ net_hdr_word(ptr++) = ++ htonl((TCPOPT_NOP << 24) | ++ (TCPOPT_WINDOW << 16) | ++ (TCPOLEN_WINDOW << 8) | ++ opts->ws); + } + + if (unlikely(opts->num_sack_blocks)) { +@@ -674,16 +679,17 @@ static void tcp_options_write(struct tcp + tp->duplicate_sack : tp->selective_acks; + int this_sack; + +- *ptr++ = htonl((TCPOPT_NOP << 24) | +- (TCPOPT_NOP << 16) | +- (TCPOPT_SACK << 8) | +- (TCPOLEN_SACK_BASE + (opts->num_sack_blocks * ++ net_hdr_word(ptr++) = ++ htonl((TCPOPT_NOP << 24) | ++ (TCPOPT_NOP << 16) | ++ (TCPOPT_SACK << 8) | ++ (TCPOLEN_SACK_BASE + (opts->num_sack_blocks * + TCPOLEN_SACK_PERBLOCK))); + + for (this_sack = 0; this_sack < opts->num_sack_blocks; + ++this_sack) { +- *ptr++ = htonl(sp[this_sack].start_seq); +- *ptr++ = htonl(sp[this_sack].end_seq); ++ net_hdr_word(ptr++) = htonl(sp[this_sack].start_seq); ++ net_hdr_word(ptr++) = htonl(sp[this_sack].end_seq); + } + + tp->rx_opt.dsack = 0; +@@ -696,13 +702,14 @@ static void tcp_options_write(struct tcp + + if (foc->exp) { + len = TCPOLEN_EXP_FASTOPEN_BASE + foc->len; +- *ptr = htonl((TCPOPT_EXP << 24) | (len << 16) | ++ net_hdr_word(ptr) = ++ htonl((TCPOPT_EXP << 24) | (len << 16) | + TCPOPT_FASTOPEN_MAGIC); + p += TCPOLEN_EXP_FASTOPEN_BASE; + } else { + len = TCPOLEN_FASTOPEN_BASE + foc->len; +- *p++ = TCPOPT_FASTOPEN; +- *p++ = len; ++ net_hdr_word(p++) = TCPOPT_FASTOPEN; ++ net_hdr_word(p++) = len; + } + + memcpy(p, foc->val, foc->len); +--- a/include/uapi/linux/igmp.h ++++ b/include/uapi/linux/igmp.h +@@ -33,7 +33,7 @@ struct igmphdr { + __u8 code; /* For newer IGMP */ + __sum16 csum; + __be32 group; +-}; ++} __attribute__((packed, aligned(2))); + + /* V3 group record types [grec_type] */ + #define IGMPV3_MODE_IS_INCLUDE 1 +@@ -49,7 +49,7 @@ struct igmpv3_grec { + __be16 grec_nsrcs; + __be32 grec_mca; + __be32 grec_src[]; +-}; ++} __attribute__((packed, aligned(2))); + + struct igmpv3_report { + __u8 type; +@@ -58,7 +58,7 @@ struct igmpv3_report { + __be16 resv2; + __be16 ngrec; + struct igmpv3_grec grec[]; +-}; ++} __attribute__((packed, aligned(2))); + + struct igmpv3_query { + __u8 type; +@@ -79,7 +79,7 @@ struct igmpv3_query { + __u8 qqic; + __be16 nsrcs; + __be32 srcs[]; +-}; ++} __attribute__((packed, aligned(2))); + + #define IGMP_HOST_MEMBERSHIP_QUERY 0x11 /* From RFC1112 */ + #define IGMP_HOST_MEMBERSHIP_REPORT 0x12 /* Ditto */ +--- a/net/core/flow_dissector.c ++++ b/net/core/flow_dissector.c +@@ -132,7 +132,7 @@ __be32 __skb_flow_get_ports(const struct + ports = __skb_header_pointer(skb, thoff + poff, + sizeof(_ports), data, hlen, &_ports); + if (ports) +- return *ports; ++ return (__be32)net_hdr_word(ports); + } + + return 0; +--- a/include/uapi/linux/icmpv6.h ++++ b/include/uapi/linux/icmpv6.h +@@ -78,7 +78,7 @@ struct icmp6hdr { + #define icmp6_addrconf_other icmp6_dataun.u_nd_ra.other + #define icmp6_rt_lifetime icmp6_dataun.u_nd_ra.rt_lifetime + #define icmp6_router_pref icmp6_dataun.u_nd_ra.router_pref +-}; ++} __attribute__((packed, aligned(2))); + + + #define ICMPV6_ROUTER_PREF_LOW 0x3 +--- a/include/net/ndisc.h ++++ b/include/net/ndisc.h +@@ -93,7 +93,7 @@ struct ra_msg { + struct icmp6hdr icmph; + __be32 reachable_time; + __be32 retrans_timer; +-}; ++} __attribute__((packed, aligned(2))); + + struct rd_msg { + struct icmp6hdr icmph; +@@ -372,10 +372,10 @@ static inline u32 ndisc_hashfn(const voi + { + const u32 *p32 = pkey; + +- return (((p32[0] ^ hash32_ptr(dev)) * hash_rnd[0]) + +- (p32[1] * hash_rnd[1]) + +- (p32[2] * hash_rnd[2]) + +- (p32[3] * hash_rnd[3])); ++ return (((net_hdr_word(&p32[0]) ^ hash32_ptr(dev)) * hash_rnd[0]) + ++ (net_hdr_word(&p32[1]) * hash_rnd[1]) + ++ (net_hdr_word(&p32[2]) * hash_rnd[2]) + ++ (net_hdr_word(&p32[3]) * hash_rnd[3])); + } + + static inline struct neighbour *__ipv6_neigh_lookup_noref(struct net_device *dev, const void *pkey) +--- a/net/sched/cls_u32.c ++++ b/net/sched/cls_u32.c +@@ -167,7 +167,7 @@ next_knode: + data = skb_header_pointer(skb, toff, 4, &hdata); + if (!data) + goto out; +- if ((*data ^ key->val) & key->mask) { ++ if ((net_hdr_word(data) ^ key->val) & key->mask) { + n = rcu_dereference_bh(n->next); + goto next_knode; + } +@@ -218,8 +218,8 @@ check_terminal: + &hdata); + if (!data) + goto out; +- sel = ht->divisor & u32_hash_fold(*data, &n->sel, +- n->fshift); ++ sel = ht->divisor & u32_hash_fold(net_hdr_word(data), ++ &n->sel, n->fshift); + } + if (!(n->sel.flags & (TC_U32_VAROFFSET | TC_U32_OFFSET | TC_U32_EAT))) + goto next_ht; +--- a/net/ipv6/ip6_offload.c ++++ b/net/ipv6/ip6_offload.c +@@ -273,7 +273,7 @@ INDIRECT_CALLABLE_SCOPE struct sk_buff * + continue; + + iph2 = (struct ipv6hdr *)(p->data + off); +- first_word = *(__be32 *)iph ^ *(__be32 *)iph2; ++ first_word = net_hdr_word(iph) ^ net_hdr_word(iph2); + + /* All fields must match except length and Traffic Class. + * XXX skbs on the gro_list have all been parsed and pulled +--- a/include/net/addrconf.h ++++ b/include/net/addrconf.h +@@ -52,7 +52,7 @@ struct prefix_info { + __be32 reserved2; + + struct in6_addr prefix; +-}; ++} __attribute__((packed, aligned(2))); + + /* rfc4861 4.6.2: IPv6 PIO is 32 bytes in size */ + static_assert(sizeof(struct prefix_info) == 32); +--- a/include/net/inet_ecn.h ++++ b/include/net/inet_ecn.h +@@ -138,9 +138,9 @@ static inline int IP6_ECN_set_ce(struct + if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph))) + return 0; + +- from = *(__be32 *)iph; ++ from = net_hdr_word(iph); + to = from | htonl(INET_ECN_CE << 20); +- *(__be32 *)iph = to; ++ net_hdr_word(iph) = to; + if (skb->ip_summed == CHECKSUM_COMPLETE) + skb->csum = csum_add(csum_sub(skb->csum, (__force __wsum)from), + (__force __wsum)to); +--- a/include/net/ipv6.h ++++ b/include/net/ipv6.h +@@ -149,7 +149,7 @@ struct frag_hdr { + __u8 reserved; + __be16 frag_off; + __be32 identification; +-}; ++} __attribute__((packed, aligned(2))); + + /* + * Jumbo payload option, as described in RFC 2675 2. +@@ -649,8 +649,8 @@ static inline void __ipv6_addr_set_half( + } + #endif + #endif +- addr[0] = wh; +- addr[1] = wl; ++ net_hdr_word(&addr[0]) = wh; ++ net_hdr_word(&addr[1]) = wl; + } + + static inline void ipv6_addr_set(struct in6_addr *addr, +@@ -709,6 +709,8 @@ static inline bool ipv6_prefix_equal(con + const __be32 *a1 = addr1->s6_addr32; + const __be32 *a2 = addr2->s6_addr32; + unsigned int pdw, pbi; ++ /* Used for last <32-bit fraction of prefix */ ++ u32 pbia1, pbia2; + + /* check complete u32 in prefix */ + pdw = prefixlen >> 5; +@@ -717,7 +719,9 @@ static inline bool ipv6_prefix_equal(con + + /* check incomplete u32 in prefix */ + pbi = prefixlen & 0x1f; +- if (pbi && ((a1[pdw] ^ a2[pdw]) & htonl((0xffffffff) << (32 - pbi)))) ++ pbia1 = net_hdr_word(&a1[pdw]); ++ pbia2 = net_hdr_word(&a2[pdw]); ++ if (pbi && ((pbia1 ^ pbia2) & htonl((0xffffffff) << (32 - pbi)))) + return false; + + return true; +@@ -839,13 +843,13 @@ static inline void ipv6_addr_set_v4mappe + */ + static inline int __ipv6_addr_diff32(const void *token1, const void *token2, int addrlen) + { +- const __be32 *a1 = token1, *a2 = token2; ++ const struct in6_addr *a1 = token1, *a2 = token2; + int i; + + addrlen >>= 2; + + for (i = 0; i < addrlen; i++) { +- __be32 xb = a1[i] ^ a2[i]; ++ __be32 xb = a1->s6_addr32[i] ^ a2->s6_addr32[i]; + if (xb) + return i * 32 + 31 - __fls(ntohl(xb)); + } +@@ -1040,17 +1044,18 @@ static inline u32 ip6_multipath_hash_fie + static inline void ip6_flow_hdr(struct ipv6hdr *hdr, unsigned int tclass, + __be32 flowlabel) + { +- *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | flowlabel; ++ net_hdr_word((__be32 *)hdr) = ++ htonl(0x60000000 | (tclass << 20)) | flowlabel; + } + + static inline __be32 ip6_flowinfo(const struct ipv6hdr *hdr) + { +- return *(__be32 *)hdr & IPV6_FLOWINFO_MASK; ++ return net_hdr_word((__be32 *)hdr) & IPV6_FLOWINFO_MASK; + } + + static inline __be32 ip6_flowlabel(const struct ipv6hdr *hdr) + { +- return *(__be32 *)hdr & IPV6_FLOWLABEL_MASK; ++ return net_hdr_word((__be32 *)hdr) & IPV6_FLOWLABEL_MASK; + } + + static inline u8 ip6_tclass(__be32 flowinfo) +--- a/include/net/secure_seq.h ++++ b/include/net/secure_seq.h +@@ -3,6 +3,7 @@ + #define _NET_SECURE_SEQ + + #include ++#include + + struct net; + +--- a/include/uapi/linux/in.h ++++ b/include/uapi/linux/in.h +@@ -91,7 +91,7 @@ enum { + /* Internet address. */ + struct in_addr { + __be32 s_addr; +-}; ++} __attribute__((packed, aligned(2))); + #endif + + #define IP_TOS 1 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -141,7 +141,7 @@ static __be32 addr_bit_set(const void *t + * See include/asm-generic/bitops/le.h. + */ + return (__force __be32)(1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f)) & +- addr[fn_bit >> 5]; ++ net_hdr_word(&addr[fn_bit >> 5]); + } + + struct fib6_info *fib6_info_alloc(gfp_t gfp_flags, bool with_fib6_nh) +--- a/net/netfilter/nf_conntrack_proto_tcp.c ++++ b/net/netfilter/nf_conntrack_proto_tcp.c +@@ -406,7 +406,7 @@ static void tcp_sack(const struct sk_buf + + /* Fast path for timestamp-only option */ + if (length == TCPOLEN_TSTAMP_ALIGNED +- && *(__be32 *)ptr == htonl((TCPOPT_NOP << 24) ++ && net_hdr_word(ptr) == htonl((TCPOPT_NOP << 24) + | (TCPOPT_NOP << 16) + | (TCPOPT_TIMESTAMP << 8) + | TCPOLEN_TIMESTAMP)) +--- a/net/xfrm/xfrm_input.c ++++ b/net/xfrm/xfrm_input.c +@@ -168,8 +168,8 @@ int xfrm_parse_spi(struct sk_buff *skb, + if (!pskb_may_pull(skb, hlen)) + return -EINVAL; + +- *spi = *(__be32 *)(skb_transport_header(skb) + offset); +- *seq = *(__be32 *)(skb_transport_header(skb) + offset_seq); ++ *spi = net_hdr_word(skb_transport_header(skb) + offset); ++ *seq = net_hdr_word(skb_transport_header(skb) + offset_seq); + return 0; + } + EXPORT_SYMBOL(xfrm_parse_spi); +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -4268,14 +4268,16 @@ static bool tcp_parse_aligned_timestamp( + { + const __be32 *ptr = (const __be32 *)(th + 1); + +- if (*ptr == htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) +- | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) { ++ if (net_hdr_word(ptr) == ++ htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | ++ (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) { + tp->rx_opt.saw_tstamp = 1; + ++ptr; +- tp->rx_opt.rcv_tsval = ntohl(*ptr); ++ tp->rx_opt.rcv_tsval = get_unaligned_be32(ptr); + ++ptr; +- if (*ptr) +- tp->rx_opt.rcv_tsecr = ntohl(*ptr) - tp->tsoffset; ++ if (net_hdr_word(ptr)) ++ tp->rx_opt.rcv_tsecr = get_unaligned_be32(ptr) - ++ tp->tsoffset; + else + tp->rx_opt.rcv_tsecr = 0; + return true; +--- a/include/uapi/linux/if_pppox.h ++++ b/include/uapi/linux/if_pppox.h +@@ -51,6 +51,7 @@ struct pppoe_addr { + */ + struct pptp_addr { + __u16 call_id; ++ __u16 pad; + struct in_addr sin_addr; + }; + +--- a/include/net/neighbour.h ++++ b/include/net/neighbour.h +@@ -286,8 +286,10 @@ static inline bool neigh_key_eq128(const + const u32 *n32 = (const u32 *)n->primary_key; + const u32 *p32 = pkey; + +- return ((n32[0] ^ p32[0]) | (n32[1] ^ p32[1]) | +- (n32[2] ^ p32[2]) | (n32[3] ^ p32[3])) == 0; ++ return ((n32[0] ^ net_hdr_word(&p32[0])) | ++ (n32[1] ^ net_hdr_word(&p32[1])) | ++ (n32[2] ^ net_hdr_word(&p32[2])) | ++ (n32[3] ^ net_hdr_word(&p32[3]))) == 0; + } + + static inline struct neighbour *___neigh_lookup_noref( +--- a/include/uapi/linux/netfilter_arp/arp_tables.h ++++ b/include/uapi/linux/netfilter_arp/arp_tables.h +@@ -70,7 +70,7 @@ struct arpt_arp { + __u8 flags; + /* Inverse flags */ + __u16 invflags; +-}; ++} __attribute__((aligned(4))); + + /* Values for "flag" field in struct arpt_ip (general arp structure). + * No flags defined yet. +--- a/net/core/utils.c ++++ b/net/core/utils.c +@@ -460,8 +460,14 @@ void inet_proto_csum_replace16(__sum16 * + bool pseudohdr) + { + __be32 diff[] = { +- ~from[0], ~from[1], ~from[2], ~from[3], +- to[0], to[1], to[2], to[3], ++ ~net_hdr_word(&from[0]), ++ ~net_hdr_word(&from[1]), ++ ~net_hdr_word(&from[2]), ++ ~net_hdr_word(&from[3]), ++ net_hdr_word(&to[0]), ++ net_hdr_word(&to[1]), ++ net_hdr_word(&to[2]), ++ net_hdr_word(&to[3]), + }; + if (skb->ip_summed != CHECKSUM_PARTIAL) { + *sum = csum_fold(csum_partial(diff, sizeof(diff), +--- a/include/linux/etherdevice.h ++++ b/include/linux/etherdevice.h +@@ -555,7 +555,7 @@ static inline bool is_etherdev_addr(cons + * @b: Pointer to Ethernet header + * + * Compare two Ethernet headers, returns 0 if equal. +- * This assumes that the network header (i.e., IP header) is 4-byte ++ * This assumes that the network header (i.e., IP header) is 2-byte + * aligned OR the platform can handle unaligned access. This is the + * case for all packets coming into netif_receive_skb or similar + * entry points. +@@ -578,11 +578,12 @@ static inline unsigned long compare_ethe + fold |= *(unsigned long *)(a + 6) ^ *(unsigned long *)(b + 6); + return fold; + #else +- u32 *a32 = (u32 *)((u8 *)a + 2); +- u32 *b32 = (u32 *)((u8 *)b + 2); ++ const u16 *a16 = a; ++ const u16 *b16 = b; + +- return (*(u16 *)a ^ *(u16 *)b) | (a32[0] ^ b32[0]) | +- (a32[1] ^ b32[1]) | (a32[2] ^ b32[2]); ++ return (a16[0] ^ b16[0]) | (a16[1] ^ b16[1]) | (a16[2] ^ b16[2]) | ++ (a16[3] ^ b16[3]) | (a16[4] ^ b16[4]) | (a16[5] ^ b16[5]) | ++ (a16[6] ^ b16[6]); + #endif + } + +--- a/net/ipv4/tcp_offload.c ++++ b/net/ipv4/tcp_offload.c +@@ -223,7 +223,7 @@ struct sk_buff *tcp_gro_receive(struct l + + th2 = tcp_hdr(p); + +- if (*(u32 *)&th->source ^ *(u32 *)&th2->source) { ++ if (net_hdr_word(&th->source) ^ net_hdr_word(&th2->source)) { + NAPI_GRO_CB(p)->same_flow = 0; + continue; + } +@@ -241,8 +241,8 @@ found: + ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH)); + flush |= (__force int)(th->ack_seq ^ th2->ack_seq); + for (i = sizeof(*th); i < thlen; i += 4) +- flush |= *(u32 *)((u8 *)th + i) ^ +- *(u32 *)((u8 *)th2 + i); ++ flush |= net_hdr_word((u8 *)th + i) ^ ++ net_hdr_word((u8 *)th2 + i); + + /* When we receive our second frame we can made a decision on if we + * continue this flow as an atomic flow with a fixed ID or if we use +--- a/net/ipv6/netfilter/ip6table_mangle.c ++++ b/net/ipv6/netfilter/ip6table_mangle.c +@@ -44,7 +44,7 @@ ip6t_mangle_out(void *priv, struct sk_bu + hop_limit = ipv6_hdr(skb)->hop_limit; + + /* flowlabel and prio (includes version, which shouldn't change either */ +- flowlabel = *((u_int32_t *)ipv6_hdr(skb)); ++ flowlabel = net_hdr_word(ipv6_hdr(skb)); + + ret = ip6t_do_table(priv, skb, state); + +@@ -53,7 +53,7 @@ ip6t_mangle_out(void *priv, struct sk_bu + !ipv6_addr_equal(&ipv6_hdr(skb)->daddr, &daddr) || + skb->mark != mark || + ipv6_hdr(skb)->hop_limit != hop_limit || +- flowlabel != *((u_int32_t *)ipv6_hdr(skb)))) { ++ flowlabel != net_hdr_word(ipv6_hdr(skb)))) { + err = ip6_route_me_harder(state->net, state->sk, skb); + if (err < 0) + ret = NF_DROP_ERR(err); diff --git a/lede/target/linux/ath79/patches-6.6/910-mikrotik-rb4xx.patch b/lede/target/linux/ath79/patches-6.6/910-mikrotik-rb4xx.patch new file mode 100644 index 0000000000..674cc2fe66 --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/910-mikrotik-rb4xx.patch @@ -0,0 +1,121 @@ +From: Christopher Hill +Subject: [PATCH] ath79: add Mikrotik rb4xx series drivers + +This adds 3 Mikrotik rb4xx series drivers as follows: + +rb4xx-cpld: This is in the mfd subsystem, and is the parent CPLD device +that interfaces between the SoC SPI bus and its two children below. +rb4xx-gpio: This is the GPIO expander. +rb4xx-nand: This is the NAND driver. + +The history of this code comes in three phases. + +1. The first is a May 2015 attempt to push the equivalient ar71xx rb4xx +drivers upstream. See https://lore.kernel.org/patchwork/patch/940880/. + +Module-author: Gabor Juhos +Module-author: Imre Kaloz +Module-author: Bert Vermeulen + +2. Next several ar71xx patches were applied bringing the code current. + +commit 7bbf4117c6fe4b764d9d7c62fb2bcf6dd93bff2c +Submitted-by: Hauke Mehrtens + +commit af79fdbe4af32a287798b579141204bda056b8aa +commit 889272d92db689fd9c910243635e44c9d8323095 +commit e21cb649a235180563363b8af5ba8296b9ac0baa +commit 7c09fa4a7492ca436f2c94bd9a465b7c5bbeed6f +Submitted-by: Felix Fietkau + +3. Finally a heavy refactor to split the driver into the three new +subsystems, and updated to work with the device tree configuration, plus +updates and review feedback incorporated + +Reviewed-by: Thibaut VARÈNE +Submitted-by: Christopher Hill +--- + drivers/mfd/Kconfig | 8 ++++++++ + drivers/mfd/Makefile | 1 + + drivers/gpio/Kconfig | 6 ++++++ + drivers/gpio/Makefile | 1 + + drivers/mtd/nand/raw/Kconfig | 7 +++++++ + drivers/mtd/nand/raw/Makefile | 1 + + 6 files changed, 24 insertions(+) + +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -2261,6 +2261,14 @@ config RAVE_SP_CORE + Select this to get support for the Supervisory Processor + device found on several devices in RAVE line of hardware. + ++config MFD_RB4XX_CPLD ++ tristate "CPLD driver for Mikrotik RB4xx series boards" ++ select MFD_CORE ++ depends on ATH79 || COMPILE_TEST ++ help ++ Enables support for the CPLD chip (NAND & GPIO) on Mikrotik ++ Routerboard RB4xx series. ++ + config SGI_MFD_IOC3 + bool "SGI IOC3 core driver" + depends on PCI && MIPS && 64BIT +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -269,6 +269,7 @@ obj-$(CONFIG_MFD_KHADAS_MCU) += khadas- + obj-$(CONFIG_MFD_ACER_A500_EC) += acer-ec-a500.o + obj-$(CONFIG_MFD_QCOM_PM8008) += qcom-pm8008.o + ++obj-$(CONFIG_MFD_RB4XX_CPLD) += rb4xx-cpld.o + obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o + obj-$(CONFIG_MFD_SIMPLE_MFD_I2C) += simple-mfd-i2c.o + obj-$(CONFIG_MFD_SMPRO) += smpro-core.o +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -1696,6 +1696,12 @@ config GPIO_SODAVILLE + help + Say Y here to support Intel Sodaville GPIO. + ++config GPIO_RB4XX ++ tristate "GPIO expander for Mikrotik RB4xx series boards" ++ depends on MFD_RB4XX_CPLD ++ help ++ GPIO driver for Mikrotik Routerboard RB4xx series. ++ + endmenu + + menu "SPI GPIO expanders" +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -131,6 +131,7 @@ obj-$(CONFIG_GPIO_PL061) += gpio-pl061. + obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio-pmic-eic-sprd.o + obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o + obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o ++obj-$(CONFIG_GPIO_RB4XX) += gpio-rb4xx.o + obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o + obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o + obj-$(CONFIG_GPIO_RDA) += gpio-rda.o +--- a/drivers/mtd/nand/raw/Kconfig ++++ b/drivers/mtd/nand/raw/Kconfig +@@ -550,4 +550,11 @@ config MTD_NAND_AR934X + Enables support for NAND controller on Qualcomm Atheros SoCs. + This controller is found on AR934x and QCA955x SoCs. + ++config MTD_NAND_RB4XX ++ tristate "Support for NAND driver for Mikrotik RB4xx series boards" ++ depends on MFD_RB4XX_CPLD ++ help ++ Enables support for the NAND flash chip on Mikrotik Routerboard ++ RB4xx series. ++ + endif # MTD_RAW_NAND +--- a/drivers/mtd/nand/raw/Makefile ++++ b/drivers/mtd/nand/raw/Makefile +@@ -58,6 +58,7 @@ obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rock + obj-$(CONFIG_MTD_NAND_PL35X) += pl35x-nand-controller.o + obj-$(CONFIG_MTD_NAND_RENESAS) += renesas-nand-controller.o + obj-$(CONFIG_MTD_NAND_AR934X) += ar934x_nand.o ++obj-$(CONFIG_MTD_NAND_RB4XX) += nand_rb4xx.o + + nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o + nand-objs += nand_onfi.o diff --git a/lede/target/linux/ath79/patches-6.6/911-mikrotik-rb91x.patch b/lede/target/linux/ath79/patches-6.6/911-mikrotik-rb91x.patch new file mode 100644 index 0000000000..ddb7b52cbe --- /dev/null +++ b/lede/target/linux/ath79/patches-6.6/911-mikrotik-rb91x.patch @@ -0,0 +1,96 @@ +From: Denis Kalashnikov +Subject: [PATCH] ath79: add support for reset key on MikroTik RB912UAG-2HPnD + +On MikroTik RB91x board series a reset key shares SoC gpio +line #15 with NAND ALE and NAND IO7. So we need a custom +gpio driver to manage this non-trivial connection schema. +Also rb91x-nand needs to have an ability to disable a polling +of the key while it works with NAND. + +While we've been integrating rb91x-key into a firmware, we've +figured out that: +* In the gpio-latch driver we need to add a "cansleep" suffix to +several gpiolib calls, +* When gpio-latch and rb91x-nand fail to get a gpio and an error +is -EPROBE_DEFER, they shouldn't report about this, since this +actually is not an error and occurs when the gpio-latch probe +function is called before the rb91x-key probe. +We fix these related things here too. + +Submitted-by: Denis Kalashnikov +Reviewed-by: Sergey Ryazanov +Tested-by: Koen Vandeputte +--- + drivers/gpio/Kconfig | 11 +++++++++++ + drivers/gpio/Makefile | 2 ++ + drivers/mtd/nand/raw/Kconfig | 6 ++++++ + drivers/mtd/nand/raw/Makefile | 1 + + 7 files changed, 20 insertions(+) + +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -371,6 +371,12 @@ config GPIO_IXP4XX + + If unsure, say N. + ++config GPIO_LATCH_MIKROTIK ++ tristate "MikroTik RouterBOARD GPIO latch support" ++ depends on ATH79 ++ help ++ GPIO driver for latch on some MikroTik RouterBOARDs. ++ + config GPIO_LOGICVC + tristate "Xylon LogiCVC GPIO support" + depends on MFD_SYSCON && OF +@@ -553,6 +559,10 @@ config GPIO_ROCKCHIP + help + Say yes here to support GPIO on Rockchip SoCs. + ++config GPIO_RB91X_KEY ++ tristate "MikroTik RB91x board series reset key support" ++ depends on ATH79 ++ + config GPIO_SAMA5D2_PIOBU + tristate "SAMA5D2 PIOBU GPIO support" + depends on MFD_SYSCON +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -81,6 +81,7 @@ obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4x + obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o + obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o + obj-$(CONFIG_GPIO_LATCH) += gpio-latch.o ++obj-$(CONFIG_GPIO_LATCH_MIKROTIK) += gpio-latch-mikrotik.o + obj-$(CONFIG_GPIO_LJCA) += gpio-ljca.o + obj-$(CONFIG_GPIO_LOGICVC) += gpio-logicvc.o + obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o +@@ -132,6 +133,7 @@ obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio + obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o + obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o + obj-$(CONFIG_GPIO_RB4XX) += gpio-rb4xx.o ++obj-$(CONFIG_GPIO_RB91X_KEY) += gpio-rb91x-key.o + obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o + obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o + obj-$(CONFIG_GPIO_RDA) += gpio-rda.o +--- a/drivers/mtd/nand/raw/Kconfig ++++ b/drivers/mtd/nand/raw/Kconfig +@@ -557,4 +557,10 @@ config MTD_NAND_RB4XX + Enables support for the NAND flash chip on Mikrotik Routerboard + RB4xx series. + ++config MTD_NAND_RB91X ++ tristate "MikroTik RB91x NAND driver support" ++ depends on ATH79 && MTD_RAW_NAND ++ help ++ Enables support for the NAND flash chip on MikroTik RB91x series. ++ + endif # MTD_RAW_NAND +--- a/drivers/mtd/nand/raw/Makefile ++++ b/drivers/mtd/nand/raw/Makefile +@@ -59,6 +59,7 @@ obj-$(CONFIG_MTD_NAND_PL35X) += pl35x-n + obj-$(CONFIG_MTD_NAND_RENESAS) += renesas-nand-controller.o + obj-$(CONFIG_MTD_NAND_AR934X) += ar934x_nand.o + obj-$(CONFIG_MTD_NAND_RB4XX) += nand_rb4xx.o ++obj-$(CONFIG_MTD_NAND_RB91X) += rb91x_nand.o + + nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o + nand-objs += nand_onfi.o diff --git a/lede/target/linux/bcm53xx/Makefile b/lede/target/linux/bcm53xx/Makefile index 215b6b675b..3dd17bc9c5 100644 --- a/lede/target/linux/bcm53xx/Makefile +++ b/lede/target/linux/bcm53xx/Makefile @@ -11,8 +11,8 @@ FEATURES:=squashfs nand usb pci pcie gpio pwm CPU_TYPE:=cortex-a9 SUBTARGETS:=generic -KERNEL_PATCHVER:=5.4 -KERNEL_TESTING_PATCHVER:=5.15 +KERNEL_PATCHVER:=6.6 +KERNEL_TESTING_PATCHVER:=5.4 define Target/Description Build firmware images for Broadcom based BCM47xx/53xx routers with ARM CPU, *not* MIPS. diff --git a/lede/target/linux/bcm53xx/config-6.6 b/lede/target/linux/bcm53xx/config-6.6 new file mode 100644 index 0000000000..a3030c116f --- /dev/null +++ b/lede/target/linux/bcm53xx/config-6.6 @@ -0,0 +1,357 @@ +CONFIG_ALIGNMENT_TRAP=y +CONFIG_ARCH_32BIT_OFF_T=y +CONFIG_ARCH_BCM=y +CONFIG_ARCH_BCM_5301X=y +CONFIG_ARCH_BCM_53573=y +CONFIG_ARCH_BCM_IPROC=y +CONFIG_ARCH_BCM_NSP=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_ARCH_MULTIPLATFORM=y +CONFIG_ARCH_MULTI_V6_V7=y +CONFIG_ARCH_MULTI_V7=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_APPENDED_DTB=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ARM_ATAG_DTB_COMPAT is not set +CONFIG_ARM_ERRATA_754322=y +CONFIG_ARM_ERRATA_764369=y +CONFIG_ARM_ERRATA_775420=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GLOBAL_TIMER=y +CONFIG_ARM_GT_INITIAL_PRESCALER_VAL=1 +CONFIG_ARM_HAS_GROUP_RELOCS=y +CONFIG_ARM_HEAVY_MB=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_PATCH_IDIV=y +CONFIG_ARM_PATCH_PHYS_VIRT=y +CONFIG_ARM_SP805_WATCHDOG=y +CONFIG_ARM_THUMB=y +CONFIG_ARM_TIMER_SP804=y +CONFIG_ARM_UNWIND=y +CONFIG_ARM_VIRT_EXT=y +CONFIG_ATAGS=y +CONFIG_AUTO_ZRELADDR=y +CONFIG_B53=y +CONFIG_B53_MDIO_DRIVER=y +CONFIG_B53_SERDES=y +CONFIG_B53_SRAB_DRIVER=y +CONFIG_BCM47XX_NVRAM=y +CONFIG_BCM47XX_SPROM=y +CONFIG_BCM47XX_WDT=y +CONFIG_BCMA=y +CONFIG_BCMA_BLOCKIO=y +CONFIG_BCMA_DEBUG=y +CONFIG_BCMA_DRIVER_GMAC_CMN=y +CONFIG_BCMA_DRIVER_GPIO=y +CONFIG_BCMA_DRIVER_PCI=y +CONFIG_BCMA_FALLBACK_SPROM=y +CONFIG_BCMA_HOST_PCI=y +CONFIG_BCMA_HOST_PCI_POSSIBLE=y +CONFIG_BCMA_HOST_SOC=y +CONFIG_BCMA_SFLASH=y +# CONFIG_BCM_CYGNUS_PHY is not set +CONFIG_BCM_NET_PHYLIB=y +CONFIG_BCM_NS_THERMAL=y +CONFIG_BCM_SR_THERMAL=y +CONFIG_BGMAC=y +CONFIG_BGMAC_BCMA=y +CONFIG_BGMAC_PLATFORM=y +CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BOUNCE=y +CONFIG_BROADCOM_PHY=y +CONFIG_CACHE_L2X0=y +CONFIG_CC_HAVE_STACKPROTECTOR_TLS=y +CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK=y +CONFIG_CLKSRC_MMIO=y +# CONFIG_CLK_BCM_NS2 is not set +CONFIG_CLK_BCM_NSP=y +# CONFIG_CLK_BCM_SR is not set +CONFIG_CLONE_BACKWARDS=y +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_IPROC=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_SPECTRE=y +CONFIG_CPU_THUMB_CAPABLE=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_V7=y +CONFIG_CRC16=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_CURRENT_POINTER_IN_TPIDRURO=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_BCM_5301X=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_LL=y +CONFIG_DEBUG_LL_INCLUDE="debug/8250.S" +CONFIG_DEBUG_MISC=y +CONFIG_DEBUG_UART_8250=y +CONFIG_DEBUG_UART_8250_SHIFT=0 +CONFIG_DEBUG_UART_PHYS=0x18000300 +CONFIG_DEBUG_UART_VIRT=0xf1000300 +CONFIG_DEBUG_USER=y +CONFIG_DMA_OPS=y +CONFIG_DTC=y +CONFIG_EARLY_PRINTK=y +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EEPROM_AT24=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_EXTCON=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FS_IOMAP=y +CONFIG_FUNCTION_ALIGNMENT=0 +CONFIG_FWNODE_MDIO=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=y +# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set +CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_MULTI_HANDLER=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=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_GENERIC_VDSO_32=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_74X164=y +CONFIG_GPIO_BCM_XGS_IPROC=y +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_GENERIC=y +CONFIG_GRO_CELLS=y +CONFIG_HARDEN_BRANCH_PREDICTOR=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAVE_SMP=y +CONFIG_HIGHMEM=y +CONFIG_HIGHPTE=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_BCM2835=y +CONFIG_HZ_FIXED=0 +CONFIG_HZ_PERIODIC=y +CONFIG_I2C=y +CONFIG_I2C_BCM_IPROC=y +# CONFIG_I2C_SLAVE_TESTUNIT is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQCHIP=y +CONFIG_IRQSTACKS=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_WORK=y +CONFIG_KMAP_LOCAL=y +CONFIG_KMAP_LOCAL_NON_LINEAR_PTE_ARRAY=y +# CONFIG_LEDS_BCM63138 is not set +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MDIO_BCM_IPROC=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_BUS_MUX=y +# CONFIG_MDIO_BUS_MUX_BCM_IPROC is not set +CONFIG_MDIO_BUS_MUX_MMIOREG=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y +CONFIG_MFD_SYSCON=y +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_MIGRATION=y +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MTD_BCM47XXSFLASH=y +CONFIG_MTD_BCM47XX_PARTS=y +CONFIG_MTD_NAND_BRCMNAND=y +CONFIG_MTD_NAND_BRCMNAND_IPROC=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_ECC_SW_HAMMING=y +CONFIG_MTD_OF_PARTS_LINKSYS_NS=y +CONFIG_MTD_PARSER_TPLINK_SAFELOADER=y +CONFIG_MTD_PARSER_TRX=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPLIT_SEAMA_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_SRCU_NMI_SAFE=y +CONFIG_NET_DEVLINK=y +CONFIG_NET_DSA=y +CONFIG_NET_DSA_QCA8K=y +CONFIG_NET_DSA_QCA8K_LEDS_SUPPORT=y +CONFIG_NET_DSA_TAG_BRCM=y +CONFIG_NET_DSA_TAG_BRCM_COMMON=y +CONFIG_NET_DSA_TAG_BRCM_LEGACY=y +CONFIG_NET_DSA_TAG_BRCM_PREPEND=y +CONFIG_NET_DSA_TAG_NONE=y +CONFIG_NET_DSA_TAG_QCA=y +CONFIG_NET_EGRESS=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_INGRESS=y +CONFIG_NET_SELFTESTS=y +CONFIG_NET_XGRESS=y +CONFIG_NR_CPUS=2 +CONFIG_NVMEM=y +CONFIG_NVMEM_BRCM_NVRAM=y +CONFIG_NVMEM_LAYOUTS=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_OLD_SIGACTION=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_PADATA=y +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PAGE_POOL=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PCI=y +CONFIG_PCIE_IPROC=y +CONFIG_PCIE_IPROC_BCMA=y +# CONFIG_PCIE_IPROC_PLATFORM is not set +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHYLIB=y +CONFIG_PHYLIB_LEDS=y +CONFIG_PHYLINK=y +# CONFIG_PHY_BCM_NS_USB2 is not set +# CONFIG_PHY_BCM_NS_USB3 is not set +# CONFIG_PHY_BCM_SR_PCIE is not set +CONFIG_PHY_BCM_SR_USB=y +# CONFIG_PHY_BRCM_SATA is not set +# CONFIG_PHY_NS2_USB_DRD is not set +CONFIG_PINCTRL=y +CONFIG_PINCTRL_IPROC_GPIO=y +CONFIG_PINCTRL_NS=y +# CONFIG_PINCTRL_NS2_MUX is not set +CONFIG_PINCTRL_NSP_GPIO=y +CONFIG_PINCTRL_NSP_MUX=y +CONFIG_PREEMPT_NONE_BUILD=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_PWM=y +CONFIG_PWM_BCM_IPROC=y +CONFIG_PWM_SYSFS=y +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RATIONAL=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_MMIO=y +CONFIG_RFS_ACCEL=y +CONFIG_RPS=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SGL_ALLOC=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SOFTIRQ_ON_OWN_STACK=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_BCM_QSPI=y +CONFIG_SPI_BITBANG=y +CONFIG_SPI_GPIO=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y +CONFIG_SWPHY=y +CONFIG_SWP_EMULATE=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=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_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +CONFIG_UNWINDER_ARM=y +CONFIG_USB_SUPPORT=y +CONFIG_USE_OF=y +# CONFIG_VFP is not set +CONFIG_WATCHDOG_CORE=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_BCJ=y +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZSTD_COMMON=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y diff --git a/lede/target/linux/bcm53xx/image/Makefile b/lede/target/linux/bcm53xx/image/Makefile index cb5b122e80..628a10dea6 100644 --- a/lede/target/linux/bcm53xx/image/Makefile +++ b/lede/target/linux/bcm53xx/image/Makefile @@ -105,6 +105,10 @@ define Build/seama-nand -i $@.entity endef +ifdef CONFIG_LINUX_6_6 +DTS_DIR := $(DTS_DIR)/broadcom +endif + DEVICE_VARS += ASUS_PRODUCTID DEVICE_VARS += BUFFALO_TAG_PLATFORM BUFFALO_TAG_VERSION BUFFALO_TAG_MINOR DEVICE_VARS += SIGNATURE diff --git a/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0001-ARM-dts-BCM5301X-Set-MACs-for-D-Link-DIR-885L.patch b/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0001-ARM-dts-BCM5301X-Set-MACs-for-D-Link-DIR-885L.patch new file mode 100644 index 0000000000..707e4a31e9 --- /dev/null +++ b/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0001-ARM-dts-BCM5301X-Set-MACs-for-D-Link-DIR-885L.patch @@ -0,0 +1,56 @@ +From 5cbee5828219c4f7b33e96b5d8ce5e467b2857c8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 1 Sep 2023 12:55:49 +0200 +Subject: [PATCH] ARM: dts: BCM5301X: Set MACs for D-Link DIR-885L +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Specify NVRAM access and use its "et2macaddr" NVMEM cell. + +Signed-off-by: Rafał Miłecki +Link: https://lore.kernel.org/r/20230901105549.7076-1-zajec5@gmail.com +Signed-off-by: Florian Fainelli +--- + .../dts/broadcom/bcm47094-dlink-dir-885l.dts | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-885l.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-885l.dts +@@ -25,6 +25,15 @@ + <0x88000000 0x08000000>; + }; + ++ nvram@1e3f0000 { ++ compatible = "brcm,nvram"; ++ reg = <0x1e3f0000 0x10000>; ++ ++ et2macaddr: et2macaddr { ++ #nvmem-cell-cells = <1>; ++ }; ++ }; ++ + nand_controller: nand-controller@18028000 { + nand@0 { + partitions { +@@ -112,6 +121,11 @@ + vcc-gpio = <&chipcommon 18 GPIO_ACTIVE_HIGH>; + }; + ++&gmac0 { ++ nvmem-cells = <&et2macaddr 0>; ++ nvmem-cell-names = "mac-address"; ++}; ++ + &spi_nor { + status = "okay"; + }; +@@ -142,6 +156,8 @@ + + port@4 { + label = "wan"; ++ nvmem-cells = <&et2macaddr 3>; ++ nvmem-cell-names = "mac-address"; + }; + + port@5 { diff --git a/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0002-ARM-dts-BCM5301X-Set-MAC-address-for-Asus-RT-AC87U.patch b/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0002-ARM-dts-BCM5301X-Set-MAC-address-for-Asus-RT-AC87U.patch new file mode 100644 index 0000000000..8a8066ba63 --- /dev/null +++ b/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0002-ARM-dts-BCM5301X-Set-MAC-address-for-Asus-RT-AC87U.patch @@ -0,0 +1,44 @@ +From a9e79863b62aaaefcdf469fc331bf482ae00db0d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 1 Sep 2023 14:43:11 +0200 +Subject: [PATCH] ARM: dts: BCM5301X: Set MAC address for Asus RT-AC87U +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Specify NVRAM access and use its "et1macaddr" NVMEM cell. + +Signed-off-by: Rafał Miłecki +Link: https://lore.kernel.org/r/20230901124311.31156-1-zajec5@gmail.com +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts +@@ -25,6 +25,12 @@ + <0x88000000 0x08000000>; + }; + ++ nvram@1c080000 { ++ et1macaddr: et1macaddr { ++ #nvmem-cell-cells = <1>; ++ }; ++ }; ++ + leds { + compatible = "gpio-leds"; + +@@ -62,6 +68,11 @@ + }; + }; + ++&gmac0 { ++ nvmem-cells = <&et1macaddr 0>; ++ nvmem-cell-names = "mac-address"; ++}; ++ + &usb3_phy { + status = "okay"; + }; diff --git a/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0003-ARM-dts-BCM5301X-Relicense-Felix-s-code-to-the-GPL-2.patch b/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0003-ARM-dts-BCM5301X-Relicense-Felix-s-code-to-the-GPL-2.patch new file mode 100644 index 0000000000..842f47af42 --- /dev/null +++ b/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0003-ARM-dts-BCM5301X-Relicense-Felix-s-code-to-the-GPL-2.patch @@ -0,0 +1,57 @@ +From 81ea360a16978a4df61df9db56b171909bd659c0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Sat, 16 Sep 2023 10:30:57 +0200 +Subject: [PATCH] ARM: dts: BCM5301X: Relicense Felix's code to the GPL 2.0+ / + MIT +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Move code added by Felix to the bcm-ns.dtsi which uses dual licensing. +That syncs more Northstar code to be based on the same licensing schema. + +This code was added in the commit 1ff80363524c ("ARM: BCM5301X: Add +profiling support"). + +Cc: Felix Fietkau +Signed-off-by: Rafał Miłecki +Acked-by: Felix Fietkau +Link: https://lore.kernel.org/r/20230916083057.10458-1-zajec5@gmail.com +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/broadcom/bcm-ns.dtsi | 7 +++++++ + arch/arm/boot/dts/broadcom/bcm5301x.dtsi | 7 ------- + 2 files changed, 7 insertions(+), 7 deletions(-) + +--- a/arch/arm/boot/dts/broadcom/bcm-ns.dtsi ++++ b/arch/arm/boot/dts/broadcom/bcm-ns.dtsi +@@ -14,6 +14,13 @@ + #address-cells = <1>; + #size-cells = <1>; + ++ pmu { ++ compatible = "arm,cortex-a9-pmu"; ++ interrupts = ++ , ++ ; ++ }; ++ + chipcommon-a-bus@18000000 { + compatible = "simple-bus"; + ranges = <0x00000000 0x18000000 0x00001000>; +--- a/arch/arm/boot/dts/broadcom/bcm5301x.dtsi ++++ b/arch/arm/boot/dts/broadcom/bcm5301x.dtsi +@@ -26,13 +26,6 @@ + }; + }; + +- pmu { +- compatible = "arm,cortex-a9-pmu"; +- interrupts = +- , +- ; +- }; +- + clocks { + #address-cells = <1>; + #size-cells = <1>; diff --git a/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0004-ARM-dts-BCM5301X-Relicense-Vivek-s-code-to-the-GPL-2.patch b/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0004-ARM-dts-BCM5301X-Relicense-Vivek-s-code-to-the-GPL-2.patch new file mode 100644 index 0000000000..960908100e --- /dev/null +++ b/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0004-ARM-dts-BCM5301X-Relicense-Vivek-s-code-to-the-GPL-2.patch @@ -0,0 +1,104 @@ +From b8d4f7c1be04d66c37c119c501c87bccc4197694 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Sat, 16 Sep 2023 10:58:55 +0200 +Subject: [PATCH] ARM: dts: BCM5301X: Relicense Vivek's code to the GPL 2.0+ / + MIT +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Move code added by Vivek to the bcm-ns.dtsi which uses dual licensing. +That syncs more Northstar code to be based on the same licensing schema. + +This code was added in the commit 37f6130ec39f ("ARM: dts: BCM5301X: +Make USB 3.0 PHY use MDIO PHY driver"). + +Cc: Vivek Unune +Signed-off-by: Rafał Miłecki +Acked-by: Vivek Unune +Link: https://lore.kernel.org/r/20230916085855.28375-1-zajec5@gmail.com +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/broadcom/bcm-ns.dtsi | 27 ++++++++++++++++++++++++ + arch/arm/boot/dts/broadcom/bcm5301x.dtsi | 27 ------------------------ + 2 files changed, 27 insertions(+), 27 deletions(-) + +--- a/arch/arm/boot/dts/broadcom/bcm-ns.dtsi ++++ b/arch/arm/boot/dts/broadcom/bcm-ns.dtsi +@@ -327,6 +327,29 @@ + #address-cells = <1>; + }; + ++ mdio-mux@18003000 { ++ compatible = "mdio-mux-mmioreg", "mdio-mux"; ++ mdio-parent-bus = <&mdio>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x18003000 0x4>; ++ mux-mask = <0x200>; ++ ++ mdio@0 { ++ reg = <0x0>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ usb3_phy: usb3-phy@10 { ++ compatible = "brcm,ns-ax-usb3-phy"; ++ reg = <0x10>; ++ usb3-dmp-syscon = <&usb3_dmp>; ++ #phy-cells = <0>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ + rng: rng@18004000 { + compatible = "brcm,bcm5301x-rng"; + reg = <0x18004000 0x14>; +@@ -467,6 +490,10 @@ + brcm,nand-has-wp; + }; + ++ usb3_dmp: syscon@18105000 { ++ reg = <0x18105000 0x1000>; ++ }; ++ + thermal-zones { + cpu_thermal: cpu-thermal { + polling-delay-passive = <0>; +--- a/arch/arm/boot/dts/broadcom/bcm5301x.dtsi ++++ b/arch/arm/boot/dts/broadcom/bcm5301x.dtsi +@@ -62,33 +62,6 @@ + }; + }; + +- mdio-mux@18003000 { +- compatible = "mdio-mux-mmioreg", "mdio-mux"; +- mdio-parent-bus = <&mdio>; +- #address-cells = <1>; +- #size-cells = <0>; +- reg = <0x18003000 0x4>; +- mux-mask = <0x200>; +- +- mdio@0 { +- reg = <0x0>; +- #address-cells = <1>; +- #size-cells = <0>; +- +- usb3_phy: usb3-phy@10 { +- compatible = "brcm,ns-ax-usb3-phy"; +- reg = <0x10>; +- usb3-dmp-syscon = <&usb3_dmp>; +- #phy-cells = <0>; +- status = "disabled"; +- }; +- }; +- }; +- +- usb3_dmp: syscon@18105000 { +- reg = <0x18105000 0x1000>; +- }; +- + i2c0: i2c@18009000 { + compatible = "brcm,iproc-i2c"; + reg = <0x18009000 0x50>; diff --git a/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0005-ARM-dts-BCM5301X-Explicitly-disable-unused-switch-CP.patch b/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0005-ARM-dts-BCM5301X-Explicitly-disable-unused-switch-CP.patch new file mode 100644 index 0000000000..28f4d2b743 --- /dev/null +++ b/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0005-ARM-dts-BCM5301X-Explicitly-disable-unused-switch-CP.patch @@ -0,0 +1,377 @@ +From 473baeab929444295b0530f8766e4becb6a08973 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 13 Oct 2023 12:33:13 +0200 +Subject: [PATCH] ARM: dts: BCM5301X: Explicitly disable unused switch CPU + ports +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When redescribing ports I assumed that missing "label" (like "cpu") +means switch port isn't used. That was incorrect and I realized my +change made Linux always use the first (5) CPU port (there are 3 of +them). + +While above should technically be possible it often isn't correct: +1. Non-default switch ports are often connected to Ethernet interfaces + not fully covered by vendor setup (they may miss MACs) +2. On some devices non-default ports require specifying fixed link + +This fixes network connectivity for some devices. It was reported & +tested for Netgear R8000. It also affects Linksys EA9200 with its +downstream DTS. + +Fixes: ba4aebce23b2 ("ARM: dts: BCM5301X: Describe switch ports in the main DTS") +Signed-off-by: Rafał Miłecki +Link: https://lore.kernel.org/r/20231013103314.10306-1-zajec5@gmail.com +Signed-off-by: Florian Fainelli +--- + .../dts/broadcom/bcm4708-buffalo-wzr-1166dhp-common.dtsi | 8 ++++++++ + arch/arm/boot/dts/broadcom/bcm4708-luxul-xap-1510.dts | 8 ++++++++ + arch/arm/boot/dts/broadcom/bcm4708-luxul-xwc-1000.dts | 8 ++++++++ + arch/arm/boot/dts/broadcom/bcm4708-netgear-r6250.dts | 8 ++++++++ + arch/arm/boot/dts/broadcom/bcm4708-smartrg-sr400ac.dts | 8 ++++++++ + .../boot/dts/broadcom/bcm47081-buffalo-wzr-600dhp2.dts | 8 ++++++++ + arch/arm/boot/dts/broadcom/bcm47081-luxul-xap-1410.dts | 8 ++++++++ + arch/arm/boot/dts/broadcom/bcm47081-luxul-xwr-1200.dts | 8 ++++++++ + arch/arm/boot/dts/broadcom/bcm4709-netgear-r8000.dts | 8 ++++++++ + arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-885l.dts | 8 ++++++++ + arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-890l.dts | 8 ++++++++ + arch/arm/boot/dts/broadcom/bcm47094-luxul-abr-4500.dts | 8 ++++++++ + arch/arm/boot/dts/broadcom/bcm47094-luxul-xap-1610.dts | 8 ++++++++ + arch/arm/boot/dts/broadcom/bcm47094-luxul-xbr-4500.dts | 8 ++++++++ + arch/arm/boot/dts/broadcom/bcm47094-luxul-xwc-2000.dts | 8 ++++++++ + arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3100.dts | 8 ++++++++ + arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3150-v1.dts | 8 ++++++++ + arch/arm/boot/dts/broadcom/bcm53015-meraki-mr26.dts | 8 ++++++++ + arch/arm/boot/dts/broadcom/bcm53016-meraki-mr32.dts | 8 ++++++++ + arch/arm/boot/dts/broadcom/bcm953012er.dts | 8 ++++++++ + 20 files changed, 160 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm4708-buffalo-wzr-1166dhp-common.dtsi ++++ b/arch/arm/boot/dts/broadcom/bcm4708-buffalo-wzr-1166dhp-common.dtsi +@@ -189,5 +189,13 @@ + port@8 { + status = "disabled"; + }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; + }; + }; +--- a/arch/arm/boot/dts/broadcom/bcm4708-luxul-xap-1510.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4708-luxul-xap-1510.dts +@@ -93,5 +93,13 @@ + port@8 { + status = "disabled"; + }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; + }; + }; +--- a/arch/arm/boot/dts/broadcom/bcm4708-luxul-xwc-1000.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4708-luxul-xwc-1000.dts +@@ -96,5 +96,13 @@ + port@8 { + status = "disabled"; + }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; + }; + }; +--- a/arch/arm/boot/dts/broadcom/bcm4708-netgear-r6250.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4708-netgear-r6250.dts +@@ -130,5 +130,13 @@ + port@8 { + status = "disabled"; + }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; + }; + }; +--- a/arch/arm/boot/dts/broadcom/bcm4708-smartrg-sr400ac.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4708-smartrg-sr400ac.dts +@@ -153,6 +153,14 @@ + port@8 { + status = "disabled"; + }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; + }; + }; + +--- a/arch/arm/boot/dts/broadcom/bcm47081-buffalo-wzr-600dhp2.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47081-buffalo-wzr-600dhp2.dts +@@ -153,5 +153,13 @@ + port@8 { + status = "disabled"; + }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; + }; + }; +--- a/arch/arm/boot/dts/broadcom/bcm47081-luxul-xap-1410.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47081-luxul-xap-1410.dts +@@ -89,5 +89,13 @@ + port@8 { + status = "disabled"; + }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; + }; + }; +--- a/arch/arm/boot/dts/broadcom/bcm47081-luxul-xwr-1200.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47081-luxul-xwr-1200.dts +@@ -156,5 +156,13 @@ + port@8 { + status = "disabled"; + }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; + }; + }; +--- a/arch/arm/boot/dts/broadcom/bcm4709-netgear-r8000.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4709-netgear-r8000.dts +@@ -235,6 +235,14 @@ + status = "disabled"; + }; + ++ port@5 { ++ status = "disabled"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ + port@8 { + label = "cpu"; + }; +--- a/arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-885l.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-885l.dts +@@ -168,6 +168,14 @@ + status = "disabled"; + }; + ++ port@5 { ++ status = "disabled"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ + port@8 { + label = "cpu"; + }; +--- a/arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-890l.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47094-dlink-dir-890l.dts +@@ -200,6 +200,14 @@ + status = "disabled"; + }; + ++ port@5 { ++ status = "disabled"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ + port@8 { + label = "cpu"; + phy-mode = "rgmii"; +--- a/arch/arm/boot/dts/broadcom/bcm47094-luxul-abr-4500.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47094-luxul-abr-4500.dts +@@ -115,5 +115,13 @@ + port@8 { + status = "disabled"; + }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; + }; + }; +--- a/arch/arm/boot/dts/broadcom/bcm47094-luxul-xap-1610.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xap-1610.dts +@@ -128,5 +128,13 @@ + port@8 { + status = "disabled"; + }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; + }; + }; +--- a/arch/arm/boot/dts/broadcom/bcm47094-luxul-xbr-4500.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xbr-4500.dts +@@ -115,5 +115,13 @@ + port@8 { + status = "disabled"; + }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; + }; + }; +--- a/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwc-2000.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwc-2000.dts +@@ -83,5 +83,13 @@ + port@8 { + status = "disabled"; + }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; + }; + }; +--- a/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3100.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3100.dts +@@ -155,5 +155,13 @@ + port@8 { + status = "disabled"; + }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; + }; + }; +--- a/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3150-v1.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47094-luxul-xwr-3150-v1.dts +@@ -166,5 +166,13 @@ + port@8 { + status = "disabled"; + }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; + }; + }; +--- a/arch/arm/boot/dts/broadcom/bcm53015-meraki-mr26.dts ++++ b/arch/arm/boot/dts/broadcom/bcm53015-meraki-mr26.dts +@@ -132,6 +132,14 @@ + port@8 { + status = "disabled"; + }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; + }; + }; + +--- a/arch/arm/boot/dts/broadcom/bcm53016-meraki-mr32.dts ++++ b/arch/arm/boot/dts/broadcom/bcm53016-meraki-mr32.dts +@@ -193,6 +193,14 @@ + port@8 { + status = "disabled"; + }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; + }; + }; + +--- a/arch/arm/boot/dts/broadcom/bcm953012er.dts ++++ b/arch/arm/boot/dts/broadcom/bcm953012er.dts +@@ -92,6 +92,14 @@ + port@8 { + status = "disabled"; + }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; + }; + }; + diff --git a/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0006-ARM-dts-BCM5301X-Set-fixed-link-for-extra-Netgear-R8.patch b/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0006-ARM-dts-BCM5301X-Set-fixed-link-for-extra-Netgear-R8.patch new file mode 100644 index 0000000000..85f093ff0d --- /dev/null +++ b/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0006-ARM-dts-BCM5301X-Set-fixed-link-for-extra-Netgear-R8.patch @@ -0,0 +1,47 @@ +From d313b0e9070a7100ca55e64fe3b081d176d8806d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Fri, 13 Oct 2023 12:33:14 +0200 +Subject: [PATCH] ARM: dts: BCM5301X: Set fixed-link for extra Netgear R8000 + CPU ports +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Ports 5 and 7 are disabled by default because the standard use case is +for port 8 to manage all CPU directed traffic. For experimentation +purposes however it is desirable to provide adequate properties such +that people can experiment with using different ports without having to +figure out their configuration. Some of the use cases include but are +not limited to doubling or tripling the bandwidth by leveraging the +additional ports/Ethernet MAC combinations. + +Signed-off-by: Rafał Miłecki +Link: https://lore.kernel.org/r/20231013103314.10306-2-zajec5@gmail.com +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/broadcom/bcm4709-netgear-r8000.dts | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm4709-netgear-r8000.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4709-netgear-r8000.dts +@@ -237,10 +237,20 @@ + + port@5 { + status = "disabled"; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; + }; + + port@7 { + status = "disabled"; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; + }; + + port@8 { diff --git a/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0007-ARM-dts-BCM5301X-Set-switch-ports-for-Linksys-EA9200.patch b/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0007-ARM-dts-BCM5301X-Set-switch-ports-for-Linksys-EA9200.patch new file mode 100644 index 0000000000..87b6ade5f6 --- /dev/null +++ b/lede/target/linux/bcm53xx/patches-6.6/030-v6.7-0007-ARM-dts-BCM5301X-Set-switch-ports-for-Linksys-EA9200.patch @@ -0,0 +1,63 @@ +From 253358f373492608348136e569366d73cb969f6a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 24 Oct 2023 09:26:05 +0200 +Subject: [PATCH] ARM: dts: BCM5301X: Set switch ports for Linksys EA9200 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch was developed as OpenWrt downstream change and was recently +confirmed to work as expected. + +Tested-by: Rani Hod +Signed-off-by: Rafał Miłecki +Link: https://lore.kernel.org/r/20231024072605.32517-1-zajec5@gmail.com +Signed-off-by: Florian Fainelli +--- + .../dts/broadcom/bcm4709-linksys-ea9200.dts | 38 +++++++++++++++++++ + 1 file changed, 38 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4709-linksys-ea9200.dts +@@ -47,3 +47,41 @@ + &usb3_phy { + status = "okay"; + }; ++ ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "lan1"; ++ }; ++ ++ port@1 { ++ label = "lan2"; ++ }; ++ ++ port@2 { ++ label = "lan3"; ++ }; ++ ++ port@3 { ++ label = "lan4"; ++ }; ++ ++ port@4 { ++ label = "wan"; ++ }; ++ ++ port@5 { ++ status = "disabled"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ label = "cpu"; ++ }; ++ }; ++}; diff --git a/lede/target/linux/bcm53xx/patches-6.6/040-v6.11-ARM-dts-broadcom-convert-NVMEM-content-to-layout-syntax.patch b/lede/target/linux/bcm53xx/patches-6.6/040-v6.11-ARM-dts-broadcom-convert-NVMEM-content-to-layout-syntax.patch new file mode 100644 index 0000000000..864fd01629 --- /dev/null +++ b/lede/target/linux/bcm53xx/patches-6.6/040-v6.11-ARM-dts-broadcom-convert-NVMEM-content-to-layout-syntax.patch @@ -0,0 +1,64 @@ +From ed0d78c75ca93c9f1d7f0d08ac5abe0de71fe312 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 16 May 2024 10:47:37 +0200 +Subject: [PATCH] ARM: dts: broadcom: convert NVMEM content to layout syntax +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use cleaner (and non-deprecated) bindings syntax. See commit +bd912c991d2e ("dt-bindings: nvmem: layouts: add fixed-layout") for +details. + +Signed-off-by: Rafał Miłecki +Link: https://lore.kernel.org/r/20240516084737.2789-1-zajec5@gmail.com +Signed-off-by: Florian Fainelli +--- + arch/arm/boot/dts/broadcom/bcm53016-meraki-mr32.dts | 12 ++++++++---- + .../dts/broadcom/bcm958625-meraki-mx6x-common.dtsi | 12 ++++++++---- + 2 files changed, 16 insertions(+), 8 deletions(-) + +--- a/arch/arm/boot/dts/broadcom/bcm53016-meraki-mr32.dts ++++ b/arch/arm/boot/dts/broadcom/bcm53016-meraki-mr32.dts +@@ -223,11 +223,15 @@ + reg = <0x50>; + pagesize = <32>; + read-only; +- #address-cells = <1>; +- #size-cells = <1>; + +- mac_address: mac-address@66 { +- reg = <0x66 0x6>; ++ nvmem-layout { ++ compatible = "fixed-layout"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ mac_address: mac-address@66 { ++ reg = <0x66 0x6>; ++ }; + }; + }; + }; +--- a/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi ++++ b/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi +@@ -55,11 +55,15 @@ + reg = <0x50>; + pagesize = <32>; + read-only; +- #address-cells = <1>; +- #size-cells = <1>; + +- mac_address: mac-address@66 { +- reg = <0x66 0x6>; ++ nvmem-layout { ++ compatible = "fixed-layout"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ mac_address: mac-address@66 { ++ reg = <0x66 0x6>; ++ }; + }; + }; + }; diff --git a/lede/target/linux/bcm53xx/patches-6.6/050-v6.13-ARM-dts-meraki-mr26-set-mac-address-for-gmac0.patch b/lede/target/linux/bcm53xx/patches-6.6/050-v6.13-ARM-dts-meraki-mr26-set-mac-address-for-gmac0.patch new file mode 100644 index 0000000000..f6a6f819d1 --- /dev/null +++ b/lede/target/linux/bcm53xx/patches-6.6/050-v6.13-ARM-dts-meraki-mr26-set-mac-address-for-gmac0.patch @@ -0,0 +1,52 @@ +From ad1915e2070cf832bfb81dcbeb44b073c09e6dcc Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Sun, 20 Oct 2024 18:51:47 -0700 +Subject: [PATCH] ARM: dts: meraki-mr26: set mac address for gmac0 + +Currently this needs to be done in userspace. + +Signed-off-by: Rosen Penev +Link: https://lore.kernel.org/r/20241021015147.172700-1-rosenp@gmail.com +Signed-off-by: Florian Fainelli +--- + .../dts/broadcom/bcm53015-meraki-mr26.dts | 20 +++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/arch/arm/boot/dts/broadcom/bcm53015-meraki-mr26.dts ++++ b/arch/arm/boot/dts/broadcom/bcm53015-meraki-mr26.dts +@@ -59,6 +59,9 @@ + + &gmac0 { + status = "okay"; ++ ++ nvmem-cells = <&macaddr_board_config_66>; ++ nvmem-cell-names = "mac-address"; + }; + + &gmac1 { +@@ -102,8 +105,25 @@ + }; + + partition@800000 { ++ compatible = "linux,ubi"; + label = "ubi"; + reg = <0x800000 0x7780000>; ++ ++ volumes { ++ ubi-volume-board-config { ++ volname = "board-config"; ++ ++ nvmem-layout { ++ compatible = "fixed-layout"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ macaddr_board_config_66: macaddr@66 { ++ reg = <0x66 0x6>; ++ }; ++ }; ++ }; ++ }; + }; + }; + }; diff --git a/lede/target/linux/bcm53xx/patches-6.6/051-ARM-dts-meraki-mr26-wifi-MACs-in-dts.patch b/lede/target/linux/bcm53xx/patches-6.6/051-ARM-dts-meraki-mr26-wifi-MACs-in-dts.patch new file mode 100644 index 0000000000..fd31438cdb --- /dev/null +++ b/lede/target/linux/bcm53xx/patches-6.6/051-ARM-dts-meraki-mr26-wifi-MACs-in-dts.patch @@ -0,0 +1,67 @@ +From c18e0b14b466fb0aa17c8ca6e61f16ba1254aebd Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Sun, 24 Nov 2024 12:58:51 -0800 +Subject: [PATCH] ARM: dts: meraki-mr26: wifi MACs in dts + +OPENWRT HACK. Probably will not be accepted upstream. + +Signed-off-by: Rosen Penev +--- + .../dts/broadcom/bcm53015-meraki-mr26.dts | 31 ++++++++++++++++++- + 1 file changed, 30 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/broadcom/bcm53015-meraki-mr26.dts ++++ b/arch/arm/boot/dts/broadcom/bcm53015-meraki-mr26.dts +@@ -60,7 +60,7 @@ + &gmac0 { + status = "okay"; + +- nvmem-cells = <&macaddr_board_config_66>; ++ nvmem-cells = <&macaddr_board_config_66 0>; + nvmem-cell-names = "mac-address"; + }; + +@@ -74,6 +74,33 @@ + status = "disabled"; + }; + ++&pcie0 { ++ wifi@0,0 { ++ reg = <0x0000 0 0 0 0>; ++ compatible = "brcm,bcm43431"; ++ nvmem-cells = <&macaddr_board_config_66 1>; ++ nvmem-cell-names = "mac-address"; ++ }; ++}; ++ ++&pcie1 { ++ wifi@0,0 { ++ reg = <0x0000 0 0 0 0>; ++ compatible = "brcm,bcm43431"; ++ nvmem-cells = <&macaddr_board_config_66 2>; ++ nvmem-cell-names = "mac-address"; ++ }; ++}; ++ ++&pcie2 { ++ wifi@0,0 { ++ reg = <0x0000 0 0 0 0>; ++ compatible = "brcm,bcm43428"; ++ nvmem-cells = <&macaddr_board_config_66 3>; ++ nvmem-cell-names = "mac-address"; ++ }; ++}; ++ + &nandcs { + partitions { + compatible = "fixed-partitions"; +@@ -119,7 +146,9 @@ + #size-cells = <1>; + + macaddr_board_config_66: macaddr@66 { ++ compatible = "mac-base"; + reg = <0x66 0x6>; ++ #nvmem-cell-cells = <1>; + }; + }; + }; diff --git a/lede/target/linux/bcm53xx/patches-6.6/140-mtd-parsers-trx-parse-firmware-MTD-partitions-only.patch b/lede/target/linux/bcm53xx/patches-6.6/140-mtd-parsers-trx-parse-firmware-MTD-partitions-only.patch new file mode 100644 index 0000000000..e1933e75c7 --- /dev/null +++ b/lede/target/linux/bcm53xx/patches-6.6/140-mtd-parsers-trx-parse-firmware-MTD-partitions-only.patch @@ -0,0 +1,43 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Tue, 13 Apr 2021 18:25:20 +0200 +Subject: [PATCH] mtd: parsers: trx: parse "firmware" MTD partitions only +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Parsing every partition with "compatible" set to "brcm,trx" results in +parsing both: firmware partition and failsafe partition on devices that +implement failsafe booting. This affects e.g. Linksys EA9500 which has: + +partition@200000 { + reg = <0x0200000 0x01d00000>; + compatible = "linksys,ns-firmware", "brcm,trx"; +}; + +partition@1f00000 { + reg = <0x01f00000 0x01d00000>; + compatible = "linksys,ns-firmware", "brcm,trx"; +}; + +Check for MTD partition name "firmware" before parsing. Recently added +ofpart_linksys_ns.c creates "firmware" and "failsafe" depending on +bootloader setup. + +Signed-off-by: Rafał Miłecki +--- + drivers/mtd/parsers/parser_trx.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/mtd/parsers/parser_trx.c ++++ b/drivers/mtd/parsers/parser_trx.c +@@ -92,6 +92,10 @@ static int parser_trx_parse(struct mtd_i + if (err != 0 && err != -EINVAL) + pr_err("failed to parse \"brcm,trx-magic\" DT attribute, using default: %d\n", err); + ++ /* Don't parse any failsafe / backup partitions */ ++ if (strcmp(mtd->name, "firmware")) ++ return -EINVAL; ++ + parts = kcalloc(TRX_PARSER_MAX_PARTS, sizeof(struct mtd_partition), + GFP_KERNEL); + if (!parts) diff --git a/lede/target/linux/bcm53xx/patches-6.6/180-usb-xhci-add-support-for-performing-fake-doorbell.patch b/lede/target/linux/bcm53xx/patches-6.6/180-usb-xhci-add-support-for-performing-fake-doorbell.patch new file mode 100644 index 0000000000..aef8435148 --- /dev/null +++ b/lede/target/linux/bcm53xx/patches-6.6/180-usb-xhci-add-support-for-performing-fake-doorbell.patch @@ -0,0 +1,113 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Sat, 1 Oct 2016 22:54:48 +0200 +Subject: [PATCH] usb: xhci: add support for performing fake doorbell + +Broadcom's Northstar XHCI controllers seem to need a special start +procedure to work correctly. There isn't any official documentation of +this, the problem is that controller doesn't detect any connected +devices with default setup. Moreover connecting USB device to controller +that doesn't run properly can cause SoC's watchdog issues. + +A workaround that was successfully tested on multiple devices is to +perform a fake doorbell. This patch adds code for doing this and enables +it on BCM4708 family. +--- + drivers/usb/host/xhci-plat.c | 6 +++++ + drivers/usb/host/xhci.c | 63 +++++++++++++++++++++++++++++++++++++++++--- + drivers/usb/host/xhci.h | 1 + + 3 files changed, 67 insertions(+), 3 deletions(-) + +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -77,8 +77,13 @@ static int xhci_priv_resume_quirk(struct + static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci) + { + struct xhci_plat_priv *priv = xhci_to_priv(xhci); ++ struct platform_device*pdev = to_platform_device(dev); ++ struct device_node *node = pdev->dev.of_node; + + xhci->quirks |= priv->quirks; ++ ++ if (node && of_machine_is_compatible("brcm,bcm4708")) ++ xhci->quirks |= XHCI_FAKE_DOORBELL; + } + + /* called during probe() after chip reset completes */ +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -162,6 +162,49 @@ int xhci_start(struct xhci_hcd *xhci) + return ret; + } + ++/** ++ * xhci_fake_doorbell - Perform a fake doorbell on a specified slot ++ * ++ * Some controllers require a fake doorbell to start correctly. Without that ++ * they simply don't detect any devices. ++ */ ++static int xhci_fake_doorbell(struct xhci_hcd *xhci, int slot_id) ++{ ++ u32 temp; ++ ++ /* Alloc a virt device for that slot */ ++ if (!xhci_alloc_virt_device(xhci, slot_id, NULL, GFP_NOIO)) { ++ xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n"); ++ return -ENOMEM; ++ } ++ ++ /* Ring fake doorbell for slot_id ep 0 */ ++ xhci_ring_ep_doorbell(xhci, slot_id, 0, 0); ++ usleep_range(1000, 1500); ++ ++ /* Read the status to check if HSE is set or not */ ++ temp = readl(&xhci->op_regs->status); ++ ++ /* Clear HSE if set */ ++ if (temp & STS_FATAL) { ++ xhci_dbg(xhci, "HSE problem detected, status: 0x%08x\n", temp); ++ temp &= ~0x1fff; ++ temp |= STS_FATAL; ++ writel(temp, &xhci->op_regs->status); ++ usleep_range(1000, 1500); ++ readl(&xhci->op_regs->status); ++ } ++ ++ /* Free virt device */ ++ xhci_free_virt_device(xhci, slot_id); ++ ++ /* We're done if controller is already running */ ++ if (readl(&xhci->op_regs->command) & CMD_RUN) ++ return 0; ++ ++ return xhci_start(xhci); ++} ++ + /* + * Reset a halted HC. + * +@@ -481,6 +524,15 @@ static int xhci_run_finished(struct xhci + return -ENODEV; + } + ++ if (xhci->quirks & XHCI_FAKE_DOORBELL) { ++ int err = xhci_fake_doorbell(xhci, 1); ++ if (err) { ++ xhci_halt(xhci); ++ spin_unlock_irqrestore(&xhci->lock, flags); ++ return err; ++ } ++ } ++ + xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; + + if (xhci->quirks & XHCI_NEC_HOST) +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1662,6 +1662,7 @@ struct xhci_hcd { + #define XHCI_WRITE_64_HI_LO BIT_ULL(47) + #define XHCI_CDNS_SCTX_QUIRK BIT_ULL(48) + #define XHCI_ETRON_HOST BIT_ULL(49) ++#define XHCI_FAKE_DOORBELL BIT_ULL(50) + + unsigned int num_active_eps; + unsigned int limit_active_eps; diff --git a/lede/target/linux/bcm53xx/patches-6.6/300-ARM-BCM5301X-Disable-MMU-and-Dcache-during-decompres.patch b/lede/target/linux/bcm53xx/patches-6.6/300-ARM-BCM5301X-Disable-MMU-and-Dcache-during-decompres.patch new file mode 100644 index 0000000000..789326310a --- /dev/null +++ b/lede/target/linux/bcm53xx/patches-6.6/300-ARM-BCM5301X-Disable-MMU-and-Dcache-during-decompres.patch @@ -0,0 +1,111 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Wed, 24 Sep 2014 22:14:07 +0200 +Subject: [PATCH] ARM: BCM5301X: Disable MMU and Dcache during decompression +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Broadcom devices have broken CFE (bootloader) that leaves hardware in an +invalid state. It causes problems with booting Linux. On Northstar +devices kernel was randomly hanging in ~25% of tries during early init. +Hangs used to happen at random places in the start_kernel. On BCM53573 +kernel doesn't even seem to start booting. + +To workaround this problem we need to do following very early: +1) Clear 2 following bits in the SCTLR register: +#define CR_M (1 << 0) /* MMU enable */ +#define CR_C (1 << 2) /* Dcache enable */ +2) Flush the whole D-cache +3) Disable L2 cache + +Unfortunately this patch is not upstreamable as it does above things +unconditionally. We can't check if we are running on Broadcom platform +in any safe way and doing such hacks with ARCH_MULTI_V7 is unacceptable +as it could break other devices support. + +Signed-off-by: Rafał Miłecki +--- + +--- a/arch/arm/boot/compressed/Makefile ++++ b/arch/arm/boot/compressed/Makefile +@@ -36,6 +36,11 @@ ifeq ($(CONFIG_ARCH_ACORN),y) + OBJS += ll_char_wr.o font.o + endif + ++ifeq ($(CONFIG_ARCH_BCM_5301X),y) ++OBJS += head-bcm_5301x-mpcore.o ++OBJS += cache-v7-min.o ++endif ++ + ifeq ($(CONFIG_ARCH_SA1100),y) + OBJS += head-sa1100.o + endif +--- /dev/null ++++ b/arch/arm/boot/compressed/head-bcm_5301x-mpcore.S +@@ -0,0 +1,37 @@ ++/* ++ * ++ * Platform specific tweaks. This is merged into head.S by the linker. ++ * ++ */ ++ ++#include ++#include ++#include ++ ++ .section ".start", "ax" ++ ++/* ++ * This code section is spliced into the head code by the linker ++ */ ++ ++__plat_uncompress_start: ++ ++ @ Preserve r8/r7 i.e. kernel entry values ++ mov r12, r8 ++ ++ @ Clear MMU enable and Dcache enable bits ++ mrc p15, 0, r0, c1, c0, 0 @ Read SCTLR ++ bic r0, #CR_C|CR_M ++ mcr p15, 0, r0, c1, c0, 0 @ Write SCTLR ++ nop ++ ++ @ Call the cache invalidation routine ++ bl v7_flush_dcache_all ++ nop ++ mov r0,#0 ++ ldr r3, =0x19022000 @ L2 cache controller, control reg ++ str r0, [r3, #0x100] @ Disable L2 cache ++ nop ++ ++ @ Restore ++ mov r8, r12 +--- a/arch/arm/boot/compressed/cache-v7-min.S ++++ b/arch/arm/boot/compressed/cache-v7-min.S +@@ -12,6 +12,7 @@ + + #include + #include ++#include + + __INIT + +@@ -63,7 +64,7 @@ loop2: + ARM( orr r11, r11, r9, lsl r2 ) @ factor index number into r11 + THUMB( lsl r6, r9, r2 ) + THUMB( orr r11, r11, r6 ) @ factor index number into r11 +- mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way ++ mcr p15, 0, r11, c7, c6, 2 @ clean & invalidate by set/way + subs r9, r9, #1 @ decrement the index + bge loop2 + subs r4, r4, #1 @ decrement the way +--- a/arch/arm/boot/compressed/vmlinux.lds.S ++++ b/arch/arm/boot/compressed/vmlinux.lds.S +@@ -41,6 +41,7 @@ SECTIONS + *(.start) + *(.text) + *(.text.*) ++ *(.init.text) + ARM_STUBS_TEXT + } + .table : ALIGN(4) { diff --git a/lede/target/linux/bcm53xx/patches-6.6/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch b/lede/target/linux/bcm53xx/patches-6.6/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch new file mode 100644 index 0000000000..9cfc3aac15 --- /dev/null +++ b/lede/target/linux/bcm53xx/patches-6.6/304-ARM-dts-BCM5301X-Specify-switch-ports-for-remaining-.patch @@ -0,0 +1,675 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Subject: [PATCH] ARM: dts: BCM5301X: Specify switch ports for remaining + devices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rafał Miłecki +--- + +--- a/arch/arm/boot/dts/broadcom/bcm4708-asus-rt-ac56u.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4708-asus-rt-ac56u.dts +@@ -92,3 +92,41 @@ + &usb3_phy { + status = "okay"; + }; ++ ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "lan1"; ++ }; ++ ++ port@1 { ++ label = "lan2"; ++ }; ++ ++ port@2 { ++ label = "lan3"; ++ }; ++ ++ port@3 { ++ label = "lan4"; ++ }; ++ ++ port@4 { ++ label = "wan"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/broadcom/bcm4708-asus-rt-ac68u.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4708-asus-rt-ac68u.dts +@@ -83,3 +83,41 @@ + &usb3_phy { + status = "okay"; + }; ++ ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "wan"; ++ }; ++ ++ port@1 { ++ label = "lan1"; ++ }; ++ ++ port@2 { ++ label = "lan2"; ++ }; ++ ++ port@3 { ++ label = "lan3"; ++ }; ++ ++ port@4 { ++ label = "lan4"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/broadcom/bcm4708-buffalo-wzr-1750dhp.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4708-buffalo-wzr-1750dhp.dts +@@ -149,3 +149,41 @@ + &usb3_phy { + status = "okay"; + }; ++ ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "lan1"; ++ }; ++ ++ port@1 { ++ label = "lan2"; ++ }; ++ ++ port@2 { ++ label = "lan3"; ++ }; ++ ++ port@3 { ++ label = "lan4"; ++ }; ++ ++ port@4 { ++ label = "wan"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6300-v1.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6300-v1.dts +@@ -46,3 +46,41 @@ + &usb3_phy { + status = "okay"; + }; ++ ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "lan1"; ++ }; ++ ++ port@1 { ++ label = "lan2"; ++ }; ++ ++ port@2 { ++ label = "lan3"; ++ }; ++ ++ port@3 { ++ label = "lan4"; ++ }; ++ ++ port@4 { ++ label = "wan"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6500-v2.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4708-linksys-ea6500-v2.dts +@@ -43,3 +43,41 @@ + &usb3_phy { + status = "okay"; + }; ++ ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "lan1"; ++ }; ++ ++ port@1 { ++ label = "lan2"; ++ }; ++ ++ port@2 { ++ label = "lan3"; ++ }; ++ ++ port@3 { ++ label = "lan4"; ++ }; ++ ++ port@4 { ++ label = "wan"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/broadcom/bcm4708-netgear-r6300-v2.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4708-netgear-r6300-v2.dts +@@ -86,3 +86,41 @@ + &usb3_phy { + status = "okay"; + }; ++ ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "lan1"; ++ }; ++ ++ port@1 { ++ label = "lan2"; ++ }; ++ ++ port@2 { ++ label = "lan3"; ++ }; ++ ++ port@3 { ++ label = "lan4"; ++ }; ++ ++ port@4 { ++ label = "wan"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/broadcom/bcm47081-asus-rt-n18u.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47081-asus-rt-n18u.dts +@@ -77,3 +77,41 @@ + &usb3_phy { + status = "okay"; + }; ++ ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "wan"; ++ }; ++ ++ port@1 { ++ label = "lan1"; ++ }; ++ ++ port@2 { ++ label = "lan2"; ++ }; ++ ++ port@3 { ++ label = "lan3"; ++ }; ++ ++ port@4 { ++ label = "lan4"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4709-asus-rt-ac87u.dts +@@ -77,6 +77,40 @@ + status = "okay"; + }; + ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "wan"; ++ }; ++ ++ port@1 { ++ label = "lan1"; ++ }; ++ ++ port@2 { ++ label = "lan2"; ++ }; ++ ++ port@3 { ++ label = "lan3"; ++ }; ++ ++ port@5 { ++ status = "disabled"; ++ }; ++ ++ port@7 { ++ label = "cpu"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; ++ + &nandcs { + partitions { + compatible = "fixed-partitions"; +--- a/arch/arm/boot/dts/broadcom/bcm4709-buffalo-wxr-1900dhp.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4709-buffalo-wxr-1900dhp.dts +@@ -130,3 +130,41 @@ + &usb3_phy { + status = "okay"; + }; ++ ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "lan1"; ++ }; ++ ++ port@1 { ++ label = "lan2"; ++ }; ++ ++ port@2 { ++ label = "lan3"; ++ }; ++ ++ port@3 { ++ label = "lan4"; ++ }; ++ ++ port@4 { ++ label = "wan"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/broadcom/bcm4709-netgear-r7000.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4709-netgear-r7000.dts +@@ -104,3 +104,41 @@ + &usb3_phy { + status = "okay"; + }; ++ ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "wan"; ++ }; ++ ++ port@1 { ++ label = "lan1"; ++ }; ++ ++ port@2 { ++ label = "lan2"; ++ }; ++ ++ port@3 { ++ label = "lan3"; ++ }; ++ ++ port@4 { ++ label = "lan4"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/broadcom/bcm47094-netgear-r8500.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47094-netgear-r8500.dts +@@ -94,3 +94,41 @@ + &usb3_phy { + status = "okay"; + }; ++ ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "wan"; ++ }; ++ ++ port@1 { ++ label = "lan1"; ++ }; ++ ++ port@2 { ++ label = "lan2"; ++ }; ++ ++ port@3 { ++ label = "lan3"; ++ }; ++ ++ port@4 { ++ label = "lan4"; ++ }; ++ ++ port@5 { ++ status = "disabled"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ label = "cpu"; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/broadcom/bcm47094-phicomm-k3.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47094-phicomm-k3.dts +@@ -38,6 +38,40 @@ + status = "okay"; + }; + ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "lan1"; ++ }; ++ ++ port@1 { ++ label = "lan2"; ++ }; ++ ++ port@2 { ++ label = "lan3"; ++ }; ++ ++ port@3 { ++ label = "wan"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; ++ + &nandcs { + partitions { + compatible = "fixed-partitions"; +--- a/arch/arm/boot/dts/broadcom/bcm47081-tplink-archer-c5-v2.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47081-tplink-archer-c5-v2.dts +@@ -91,6 +91,44 @@ + }; + }; + ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "wan"; ++ }; ++ ++ port@1 { ++ label = "lan1"; ++ }; ++ ++ port@2 { ++ label = "lan2"; ++ }; ++ ++ port@3 { ++ label = "lan3"; ++ }; ++ ++ port@4 { ++ label = "lan4"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; ++ + &spi_nor { + status = "okay"; + +--- a/arch/arm/boot/dts/broadcom/bcm4709-tplink-archer-c9-v1.dts ++++ b/arch/arm/boot/dts/broadcom/bcm4709-tplink-archer-c9-v1.dts +@@ -100,6 +100,44 @@ + vcc-gpio = <&chipcommon 12 GPIO_ACTIVE_HIGH>; + }; + ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "wan"; ++ }; ++ ++ port@1 { ++ label = "lan1"; ++ }; ++ ++ port@2 { ++ label = "lan2"; ++ }; ++ ++ port@3 { ++ label = "lan3"; ++ }; ++ ++ port@4 { ++ label = "lan4"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; ++ + &spi_nor { + status = "okay"; + +--- a/arch/arm/boot/dts/broadcom/bcm47081-buffalo-wzr-900dhp.dts ++++ b/arch/arm/boot/dts/broadcom/bcm47081-buffalo-wzr-900dhp.dts +@@ -107,3 +107,42 @@ + &usb3_phy { + status = "okay"; + }; ++ ++&srab { ++ status = "okay"; ++ ++ ports { ++ port@0 { ++ label = "lan1"; ++ }; ++ ++ port@1 { ++ label = "lan2"; ++ }; ++ ++ port@2 { ++ label = "lan3"; ++ }; ++ ++ port@3 { ++ label = "lan4"; ++ }; ++ ++ port@4 { ++ label = "wan"; ++ }; ++ ++ port@5 { ++ label = "cpu"; ++ }; ++ ++ port@7 { ++ status = "disabled"; ++ }; ++ ++ port@8 { ++ status = "disabled"; ++ }; ++ }; ++}; ++ diff --git a/lede/target/linux/bcm53xx/patches-6.6/310-ARM-BCM5301X-Add-DT-for-Netgear-R7900.patch b/lede/target/linux/bcm53xx/patches-6.6/310-ARM-BCM5301X-Add-DT-for-Netgear-R7900.patch new file mode 100644 index 0000000000..053e5347d1 --- /dev/null +++ b/lede/target/linux/bcm53xx/patches-6.6/310-ARM-BCM5301X-Add-DT-for-Netgear-R7900.patch @@ -0,0 +1,64 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Subject: [PATCH] ARM: BCM5301X: Add DT for Netgear R7900 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rafał Miłecki +--- + +--- a/arch/arm/boot/dts/broadcom/Makefile ++++ b/arch/arm/boot/dts/broadcom/Makefile +@@ -68,6 +68,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ + bcm4709-buffalo-wxr-1900dhp.dtb \ + bcm4709-linksys-ea9200.dtb \ + bcm4709-netgear-r7000.dtb \ ++ bcm4709-netgear-r7900.dtb \ + bcm4709-netgear-r8000.dtb \ + bcm4709-tplink-archer-c9-v1.dtb \ + bcm47094-asus-rt-ac3100.dtb \ +--- /dev/null ++++ b/arch/arm/boot/dts/broadcom/bcm4709-netgear-r7900.dts +@@ -0,0 +1,42 @@ ++/* ++ * Broadcom BCM470X / BCM5301X ARM platform code. ++ * DTS for Netgear R7900 ++ * ++ * Copyright (C) 2016 Rafał Miłecki ++ * ++ * Licensed under the GNU/GPL. See COPYING for details. ++ */ ++ ++/dts-v1/; ++ ++#include "bcm4709.dtsi" ++#include "bcm5301x-nand-cs0-bch8.dtsi" ++ ++/ { ++ compatible = "netgear,r7900", "brcm,bcm4709", "brcm,bcm4708"; ++ model = "Netgear R7900"; ++ ++ chosen { ++ bootargs = "console=ttyS0,115200"; ++ }; ++ ++ memory { ++ reg = <0x00000000 0x08000000 ++ 0x88000000 0x08000000>; ++ }; ++ ++ axi@18000000 { ++ usb3@23000 { ++ reg = <0x00023000 0x1000>; ++ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ vcc-gpio = <&chipcommon 0 GPIO_ACTIVE_HIGH>; ++ }; ++ }; ++}; ++ ++&uart0 { ++ status = "okay"; ++}; diff --git a/lede/target/linux/bcm53xx/patches-6.6/332-Meraki-MX6X-partition-fixups.patch b/lede/target/linux/bcm53xx/patches-6.6/332-Meraki-MX6X-partition-fixups.patch new file mode 100644 index 0000000000..9743c99f28 --- /dev/null +++ b/lede/target/linux/bcm53xx/patches-6.6/332-Meraki-MX6X-partition-fixups.patch @@ -0,0 +1,52 @@ +From 35bba88e75311242841dde83073c211310ec0259 Mon Sep 17 00:00:00 2001 +From: Matthew Hagan +Date: Wed, 4 May 2022 08:07:06 +0100 +Subject: [PATCH] bcm53xx: partition fixups for Meraki MX64/MX65 + +We need to enlarge the u-boot partition to add extra features like UBI +booting. The shmoo and newly created env partitions can easily be moved +to the nvram partition. This fixup allows u-boot to be enlarged to up to +1MiB. + +Signed-off-by: Matthew Hagan +--- + arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +--- a/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi ++++ b/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi +@@ -84,13 +84,7 @@ + + partition@0 { + label = "u-boot"; +- reg = <0x0 0x80000>; +- read-only; +- }; +- +- partition@80000 { +- label = "shmoo"; +- reg = <0x80000 0x80000>; ++ reg = <0x0 0x100000>; + read-only; + }; + +@@ -101,7 +95,18 @@ + + partition@400000 { + label = "nvram"; +- reg = <0x400000 0x100000>; ++ reg = <0x400000 0x40000>; ++ }; ++ ++ partition@440000 { ++ label = "u-boot-env"; ++ reg = <0x440000 0x40000>; ++ }; ++ ++ partition@480000 { ++ label = "shmoo"; ++ reg = <0x480000 0x80000>; ++ read-only; + }; + + partition@500000 { diff --git a/lede/target/linux/bcm53xx/patches-6.6/333-bcm53xx-dts-meraki-mx6x-add-OpenWrt-specific-LED-ali.patch b/lede/target/linux/bcm53xx/patches-6.6/333-bcm53xx-dts-meraki-mx6x-add-OpenWrt-specific-LED-ali.patch new file mode 100644 index 0000000000..950e85be9c --- /dev/null +++ b/lede/target/linux/bcm53xx/patches-6.6/333-bcm53xx-dts-meraki-mx6x-add-OpenWrt-specific-LED-ali.patch @@ -0,0 +1,83 @@ +From 9f4e68261b89df87457f46999c471d11754b5de2 Mon Sep 17 00:00:00 2001 +From: Lech Perczak +Date: Sun, 6 Oct 2024 15:57:44 +0200 +Subject: [PATCH] bcm53xx: dts: meraki-mx6x: add OpenWrt-specific LED aliases + +Assign green power LED for "boot", "running", orange for "upgrade" and +red for "failsafe" functions - the same as done for MR33 and MR74. + +Signed-off-by: Lech Perczak +--- + arch/arm/boot/dts/broadcom/bcm958625-meraki-alamo.dtsi | 9 ++++++++- + arch/arm/boot/dts/broadcom/bcm958625-meraki-kingpin.dtsi | 8 +++++++- + .../boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi | 4 ++-- + 3 files changed, 17 insertions(+), 4 deletions(-) + +--- a/arch/arm/boot/dts/broadcom/bcm958625-meraki-alamo.dtsi ++++ b/arch/arm/boot/dts/broadcom/bcm958625-meraki-alamo.dtsi +@@ -8,6 +8,13 @@ + #include "bcm958625-meraki-mx6x-common.dtsi" + + / { ++ aliases { ++ led-boot = &led_power; ++ led-running = &led_power; ++ led-upgrade = &led_fault; ++ led-failsafe = &led_failsafe; ++ }; ++ + keys { + compatible = "gpio-keys-polled"; + autorepeat; +@@ -55,7 +62,7 @@ + gpios = <&gpioa 26 GPIO_ACTIVE_LOW>; + }; + +- led-4 { ++ led_fault: led-4 { + /* amber:power */ + function = LED_FUNCTION_FAULT; + color = ; +--- a/arch/arm/boot/dts/broadcom/bcm958625-meraki-kingpin.dtsi ++++ b/arch/arm/boot/dts/broadcom/bcm958625-meraki-kingpin.dtsi +@@ -8,6 +8,12 @@ + #include "bcm958625-meraki-mx6x-common.dtsi" + + / { ++ aliases { ++ led-boot = &led_power; ++ led-running = &led_power; ++ led-upgrade = &led_fault; ++ led-failsafe = &led_failsafe; ++ }; + + keys { + compatible = "gpio-keys-polled"; +@@ -104,7 +110,7 @@ + gpios = <&gpioa 29 GPIO_ACTIVE_LOW>; + }; + +- led-a { ++ led_fault: led-a { + /* amber:power */ + function = LED_FUNCTION_FAULT; + color = ; +--- a/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi ++++ b/arch/arm/boot/dts/broadcom/bcm958625-meraki-mx6x-common.dtsi +@@ -14,14 +14,14 @@ + pwm-leds { + compatible = "pwm-leds"; + +- led-1 { ++ led_failsafe: led-1 { + function = LED_FUNCTION_INDICATOR; + color = ; + pwms = <&pwm 1 50000>; + max-brightness = <255>; + }; + +- led-2 { ++ led_power: led-2 { + function = LED_FUNCTION_POWER; + color = ; + pwms = <&pwm 2 50000>; diff --git a/lede/target/linux/bcm53xx/patches-6.6/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch b/lede/target/linux/bcm53xx/patches-6.6/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch new file mode 100644 index 0000000000..e6140d9a70 --- /dev/null +++ b/lede/target/linux/bcm53xx/patches-6.6/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch @@ -0,0 +1,59 @@ +From 2a2af518266a29323cf30c3f9ba9ef2ceb1dd84b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 16 Oct 2014 20:52:16 +0200 +Subject: [PATCH] UBI: Detect EOF mark and erase all remaining blocks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rafał Miłecki +--- + drivers/mtd/ubi/attach.c | 5 +++++ + drivers/mtd/ubi/io.c | 4 ++++ + drivers/mtd/ubi/ubi.h | 1 + + 3 files changed, 10 insertions(+) + +--- a/drivers/mtd/ubi/attach.c ++++ b/drivers/mtd/ubi/attach.c +@@ -82,6 +82,9 @@ static int self_check_ai(struct ubi_devi + #define AV_ADD BIT(1) + #define AV_FIND_OR_ADD (AV_FIND | AV_ADD) + ++/* Set on finding block with 0xdeadc0de, indicates erasing all blocks behind */ ++bool erase_all_next; ++ + /** + * find_or_add_av - internal function to find a volume, add a volume or do + * both (find and add if missing). +@@ -1580,6 +1583,8 @@ int ubi_attach(struct ubi_device *ubi, i + if (!ai) + return -ENOMEM; + ++ erase_all_next = false; ++ + #ifdef CONFIG_MTD_UBI_FASTMAP + /* On small flash devices we disable fastmap in any case. */ + if ((int)mtd_div_by_eb(ubi->mtd->size, ubi->mtd) <= UBI_FM_MAX_START) { +--- a/drivers/mtd/ubi/io.c ++++ b/drivers/mtd/ubi/io.c +@@ -717,6 +717,10 @@ int ubi_io_read_ec_hdr(struct ubi_device + } + + magic = be32_to_cpu(ec_hdr->magic); ++ if (magic == 0xdeadc0de) ++ erase_all_next = true; ++ if (erase_all_next) ++ return read_err ? UBI_IO_FF_BITFLIPS : UBI_IO_FF; + if (magic != UBI_EC_HDR_MAGIC) { + if (mtd_is_eccerr(read_err)) + return UBI_IO_BAD_HDR_EBADMSG; +--- a/drivers/mtd/ubi/ubi.h ++++ b/drivers/mtd/ubi/ubi.h +@@ -822,6 +822,7 @@ extern struct mutex ubi_devices_mutex; + extern struct blocking_notifier_head ubi_notifiers; + + /* attach.c */ ++extern bool erase_all_next; + struct ubi_ainf_peb *ubi_alloc_aeb(struct ubi_attach_info *ai, int pnum, + int ec); + void ubi_free_aeb(struct ubi_attach_info *ai, struct ubi_ainf_peb *aeb); diff --git a/lede/target/linux/bcm53xx/patches-6.6/600-net-disable-GRO-by-default.patch b/lede/target/linux/bcm53xx/patches-6.6/600-net-disable-GRO-by-default.patch new file mode 100644 index 0000000000..86615710ee --- /dev/null +++ b/lede/target/linux/bcm53xx/patches-6.6/600-net-disable-GRO-by-default.patch @@ -0,0 +1,36 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 20 Jun 2022 10:01:18 +0200 +Subject: [PATCH] net: disable GRO by default +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In many cases GRO improves network performance however it comes at a +cost of chacksums calculations. In case of slow CPU and missing hardware +csum calculation support GRO can actually decrease network speed. + +On BCM4708 *disabling* GRO results in following NAT masquarade speed +changes: +1. 364 Mb/s → 396 Mb/s (packet steering disabled) +2. 341 Mb/s → 566 Mb/s (packet steering enabled) + +Signed-off-by: Rafał Miłecki +--- + include/linux/netdev_features.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/include/linux/netdev_features.h ++++ b/include/linux/netdev_features.h +@@ -243,10 +243,10 @@ static inline int find_next_netdev_featu + #define NETIF_F_UPPER_DISABLES NETIF_F_LRO + + /* changeable features with no special hardware requirements */ +-#define NETIF_F_SOFT_FEATURES (NETIF_F_GSO | NETIF_F_GRO) ++#define NETIF_F_SOFT_FEATURES (NETIF_F_GSO) + + /* Changeable features with no special hardware requirements that defaults to off. */ +-#define NETIF_F_SOFT_FEATURES_OFF (NETIF_F_GRO_FRAGLIST | NETIF_F_GRO_UDP_FWD) ++#define NETIF_F_SOFT_FEATURES_OFF (NETIF_F_GRO_UDP_FWD | NETIF_F_GRO | NETIF_F_GRO_FRAGLIST) + + #define NETIF_F_VLAN_FEATURES (NETIF_F_HW_VLAN_CTAG_FILTER | \ + NETIF_F_HW_VLAN_CTAG_RX | \ diff --git a/lede/target/linux/bcm53xx/patches-6.6/905-BCM53573-minor-hacks.patch b/lede/target/linux/bcm53xx/patches-6.6/905-BCM53573-minor-hacks.patch new file mode 100644 index 0000000000..44573cb46a --- /dev/null +++ b/lede/target/linux/bcm53xx/patches-6.6/905-BCM53573-minor-hacks.patch @@ -0,0 +1,80 @@ +From 6f1c62440eb6846cb8045d7a5480ec7bbe47c96f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Mon, 15 Aug 2016 10:30:41 +0200 +Subject: [PATCH] BCM53573 minor hacks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Rafał Miłecki +--- + +--- a/arch/arm/boot/dts/broadcom/bcm53573.dtsi ++++ b/arch/arm/boot/dts/broadcom/bcm53573.dtsi +@@ -54,6 +54,7 @@ + , + , + ; ++ clocks = <&ilp>; + }; + + clocks { +--- a/drivers/bcma/main.c ++++ b/drivers/bcma/main.c +@@ -331,14 +331,6 @@ static int bcma_register_devices(struct + } + #endif + +-#ifdef CONFIG_BCMA_SFLASH +- if (bus->drv_cc.sflash.present) { +- err = platform_device_register(&bcma_sflash_dev); +- if (err) +- bcma_err(bus, "Error registering serial flash\n"); +- } +-#endif +- + #ifdef CONFIG_BCMA_NFLASH + if (bus->drv_cc.nflash.present) { + err = platform_device_register(&bcma_nflash_dev); +@@ -418,6 +410,14 @@ int bcma_bus_register(struct bcma_bus *b + bcma_register_core(bus, core); + } + ++#ifdef CONFIG_BCMA_SFLASH ++ if (bus->drv_cc.sflash.present) { ++ err = platform_device_register(&bcma_sflash_dev); ++ if (err) ++ bcma_err(bus, "Error registering serial flash\n"); ++ } ++#endif ++ + /* Try to get SPROM */ + err = bcma_sprom_get(bus); + if (err == -ENOENT) { +--- a/drivers/clocksource/arm_arch_timer.c ++++ b/drivers/clocksource/arm_arch_timer.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1048,6 +1049,16 @@ static void __init arch_timer_of_configu + if (of_property_read_u32(np, "clock-frequency", &arch_timer_rate)) + arch_timer_rate = rate; + ++ /* Get clk rate through clk driver if present */ ++ if (!arch_timer_rate) { ++ struct clk *clk = of_clk_get(np, 0); ++ ++ if (!IS_ERR(clk)) { ++ if (!clk_prepare_enable(clk)) ++ arch_timer_rate = clk_get_rate(clk); ++ } ++ } ++ + /* Check the timer frequency. */ + if (validate_timer_rate()) + pr_warn("frequency not available\n"); diff --git a/lede/target/linux/loongarch64/Makefile b/lede/target/linux/loongarch64/Makefile index c87042053c..f8401c2b2e 100644 --- a/lede/target/linux/loongarch64/Makefile +++ b/lede/target/linux/loongarch64/Makefile @@ -7,15 +7,16 @@ include $(TOPDIR)/rules.mk ARCH:=loongarch64 BOARD:=loongarch64 BOARDNAME:=Loongson LoongArch -FEATURES:=audio display squashfs ext4 pcie boot-part rootfs-part rtc usb targz +FEATURES:=audio display ext4 pcie boot-part rootfs-part rtc usb targz +SUBTARGETS:=generic KERNEL_PATCHVER:=6.6 -KERNELNAME:=vmlinuz.efi +KERNELNAME:=vmlinuz.efi dtbs include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES += \ - partx-utils blkid e2fsprogs grub2-efi-loongarch64 htop wpad-openssl + partx-utils blkid e2fsprogs grub2-efi-loongarch64 $(eval $(call BuildTarget)) diff --git a/lede/target/linux/loongarch64/config-6.6 b/lede/target/linux/loongarch64/config-6.6 index 6f637a6f01..fe0c50c98d 100644 --- a/lede/target/linux/loongarch64/config-6.6 +++ b/lede/target/linux/loongarch64/config-6.6 @@ -93,8 +93,6 @@ CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_BUFFER_HEAD=y CONFIG_BUG_ON_DATA_CORRUPTION=y CONFIG_CACHESTAT_SYSCALL=y -CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5" -CONFIG_CC_NO_ARRAY_BOUNDS=y CONFIG_CDROM=y CONFIG_CFS_BANDWIDTH=y CONFIG_CGROUPS=y @@ -171,7 +169,6 @@ CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_RSA=y CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_SHA256=y -CONFIG_DCB=y CONFIG_DEBUG_BUGVERBOSE=y CONFIG_DEBUG_INFO=y CONFIG_DEBUG_INFO_COMPRESSED_NONE=y @@ -234,8 +231,6 @@ CONFIG_ENCRYPTED_KEYS=y CONFIG_EXCLUSIVE_SYSTEM_RAM=y CONFIG_EXPORTFS_BLOCK_OPS=y CONFIG_EXT4_FS=y -CONFIG_EXT4_FS_POSIX_ACL=y -CONFIG_EXT4_FS_SECURITY=y CONFIG_FAILOVER=y CONFIG_FAIR_GROUP_SCHED=y CONFIG_FANOTIFY=y @@ -282,13 +277,11 @@ CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y CONFIG_FREEZER=y CONFIG_FS_IOMAP=y CONFIG_FS_MBCACHE=y -CONFIG_FS_POSIX_ACL=y CONFIG_FUNCTION_ALIGNMENT=0 CONFIG_FW_CACHE=y # CONFIG_FW_DEVLINK_SYNC_STATE_TIMEOUT is not set CONFIG_FW_LOADER_PAGED_BUF=y CONFIG_FW_LOADER_SYSFS=y -CONFIG_GCC11_NO_ARRAY_BOUNDS=y CONFIG_GENERIC_ALLOCATOR=y CONFIG_GENERIC_BUG=y CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y @@ -402,7 +395,6 @@ CONFIG_LEDS_TRIGGER_MTD=y CONFIG_LEDS_TRIGGER_PANIC=y CONFIG_LEGACY_TIOCSTI=y CONFIG_LIBFDT=y -CONFIG_LIST_HARDENED=y CONFIG_LOCKUP_DETECTOR=y CONFIG_LOCK_DEBUGGING_SUPPORT=y CONFIG_LOCK_SPIN_ON_OWNER=y @@ -532,7 +524,6 @@ CONFIG_PCI_LOONGSON=y CONFIG_PCI_MSI=y CONFIG_PCI_MSI_ARCH_FALLBACKS=y CONFIG_PCI_REALLOC_ENABLE_AUTO=y -CONFIG_PCPU_DEV_REFCNT=y # CONFIG_PDS_CORE is not set CONFIG_PERF_USE_VMALLOC=y CONFIG_PGTABLE_3LEVEL=y @@ -752,7 +743,6 @@ CONFIG_THERMAL_STATISTICS=y CONFIG_THERMAL_WRITABLE_TRIPS=y CONFIG_TICK_CPU_ACCOUNTING=y CONFIG_TMPFS_INODE64=y -CONFIG_TMPFS_POSIX_ACL=y # CONFIG_TMPFS_QUOTA is not set CONFIG_TRANSPARENT_HUGEPAGE=y CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y diff --git a/lede/target/linux/loongarch64/generic/target.mk b/lede/target/linux/loongarch64/generic/target.mk new file mode 100644 index 0000000000..f5cb1fb19b --- /dev/null +++ b/lede/target/linux/loongarch64/generic/target.mk @@ -0,0 +1 @@ +BOARDNAME:=Generic diff --git a/lede/target/linux/loongarch64/image/Makefile b/lede/target/linux/loongarch64/image/Makefile index c9e5d60c5d..7000356292 100644 --- a/lede/target/linux/loongarch64/image/Makefile +++ b/lede/target/linux/loongarch64/image/Makefile @@ -16,7 +16,7 @@ ifneq ($(CONFIG_GRUB_CONSOLE),) GRUB_TERMINALS += console endif -GRUB_SERIAL:=$(call qstrip,$(CONFIG_GRUB_SERIAL)) +GRUB_SERIAL:=$(call qstrip,$(CONFIG_TARGET_SERIAL)) GRUB_CONSOLE_CMDLINE += console=$(GRUB_SERIAL),$(CONFIG_GRUB_BAUDRATE)n8$(if $(CONFIG_GRUB_FLOWCONTROL),r,) GRUB_SERIAL_CONFIG := serial --unit=0 --speed=$(CONFIG_GRUB_BAUDRATE) --word=8 --parity=no --stop=1 --rtscts=$(if $(CONFIG_GRUB_FLOWCONTROL),on,off) @@ -63,6 +63,17 @@ define Build/grub-config endef define Device/Default + KERNEL_INSTALL := 1 + ARTIFACTS := $$(ARTIFACTS-y) + SUPPORTED_DEVICES := +endef + +define Device/generic + DEVICE_VENDOR := Generic + DEVICE_MODEL := LoongArch64 + DEVICE_PACKAGES += kmod-r8169 kmod-drm-amdgpu + KERNEL := kernel-bin + KERNEL_NAME := vmlinuz.efi IMAGE/rootfs.img := append-rootfs | pad-to $(ROOTFS_PARTSIZE) IMAGE/rootfs.img.gz := append-rootfs | pad-to $(ROOTFS_PARTSIZE) | gzip IMAGE/combined-efi.img := grub-config efi | combined | append-metadata @@ -74,18 +85,7 @@ define Device/Default IMAGES-y := rootfs.img IMAGES-$$(CONFIG_GRUB_EFI_IMAGES) += combined-efi.img endif - KERNEL := kernel-bin - KERNEL_INSTALL := 1 - KERNEL_NAME := vmlinuz.efi IMAGES := $$(IMAGES-y) - ARTIFACTS := $$(ARTIFACTS-y) - SUPPORTED_DEVICES := -endef - -define Device/generic - DEVICE_VENDOR := Generic - DEVICE_MODEL := LoongArch64 - DEVICE_PACKAGES += kmod-r8169 kmod-drm-amdgpu endef TARGET_DEVICES += generic diff --git a/lede/target/linux/mediatek/Makefile b/lede/target/linux/mediatek/Makefile index 0175e62c17..c21492cdb8 100644 --- a/lede/target/linux/mediatek/Makefile +++ b/lede/target/linux/mediatek/Makefile @@ -5,11 +5,11 @@ include $(TOPDIR)/rules.mk ARCH:=arm BOARD:=mediatek BOARDNAME:=MediaTek Ralink ARM -SUBTARGETS:=mt7622 mt7623 mt7629 filogic +SUBTARGETS:=filogic mt7622 mt7623 mt7629 FEATURES:=dt-overlay emmc fpu gpio nand pci pcie rootfs-part separate_ramdisk squashfs usb -KERNEL_PATCHVER:=6.1 -KERNEL_TESTING_PATCHVER:=6.6 +KERNEL_PATCHVER:=6.6 +KERNEL_TESTING_PATCHVER:=6.1 include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES += \ diff --git a/lede/target/linux/mediatek/dts/mt7981b-xiaomi_mi-router.dtsi b/lede/target/linux/mediatek/dts/mt7981b-xiaomi_mi-router.dtsi index 3155cb250d..bb84cb8f08 100644 --- a/lede/target/linux/mediatek/dts/mt7981b-xiaomi_mi-router.dtsi +++ b/lede/target/linux/mediatek/dts/mt7981b-xiaomi_mi-router.dtsi @@ -80,6 +80,186 @@ interrupt-parent = <&pio>; interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; }; + + mfd: mfd@1 { + compatible = "airoha,an8855-mfd"; + reg = <1>; + }; +}; + +&mfd { + efuse { + compatible = "airoha,an8855-efuse"; + #nvmem-cell-cells = <0>; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + shift_sel_port0_tx_a: shift-sel-port0-tx-a@c { + reg = <0xc 0x4>; + }; + + shift_sel_port0_tx_b: shift-sel-port0-tx-b@10 { + reg = <0x10 0x4>; + }; + + shift_sel_port0_tx_c: shift-sel-port0-tx-c@14 { + reg = <0x14 0x4>; + }; + + shift_sel_port0_tx_d: shift-sel-port0-tx-d@18 { + reg = <0x18 0x4>; + }; + + shift_sel_port1_tx_a: shift-sel-port1-tx-a@1c { + reg = <0x1c 0x4>; + }; + + shift_sel_port1_tx_b: shift-sel-port1-tx-b@20 { + reg = <0x20 0x4>; + }; + + shift_sel_port1_tx_c: shift-sel-port1-tx-c@24 { + reg = <0x24 0x4>; + }; + + shift_sel_port1_tx_d: shift-sel-port1-tx-d@28 { + reg = <0x28 0x4>; + }; + + shift_sel_port2_tx_a: shift-sel-port2-tx-a@2c { + reg = <0x2c 0x4>; + }; + + shift_sel_port2_tx_b: shift-sel-port2-tx-b@30 { + reg = <0x30 0x4>; + }; + + shift_sel_port2_tx_c: shift-sel-port2-tx-c@34 { + reg = <0x34 0x4>; + }; + + shift_sel_port2_tx_d: shift-sel-port2-tx-d@38 { + reg = <0x38 0x4>; + }; + + shift_sel_port3_tx_a: shift-sel-port3-tx-a@4c { + reg = <0x4c 0x4>; + }; + + shift_sel_port3_tx_b: shift-sel-port3-tx-b@50 { + reg = <0x50 0x4>; + }; + + shift_sel_port3_tx_c: shift-sel-port3-tx-c@54 { + reg = <0x54 0x4>; + }; + + shift_sel_port3_tx_d: shift-sel-port3-tx-d@58 { + reg = <0x58 0x4>; + }; + }; + }; + + ethernet-switch { + compatible = "airoha,an8855-switch"; + reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; + airoha,ext-surge; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "wan"; + phy-mode = "internal"; + phy-handle = <&internal_phy1>; + }; + + port@1 { + reg = <1>; + label = "lan2"; + phy-mode = "internal"; + phy-handle = <&internal_phy2>; + }; + + port@2 { + reg = <2>; + label = "lan3"; + phy-mode = "internal"; + phy-handle = <&internal_phy3>; + }; + + port@3 { + reg = <3>; + label = "lan4"; + phy-mode = "internal"; + phy-handle = <&internal_phy4>; + }; + + port@5 { + reg = <5>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; + }; + + mdio { + compatible = "airoha,an8855-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + internal_phy1: phy@1 { + reg = <1>; + + nvmem-cells = <&shift_sel_port0_tx_a>, + <&shift_sel_port0_tx_b>, + <&shift_sel_port0_tx_c>, + <&shift_sel_port0_tx_d>; + nvmem-cell-names = "tx_a", "tx_b", "tx_c", "tx_d"; + }; + + internal_phy2: phy@2 { + reg = <2>; + + nvmem-cells = <&shift_sel_port1_tx_a>, + <&shift_sel_port1_tx_b>, + <&shift_sel_port1_tx_c>, + <&shift_sel_port1_tx_d>; + nvmem-cell-names = "tx_a", "tx_b", "tx_c", "tx_d"; + }; + + internal_phy3: phy@3 { + reg = <3>; + + nvmem-cells = <&shift_sel_port2_tx_a>, + <&shift_sel_port2_tx_b>, + <&shift_sel_port2_tx_c>, + <&shift_sel_port2_tx_d>; + nvmem-cell-names = "tx_a", "tx_b", "tx_c", "tx_d"; + }; + + internal_phy4: phy@4 { + reg = <4>; + + nvmem-cells = <&shift_sel_port3_tx_a>, + <&shift_sel_port3_tx_b>, + <&shift_sel_port3_tx_c>, + <&shift_sel_port3_tx_d>; + nvmem-cell-names = "tx_a", "tx_b", "tx_c", "tx_d"; + }; + }; }; &spi0 { diff --git a/lede/target/linux/mediatek/files/drivers/mfd/airoha-an8855.c b/lede/target/linux/mediatek/files/drivers/mfd/airoha-an8855.c new file mode 100644 index 0000000000..eeaea348aa --- /dev/null +++ b/lede/target/linux/mediatek/files/drivers/mfd/airoha-an8855.c @@ -0,0 +1,278 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * MFD driver for Airoha AN8855 Switch + */ + +#include +#include +#include +#include +#include +#include + +static const struct mfd_cell an8855_mfd_devs[] = { + { + .name = "an8855-efuse", + .of_compatible = "airoha,an8855-efuse", + }, { + .name = "an8855-switch", + .of_compatible = "airoha,an8855-switch", + }, { + .name = "an8855-mdio", + .of_compatible = "airoha,an8855-mdio", + } +}; + +int an8855_mii_set_page(struct an8855_mfd_priv *priv, u8 phy_id, + u8 page) __must_hold(&priv->bus->mdio_lock) +{ + struct mii_bus *bus = priv->bus; + int ret; + + ret = __mdiobus_write(bus, phy_id, AN8855_PHY_SELECT_PAGE, page); + if (ret < 0) + dev_err_ratelimited(&bus->dev, + "failed to set an8855 mii page\n"); + + /* Cache current page if next mii read/write is for switch */ + priv->current_page = page; + return ret < 0 ? ret : 0; +} +EXPORT_SYMBOL_GPL(an8855_mii_set_page); + +static int an8855_mii_read32(struct mii_bus *bus, u8 phy_id, u32 reg, + u32 *val) __must_hold(&bus->mdio_lock) +{ + int lo, hi, ret; + + ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_MODE, + AN8855_PBUS_MODE_ADDR_FIXED); + if (ret < 0) + goto err; + + ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_RD_ADDR_HIGH, + upper_16_bits(reg)); + if (ret < 0) + goto err; + ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_RD_ADDR_LOW, + lower_16_bits(reg)); + if (ret < 0) + goto err; + + hi = __mdiobus_read(bus, phy_id, AN8855_PBUS_RD_DATA_HIGH); + if (hi < 0) { + ret = hi; + goto err; + } + lo = __mdiobus_read(bus, phy_id, AN8855_PBUS_RD_DATA_LOW); + if (lo < 0) { + ret = lo; + goto err; + } + + *val = ((u16)hi << 16) | ((u16)lo & 0xffff); + + return 0; +err: + dev_err_ratelimited(&bus->dev, + "failed to read an8855 register\n"); + return ret; +} + +static int an8855_regmap_read(void *ctx, uint32_t reg, uint32_t *val) +{ + struct an8855_mfd_priv *priv = ctx; + struct mii_bus *bus = priv->bus; + u16 addr = priv->switch_addr; + int ret; + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4); + if (ret < 0) + goto exit; + + ret = an8855_mii_read32(bus, addr, reg, val); + +exit: + mutex_unlock(&bus->mdio_lock); + + return ret < 0 ? ret : 0; +} + +static int an8855_mii_write32(struct mii_bus *bus, u8 phy_id, u32 reg, + u32 val) __must_hold(&bus->mdio_lock) +{ + int ret; + + ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_MODE, + AN8855_PBUS_MODE_ADDR_FIXED); + if (ret < 0) + goto err; + + ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_ADDR_HIGH, + upper_16_bits(reg)); + if (ret < 0) + goto err; + ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_ADDR_LOW, + lower_16_bits(reg)); + if (ret < 0) + goto err; + + ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_DATA_HIGH, + upper_16_bits(val)); + if (ret < 0) + goto err; + ret = __mdiobus_write(bus, phy_id, AN8855_PBUS_WR_DATA_LOW, + lower_16_bits(val)); + if (ret < 0) + goto err; + + return 0; +err: + dev_err_ratelimited(&bus->dev, + "failed to write an8855 register\n"); + return ret; +} + +static int +an8855_regmap_write(void *ctx, uint32_t reg, uint32_t val) +{ + struct an8855_mfd_priv *priv = ctx; + struct mii_bus *bus = priv->bus; + u16 addr = priv->switch_addr; + int ret; + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4); + if (ret < 0) + goto exit; + + ret = an8855_mii_write32(bus, addr, reg, val); + +exit: + mutex_unlock(&bus->mdio_lock); + + return ret < 0 ? ret : 0; +} + +static int an8855_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, + uint32_t write_val) +{ + struct an8855_mfd_priv *priv = ctx; + struct mii_bus *bus = priv->bus; + u16 addr = priv->switch_addr; + u32 val; + int ret; + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + ret = an8855_mii_set_page(priv, addr, AN8855_PHY_PAGE_EXTENDED_4); + if (ret < 0) + goto exit; + + ret = an8855_mii_read32(bus, addr, reg, &val); + if (ret < 0) + goto exit; + + val &= ~mask; + val |= write_val; + ret = an8855_mii_write32(bus, addr, reg, val); + +exit: + mutex_unlock(&bus->mdio_lock); + + return ret < 0 ? ret : 0; +} + +static const struct regmap_range an8855_readable_ranges[] = { + regmap_reg_range(0x10000000, 0x10000fff), /* SCU */ + regmap_reg_range(0x10001000, 0x10001fff), /* RBUS */ + regmap_reg_range(0x10002000, 0x10002fff), /* MCU */ + regmap_reg_range(0x10005000, 0x10005fff), /* SYS SCU */ + regmap_reg_range(0x10007000, 0x10007fff), /* I2C Slave */ + regmap_reg_range(0x10008000, 0x10008fff), /* I2C Master */ + regmap_reg_range(0x10009000, 0x10009fff), /* PDMA */ + regmap_reg_range(0x1000a100, 0x1000a2ff), /* General Purpose Timer */ + regmap_reg_range(0x1000a200, 0x1000a2ff), /* GPU timer */ + regmap_reg_range(0x1000a300, 0x1000a3ff), /* GPIO */ + regmap_reg_range(0x1000a400, 0x1000a5ff), /* EFUSE */ + regmap_reg_range(0x1000c000, 0x1000cfff), /* GDMP CSR */ + regmap_reg_range(0x10010000, 0x1001ffff), /* GDMP SRAM */ + regmap_reg_range(0x10200000, 0x10203fff), /* Switch - ARL Global */ + regmap_reg_range(0x10204000, 0x10207fff), /* Switch - BMU */ + regmap_reg_range(0x10208000, 0x1020bfff), /* Switch - ARL Port */ + regmap_reg_range(0x1020c000, 0x1020cfff), /* Switch - SCH */ + regmap_reg_range(0x10210000, 0x10213fff), /* Switch - MAC */ + regmap_reg_range(0x10214000, 0x10217fff), /* Switch - MIB */ + regmap_reg_range(0x10218000, 0x1021bfff), /* Switch - Port Control */ + regmap_reg_range(0x1021c000, 0x1021ffff), /* Switch - TOP */ + regmap_reg_range(0x10220000, 0x1022ffff), /* SerDes */ + regmap_reg_range(0x10286000, 0x10286fff), /* RG Batcher */ + regmap_reg_range(0x1028c000, 0x1028ffff), /* ETHER_SYS */ + regmap_reg_range(0x30000000, 0x37ffffff), /* I2C EEPROM */ + regmap_reg_range(0x38000000, 0x3fffffff), /* BOOT_ROM */ + regmap_reg_range(0xa0000000, 0xbfffffff), /* GPHY */ +}; + +static const struct regmap_access_table an8855_readable_table = { + .yes_ranges = an8855_readable_ranges, + .n_yes_ranges = ARRAY_SIZE(an8855_readable_ranges), +}; + +static const struct regmap_config an8855_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0xbfffffff, + .reg_read = an8855_regmap_read, + .reg_write = an8855_regmap_write, + .reg_update_bits = an8855_regmap_update_bits, + .disable_locking = true, + .rd_table = &an8855_readable_table, +}; + +static int an8855_mfd_probe(struct mdio_device *mdiodev) +{ + struct an8855_mfd_priv *priv; + struct regmap *regmap; + + priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->bus = mdiodev->bus; + priv->dev = &mdiodev->dev; + priv->switch_addr = mdiodev->addr; + /* no DMA for mdiobus, mute warning for DMA mask not set */ + priv->dev->dma_mask = &priv->dev->coherent_dma_mask; + + regmap = devm_regmap_init(priv->dev, NULL, priv, + &an8855_regmap_config); + if (IS_ERR(regmap)) + dev_err_probe(priv->dev, PTR_ERR(priv->dev), + "regmap initialization failed\n"); + + dev_set_drvdata(&mdiodev->dev, priv); + + return devm_mfd_add_devices(priv->dev, PLATFORM_DEVID_AUTO, an8855_mfd_devs, + ARRAY_SIZE(an8855_mfd_devs), NULL, 0, + NULL); +} + +static const struct of_device_id an8855_mfd_of_match[] = { + { .compatible = "airoha,an8855-mfd" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, an8855_mfd_of_match); + +static struct mdio_driver an8855_mfd_driver = { + .probe = an8855_mfd_probe, + .mdiodrv.driver = { + .name = "an8855", + .of_match_table = an8855_mfd_of_match, + }, +}; +mdio_module_driver(an8855_mfd_driver); + +MODULE_AUTHOR("Christian Marangi "); +MODULE_DESCRIPTION("Driver for Airoha AN8855 MFD"); +MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/mediatek/files/drivers/net/dsa/an8855.c b/lede/target/linux/mediatek/files/drivers/net/dsa/an8855.c new file mode 100644 index 0000000000..7dd62e1a86 --- /dev/null +++ b/lede/target/linux/mediatek/files/drivers/net/dsa/an8855.c @@ -0,0 +1,2311 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Airoha AN8855 DSA Switch driver + * Copyright (C) 2023 Min Yao + * Copyright (C) 2024 Christian Marangi + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "an8855.h" + +static const struct an8855_mib_desc an8855_mib[] = { + MIB_DESC(1, AN8855_PORT_MIB_TX_DROP, "TxDrop"), + MIB_DESC(1, AN8855_PORT_MIB_TX_CRC_ERR, "TxCrcErr"), + MIB_DESC(1, AN8855_PORT_MIB_TX_COLLISION, "TxCollision"), + MIB_DESC(1, AN8855_PORT_MIB_TX_OVERSIZE_DROP, "TxOversizeDrop"), + MIB_DESC(2, AN8855_PORT_MIB_TX_BAD_PKT_BYTES, "TxBadPktBytes"), + MIB_DESC(1, AN8855_PORT_MIB_RX_DROP, "RxDrop"), + MIB_DESC(1, AN8855_PORT_MIB_RX_FILTERING, "RxFiltering"), + MIB_DESC(1, AN8855_PORT_MIB_RX_CRC_ERR, "RxCrcErr"), + MIB_DESC(1, AN8855_PORT_MIB_RX_CTRL_DROP, "RxCtrlDrop"), + MIB_DESC(1, AN8855_PORT_MIB_RX_INGRESS_DROP, "RxIngressDrop"), + MIB_DESC(1, AN8855_PORT_MIB_RX_ARL_DROP, "RxArlDrop"), + MIB_DESC(1, AN8855_PORT_MIB_FLOW_CONTROL_DROP, "FlowControlDrop"), + MIB_DESC(1, AN8855_PORT_MIB_WRED_DROP, "WredDrop"), + MIB_DESC(1, AN8855_PORT_MIB_MIRROR_DROP, "MirrorDrop"), + MIB_DESC(2, AN8855_PORT_MIB_RX_BAD_PKT_BYTES, "RxBadPktBytes"), + MIB_DESC(1, AN8855_PORT_MIB_RXS_FLOW_SAMPLING_PKT_DROP, "RxsFlowSamplingPktDrop"), + MIB_DESC(1, AN8855_PORT_MIB_RXS_FLOW_TOTAL_PKT_DROP, "RxsFlowTotalPktDrop"), + MIB_DESC(1, AN8855_PORT_MIB_PORT_CONTROL_DROP, "PortControlDrop"), +}; + +static int +an8855_mib_init(struct an8855_priv *priv) +{ + int ret; + + ret = regmap_write(priv->regmap, AN8855_MIB_CCR, + AN8855_CCR_MIB_ENABLE); + if (ret) + return ret; + + return regmap_write(priv->regmap, AN8855_MIB_CCR, + AN8855_CCR_MIB_ACTIVATE); +} + +static void an8855_fdb_write(struct an8855_priv *priv, u16 vid, + u8 port_mask, const u8 *mac, + bool add) __must_hold(&priv->reg_mutex) +{ + u32 mac_reg[2] = { }; + u32 reg; + + mac_reg[0] |= FIELD_PREP(AN8855_ATA1_MAC0, mac[0]); + mac_reg[0] |= FIELD_PREP(AN8855_ATA1_MAC1, mac[1]); + mac_reg[0] |= FIELD_PREP(AN8855_ATA1_MAC2, mac[2]); + mac_reg[0] |= FIELD_PREP(AN8855_ATA1_MAC3, mac[3]); + mac_reg[1] |= FIELD_PREP(AN8855_ATA2_MAC4, mac[4]); + mac_reg[1] |= FIELD_PREP(AN8855_ATA2_MAC5, mac[5]); + + regmap_bulk_write(priv->regmap, AN8855_ATA1, mac_reg, + ARRAY_SIZE(mac_reg)); + + reg = AN8855_ATWD_IVL; + if (add) + reg |= AN8855_ATWD_VLD; + reg |= FIELD_PREP(AN8855_ATWD_VID, vid); + reg |= FIELD_PREP(AN8855_ATWD_FID, AN8855_FID_BRIDGED); + regmap_write(priv->regmap, AN8855_ATWD, reg); + regmap_write(priv->regmap, AN8855_ATWD2, + FIELD_PREP(AN8855_ATWD2_PORT, port_mask)); +} + +static void an8855_fdb_read(struct an8855_priv *priv, struct an8855_fdb *fdb) +{ + u32 reg[4]; + + regmap_bulk_read(priv->regmap, AN8855_ATRD0, reg, + ARRAY_SIZE(reg)); + + fdb->live = FIELD_GET(AN8855_ATRD0_LIVE, reg[0]); + fdb->type = FIELD_GET(AN8855_ATRD0_TYPE, reg[0]); + fdb->ivl = FIELD_GET(AN8855_ATRD0_IVL, reg[0]); + fdb->vid = FIELD_GET(AN8855_ATRD0_VID, reg[0]); + fdb->fid = FIELD_GET(AN8855_ATRD0_FID, reg[0]); + fdb->aging = FIELD_GET(AN8855_ATRD1_AGING, reg[1]); + fdb->port_mask = FIELD_GET(AN8855_ATRD3_PORTMASK, reg[3]); + fdb->mac[0] = FIELD_GET(AN8855_ATRD2_MAC0, reg[2]); + fdb->mac[1] = FIELD_GET(AN8855_ATRD2_MAC1, reg[2]); + fdb->mac[2] = FIELD_GET(AN8855_ATRD2_MAC2, reg[2]); + fdb->mac[3] = FIELD_GET(AN8855_ATRD2_MAC3, reg[2]); + fdb->mac[4] = FIELD_GET(AN8855_ATRD1_MAC4, reg[1]); + fdb->mac[5] = FIELD_GET(AN8855_ATRD1_MAC5, reg[1]); + fdb->noarp = !!FIELD_GET(AN8855_ATRD0_ARP, reg[0]); +} + +static int an8855_fdb_cmd(struct an8855_priv *priv, u32 cmd, + u32 *rsp) __must_hold(&priv->reg_mutex) +{ + u32 val; + int ret; + + /* Set the command operating upon the MAC address entries */ + val = AN8855_ATC_BUSY | cmd; + ret = regmap_write(priv->regmap, AN8855_ATC, val); + if (ret) + return ret; + + ret = regmap_read_poll_timeout(priv->regmap, AN8855_ATC, val, + !(val & AN8855_ATC_BUSY), 20, 200000); + if (ret) + return ret; + + if (rsp) + *rsp = val; + + return 0; +} + +static void +an8855_port_stp_state_set(struct dsa_switch *ds, int port, u8 state) +{ + struct dsa_port *dp = dsa_to_port(ds, port); + struct an8855_priv *priv = ds->priv; + bool learning = false; + u32 stp_state; + + switch (state) { + case BR_STATE_DISABLED: + stp_state = AN8855_STP_DISABLED; + break; + case BR_STATE_BLOCKING: + stp_state = AN8855_STP_BLOCKING; + break; + case BR_STATE_LISTENING: + stp_state = AN8855_STP_LISTENING; + break; + case BR_STATE_LEARNING: + stp_state = AN8855_STP_LEARNING; + learning = dp->learning; + break; + case BR_STATE_FORWARDING: + learning = dp->learning; + fallthrough; + default: + stp_state = AN8855_STP_FORWARDING; + break; + } + + regmap_update_bits(priv->regmap, AN8855_SSP_P(port), + AN8855_FID_PST_MASK(AN8855_FID_BRIDGED), + AN8855_FID_PST_VAL(AN8855_FID_BRIDGED, stp_state)); + + regmap_update_bits(priv->regmap, AN8855_PSC_P(port), AN8855_SA_DIS, + learning ? 0 : AN8855_SA_DIS); +} + +static void an8855_port_fast_age(struct dsa_switch *ds, int port) +{ + struct an8855_priv *priv = ds->priv; + int ret; + + /* Set to clean Dynamic entry */ + ret = regmap_write(priv->regmap, AN8855_ATA2, AN8855_ATA2_TYPE); + if (ret) + return; + + /* Set Port */ + ret = regmap_write(priv->regmap, AN8855_ATWD2, + FIELD_PREP(AN8855_ATWD2_PORT, BIT(port))); + if (ret) + return; + + /* Flush Dynamic entry at port */ + an8855_fdb_cmd(priv, AN8855_ATC_MAT(AND8855_FDB_MAT_MAC_TYPE_PORT) | + AN8855_FDB_FLUSH, NULL); +} + +static int an8855_update_port_member(struct dsa_switch *ds, int port, + const struct net_device *bridge_dev, + bool join) +{ + struct an8855_priv *priv = ds->priv; + bool isolated, other_isolated; + struct dsa_port *dp; + u32 port_mask = 0; + int ret; + + isolated = !!(priv->port_isolated_map & BIT(port)); + + dsa_switch_for_each_user_port(dp, ds) { + if (dp->index == port) + continue; + + if (!dsa_port_offloads_bridge_dev(dp, bridge_dev)) + continue; + + other_isolated = !!(priv->port_isolated_map & BIT(dp->index)); + port_mask |= BIT(dp->index); + /* Add/remove this port to the portvlan mask of the other + * ports in the bridge + */ + if (join && !(isolated && other_isolated)) + ret = regmap_set_bits(priv->regmap, + AN8855_PORTMATRIX_P(dp->index), + FIELD_PREP(AN8855_USER_PORTMATRIX, + BIT(port))); + else + ret = regmap_clear_bits(priv->regmap, + AN8855_PORTMATRIX_P(dp->index), + FIELD_PREP(AN8855_USER_PORTMATRIX, + BIT(port))); + if (ret) + return ret; + } + + /* Add/remove all other ports to this port's portvlan mask */ + return regmap_update_bits(priv->regmap, AN8855_PORTMATRIX_P(port), + AN8855_USER_PORTMATRIX, + join ? port_mask : ~port_mask); +} + +static int an8855_port_pre_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack) +{ + if (flags.mask & ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | + BR_BCAST_FLOOD | BR_ISOLATED)) + return -EINVAL; + + return 0; +} + +static int an8855_port_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack) +{ + struct an8855_priv *priv = ds->priv; + int ret; + + if (flags.mask & BR_LEARNING) { + ret = regmap_update_bits(priv->regmap, AN8855_PSC_P(port), AN8855_SA_DIS, + flags.val & BR_LEARNING ? 0 : AN8855_SA_DIS); + if (ret) + return ret; + } + + if (flags.mask & BR_FLOOD) { + ret = regmap_update_bits(priv->regmap, AN8855_UNUF, BIT(port), + flags.val & BR_FLOOD ? BIT(port) : 0); + if (ret) + return ret; + } + + if (flags.mask & BR_MCAST_FLOOD) { + ret = regmap_update_bits(priv->regmap, AN8855_UNMF, BIT(port), + flags.val & BR_MCAST_FLOOD ? BIT(port) : 0); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, AN8855_UNIPMF, BIT(port), + flags.val & BR_MCAST_FLOOD ? BIT(port) : 0); + if (ret) + return ret; + } + + if (flags.mask & BR_BCAST_FLOOD) { + ret = regmap_update_bits(priv->regmap, AN8855_BCF, BIT(port), + flags.val & BR_BCAST_FLOOD ? BIT(port) : 0); + if (ret) + return ret; + } + + if (flags.mask & BR_ISOLATED) { + struct dsa_port *dp = dsa_to_port(ds, port); + struct net_device *bridge_dev = dsa_port_bridge_dev_get(dp); + + if (flags.val & BR_ISOLATED) + priv->port_isolated_map |= BIT(port); + else + priv->port_isolated_map &= ~BIT(port); + + ret = an8855_update_port_member(ds, port, bridge_dev, true); + if (ret) + return ret; + } + + return 0; +} + +static int an8855_set_ageing_time(struct dsa_switch *ds, unsigned int msecs) +{ + struct an8855_priv *priv = ds->priv; + u32 age_count, age_unit, val; + + /* Convert msec in AN8855_L2_AGING_MS_CONSTANT counter */ + val = msecs / AN8855_L2_AGING_MS_CONSTANT; + /* Derive the count unit */ + age_unit = val / FIELD_MAX(AN8855_AGE_UNIT); + /* Get the count in unit, age_unit is always incremented by 1 internally */ + age_count = val / (age_unit + 1); + + return regmap_update_bits(priv->regmap, AN8855_AAC, + AN8855_AGE_CNT | AN8855_AGE_UNIT, + FIELD_PREP(AN8855_AGE_CNT, age_count) | + FIELD_PREP(AN8855_AGE_UNIT, age_unit)); +} + +static int an8855_port_bridge_join(struct dsa_switch *ds, int port, + struct dsa_bridge bridge, + bool *tx_fwd_offload, + struct netlink_ext_ack *extack) +{ + struct an8855_priv *priv = ds->priv; + int ret; + + ret = an8855_update_port_member(ds, port, bridge.dev, true); + if (ret) + return ret; + + /* Set to fallback mode for independent VLAN learning if in a bridge */ + return regmap_update_bits(priv->regmap, AN8855_PCR_P(port), + AN8855_PORT_VLAN, + FIELD_PREP(AN8855_PORT_VLAN, + AN8855_PORT_FALLBACK_MODE)); +} + +static void an8855_port_bridge_leave(struct dsa_switch *ds, int port, + struct dsa_bridge bridge) +{ + struct an8855_priv *priv = ds->priv; + + an8855_update_port_member(ds, port, bridge.dev, false); + + /* When a port is removed from the bridge, the port would be set up + * back to the default as is at initial boot which is a VLAN-unaware + * port. + */ + regmap_update_bits(priv->regmap, AN8855_PCR_P(port), + AN8855_PORT_VLAN, + FIELD_PREP(AN8855_PORT_VLAN, + AN8855_PORT_MATRIX_MODE)); +} + +static int an8855_port_fdb_add(struct dsa_switch *ds, int port, + const unsigned char *addr, u16 vid, + struct dsa_db db) +{ + struct an8855_priv *priv = ds->priv; + u8 port_mask = BIT(port); + int ret; + + /* Set the vid to the port vlan id if no vid is set */ + if (!vid) + vid = AN8855_PORT_VID_DEFAULT; + + mutex_lock(&priv->reg_mutex); + an8855_fdb_write(priv, vid, port_mask, addr, true); + ret = an8855_fdb_cmd(priv, AN8855_FDB_WRITE, NULL); + mutex_unlock(&priv->reg_mutex); + + return ret; +} + +static int an8855_port_fdb_del(struct dsa_switch *ds, int port, + const unsigned char *addr, u16 vid, + struct dsa_db db) +{ + struct an8855_priv *priv = ds->priv; + u8 port_mask = BIT(port); + int ret; + + /* Set the vid to the port vlan id if no vid is set */ + if (!vid) + vid = AN8855_PORT_VID_DEFAULT; + + mutex_lock(&priv->reg_mutex); + an8855_fdb_write(priv, vid, port_mask, addr, false); + ret = an8855_fdb_cmd(priv, AN8855_FDB_WRITE, NULL); + mutex_unlock(&priv->reg_mutex); + + return ret; +} + +static int an8855_port_fdb_dump(struct dsa_switch *ds, int port, + dsa_fdb_dump_cb_t *cb, void *data) +{ + struct an8855_priv *priv = ds->priv; + int banks, count = 0; + u32 rsp; + int ret; + int i; + + mutex_lock(&priv->reg_mutex); + + /* Load search port */ + ret = regmap_write(priv->regmap, AN8855_ATWD2, + FIELD_PREP(AN8855_ATWD2_PORT, BIT(port))); + if (ret) + goto exit; + ret = an8855_fdb_cmd(priv, AN8855_ATC_MAT(AND8855_FDB_MAT_MAC_PORT) | + AN8855_FDB_START, &rsp); + if (ret < 0) + goto exit; + + do { + /* From response get the number of banks to read, exit if 0 */ + banks = FIELD_GET(AN8855_ATC_HIT, rsp); + if (!banks) + break; + + /* Each banks have 4 entry */ + for (i = 0; i < 4; i++) { + struct an8855_fdb _fdb = { }; + + count++; + + /* Check if bank is present */ + if (!(banks & BIT(i))) + continue; + + /* Select bank entry index */ + ret = regmap_write(priv->regmap, AN8855_ATRDS, + FIELD_PREP(AN8855_ATRD_SEL, i)); + if (ret) + break; + /* wait 1ms for the bank entry to be filled */ + usleep_range(1000, 1500); + an8855_fdb_read(priv, &_fdb); + + if (!_fdb.live) + continue; + ret = cb(_fdb.mac, _fdb.vid, _fdb.noarp, data); + if (ret < 0) + break; + } + + /* Stop if reached max FDB number */ + if (count >= AN8855_NUM_FDB_RECORDS) + break; + + /* Read next bank */ + ret = an8855_fdb_cmd(priv, AN8855_ATC_MAT(AND8855_FDB_MAT_MAC_PORT) | + AN8855_FDB_NEXT, &rsp); + if (ret < 0) + break; + } while (true); + +exit: + mutex_unlock(&priv->reg_mutex); + return ret; +} + +static int an8855_vlan_cmd(struct an8855_priv *priv, enum an8855_vlan_cmd cmd, + u16 vid) __must_hold(&priv->reg_mutex) +{ + u32 val; + int ret; + + val = AN8855_VTCR_BUSY | FIELD_PREP(AN8855_VTCR_FUNC, cmd) | + FIELD_PREP(AN8855_VTCR_VID, vid); + ret = regmap_write(priv->regmap, AN8855_VTCR, val); + if (ret) + return ret; + + return regmap_read_poll_timeout(priv->regmap, AN8855_VTCR, val, + !(val & AN8855_VTCR_BUSY), 20, 200000); +} + +static int an8855_vlan_add(struct an8855_priv *priv, u8 port, u16 vid, + bool untagged) __must_hold(&priv->reg_mutex) +{ + u32 port_mask; + u32 val; + int ret; + + /* Fetch entry */ + ret = an8855_vlan_cmd(priv, AN8855_VTCR_RD_VID, vid); + if (ret) + return ret; + + ret = regmap_read(priv->regmap, AN8855_VARD0, &val); + if (ret) + return ret; + port_mask = FIELD_GET(AN8855_VA0_PORT, val) | BIT(port); + + /* Validate the entry with independent learning, create egress tag per + * VLAN and joining the port as one of the port members. + */ + val = (val & AN8855_VA0_ETAG) | AN8855_VA0_IVL_MAC | + AN8855_VA0_VTAG_EN | AN8855_VA0_VLAN_VALID | + FIELD_PREP(AN8855_VA0_PORT, port_mask) | + FIELD_PREP(AN8855_VA0_FID, AN8855_FID_BRIDGED); + ret = regmap_write(priv->regmap, AN8855_VAWD0, val); + if (ret) + return ret; + ret = regmap_write(priv->regmap, AN8855_VAWD1, 0); + if (ret) + return ret; + + /* CPU port is always taken as a tagged port for serving more than one + * VLANs across and also being applied with egress type stack mode for + * that VLAN tags would be appended after hardware special tag used as + * DSA tag. + */ + if (port == AN8855_CPU_PORT) + val = AN8855_VLAN_EGRESS_STACK; + /* Decide whether adding tag or not for those outgoing packets from the + * port inside the VLAN. + */ + else + val = untagged ? AN8855_VLAN_EGRESS_UNTAG : AN8855_VLAN_EGRESS_TAG; + ret = regmap_update_bits(priv->regmap, AN8855_VAWD0, + AN8855_VA0_ETAG_PORT_MASK(port), + AN8855_VA0_ETAG_PORT_VAL(port, val)); + if (ret) + return ret; + + /* Flush result to hardware */ + return an8855_vlan_cmd(priv, AN8855_VTCR_WR_VID, vid); +} + +static int an8855_vlan_del(struct an8855_priv *priv, u8 port, + u16 vid) __must_hold(&priv->reg_mutex) +{ + u32 port_mask; + u32 val; + int ret; + + /* Fetch entry */ + ret = an8855_vlan_cmd(priv, AN8855_VTCR_RD_VID, vid); + if (ret) + return ret; + + ret = regmap_read(priv->regmap, AN8855_VARD0, &val); + if (ret) + return ret; + port_mask = FIELD_GET(AN8855_VA0_PORT, val) & ~BIT(port); + + if (!(val & AN8855_VA0_VLAN_VALID)) { + dev_err(priv->dev, "Cannot be deleted due to invalid entry\n"); + return -EINVAL; + } + + if (port_mask) { + val = (val & AN8855_VA0_ETAG) | AN8855_VA0_IVL_MAC | + AN8855_VA0_VTAG_EN | AN8855_VA0_VLAN_VALID | + FIELD_PREP(AN8855_VA0_PORT, port_mask); + ret = regmap_write(priv->regmap, AN8855_VAWD0, val); + if (ret) + return ret; + } else { + ret = regmap_write(priv->regmap, AN8855_VAWD0, 0); + if (ret) + return ret; + } + ret = regmap_write(priv->regmap, AN8855_VAWD1, 0); + if (ret) + return ret; + + /* Flush result to hardware */ + return an8855_vlan_cmd(priv, AN8855_VTCR_WR_VID, vid); +} + +static int an8855_port_set_vlan_mode(struct an8855_priv *priv, int port, + enum an8855_port_mode port_mode, + enum an8855_vlan_port_eg_tag eg_tag, + enum an8855_vlan_port_attr vlan_attr, + enum an8855_vlan_port_acc_frm acc_frm) +{ + int ret; + + ret = regmap_update_bits(priv->regmap, AN8855_PCR_P(port), + AN8855_PORT_VLAN, + FIELD_PREP(AN8855_PORT_VLAN, port_mode)); + if (ret) + return ret; + + return regmap_update_bits(priv->regmap, AN8855_PVC_P(port), + AN8855_PVC_EG_TAG | AN8855_VLAN_ATTR | AN8855_ACC_FRM, + FIELD_PREP(AN8855_PVC_EG_TAG, eg_tag) | + FIELD_PREP(AN8855_VLAN_ATTR, vlan_attr) | + FIELD_PREP(AN8855_ACC_FRM, acc_frm)); +} + +static int an8855_port_set_pid(struct an8855_priv *priv, int port, + u16 pid) +{ + int ret; + + ret = regmap_update_bits(priv->regmap, AN8855_PPBV1_P(port), + AN8855_PPBV_G0_PORT_VID, + FIELD_PREP(AN8855_PPBV_G0_PORT_VID, pid)); + if (ret) + return ret; + + return regmap_update_bits(priv->regmap, AN8855_PVID_P(port), + AN8855_G0_PORT_VID, + FIELD_PREP(AN8855_G0_PORT_VID, pid)); +} + +static int an8855_port_vlan_filtering(struct dsa_switch *ds, int port, + bool vlan_filtering, + struct netlink_ext_ack *extack) +{ + struct an8855_priv *priv = ds->priv; + u32 val; + int ret; + + /* The port is being kept as VLAN-unaware port when bridge is + * set up with vlan_filtering not being set, Otherwise, the + * port and the corresponding CPU port is required the setup + * for becoming a VLAN-aware port. + */ + if (vlan_filtering) { + u32 acc_frm; + /* CPU port is set to fallback mode to let untagged + * frames pass through. + */ + ret = an8855_port_set_vlan_mode(priv, AN8855_CPU_PORT, + AN8855_PORT_FALLBACK_MODE, + AN8855_VLAN_EG_CONSISTENT, + AN8855_VLAN_USER, + AN8855_VLAN_ACC_ALL); + if (ret) + return ret; + + ret = regmap_read(priv->regmap, AN8855_PVID_P(port), &val); + if (ret) + return ret; + + /* Only accept tagged frames if PVID is not set */ + if (FIELD_GET(AN8855_G0_PORT_VID, val) != AN8855_PORT_VID_DEFAULT) + acc_frm = AN8855_VLAN_ACC_TAGGED; + else + acc_frm = AN8855_VLAN_ACC_ALL; + + /* Trapped into security mode allows packet forwarding through VLAN + * table lookup. + * Set the port as a user port which is to be able to recognize VID + * from incoming packets before fetching entry within the VLAN table. + */ + ret = an8855_port_set_vlan_mode(priv, port, + AN8855_PORT_SECURITY_MODE, + AN8855_VLAN_EG_DISABLED, + AN8855_VLAN_USER, + acc_frm); + if (ret) + return ret; + } else { + bool disable_cpu_vlan = true; + struct dsa_port *dp; + u32 port_mode; + + /* This is called after .port_bridge_leave when leaving a VLAN-aware + * bridge. Don't set standalone ports to fallback mode. + */ + if (dsa_port_bridge_dev_get(dsa_to_port(ds, port))) + port_mode = AN8855_PORT_FALLBACK_MODE; + else + port_mode = AN8855_PORT_MATRIX_MODE; + + /* When a port is removed from the bridge, the port would be set up + * back to the default as is at initial boot which is a VLAN-unaware + * port. + */ + ret = an8855_port_set_vlan_mode(priv, port, port_mode, + AN8855_VLAN_EG_CONSISTENT, + AN8855_VLAN_TRANSPARENT, + AN8855_VLAN_ACC_ALL); + if (ret) + return ret; + + /* Restore default PVID */ + ret = an8855_port_set_pid(priv, port, AN8855_PORT_VID_DEFAULT); + if (ret) + return ret; + + dsa_switch_for_each_user_port(dp, ds) { + if (dsa_port_is_vlan_filtering(dp)) { + disable_cpu_vlan = false; + break; + } + } + + if (disable_cpu_vlan) { + ret = an8855_port_set_vlan_mode(priv, AN8855_CPU_PORT, + AN8855_PORT_MATRIX_MODE, + AN8855_VLAN_EG_CONSISTENT, + AN8855_VLAN_USER, + AN8855_VLAN_ACC_ALL); + if (ret) + return ret; + } + } + + return 0; +} + +static int an8855_port_vlan_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan, + struct netlink_ext_ack *extack) +{ + bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; + bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; + struct an8855_priv *priv = ds->priv; + u32 val; + int ret; + + mutex_lock(&priv->reg_mutex); + ret = an8855_vlan_add(priv, port, vlan->vid, untagged); + mutex_unlock(&priv->reg_mutex); + if (ret) + return ret; + + if (pvid) { + /* Accept all frames if PVID is set */ + regmap_update_bits(priv->regmap, AN8855_PVC_P(port), AN8855_ACC_FRM, + FIELD_PREP(AN8855_ACC_FRM, AN8855_VLAN_ACC_ALL)); + + /* Only configure PVID if VLAN filtering is enabled */ + if (dsa_port_is_vlan_filtering(dsa_to_port(ds, port))) { + ret = an8855_port_set_pid(priv, port, vlan->vid); + if (ret) + return ret; + } + } else if (vlan->vid) { + ret = regmap_read(priv->regmap, AN8855_PVID_P(port), &val); + if (ret) + return ret; + + if (FIELD_GET(AN8855_G0_PORT_VID, val) != vlan->vid) + return 0; + + /* This VLAN is overwritten without PVID, so unset it */ + if (dsa_port_is_vlan_filtering(dsa_to_port(ds, port))) { + ret = regmap_update_bits(priv->regmap, AN8855_PVC_P(port), + AN8855_ACC_FRM, + FIELD_PREP(AN8855_ACC_FRM, + AN8855_VLAN_ACC_TAGGED)); + if (ret) + return ret; + } + + ret = an8855_port_set_pid(priv, port, AN8855_PORT_VID_DEFAULT); + if (ret) + return ret; + } + + return 0; +} + +static int an8855_port_vlan_del(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_vlan *vlan) +{ + struct an8855_priv *priv = ds->priv; + u32 val; + int ret; + + mutex_lock(&priv->reg_mutex); + ret = an8855_vlan_del(priv, port, vlan->vid); + mutex_unlock(&priv->reg_mutex); + if (ret) + return ret; + + ret = regmap_read(priv->regmap, AN8855_PVID_P(port), &val); + if (ret) + return ret; + + /* PVID is being restored to the default whenever the PVID port + * is being removed from the VLAN. + */ + if (FIELD_GET(AN8855_G0_PORT_VID, val) == vlan->vid) { + /* Only accept tagged frames if the port is VLAN-aware */ + if (dsa_port_is_vlan_filtering(dsa_to_port(ds, port))) { + ret = regmap_update_bits(priv->regmap, AN8855_PVC_P(port), + AN8855_ACC_FRM, + FIELD_PREP(AN8855_ACC_FRM, + AN8855_VLAN_ACC_TAGGED)); + if (ret) + return ret; + } + + ret = an8855_port_set_pid(priv, port, AN8855_PORT_VID_DEFAULT); + if (ret) + return ret; + } + + return 0; +} + +static int +an8855_port_mdb_add(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_mdb *mdb, + struct dsa_db db) +{ + struct an8855_priv *priv = ds->priv; + const u8 *addr = mdb->addr; + u16 vid = mdb->vid; + u8 port_mask = 0; + u32 val; + int ret; + + /* Set the vid to the port vlan id if no vid is set */ + if (!vid) + vid = AN8855_PORT_VID_DEFAULT; + + mutex_lock(&priv->reg_mutex); + + an8855_fdb_write(priv, vid, 0, addr, false); + if (!an8855_fdb_cmd(priv, AN8855_FDB_READ, NULL)) { + ret = regmap_read(priv->regmap, AN8855_ATRD3, &val); + if (ret) + goto exit; + + port_mask = FIELD_GET(AN8855_ATRD3_PORTMASK, val); + } + + port_mask |= BIT(port); + an8855_fdb_write(priv, vid, port_mask, addr, true); + ret = an8855_fdb_cmd(priv, AN8855_FDB_WRITE, NULL); + +exit: + mutex_unlock(&priv->reg_mutex); + + return ret; +} + +static int +an8855_port_mdb_del(struct dsa_switch *ds, int port, + const struct switchdev_obj_port_mdb *mdb, + struct dsa_db db) +{ + struct an8855_priv *priv = ds->priv; + const u8 *addr = mdb->addr; + u16 vid = mdb->vid; + u8 port_mask = 0; + u32 val; + int ret; + + /* Set the vid to the port vlan id if no vid is set */ + if (!vid) + vid = AN8855_PORT_VID_DEFAULT; + + mutex_lock(&priv->reg_mutex); + + an8855_fdb_write(priv, vid, 0, addr, 0); + if (!an8855_fdb_cmd(priv, AN8855_FDB_READ, NULL)) { + ret = regmap_read(priv->regmap, AN8855_ATRD3, &val); + if (ret) + goto exit; + + port_mask = FIELD_GET(AN8855_ATRD3_PORTMASK, val); + } + + port_mask &= ~BIT(port); + an8855_fdb_write(priv, vid, port_mask, addr, port_mask ? true : false); + ret = an8855_fdb_cmd(priv, AN8855_FDB_WRITE, NULL); + +exit: + mutex_unlock(&priv->reg_mutex); + + return ret; +} + +static int +an8855_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu) +{ + struct an8855_priv *priv = ds->priv; + int length; + u32 val; + + /* When a new MTU is set, DSA always set the CPU port's MTU to the + * largest MTU of the slave ports. Because the switch only has a global + * RX length register, only allowing CPU port here is enough. + */ + if (!dsa_is_cpu_port(ds, port)) + return 0; + + /* RX length also includes Ethernet header, MTK tag, and FCS length */ + length = new_mtu + ETH_HLEN + MTK_TAG_LEN + ETH_FCS_LEN; + if (length <= 1522) + val = AN8855_MAX_RX_PKT_1518_1522; + else if (length <= 1536) + val = AN8855_MAX_RX_PKT_1536; + else if (length <= 1552) + val = AN8855_MAX_RX_PKT_1552; + else if (length <= 3072) + val = AN8855_MAX_RX_JUMBO_3K; + else if (length <= 4096) + val = AN8855_MAX_RX_JUMBO_4K; + else if (length <= 5120) + val = AN8855_MAX_RX_JUMBO_5K; + else if (length <= 6144) + val = AN8855_MAX_RX_JUMBO_6K; + else if (length <= 7168) + val = AN8855_MAX_RX_JUMBO_7K; + else if (length <= 8192) + val = AN8855_MAX_RX_JUMBO_8K; + else if (length <= 9216) + val = AN8855_MAX_RX_JUMBO_9K; + else if (length <= 12288) + val = AN8855_MAX_RX_JUMBO_12K; + else if (length <= 15360) + val = AN8855_MAX_RX_JUMBO_15K; + else + val = AN8855_MAX_RX_JUMBO_16K; + + /* Enable JUMBO packet */ + if (length > 1552) + val |= AN8855_MAX_RX_PKT_JUMBO; + + return regmap_update_bits(priv->regmap, AN8855_GMACCR, + AN8855_MAX_RX_JUMBO | AN8855_MAX_RX_PKT_LEN, + val); +} + +static int +an8855_port_max_mtu(struct dsa_switch *ds, int port) +{ + return AN8855_MAX_MTU; +} + +static void +an8855_get_strings(struct dsa_switch *ds, int port, u32 stringset, + uint8_t *data) +{ + int i; + + if (stringset != ETH_SS_STATS) + return; + + for (i = 0; i < ARRAY_SIZE(an8855_mib); i++) + ethtool_puts(&data, an8855_mib[i].name); +} + +static void +an8855_read_port_stats(struct an8855_priv *priv, int port, u32 offset, u8 size, + uint64_t *data) +{ + u32 val, reg = AN8855_PORT_MIB_COUNTER(port) + offset; + + regmap_read(priv->regmap, reg, &val); + *data = val; + + if (size == 2) { + regmap_read(priv->regmap, reg + 4, &val); + *data |= (u64)val << 32; + } +} + +static void +an8855_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data) +{ + struct an8855_priv *priv = ds->priv; + const struct an8855_mib_desc *mib; + int i; + + for (i = 0; i < ARRAY_SIZE(an8855_mib); i++) { + mib = &an8855_mib[i]; + + an8855_read_port_stats(priv, port, mib->offset, mib->size, + data + i); + } +} + +static int +an8855_get_sset_count(struct dsa_switch *ds, int port, int sset) +{ + if (sset != ETH_SS_STATS) + return 0; + + return ARRAY_SIZE(an8855_mib); +} + +static void +an8855_get_eth_mac_stats(struct dsa_switch *ds, int port, + struct ethtool_eth_mac_stats *mac_stats) +{ + struct an8855_priv *priv = ds->priv; + + /* MIB counter doesn't provide a FramesTransmittedOK but instead + * provide stats for Unicast, Broadcast and Multicast frames separately. + * To simulate a global frame counter, read Unicast and addition Multicast + * and Broadcast later + */ + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_UNICAST, 1, + &mac_stats->FramesTransmittedOK); + + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_SINGLE_COLLISION, 1, + &mac_stats->SingleCollisionFrames); + + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_MULTIPLE_COLLISION, 1, + &mac_stats->MultipleCollisionFrames); + + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_UNICAST, 1, + &mac_stats->FramesReceivedOK); + + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_BYTES, 2, + &mac_stats->OctetsTransmittedOK); + + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_ALIGN_ERR, 1, + &mac_stats->AlignmentErrors); + + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_DEFERRED, 1, + &mac_stats->FramesWithDeferredXmissions); + + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_LATE_COLLISION, 1, + &mac_stats->LateCollisions); + + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_EXCESSIVE_COLLISION, 1, + &mac_stats->FramesAbortedDueToXSColls); + + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_BYTES, 2, + &mac_stats->OctetsReceivedOK); + + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_MULTICAST, 1, + &mac_stats->MulticastFramesXmittedOK); + mac_stats->FramesTransmittedOK += mac_stats->MulticastFramesXmittedOK; + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_BROADCAST, 1, + &mac_stats->BroadcastFramesXmittedOK); + mac_stats->FramesTransmittedOK += mac_stats->BroadcastFramesXmittedOK; + + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_MULTICAST, 1, + &mac_stats->MulticastFramesReceivedOK); + mac_stats->FramesReceivedOK += mac_stats->MulticastFramesReceivedOK; + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_BROADCAST, 1, + &mac_stats->BroadcastFramesReceivedOK); + mac_stats->FramesReceivedOK += mac_stats->BroadcastFramesReceivedOK; +} + +static const struct ethtool_rmon_hist_range an8855_rmon_ranges[] = { + { 0, 64 }, + { 65, 127 }, + { 128, 255 }, + { 256, 511 }, + { 512, 1023 }, + { 1024, 1518 }, + { 1519, AN8855_MAX_MTU }, + {} +}; + +static void an8855_get_rmon_stats(struct dsa_switch *ds, int port, + struct ethtool_rmon_stats *rmon_stats, + const struct ethtool_rmon_hist_range **ranges) +{ + struct an8855_priv *priv = ds->priv; + + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_UNDER_SIZE_ERR, 1, + &rmon_stats->undersize_pkts); + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_OVER_SZ_ERR, 1, + &rmon_stats->oversize_pkts); + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_FRAG_ERR, 1, + &rmon_stats->fragments); + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_JABBER_ERR, 1, + &rmon_stats->jabbers); + + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_PKT_SZ_64, 1, + &rmon_stats->hist[0]); + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_PKT_SZ_65_TO_127, 1, + &rmon_stats->hist[1]); + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_PKT_SZ_128_TO_255, 1, + &rmon_stats->hist[2]); + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_PKT_SZ_256_TO_511, 1, + &rmon_stats->hist[3]); + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_PKT_SZ_512_TO_1023, 1, + &rmon_stats->hist[4]); + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_PKT_SZ_1024_TO_1518, 1, + &rmon_stats->hist[5]); + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_PKT_SZ_1519_TO_MAX, 1, + &rmon_stats->hist[6]); + + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_PKT_SZ_64, 1, + &rmon_stats->hist_tx[0]); + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_PKT_SZ_65_TO_127, 1, + &rmon_stats->hist_tx[1]); + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_PKT_SZ_128_TO_255, 1, + &rmon_stats->hist_tx[2]); + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_PKT_SZ_256_TO_511, 1, + &rmon_stats->hist_tx[3]); + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_PKT_SZ_512_TO_1023, 1, + &rmon_stats->hist_tx[4]); + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_PKT_SZ_1024_TO_1518, 1, + &rmon_stats->hist_tx[5]); + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_PKT_SZ_1519_TO_MAX, 1, + &rmon_stats->hist_tx[6]); + + *ranges = an8855_rmon_ranges; +} + +static void an8855_get_eth_ctrl_stats(struct dsa_switch *ds, int port, + struct ethtool_eth_ctrl_stats *ctrl_stats) +{ + struct an8855_priv *priv = ds->priv; + + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_TX_PAUSE, 1, + &ctrl_stats->MACControlFramesTransmitted); + + an8855_read_port_stats(priv, port, AN8855_PORT_MIB_RX_PAUSE, 1, + &ctrl_stats->MACControlFramesReceived); +} + +static int an8855_port_mirror_add(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror, + bool ingress, + struct netlink_ext_ack *extack) +{ + struct an8855_priv *priv = ds->priv; + int monitor_port; + u32 val; + int ret; + + /* Check for existent entry */ + if ((ingress ? priv->mirror_rx : priv->mirror_tx) & BIT(port)) + return -EEXIST; + + ret = regmap_read(priv->regmap, AN8855_MIR, &val); + if (ret) + return ret; + + /* AN8855 supports 4 monitor port, but only use first group */ + monitor_port = FIELD_GET(AN8855_MIRROR_PORT, val); + if (val & AN8855_MIRROR_EN && monitor_port != mirror->to_local_port) + return -EEXIST; + + val = AN8855_MIRROR_EN; + val |= FIELD_PREP(AN8855_MIRROR_PORT, mirror->to_local_port); + ret = regmap_update_bits(priv->regmap, AN8855_MIR, + AN8855_MIRROR_EN | AN8855_MIRROR_PORT, + val); + if (ret) + return ret; + + ret = regmap_set_bits(priv->regmap, AN8855_PCR_P(port), + ingress ? AN8855_PORT_RX_MIR : AN8855_PORT_TX_MIR); + if (ret) + return ret; + + if (ingress) + priv->mirror_rx |= BIT(port); + else + priv->mirror_tx |= BIT(port); + + return 0; +} + +static void an8855_port_mirror_del(struct dsa_switch *ds, int port, + struct dsa_mall_mirror_tc_entry *mirror) +{ + struct an8855_priv *priv = ds->priv; + + if (mirror->ingress) + priv->mirror_rx &= ~BIT(port); + else + priv->mirror_tx &= ~BIT(port); + + regmap_clear_bits(priv->regmap, AN8855_PCR_P(port), + mirror->ingress ? AN8855_PORT_RX_MIR : + AN8855_PORT_TX_MIR); + + if (!priv->mirror_rx && !priv->mirror_tx) + regmap_clear_bits(priv->regmap, AN8855_MIR, AN8855_MIRROR_EN); +} + +static int an8855_port_set_status(struct an8855_priv *priv, int port, + bool enable) +{ + if (enable) + return regmap_set_bits(priv->regmap, AN8855_PMCR_P(port), + AN8855_PMCR_TX_EN | AN8855_PMCR_RX_EN); + else + return regmap_clear_bits(priv->regmap, AN8855_PMCR_P(port), + AN8855_PMCR_TX_EN | AN8855_PMCR_RX_EN); +} + +static int an8855_port_enable(struct dsa_switch *ds, int port, + struct phy_device *phy) +{ + return an8855_port_set_status(ds->priv, port, true); +} + +static void an8855_port_disable(struct dsa_switch *ds, int port) +{ + an8855_port_set_status(ds->priv, port, false); +} + +static u32 en8855_get_phy_flags(struct dsa_switch *ds, int port) +{ + struct an8855_priv *priv = ds->priv; + + /* PHY doesn't need calibration */ + if (!priv->phy_require_calib) + return 0; + + /* Use AN8855_PHY_FLAGS_EN_CALIBRATION to signal + * calibration needed. + */ + return AN8855_PHY_FLAGS_EN_CALIBRATION; +} + +static enum dsa_tag_protocol +an8855_get_tag_protocol(struct dsa_switch *ds, int port, + enum dsa_tag_protocol mp) +{ + return DSA_TAG_PROTO_MTK; +} + +/* Similar to MT7530 also trap link local frame and special frame to CPU */ +static int an8855_trap_special_frames(struct an8855_priv *priv) +{ + int ret; + + /* Trap BPDUs to the CPU port(s) and egress them + * VLAN-untagged. + */ + ret = regmap_update_bits(priv->regmap, AN8855_BPC, + AN8855_BPDU_BPDU_FR | AN8855_BPDU_EG_TAG | + AN8855_BPDU_PORT_FW, + AN8855_BPDU_BPDU_FR | + FIELD_PREP(AN8855_BPDU_EG_TAG, AN8855_VLAN_EG_UNTAGGED) | + FIELD_PREP(AN8855_BPDU_PORT_FW, AN8855_BPDU_CPU_ONLY)); + if (ret) + return ret; + + /* Trap 802.1X PAE frames to the CPU port(s) and egress them + * VLAN-untagged. + */ + ret = regmap_update_bits(priv->regmap, AN8855_PAC, + AN8855_PAE_BPDU_FR | AN8855_PAE_EG_TAG | + AN8855_PAE_PORT_FW, + AN8855_PAE_BPDU_FR | + FIELD_PREP(AN8855_PAE_EG_TAG, AN8855_VLAN_EG_UNTAGGED) | + FIELD_PREP(AN8855_PAE_PORT_FW, AN8855_BPDU_CPU_ONLY)); + if (ret) + return ret; + + /* Trap frames with :01 MAC DAs to the CPU port(s) and egress + * them VLAN-untagged. + */ + ret = regmap_update_bits(priv->regmap, AN8855_RGAC1, + AN8855_R01_BPDU_FR | AN8855_R01_EG_TAG | + AN8855_R01_PORT_FW, + AN8855_R01_BPDU_FR | + FIELD_PREP(AN8855_R01_EG_TAG, AN8855_VLAN_EG_UNTAGGED) | + FIELD_PREP(AN8855_R01_PORT_FW, AN8855_BPDU_CPU_ONLY)); + if (ret) + return ret; + + /* Trap frames with :02 MAC DAs to the CPU port(s) and egress + * them VLAN-untagged. + */ + ret = regmap_update_bits(priv->regmap, AN8855_RGAC1, + AN8855_R02_BPDU_FR | AN8855_R02_EG_TAG | + AN8855_R02_PORT_FW, + AN8855_R02_BPDU_FR | + FIELD_PREP(AN8855_R02_EG_TAG, AN8855_VLAN_EG_UNTAGGED) | + FIELD_PREP(AN8855_R02_PORT_FW, AN8855_BPDU_CPU_ONLY)); + if (ret) + return ret; + + /* Trap frames with :03 MAC DAs to the CPU port(s) and egress + * them VLAN-untagged. + */ + ret = regmap_update_bits(priv->regmap, AN8855_RGAC1, + AN8855_R03_BPDU_FR | AN8855_R03_EG_TAG | + AN8855_R03_PORT_FW, + AN8855_R03_BPDU_FR | + FIELD_PREP(AN8855_R03_EG_TAG, AN8855_VLAN_EG_UNTAGGED) | + FIELD_PREP(AN8855_R03_PORT_FW, AN8855_BPDU_CPU_ONLY)); + if (ret) + return ret; + + /* Trap frames with :0E MAC DAs to the CPU port(s) and egress + * them VLAN-untagged. + */ + return regmap_update_bits(priv->regmap, AN8855_RGAC1, + AN8855_R0E_BPDU_FR | AN8855_R0E_EG_TAG | + AN8855_R0E_PORT_FW, + AN8855_R0E_BPDU_FR | + FIELD_PREP(AN8855_R0E_EG_TAG, AN8855_VLAN_EG_UNTAGGED) | + FIELD_PREP(AN8855_R0E_PORT_FW, AN8855_BPDU_CPU_ONLY)); +} + +static int +an8855_setup_pvid_vlan(struct an8855_priv *priv) +{ + u32 val; + int ret; + + /* Validate the entry with independent learning, keep the original + * ingress tag attribute. + */ + val = AN8855_VA0_IVL_MAC | AN8855_VA0_EG_CON | + FIELD_PREP(AN8855_VA0_FID, AN8855_FID_BRIDGED) | + AN8855_VA0_PORT | AN8855_VA0_VLAN_VALID; + ret = regmap_write(priv->regmap, AN8855_VAWD0, val); + if (ret) + return ret; + + return an8855_vlan_cmd(priv, AN8855_VTCR_WR_VID, + AN8855_PORT_VID_DEFAULT); +} + +static int an8855_setup(struct dsa_switch *ds) +{ + struct an8855_priv *priv = ds->priv; + struct dsa_port *dp; + int ret; + + /* Enable and reset MIB counters */ + ret = an8855_mib_init(priv); + if (ret) + return ret; + + dsa_switch_for_each_user_port(dp, ds) { + /* Disable MAC by default on all user ports */ + ret = an8855_port_set_status(priv, dp->index, false); + if (ret) + return ret; + + /* Individual user ports get connected to CPU port only */ + ret = regmap_write(priv->regmap, AN8855_PORTMATRIX_P(dp->index), + FIELD_PREP(AN8855_PORTMATRIX, BIT(AN8855_CPU_PORT))); + if (ret) + return ret; + + /* Disable Broadcast Forward on user ports */ + ret = regmap_clear_bits(priv->regmap, AN8855_BCF, BIT(dp->index)); + if (ret) + return ret; + + /* Disable Unknown Unicast Forward on user ports */ + ret = regmap_clear_bits(priv->regmap, AN8855_UNUF, BIT(dp->index)); + if (ret) + return ret; + + /* Disable Unknown Multicast Forward on user ports */ + ret = regmap_clear_bits(priv->regmap, AN8855_UNMF, BIT(dp->index)); + if (ret) + return ret; + + ret = regmap_clear_bits(priv->regmap, AN8855_UNIPMF, BIT(dp->index)); + if (ret) + return ret; + + /* Set default PVID to on all user ports */ + ret = an8855_port_set_pid(priv, dp->index, AN8855_PORT_VID_DEFAULT); + if (ret) + return ret; + } + + /* Enable Airoha header mode on the cpu port */ + ret = regmap_write(priv->regmap, AN8855_PVC_P(AN8855_CPU_PORT), + AN8855_PORT_SPEC_REPLACE_MODE | AN8855_PORT_SPEC_TAG); + if (ret) + return ret; + + /* Unknown multicast frame forwarding to the cpu port */ + ret = regmap_write(priv->regmap, AN8855_UNMF, BIT(AN8855_CPU_PORT)); + if (ret) + return ret; + + /* Set CPU port number */ + ret = regmap_update_bits(priv->regmap, AN8855_MFC, + AN8855_CPU_EN | AN8855_CPU_PORT_IDX, + AN8855_CPU_EN | + FIELD_PREP(AN8855_CPU_PORT_IDX, AN8855_CPU_PORT)); + if (ret) + return ret; + + /* CPU port gets connected to all user ports of + * the switch. + */ + ret = regmap_write(priv->regmap, AN8855_PORTMATRIX_P(AN8855_CPU_PORT), + FIELD_PREP(AN8855_PORTMATRIX, dsa_user_ports(ds))); + if (ret) + return ret; + + /* CPU port is set to fallback mode to let untagged + * frames pass through. + */ + ret = regmap_update_bits(priv->regmap, AN8855_PCR_P(AN8855_CPU_PORT), + AN8855_PORT_VLAN, + FIELD_PREP(AN8855_PORT_VLAN, AN8855_PORT_FALLBACK_MODE)); + if (ret) + return ret; + + /* Enable Broadcast Forward on CPU port */ + ret = regmap_set_bits(priv->regmap, AN8855_BCF, BIT(AN8855_CPU_PORT)); + if (ret) + return ret; + + /* Enable Unknown Unicast Forward on CPU port */ + ret = regmap_set_bits(priv->regmap, AN8855_UNUF, BIT(AN8855_CPU_PORT)); + if (ret) + return ret; + + /* Enable Unknown Multicast Forward on CPU port */ + ret = regmap_set_bits(priv->regmap, AN8855_UNMF, BIT(AN8855_CPU_PORT)); + if (ret) + return ret; + + ret = regmap_set_bits(priv->regmap, AN8855_UNIPMF, BIT(AN8855_CPU_PORT)); + if (ret) + return ret; + + /* Setup Trap special frame to CPU rules */ + ret = an8855_trap_special_frames(priv); + if (ret) + return ret; + + dsa_switch_for_each_port(dp, ds) { + /* Disable Learning on all ports. + * Learning on CPU is disabled for fdb isolation and handled by + * assisted_learning_on_cpu_port. + */ + ret = regmap_set_bits(priv->regmap, AN8855_PSC_P(dp->index), + AN8855_SA_DIS); + if (ret) + return ret; + + /* Enable consistent egress tag (for VLAN unware VLAN-passtrough) */ + ret = regmap_update_bits(priv->regmap, AN8855_PVC_P(dp->index), + AN8855_PVC_EG_TAG, + FIELD_PREP(AN8855_PVC_EG_TAG, AN8855_VLAN_EG_CONSISTENT)); + if (ret) + return ret; + } + + /* Setup VLAN for Default PVID */ + ret = an8855_setup_pvid_vlan(priv); + if (ret) + return ret; + + ret = regmap_clear_bits(priv->regmap, AN8855_CKGCR, + AN8855_CKG_LNKDN_GLB_STOP | AN8855_CKG_LNKDN_PORT_STOP); + if (ret) + return ret; + + /* Release global PHY power down */ + ret = regmap_write(priv->regmap, AN8855_RG_GPHY_AFE_PWD, 0x0); + if (ret) + return ret; + + ds->configure_vlan_while_not_filtering = true; + + /* Flush the FDB table */ + ret = an8855_fdb_cmd(priv, AN8855_FDB_FLUSH, NULL); + if (ret < 0) + return ret; + + /* Set min a max ageing value supported */ + ds->ageing_time_min = AN8855_L2_AGING_MS_CONSTANT; + ds->ageing_time_max = FIELD_MAX(AN8855_AGE_CNT) * + FIELD_MAX(AN8855_AGE_UNIT) * + AN8855_L2_AGING_MS_CONSTANT; + + /* Enable assisted learning for fdb isolation */ + ds->assisted_learning_on_cpu_port = true; + + return 0; +} + +static struct phylink_pcs *an8855_phylink_mac_select_pcs(struct phylink_config *config, + phy_interface_t interface) +{ + struct dsa_port *dp = dsa_phylink_to_port(config); + struct an8855_priv *priv = dp->ds->priv; + + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_2500BASEX: + return &priv->pcs; + default: + return NULL; + } +} + +static void an8855_phylink_mac_config(struct phylink_config *config, + unsigned int mode, + const struct phylink_link_state *state) +{ + struct dsa_port *dp = dsa_phylink_to_port(config); + struct dsa_switch *ds = dp->ds; + struct an8855_priv *priv; + int port = dp->index; + + priv = ds->priv; + + /* Nothing to configure for internal ports */ + if (port != 5) + return; + + regmap_update_bits(priv->regmap, AN8855_PMCR_P(port), + AN8855_PMCR_IFG_XMIT | AN8855_PMCR_MAC_MODE | + AN8855_PMCR_BACKOFF_EN | AN8855_PMCR_BACKPR_EN, + FIELD_PREP(AN8855_PMCR_IFG_XMIT, 0x1) | + AN8855_PMCR_MAC_MODE | AN8855_PMCR_BACKOFF_EN | + AN8855_PMCR_BACKPR_EN); +} + +static void an8855_phylink_get_caps(struct dsa_switch *ds, int port, + struct phylink_config *config) +{ + switch (port) { + case 0: + case 1: + case 2: + case 3: + case 4: + __set_bit(PHY_INTERFACE_MODE_GMII, + config->supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_INTERNAL, + config->supported_interfaces); + break; + case 5: + phy_interface_set_rgmii(config->supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_SGMII, + config->supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_2500BASEX, + config->supported_interfaces); + break; + } + + config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | + MAC_10 | MAC_100 | MAC_1000FD | MAC_2500FD; +} + +static void an8855_phylink_mac_link_down(struct phylink_config *config, + unsigned int mode, + phy_interface_t interface) +{ + struct dsa_port *dp = dsa_phylink_to_port(config); + struct an8855_priv *priv = dp->ds->priv; + + /* With autoneg just disable TX/RX else also force link down */ + if (phylink_autoneg_inband(mode)) { + regmap_clear_bits(priv->regmap, AN8855_PMCR_P(dp->index), + AN8855_PMCR_TX_EN | AN8855_PMCR_RX_EN); + } else { + regmap_update_bits(priv->regmap, AN8855_PMCR_P(dp->index), + AN8855_PMCR_TX_EN | AN8855_PMCR_RX_EN | + AN8855_PMCR_FORCE_MODE | AN8855_PMCR_FORCE_LNK, + AN8855_PMCR_FORCE_MODE); + } +} + +static void an8855_phylink_mac_link_up(struct phylink_config *config, + struct phy_device *phydev, unsigned int mode, + phy_interface_t interface, int speed, + int duplex, bool tx_pause, bool rx_pause) +{ + struct dsa_port *dp = dsa_phylink_to_port(config); + struct an8855_priv *priv = dp->ds->priv; + int port = dp->index; + u32 reg; + + reg = regmap_read(priv->regmap, AN8855_PMCR_P(port), ®); + if (phylink_autoneg_inband(mode)) { + reg &= ~AN8855_PMCR_FORCE_MODE; + } else { + reg |= AN8855_PMCR_FORCE_MODE | AN8855_PMCR_FORCE_LNK; + + reg &= ~AN8855_PMCR_FORCE_SPEED; + switch (speed) { + case SPEED_10: + reg |= AN8855_PMCR_FORCE_SPEED_10; + break; + case SPEED_100: + reg |= AN8855_PMCR_FORCE_SPEED_100; + break; + case SPEED_1000: + reg |= AN8855_PMCR_FORCE_SPEED_1000; + break; + case SPEED_2500: + reg |= AN8855_PMCR_FORCE_SPEED_2500; + break; + case SPEED_5000: + dev_err(priv->dev, "Missing support for 5G speed. Aborting...\n"); + return; + } + + reg &= ~AN8855_PMCR_FORCE_FDX; + if (duplex == DUPLEX_FULL) + reg |= AN8855_PMCR_FORCE_FDX; + + reg &= ~AN8855_PMCR_RX_FC_EN; + if (rx_pause || dsa_port_is_cpu(dp)) + reg |= AN8855_PMCR_RX_FC_EN; + + reg &= ~AN8855_PMCR_TX_FC_EN; + if (rx_pause || dsa_port_is_cpu(dp)) + reg |= AN8855_PMCR_TX_FC_EN; + + /* Disable any EEE options */ + reg &= ~(AN8855_PMCR_FORCE_EEE5G | AN8855_PMCR_FORCE_EEE2P5G | + AN8855_PMCR_FORCE_EEE1G | AN8855_PMCR_FORCE_EEE100); + } + + reg |= AN8855_PMCR_TX_EN | AN8855_PMCR_RX_EN; + + regmap_write(priv->regmap, AN8855_PMCR_P(port), reg); +} + +static unsigned int an8855_pcs_inband_caps(struct phylink_pcs *pcs, + phy_interface_t interface) +{ + /* SGMII can be configured to use inband with AN result */ + if (interface == PHY_INTERFACE_MODE_SGMII) + return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; + + /* inband is not supported in 2500-baseX and must be disabled */ + return LINK_INBAND_DISABLE; +} + +static void an8855_pcs_get_state(struct phylink_pcs *pcs, + struct phylink_link_state *state) +{ + struct an8855_priv *priv = container_of(pcs, struct an8855_priv, pcs); + u32 val; + int ret; + + ret = regmap_read(priv->regmap, AN8855_PMSR_P(AN8855_CPU_PORT), &val); + if (ret < 0) { + state->link = false; + return; + } + + state->link = !!(val & AN8855_PMSR_LNK); + state->an_complete = state->link; + state->duplex = (val & AN8855_PMSR_DPX) ? DUPLEX_FULL : + DUPLEX_HALF; + + switch (val & AN8855_PMSR_SPEED) { + case AN8855_PMSR_SPEED_10: + state->speed = SPEED_10; + break; + case AN8855_PMSR_SPEED_100: + state->speed = SPEED_100; + break; + case AN8855_PMSR_SPEED_1000: + state->speed = SPEED_1000; + break; + case AN8855_PMSR_SPEED_2500: + state->speed = SPEED_2500; + break; + case AN8855_PMSR_SPEED_5000: + dev_err(priv->dev, "Missing support for 5G speed. Setting Unknown.\n"); + fallthrough; + default: + state->speed = SPEED_UNKNOWN; + break; + } + + if (val & AN8855_PMSR_RX_FC) + state->pause |= MLO_PAUSE_RX; + if (val & AN8855_PMSR_TX_FC) + state->pause |= MLO_PAUSE_TX; +} + +static int an8855_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, + phy_interface_t interface, + const unsigned long *advertising, + bool permit_pause_to_mac) +{ + struct an8855_priv *priv = container_of(pcs, struct an8855_priv, pcs); + u32 val; + int ret; + + /* !!! WELCOME TO HELL !!! */ + + /* TX FIR - improve TX EYE */ + ret = regmap_update_bits(priv->regmap, AN8855_INTF_CTRL_10, + AN8855_RG_DA_QP_TX_FIR_C2_SEL | + AN8855_RG_DA_QP_TX_FIR_C2_FORCE | + AN8855_RG_DA_QP_TX_FIR_C1_SEL | + AN8855_RG_DA_QP_TX_FIR_C1_FORCE, + AN8855_RG_DA_QP_TX_FIR_C2_SEL | + FIELD_PREP(AN8855_RG_DA_QP_TX_FIR_C2_FORCE, 0x4) | + AN8855_RG_DA_QP_TX_FIR_C1_SEL | + FIELD_PREP(AN8855_RG_DA_QP_TX_FIR_C1_FORCE, 0x0)); + if (ret) + return ret; + + if (interface == PHY_INTERFACE_MODE_2500BASEX) + val = 0x0; + else + val = 0xd; + ret = regmap_update_bits(priv->regmap, AN8855_INTF_CTRL_11, + AN8855_RG_DA_QP_TX_FIR_C0B_SEL | + AN8855_RG_DA_QP_TX_FIR_C0B_FORCE, + AN8855_RG_DA_QP_TX_FIR_C0B_SEL | + FIELD_PREP(AN8855_RG_DA_QP_TX_FIR_C0B_FORCE, val)); + if (ret) + return ret; + + /* RX CDR - improve RX Jitter Tolerance */ + if (interface == PHY_INTERFACE_MODE_2500BASEX) + val = 0x5; + else + val = 0x6; + ret = regmap_update_bits(priv->regmap, AN8855_RG_QP_CDR_LPF_BOT_LIM, + AN8855_RG_QP_CDR_LPF_KP_GAIN | + AN8855_RG_QP_CDR_LPF_KI_GAIN, + FIELD_PREP(AN8855_RG_QP_CDR_LPF_KP_GAIN, val) | + FIELD_PREP(AN8855_RG_QP_CDR_LPF_KI_GAIN, val)); + if (ret) + return ret; + + /* PLL */ + if (interface == PHY_INTERFACE_MODE_2500BASEX) + val = 0x1; + else + val = 0x0; + ret = regmap_update_bits(priv->regmap, AN8855_QP_DIG_MODE_CTRL_1, + AN8855_RG_TPHY_SPEED, + FIELD_PREP(AN8855_RG_TPHY_SPEED, val)); + if (ret) + return ret; + + /* PLL - LPF */ + ret = regmap_update_bits(priv->regmap, AN8855_PLL_CTRL_2, + AN8855_RG_DA_QP_PLL_RICO_SEL_INTF | + AN8855_RG_DA_QP_PLL_FBKSEL_INTF | + AN8855_RG_DA_QP_PLL_BR_INTF | + AN8855_RG_DA_QP_PLL_BPD_INTF | + AN8855_RG_DA_QP_PLL_BPA_INTF | + AN8855_RG_DA_QP_PLL_BC_INTF, + AN8855_RG_DA_QP_PLL_RICO_SEL_INTF | + FIELD_PREP(AN8855_RG_DA_QP_PLL_FBKSEL_INTF, 0x0) | + FIELD_PREP(AN8855_RG_DA_QP_PLL_BR_INTF, 0x3) | + FIELD_PREP(AN8855_RG_DA_QP_PLL_BPD_INTF, 0x0) | + FIELD_PREP(AN8855_RG_DA_QP_PLL_BPA_INTF, 0x5) | + FIELD_PREP(AN8855_RG_DA_QP_PLL_BC_INTF, 0x1)); + if (ret) + return ret; + + /* PLL - ICO */ + ret = regmap_set_bits(priv->regmap, AN8855_PLL_CTRL_4, + AN8855_RG_DA_QP_PLL_ICOLP_EN_INTF); + if (ret) + return ret; + ret = regmap_clear_bits(priv->regmap, AN8855_PLL_CTRL_2, + AN8855_RG_DA_QP_PLL_ICOIQ_EN_INTF); + if (ret) + return ret; + + /* PLL - CHP */ + if (interface == PHY_INTERFACE_MODE_2500BASEX) + val = 0x6; + else + val = 0x4; + ret = regmap_update_bits(priv->regmap, AN8855_PLL_CTRL_2, + AN8855_RG_DA_QP_PLL_IR_INTF, + FIELD_PREP(AN8855_RG_DA_QP_PLL_IR_INTF, val)); + if (ret) + return ret; + + /* PLL - PFD */ + ret = regmap_update_bits(priv->regmap, AN8855_PLL_CTRL_2, + AN8855_RG_DA_QP_PLL_PFD_OFFSET_EN_INTRF | + AN8855_RG_DA_QP_PLL_PFD_OFFSET_INTF | + AN8855_RG_DA_QP_PLL_KBAND_PREDIV_INTF, + FIELD_PREP(AN8855_RG_DA_QP_PLL_PFD_OFFSET_INTF, 0x1) | + FIELD_PREP(AN8855_RG_DA_QP_PLL_KBAND_PREDIV_INTF, 0x1)); + if (ret) + return ret; + + /* PLL - POSTDIV */ + ret = regmap_update_bits(priv->regmap, AN8855_PLL_CTRL_2, + AN8855_RG_DA_QP_PLL_POSTDIV_EN_INTF | + AN8855_RG_DA_QP_PLL_PHY_CK_EN_INTF | + AN8855_RG_DA_QP_PLL_PCK_SEL_INTF, + AN8855_RG_DA_QP_PLL_PCK_SEL_INTF); + if (ret) + return ret; + + /* PLL - SDM */ + ret = regmap_update_bits(priv->regmap, AN8855_PLL_CTRL_2, + AN8855_RG_DA_QP_PLL_SDM_HREN_INTF, + FIELD_PREP(AN8855_RG_DA_QP_PLL_SDM_HREN_INTF, 0x0)); + if (ret) + return ret; + ret = regmap_clear_bits(priv->regmap, AN8855_PLL_CTRL_2, + AN8855_RG_DA_QP_PLL_SDM_IFM_INTF); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, AN8855_SS_LCPLL_PWCTL_SETTING_2, + AN8855_RG_NCPO_ANA_MSB, + FIELD_PREP(AN8855_RG_NCPO_ANA_MSB, 0x1)); + if (ret) + return ret; + + if (interface == PHY_INTERFACE_MODE_2500BASEX) + val = 0x7a000000; + else + val = 0x48000000; + ret = regmap_write(priv->regmap, AN8855_SS_LCPLL_TDC_FLT_2, + FIELD_PREP(AN8855_RG_LCPLL_NCPO_VALUE, val)); + if (ret) + return ret; + ret = regmap_write(priv->regmap, AN8855_SS_LCPLL_TDC_PCW_1, + FIELD_PREP(AN8855_RG_LCPLL_PON_HRDDS_PCW_NCPO_GPON, val)); + if (ret) + return ret; + + ret = regmap_clear_bits(priv->regmap, AN8855_SS_LCPLL_TDC_FLT_5, + AN8855_RG_LCPLL_NCPO_CHG); + if (ret) + return ret; + ret = regmap_clear_bits(priv->regmap, AN8855_PLL_CK_CTRL_0, + AN8855_RG_DA_QP_PLL_SDM_DI_EN_INTF); + if (ret) + return ret; + + /* PLL - SS */ + ret = regmap_update_bits(priv->regmap, AN8855_PLL_CTRL_3, + AN8855_RG_DA_QP_PLL_SSC_DELTA_INTF, + FIELD_PREP(AN8855_RG_DA_QP_PLL_SSC_DELTA_INTF, 0x0)); + if (ret) + return ret; + ret = regmap_update_bits(priv->regmap, AN8855_PLL_CTRL_4, + AN8855_RG_DA_QP_PLL_SSC_DIR_DLY_INTF, + FIELD_PREP(AN8855_RG_DA_QP_PLL_SSC_DIR_DLY_INTF, 0x0)); + if (ret) + return ret; + ret = regmap_update_bits(priv->regmap, AN8855_PLL_CTRL_3, + AN8855_RG_DA_QP_PLL_SSC_PERIOD_INTF, + FIELD_PREP(AN8855_RG_DA_QP_PLL_SSC_PERIOD_INTF, 0x0)); + if (ret) + return ret; + + /* PLL - TDC */ + ret = regmap_clear_bits(priv->regmap, AN8855_PLL_CK_CTRL_0, + AN8855_RG_DA_QP_PLL_TDC_TXCK_SEL_INTF); + if (ret) + return ret; + + ret = regmap_set_bits(priv->regmap, AN8855_RG_QP_PLL_SDM_ORD, + AN8855_RG_QP_PLL_SSC_TRI_EN); + if (ret) + return ret; + ret = regmap_set_bits(priv->regmap, AN8855_RG_QP_PLL_SDM_ORD, + AN8855_RG_QP_PLL_SSC_PHASE_INI); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, AN8855_RG_QP_RX_DAC_EN, + AN8855_RG_QP_SIGDET_HF, + FIELD_PREP(AN8855_RG_QP_SIGDET_HF, 0x2)); + if (ret) + return ret; + + /* TCL Disable (only for Co-SIM) */ + ret = regmap_clear_bits(priv->regmap, AN8855_PON_RXFEDIG_CTRL_0, + AN8855_RG_QP_EQ_RX500M_CK_SEL); + if (ret) + return ret; + + /* TX Init */ + if (interface == PHY_INTERFACE_MODE_2500BASEX) + val = 0x4; + else + val = 0x0; + ret = regmap_update_bits(priv->regmap, AN8855_RG_QP_TX_MODE, + AN8855_RG_QP_TX_RESERVE | + AN8855_RG_QP_TX_MODE_16B_EN, + FIELD_PREP(AN8855_RG_QP_TX_RESERVE, val)); + if (ret) + return ret; + + /* RX Control/Init */ + ret = regmap_set_bits(priv->regmap, AN8855_RG_QP_RXAFE_RESERVE, + AN8855_RG_QP_CDR_PD_10B_EN); + if (ret) + return ret; + + if (interface == PHY_INTERFACE_MODE_2500BASEX) + val = 0x1; + else + val = 0x2; + ret = regmap_update_bits(priv->regmap, AN8855_RG_QP_CDR_LPF_MJV_LIM, + AN8855_RG_QP_CDR_LPF_RATIO, + FIELD_PREP(AN8855_RG_QP_CDR_LPF_RATIO, val)); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, AN8855_RG_QP_CDR_LPF_SETVALUE, + AN8855_RG_QP_CDR_PR_BUF_IN_SR | + AN8855_RG_QP_CDR_PR_BETA_SEL, + FIELD_PREP(AN8855_RG_QP_CDR_PR_BUF_IN_SR, 0x6) | + FIELD_PREP(AN8855_RG_QP_CDR_PR_BETA_SEL, 0x1)); + if (ret) + return ret; + + if (interface == PHY_INTERFACE_MODE_2500BASEX) + val = 0xf; + else + val = 0xc; + ret = regmap_update_bits(priv->regmap, AN8855_RG_QP_CDR_PR_CKREF_DIV1, + AN8855_RG_QP_CDR_PR_DAC_BAND, + FIELD_PREP(AN8855_RG_QP_CDR_PR_DAC_BAND, val)); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, AN8855_RG_QP_CDR_PR_KBAND_DIV_PCIE, + AN8855_RG_QP_CDR_PR_KBAND_PCIE_MODE | + AN8855_RG_QP_CDR_PR_KBAND_DIV_PCIE_MASK, + FIELD_PREP(AN8855_RG_QP_CDR_PR_KBAND_DIV_PCIE_MASK, 0x19)); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, AN8855_RG_QP_CDR_FORCE_IBANDLPF_R_OFF, + AN8855_RG_QP_CDR_PHYCK_SEL | + AN8855_RG_QP_CDR_PHYCK_RSTB | + AN8855_RG_QP_CDR_PHYCK_DIV, + FIELD_PREP(AN8855_RG_QP_CDR_PHYCK_SEL, 0x2) | + FIELD_PREP(AN8855_RG_QP_CDR_PHYCK_DIV, 0x21)); + if (ret) + return ret; + + ret = regmap_clear_bits(priv->regmap, AN8855_RG_QP_CDR_PR_KBAND_DIV_PCIE, + AN8855_RG_QP_CDR_PR_XFICK_EN); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, AN8855_RG_QP_CDR_PR_CKREF_DIV1, + AN8855_RG_QP_CDR_PR_KBAND_DIV, + FIELD_PREP(AN8855_RG_QP_CDR_PR_KBAND_DIV, 0x4)); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, AN8855_RX_CTRL_26, + AN8855_RG_QP_EQ_RETRAIN_ONLY_EN | + AN8855_RG_LINK_NE_EN | + AN8855_RG_LINK_ERRO_EN, + AN8855_RG_QP_EQ_RETRAIN_ONLY_EN | + AN8855_RG_LINK_ERRO_EN); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, AN8855_RX_DLY_0, + AN8855_RG_QP_RX_SAOSC_EN_H_DLY | + AN8855_RG_QP_RX_PI_CAL_EN_H_DLY, + FIELD_PREP(AN8855_RG_QP_RX_SAOSC_EN_H_DLY, 0x3f) | + FIELD_PREP(AN8855_RG_QP_RX_PI_CAL_EN_H_DLY, 0x6f)); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, AN8855_RX_CTRL_42, + AN8855_RG_QP_EQ_EN_DLY, + FIELD_PREP(AN8855_RG_QP_EQ_EN_DLY, 0x150)); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, AN8855_RX_CTRL_2, + AN8855_RG_QP_RX_EQ_EN_H_DLY, + FIELD_PREP(AN8855_RG_QP_RX_EQ_EN_H_DLY, 0x150)); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, AN8855_PON_RXFEDIG_CTRL_9, + AN8855_RG_QP_EQ_LEQOSC_DLYCNT, + FIELD_PREP(AN8855_RG_QP_EQ_LEQOSC_DLYCNT, 0x1)); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, AN8855_RX_CTRL_8, + AN8855_RG_DA_QP_SAOSC_DONE_TIME | + AN8855_RG_DA_QP_LEQOS_EN_TIME, + FIELD_PREP(AN8855_RG_DA_QP_SAOSC_DONE_TIME, 0x200) | + FIELD_PREP(AN8855_RG_DA_QP_LEQOS_EN_TIME, 0xfff)); + if (ret) + return ret; + + /* Frequency meter */ + if (interface == PHY_INTERFACE_MODE_2500BASEX) + val = 0x10; + else + val = 0x28; + ret = regmap_update_bits(priv->regmap, AN8855_RX_CTRL_5, + AN8855_RG_FREDET_CHK_CYCLE, + FIELD_PREP(AN8855_RG_FREDET_CHK_CYCLE, val)); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, AN8855_RX_CTRL_6, + AN8855_RG_FREDET_GOLDEN_CYCLE, + FIELD_PREP(AN8855_RG_FREDET_GOLDEN_CYCLE, 0x64)); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, AN8855_RX_CTRL_7, + AN8855_RG_FREDET_TOLERATE_CYCLE, + FIELD_PREP(AN8855_RG_FREDET_TOLERATE_CYCLE, 0x2710)); + if (ret) + return ret; + + ret = regmap_set_bits(priv->regmap, AN8855_PLL_CTRL_0, + AN8855_RG_PHYA_AUTO_INIT); + if (ret) + return ret; + + /* PCS Init */ + if (interface == PHY_INTERFACE_MODE_SGMII && + neg_mode == PHYLINK_PCS_NEG_INBAND_DISABLED) { + ret = regmap_clear_bits(priv->regmap, AN8855_QP_DIG_MODE_CTRL_0, + AN8855_RG_SGMII_MODE | AN8855_RG_SGMII_AN_EN); + if (ret) + return ret; + } + + ret = regmap_clear_bits(priv->regmap, AN8855_RG_HSGMII_PCS_CTROL_1, + AN8855_RG_TBI_10B_MODE); + if (ret) + return ret; + + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { + /* Set AN Ability - Interrupt */ + ret = regmap_set_bits(priv->regmap, AN8855_SGMII_REG_AN_FORCE_CL37, + AN8855_RG_FORCE_AN_DONE); + if (ret) + return ret; + + ret = regmap_update_bits(priv->regmap, AN8855_SGMII_REG_AN_13, + AN8855_SGMII_REMOTE_FAULT_DIS | + AN8855_SGMII_IF_MODE, + AN8855_SGMII_REMOTE_FAULT_DIS | + FIELD_PREP(AN8855_SGMII_IF_MODE, 0xb)); + if (ret) + return ret; + } + + /* Rate Adaption - GMII path config. */ + if (interface == PHY_INTERFACE_MODE_2500BASEX) { + ret = regmap_clear_bits(priv->regmap, AN8855_RATE_ADP_P0_CTRL_0, + AN8855_RG_P0_DIS_MII_MODE); + if (ret) + return ret; + } else { + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { + ret = regmap_set_bits(priv->regmap, AN8855_MII_RA_AN_ENABLE, + AN8855_RG_P0_RA_AN_EN); + if (ret) + return ret; + } else { + ret = regmap_update_bits(priv->regmap, AN8855_RG_AN_SGMII_MODE_FORCE, + AN8855_RG_FORCE_CUR_SGMII_MODE | + AN8855_RG_FORCE_CUR_SGMII_SEL, + AN8855_RG_FORCE_CUR_SGMII_SEL); + if (ret) + return ret; + + ret = regmap_clear_bits(priv->regmap, AN8855_RATE_ADP_P0_CTRL_0, + AN8855_RG_P0_MII_RA_RX_EN | + AN8855_RG_P0_MII_RA_TX_EN | + AN8855_RG_P0_MII_RA_RX_MODE | + AN8855_RG_P0_MII_RA_TX_MODE); + if (ret) + return ret; + } + + ret = regmap_set_bits(priv->regmap, AN8855_RATE_ADP_P0_CTRL_0, + AN8855_RG_P0_MII_MODE); + if (ret) + return ret; + } + + ret = regmap_set_bits(priv->regmap, AN8855_RG_RATE_ADAPT_CTRL_0, + AN8855_RG_RATE_ADAPT_RX_BYPASS | + AN8855_RG_RATE_ADAPT_TX_BYPASS | + AN8855_RG_RATE_ADAPT_RX_EN | + AN8855_RG_RATE_ADAPT_TX_EN); + if (ret) + return ret; + + /* Disable AN if not in autoneg */ + ret = regmap_update_bits(priv->regmap, AN8855_SGMII_REG_AN0, BMCR_ANENABLE, + neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED ? BMCR_ANENABLE : + 0); + if (ret) + return ret; + + if (interface == PHY_INTERFACE_MODE_SGMII) { + /* Follow SDK init flow with restarting AN after AN enable */ + if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) { + ret = regmap_set_bits(priv->regmap, AN8855_SGMII_REG_AN0, + BMCR_ANRESTART); + if (ret) + return ret; + } else { + ret = regmap_set_bits(priv->regmap, AN8855_PHY_RX_FORCE_CTRL_0, + AN8855_RG_FORCE_TXC_SEL); + if (ret) + return ret; + } + } + + /* Force Speed with fixed-link or 2500base-x as doesn't support aneg */ + if (interface == PHY_INTERFACE_MODE_2500BASEX || + neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) { + if (interface == PHY_INTERFACE_MODE_2500BASEX) + val = AN8855_RG_LINK_MODE_P0_SPEED_2500; + else + val = AN8855_RG_LINK_MODE_P0_SPEED_1000; + ret = regmap_update_bits(priv->regmap, AN8855_SGMII_STS_CTRL_0, + AN8855_RG_LINK_MODE_P0 | + AN8855_RG_FORCE_SPD_MODE_P0, + val | AN8855_RG_FORCE_SPD_MODE_P0); + if (ret) + return ret; + } + + /* bypass flow control to MAC */ + ret = regmap_write(priv->regmap, AN8855_MSG_RX_LIK_STS_0, + AN8855_RG_DPX_STS_P3 | AN8855_RG_DPX_STS_P2 | + AN8855_RG_DPX_STS_P1 | AN8855_RG_TXFC_STS_P0 | + AN8855_RG_RXFC_STS_P0 | AN8855_RG_DPX_STS_P0); + if (ret) + return ret; + ret = regmap_write(priv->regmap, AN8855_MSG_RX_LIK_STS_2, + AN8855_RG_RXFC_AN_BYPASS_P3 | + AN8855_RG_RXFC_AN_BYPASS_P2 | + AN8855_RG_RXFC_AN_BYPASS_P1 | + AN8855_RG_TXFC_AN_BYPASS_P3 | + AN8855_RG_TXFC_AN_BYPASS_P2 | + AN8855_RG_TXFC_AN_BYPASS_P1 | + AN8855_RG_DPX_AN_BYPASS_P3 | + AN8855_RG_DPX_AN_BYPASS_P2 | + AN8855_RG_DPX_AN_BYPASS_P1 | + AN8855_RG_DPX_AN_BYPASS_P0); + if (ret) + return ret; + + return 0; +} + +static void an8855_pcs_an_restart(struct phylink_pcs *pcs) +{ + return; +} + +static const struct phylink_pcs_ops an8855_pcs_ops = { + .pcs_inband_caps = an8855_pcs_inband_caps, + .pcs_get_state = an8855_pcs_get_state, + .pcs_config = an8855_pcs_config, + .pcs_an_restart = an8855_pcs_an_restart, +}; + +static const struct phylink_mac_ops an8855_phylink_mac_ops = { + .mac_select_pcs = an8855_phylink_mac_select_pcs, + .mac_config = an8855_phylink_mac_config, + .mac_link_down = an8855_phylink_mac_link_down, + .mac_link_up = an8855_phylink_mac_link_up, +}; + +static const struct dsa_switch_ops an8855_switch_ops = { + .get_tag_protocol = an8855_get_tag_protocol, + .setup = an8855_setup, + .get_phy_flags = en8855_get_phy_flags, + .phylink_get_caps = an8855_phylink_get_caps, + .get_strings = an8855_get_strings, + .get_ethtool_stats = an8855_get_ethtool_stats, + .get_sset_count = an8855_get_sset_count, + .get_eth_mac_stats = an8855_get_eth_mac_stats, + .get_eth_ctrl_stats = an8855_get_eth_ctrl_stats, + .get_rmon_stats = an8855_get_rmon_stats, + .port_enable = an8855_port_enable, + .port_disable = an8855_port_disable, + .set_ageing_time = an8855_set_ageing_time, + .port_bridge_join = an8855_port_bridge_join, + .port_bridge_leave = an8855_port_bridge_leave, + .port_fast_age = an8855_port_fast_age, + .port_stp_state_set = an8855_port_stp_state_set, + .port_pre_bridge_flags = an8855_port_pre_bridge_flags, + .port_bridge_flags = an8855_port_bridge_flags, + .port_vlan_filtering = an8855_port_vlan_filtering, + .port_vlan_add = an8855_port_vlan_add, + .port_vlan_del = an8855_port_vlan_del, + .port_fdb_add = an8855_port_fdb_add, + .port_fdb_del = an8855_port_fdb_del, + .port_fdb_dump = an8855_port_fdb_dump, + .port_mdb_add = an8855_port_mdb_add, + .port_mdb_del = an8855_port_mdb_del, + .port_change_mtu = an8855_port_change_mtu, + .port_max_mtu = an8855_port_max_mtu, + .port_mirror_add = an8855_port_mirror_add, + .port_mirror_del = an8855_port_mirror_del, +}; + +static int an8855_read_switch_id(struct an8855_priv *priv) +{ + u32 id; + int ret; + + ret = regmap_read(priv->regmap, AN8855_CREV, &id); + if (ret) + return ret; + + if (id != AN8855_ID) { + dev_err(priv->dev, + "Switch id detected %x but expected %x\n", + id, AN8855_ID); + return -ENODEV; + } + + return 0; +} + +static int an8855_switch_probe(struct platform_device *pdev) +{ + struct an8855_priv *priv; + u32 val; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = &pdev->dev; + priv->phy_require_calib = of_property_read_bool(priv->dev->of_node, + "airoha,ext-surge"); + + priv->reset_gpio = devm_gpiod_get_optional(priv->dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(priv->reset_gpio)) + return PTR_ERR(priv->reset_gpio); + + /* Get regmap from MFD */ + priv->regmap = dev_get_regmap(priv->dev->parent, NULL); + + if (priv->reset_gpio) { + usleep_range(100000, 150000); + gpiod_set_value_cansleep(priv->reset_gpio, 0); + usleep_range(100000, 150000); + gpiod_set_value_cansleep(priv->reset_gpio, 1); + + /* Poll HWTRAP reg to wait for Switch to fully Init */ + ret = regmap_read_poll_timeout(priv->regmap, AN8855_HWTRAP, val, + val, 20, 200000); + if (ret) + return ret; + } + + ret = an8855_read_switch_id(priv); + if (ret) + return ret; + + priv->ds = devm_kzalloc(priv->dev, sizeof(*priv->ds), GFP_KERNEL); + if (!priv->ds) + return -ENOMEM; + + priv->ds->dev = priv->dev; + priv->ds->num_ports = AN8855_NUM_PORTS; + priv->ds->priv = priv; + priv->ds->ops = &an8855_switch_ops; + devm_mutex_init(priv->dev, &priv->reg_mutex); + priv->ds->phylink_mac_ops = &an8855_phylink_mac_ops; + + priv->pcs.ops = &an8855_pcs_ops; + priv->pcs.neg_mode = true; + priv->pcs.poll = true; + + dev_set_drvdata(priv->dev, priv); + + return dsa_register_switch(priv->ds); +} + +static int an8855_switch_remove(struct platform_device *pdev) +{ + struct an8855_priv *priv = dev_get_drvdata(&pdev->dev); + + if (!priv) + return 0; + + dsa_unregister_switch(priv->ds); + return 0; +} + +static const struct of_device_id an8855_switch_of_match[] = { + { .compatible = "airoha,an8855-switch" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, an8855_switch_of_match); + +static struct platform_driver an8855_switch_driver = { + .probe = an8855_switch_probe, + .remove = an8855_switch_remove, + .driver = { + .name = "an8855-switch", + .of_match_table = an8855_switch_of_match, + }, +}; +module_platform_driver(an8855_switch_driver); + +MODULE_AUTHOR("Min Yao "); +MODULE_AUTHOR("Christian Marangi "); +MODULE_DESCRIPTION("Driver for Airoha AN8855 Switch"); +MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/mediatek/files/drivers/net/dsa/an8855.h b/lede/target/linux/mediatek/files/drivers/net/dsa/an8855.h new file mode 100644 index 0000000000..2462b9d337 --- /dev/null +++ b/lede/target/linux/mediatek/files/drivers/net/dsa/an8855.h @@ -0,0 +1,783 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2023 Min Yao + * Copyright (C) 2024 Christian Marangi + */ + +#ifndef __AN8855_H +#define __AN8855_H + +#include + +#define AN8855_NUM_PORTS 6 +#define AN8855_CPU_PORT 5 +#define AN8855_NUM_FDB_RECORDS 2048 +#define AN8855_GPHY_SMI_ADDR_DEFAULT 1 +#define AN8855_PORT_VID_DEFAULT 0 + +#define MTK_TAG_LEN 4 +#define AN8855_MAX_MTU (15360 - ETH_HLEN - ETH_FCS_LEN - MTK_TAG_LEN) + +#define AN8855_L2_AGING_MS_CONSTANT 1024 + +#define AN8855_PHY_FLAGS_EN_CALIBRATION BIT(0) + +/* AN8855_SCU 0x10000000 */ +#define AN8855_RG_GPIO_LED_MODE 0x10000054 +#define AN8855_RG_GPIO_LED_SEL(i) (0x10000000 + (0x0058 + ((i) * 4))) +#define AN8855_RG_INTB_MODE 0x10000080 +#define AN8855_RG_RGMII_TXCK_C 0x100001d0 + +#define AN8855_PKG_SEL 0x10000094 +#define AN8855_PAG_SEL_AN8855H 0x2 + +/* Register for hw trap status */ +#define AN8855_HWTRAP 0x1000009c + +#define AN8855_RG_GPIO_L_INV 0x10000010 +#define AN8855_RG_GPIO_CTRL 0x1000a300 +#define AN8855_RG_GPIO_DATA 0x1000a304 +#define AN8855_RG_GPIO_OE 0x1000a314 + +#define AN8855_CREV 0x10005000 +#define AN8855_ID 0x8855 + +/* Register for system reset */ +#define AN8855_RST_CTRL 0x100050c0 +#define AN8855_SYS_CTRL_SYS_RST BIT(31) + +#define AN8855_INT_MASK 0x100050f0 +#define AN8855_INT_SYS BIT(15) + +#define AN8855_RG_CLK_CPU_ICG 0x10005034 +#define AN8855_MCU_ENABLE BIT(3) + +#define AN8855_RG_TIMER_CTL 0x1000a100 +#define AN8855_WDOG_ENABLE BIT(25) + +#define AN8855_RG_GDMP_RAM 0x10010000 + +/* Registers to mac forward control for unknown frames */ +#define AN8855_MFC 0x10200010 +#define AN8855_CPU_EN BIT(15) +#define AN8855_CPU_PORT_IDX GENMASK(12, 8) + +#define AN8855_PAC 0x10200024 +#define AN8855_TAG_PAE_MANG_FR BIT(30) +#define AN8855_TAG_PAE_BPDU_FR BIT(28) +#define AN8855_TAG_PAE_EG_TAG GENMASK(27, 25) +#define AN8855_TAG_PAE_LKY_VLAN BIT(24) +#define AN8855_TAG_PAE_PRI_HIGH BIT(23) +#define AN8855_TAG_PAE_MIR GENMASK(20, 19) +#define AN8855_TAG_PAE_PORT_FW GENMASK(18, 16) +#define AN8855_PAE_MANG_FR BIT(14) +#define AN8855_PAE_BPDU_FR BIT(12) +#define AN8855_PAE_EG_TAG GENMASK(11, 9) +#define AN8855_PAE_LKY_VLAN BIT(8) +#define AN8855_PAE_PRI_HIGH BIT(7) +#define AN8855_PAE_MIR GENMASK(4, 3) +#define AN8855_PAE_PORT_FW GENMASK(2, 0) + +#define AN8855_RGAC1 0x10200028 +#define AN8855_R02_MANG_FR BIT(30) +#define AN8855_R02_BPDU_FR BIT(28) +#define AN8855_R02_EG_TAG GENMASK(27, 25) +#define AN8855_R02_LKY_VLAN BIT(24) +#define AN8855_R02_PRI_HIGH BIT(23) +#define AN8855_R02_MIR GENMASK(20, 19) +#define AN8855_R02_PORT_FW GENMASK(18, 16) +#define AN8855_R01_MANG_FR BIT(14) +#define AN8855_R01_BPDU_FR BIT(12) +#define AN8855_R01_EG_TAG GENMASK(11, 9) +#define AN8855_R01_LKY_VLAN BIT(8) +#define AN8855_R01_PRI_HIGH BIT(7) +#define AN8855_R01_MIR GENMASK(4, 3) +#define AN8855_R01_PORT_FW GENMASK(2, 0) + +#define AN8855_RGAC2 0x1020002c +#define AN8855_R0E_MANG_FR BIT(30) +#define AN8855_R0E_BPDU_FR BIT(28) +#define AN8855_R0E_EG_TAG GENMASK(27, 25) +#define AN8855_R0E_LKY_VLAN BIT(24) +#define AN8855_R0E_PRI_HIGH BIT(23) +#define AN8855_R0E_MIR GENMASK(20, 19) +#define AN8855_R0E_PORT_FW GENMASK(18, 16) +#define AN8855_R03_MANG_FR BIT(14) +#define AN8855_R03_BPDU_FR BIT(12) +#define AN8855_R03_EG_TAG GENMASK(11, 9) +#define AN8855_R03_LKY_VLAN BIT(8) +#define AN8855_R03_PRI_HIGH BIT(7) +#define AN8855_R03_MIR GENMASK(4, 3) +#define AN8855_R03_PORT_FW GENMASK(2, 0) + +#define AN8855_AAC 0x102000a0 +#define AN8855_MAC_AUTO_FLUSH BIT(28) +/* Control Address Table Age time. + * (AN8855_AGE_CNT + 1) * ( AN8855_AGE_UNIT + 1 ) * AN8855_L2_AGING_MS_CONSTANT + */ +#define AN8855_AGE_CNT GENMASK(20, 12) +/* Value in seconds. Value is always incremented of 1 */ +#define AN8855_AGE_UNIT GENMASK(10, 0) + +/* Registers for ARL Unknown Unicast Forward control */ +#define AN8855_UNUF 0x102000b4 + +/* Registers for ARL Unknown Multicast Forward control */ +#define AN8855_UNMF 0x102000b8 + +/* Registers for ARL Broadcast forward control */ +#define AN8855_BCF 0x102000bc + +/* Registers for port address age disable */ +#define AN8855_AGDIS 0x102000c0 + +/* Registers for mirror port control */ +#define AN8855_MIR 0x102000cc +#define AN8855_MIRROR_EN BIT(7) +#define AN8855_MIRROR_PORT GENMASK(4, 0) + +/* Registers for BPDU and PAE frame control*/ +#define AN8855_BPC 0x102000d0 +#define AN8855_BPDU_MANG_FR BIT(14) +#define AN8855_BPDU_BPDU_FR BIT(12) +#define AN8855_BPDU_EG_TAG GENMASK(11, 9) +#define AN8855_BPDU_LKY_VLAN BIT(8) +#define AN8855_BPDU_PRI_HIGH BIT(7) +#define AN8855_BPDU_MIR GENMASK(4, 3) +#define AN8855_BPDU_PORT_FW GENMASK(2, 0) + +/* Registers for IP Unknown Multicast Forward control */ +#define AN8855_UNIPMF 0x102000dc + +enum an8855_bpdu_port_fw { + AN8855_BPDU_FOLLOW_MFC = 0, + AN8855_BPDU_CPU_EXCLUDE = 4, + AN8855_BPDU_CPU_INCLUDE = 5, + AN8855_BPDU_CPU_ONLY = 6, + AN8855_BPDU_DROP = 7, +}; + +/* Register for address table control */ +#define AN8855_ATC 0x10200300 +#define AN8855_ATC_BUSY BIT(31) +#define AN8855_ATC_HASH GENMASK(24, 16) +#define AN8855_ATC_HIT GENMASK(15, 12) +#define AN8855_ATC_MAT_MASK GENMASK(11, 7) +#define AN8855_ATC_MAT(x) FIELD_PREP(AN8855_ATC_MAT_MASK, x) +#define AN8855_ATC_SAT GENMASK(5, 4) +#define AN8855_ATC_CMD GENMASK(2, 0) + +enum an8855_fdb_mat_cmds { + AND8855_FDB_MAT_ALL = 0, + AND8855_FDB_MAT_MAC, /* All MAC address */ + AND8855_FDB_MAT_DYNAMIC_MAC, /* All Dynamic MAC address */ + AND8855_FDB_MAT_STATIC_MAC, /* All Static Mac Address */ + AND8855_FDB_MAT_DIP, /* All DIP/GA address */ + AND8855_FDB_MAT_DIP_IPV4, /* All DIP/GA IPv4 address */ + AND8855_FDB_MAT_DIP_IPV6, /* All DIP/GA IPv6 address */ + AND8855_FDB_MAT_DIP_SIP, /* All DIP_SIP address */ + AND8855_FDB_MAT_DIP_SIP_IPV4, /* All DIP_SIP IPv4 address */ + AND8855_FDB_MAT_DIP_SIP_IPV6, /* All DIP_SIP IPv6 address */ + AND8855_FDB_MAT_MAC_CVID, /* All MAC address with CVID */ + AND8855_FDB_MAT_MAC_FID, /* All MAC address with Filter ID */ + AND8855_FDB_MAT_MAC_PORT, /* All MAC address with port */ + AND8855_FDB_MAT_DIP_SIP_DIP_IPV4, /* All DIP_SIP address with DIP_IPV4 */ + AND8855_FDB_MAT_DIP_SIP_SIP_IPV4, /* All DIP_SIP address with SIP_IPV4 */ + AND8855_FDB_MAT_DIP_SIP_DIP_IPV6, /* All DIP_SIP address with DIP_IPV6 */ + AND8855_FDB_MAT_DIP_SIP_SIP_IPV6, /* All DIP_SIP address with SIP_IPV6 */ + /* All MAC address with MAC type (dynamic or static) with CVID */ + AND8855_FDB_MAT_MAC_TYPE_CVID, + /* All MAC address with MAC type (dynamic or static) with Filter ID */ + AND8855_FDB_MAT_MAC_TYPE_FID, + /* All MAC address with MAC type (dynamic or static) with port */ + AND8855_FDB_MAT_MAC_TYPE_PORT, +}; + +enum an8855_fdb_cmds { + AN8855_FDB_READ = 0, + AN8855_FDB_WRITE = 1, + AN8855_FDB_FLUSH = 2, + AN8855_FDB_START = 4, + AN8855_FDB_NEXT = 5, +}; + +/* Registers for address table access */ +#define AN8855_ATA1 0x10200304 +#define AN8855_ATA1_MAC0 GENMASK(31, 24) +#define AN8855_ATA1_MAC1 GENMASK(23, 16) +#define AN8855_ATA1_MAC2 GENMASK(15, 8) +#define AN8855_ATA1_MAC3 GENMASK(7, 0) +#define AN8855_ATA2 0x10200308 +#define AN8855_ATA2_MAC4 GENMASK(31, 24) +#define AN8855_ATA2_MAC5 GENMASK(23, 16) +#define AN8855_ATA2_UNAUTH BIT(10) +#define AN8855_ATA2_TYPE BIT(9) /* 1: dynamic, 0: static */ +#define AN8855_ATA2_AGE GENMASK(8, 0) + +/* Register for address table write data */ +#define AN8855_ATWD 0x10200324 +#define AN8855_ATWD_FID GENMASK(31, 28) +#define AN8855_ATWD_VID GENMASK(27, 16) +#define AN8855_ATWD_IVL BIT(15) +#define AN8855_ATWD_EG_TAG GENMASK(14, 12) +#define AN8855_ATWD_SA_MIR GENMASK(9, 8) +#define AN8855_ATWD_SA_FWD GENMASK(7, 5) +#define AN8855_ATWD_UPRI GENMASK(4, 2) +#define AN8855_ATWD_LEAKY BIT(1) +#define AN8855_ATWD_VLD BIT(0) /* vid LOAD */ +#define AN8855_ATWD2 0x10200328 +#define AN8855_ATWD2_PORT GENMASK(7, 0) + +/* Registers for table search read address */ +#define AN8855_ATRDS 0x10200330 +#define AN8855_ATRD_SEL GENMASK(1, 0) +#define AN8855_ATRD0 0x10200334 +#define AN8855_ATRD0_FID GENMASK(28, 25) +#define AN8855_ATRD0_VID GENMASK(21, 10) +#define AN8855_ATRD0_IVL BIT(9) +#define AN8855_ATRD0_TYPE GENMASK(4, 3) +#define AN8855_ATRD0_ARP GENMASK(2, 1) +#define AN8855_ATRD0_LIVE BIT(0) +#define AN8855_ATRD1 0x10200338 +#define AN8855_ATRD1_MAC4 GENMASK(31, 24) +#define AN8855_ATRD1_MAC5 GENMASK(23, 16) +#define AN8855_ATRD1_AGING GENMASK(11, 3) +#define AN8855_ATRD2 0x1020033c +#define AN8855_ATRD2_MAC0 GENMASK(31, 24) +#define AN8855_ATRD2_MAC1 GENMASK(23, 16) +#define AN8855_ATRD2_MAC2 GENMASK(15, 8) +#define AN8855_ATRD2_MAC3 GENMASK(7, 0) +#define AN8855_ATRD3 0x10200340 +#define AN8855_ATRD3_PORTMASK GENMASK(7, 0) + +enum an8855_fdb_type { + AN8855_MAC_TB_TY_MAC = 0, + AN8855_MAC_TB_TY_DIP = 1, + AN8855_MAC_TB_TY_DIP_SIP = 2, +}; + +/* Register for vlan table control */ +#define AN8855_VTCR 0x10200600 +#define AN8855_VTCR_BUSY BIT(31) +#define AN8855_VTCR_FUNC GENMASK(15, 12) +#define AN8855_VTCR_VID GENMASK(11, 0) + +enum an8855_vlan_cmd { + /* Read/Write the specified VID entry from VAWD register based + * on VID. + */ + AN8855_VTCR_RD_VID = 0, + AN8855_VTCR_WR_VID = 1, +}; + +/* Register for setup vlan write data */ +#define AN8855_VAWD0 0x10200604 +/* VLAN Member Control */ +#define AN8855_VA0_PORT GENMASK(31, 26) +/* Egress Tag Control */ +#define AN8855_VA0_ETAG GENMASK(23, 12) +#define AN8855_VA0_ETAG_PORT GENMASK(13, 12) +#define AN8855_VA0_ETAG_PORT_SHIFT(port) ((port) * 2) +#define AN8855_VA0_ETAG_PORT_MASK(port) (AN8855_VA0_ETAG_PORT << \ + AN8855_VA0_ETAG_PORT_SHIFT(port)) +#define AN8855_VA0_ETAG_PORT_VAL(port, val) (FIELD_PREP(AN8855_VA0_ETAG_PORT, (val)) << \ + AN8855_VA0_ETAG_PORT_SHIFT(port)) +#define AN8855_VA0_EG_CON BIT(11) +#define AN8855_VA0_VTAG_EN BIT(10) /* Per VLAN Egress Tag Control */ +#define AN8855_VA0_IVL_MAC BIT(5) /* Independent VLAN Learning */ +#define AN8855_VA0_FID GENMASK(4, 1) +#define AN8855_VA0_VLAN_VALID BIT(0) /* VLAN Entry Valid */ +#define AN8855_VAWD1 0x10200608 +#define AN8855_VA1_PORT_STAG BIT(1) + +enum an8855_fid { + AN8855_FID_STANDALONE = 0, + AN8855_FID_BRIDGED = 1, +}; + +/* Same register field of VAWD0 */ +#define AN8855_VARD0 0x10200618 + +enum an8855_vlan_egress_attr { + AN8855_VLAN_EGRESS_UNTAG = 0, + AN8855_VLAN_EGRESS_TAG = 2, + AN8855_VLAN_EGRESS_STACK = 3, +}; + +/* Register for port STP state control */ +#define AN8855_SSP_P(x) (0x10208000 + ((x) * 0x200)) +/* Up to 16 FID supported, each with the same mask */ +#define AN8855_FID_PST GENMASK(1, 0) +#define AN8855_FID_PST_SHIFT(fid) (2 * (fid)) +#define AN8855_FID_PST_MASK(fid) (AN8855_FID_PST << \ + AN8855_FID_PST_SHIFT(fid)) +#define AN8855_FID_PST_VAL(fid, val) (FIELD_PREP(AN8855_FID_PST, (val)) << \ + AN8855_FID_PST_SHIFT(fid)) + +enum an8855_stp_state { + AN8855_STP_DISABLED = 0, + AN8855_STP_BLOCKING = 1, + AN8855_STP_LISTENING = AN8855_STP_BLOCKING, + AN8855_STP_LEARNING = 2, + AN8855_STP_FORWARDING = 3 +}; + +/* Register for port control */ +#define AN8855_PCR_P(x) (0x10208004 + ((x) * 0x200)) +#define AN8855_EG_TAG GENMASK(29, 28) +#define AN8855_PORT_PRI GENMASK(26, 24) +#define AN8855_PORT_TX_MIR BIT(20) +#define AN8855_PORT_RX_MIR BIT(16) +#define AN8855_PORT_VLAN GENMASK(1, 0) + +enum an8855_port_mode { + /* Port Matrix Mode: Frames are forwarded by the PCR_MATRIX members. */ + AN8855_PORT_MATRIX_MODE = 0, + + /* Fallback Mode: Forward received frames with ingress ports that do + * not belong to the VLAN member. Frames whose VID is not listed on + * the VLAN table are forwarded by the PCR_MATRIX members. + */ + AN8855_PORT_FALLBACK_MODE = 1, + + /* Check Mode: Forward received frames whose ingress do not + * belong to the VLAN member. Discard frames if VID ismiddes on the + * VLAN table. + */ + AN8855_PORT_CHECK_MODE = 2, + + /* Security Mode: Discard any frame due to ingress membership + * violation or VID missed on the VLAN table. + */ + AN8855_PORT_SECURITY_MODE = 3, +}; + +/* Register for port security control */ +#define AN8855_PSC_P(x) (0x1020800c + ((x) * 0x200)) +#define AN8855_SA_DIS BIT(4) + +/* Register for port vlan control */ +#define AN8855_PVC_P(x) (0x10208010 + ((x) * 0x200)) +#define AN8855_PORT_SPEC_REPLACE_MODE BIT(11) +#define AN8855_PVC_EG_TAG GENMASK(10, 8) +#define AN8855_VLAN_ATTR GENMASK(7, 6) +#define AN8855_PORT_SPEC_TAG BIT(5) +#define AN8855_ACC_FRM GENMASK(1, 0) + +enum an8855_vlan_port_eg_tag { + AN8855_VLAN_EG_DISABLED = 0, + AN8855_VLAN_EG_CONSISTENT = 1, + AN8855_VLAN_EG_UNTAGGED = 4, + AN8855_VLAN_EG_SWAP = 5, + AN8855_VLAN_EG_TAGGED = 6, + AN8855_VLAN_EG_STACK = 7, +}; + +enum an8855_vlan_port_attr { + AN8855_VLAN_USER = 0, + AN8855_VLAN_STACK = 1, + AN8855_VLAN_TRANSPARENT = 3, +}; + +enum an8855_vlan_port_acc_frm { + AN8855_VLAN_ACC_ALL = 0, + AN8855_VLAN_ACC_TAGGED = 1, + AN8855_VLAN_ACC_UNTAGGED = 2, +}; + +#define AN8855_PPBV1_P(x) (0x10208014 + ((x) * 0x200)) +#define AN8855_PPBV_G0_PORT_VID GENMASK(11, 0) + +#define AN8855_PORTMATRIX_P(x) (0x10208044 + ((x) * 0x200)) +#define AN8855_PORTMATRIX GENMASK(5, 0) +/* Port matrix without the CPU port that should never be removed */ +#define AN8855_USER_PORTMATRIX GENMASK(4, 0) + +/* Register for port PVID */ +#define AN8855_PVID_P(x) (0x10208048 + ((x) * 0x200)) +#define AN8855_G0_PORT_VID GENMASK(11, 0) + +/* Register for port MAC control register */ +#define AN8855_PMCR_P(x) (0x10210000 + ((x) * 0x200)) +#define AN8855_PMCR_FORCE_MODE BIT(31) +#define AN8855_PMCR_FORCE_SPEED GENMASK(30, 28) +#define AN8855_PMCR_FORCE_SPEED_5000 FIELD_PREP_CONST(AN8855_PMCR_FORCE_SPEED, 0x4) +#define AN8855_PMCR_FORCE_SPEED_2500 FIELD_PREP_CONST(AN8855_PMCR_FORCE_SPEED, 0x3) +#define AN8855_PMCR_FORCE_SPEED_1000 FIELD_PREP_CONST(AN8855_PMCR_FORCE_SPEED, 0x2) +#define AN8855_PMCR_FORCE_SPEED_100 FIELD_PREP_CONST(AN8855_PMCR_FORCE_SPEED, 0x1) +#define AN8855_PMCR_FORCE_SPEED_10 FIELD_PREP_CONST(AN8855_PMCR_FORCE_SPEED, 0x1) +#define AN8855_PMCR_FORCE_FDX BIT(25) +#define AN8855_PMCR_FORCE_LNK BIT(24) +#define AN8855_PMCR_IFG_XMIT GENMASK(21, 20) +#define AN8855_PMCR_EXT_PHY BIT(19) +#define AN8855_PMCR_MAC_MODE BIT(18) +#define AN8855_PMCR_TX_EN BIT(16) +#define AN8855_PMCR_RX_EN BIT(15) +#define AN8855_PMCR_BACKOFF_EN BIT(12) +#define AN8855_PMCR_BACKPR_EN BIT(11) +#define AN8855_PMCR_FORCE_EEE5G BIT(9) +#define AN8855_PMCR_FORCE_EEE2P5G BIT(8) +#define AN8855_PMCR_FORCE_EEE1G BIT(7) +#define AN8855_PMCR_FORCE_EEE100 BIT(6) +#define AN8855_PMCR_TX_FC_EN BIT(5) +#define AN8855_PMCR_RX_FC_EN BIT(4) + +#define AN8855_PMSR_P(x) (0x10210010 + (x) * 0x200) +#define AN8855_PMSR_SPEED GENMASK(30, 28) +#define AN8855_PMSR_SPEED_5000 FIELD_PREP_CONST(AN8855_PMSR_SPEED, 0x4) +#define AN8855_PMSR_SPEED_2500 FIELD_PREP_CONST(AN8855_PMSR_SPEED, 0x3) +#define AN8855_PMSR_SPEED_1000 FIELD_PREP_CONST(AN8855_PMSR_SPEED, 0x2) +#define AN8855_PMSR_SPEED_100 FIELD_PREP_CONST(AN8855_PMSR_SPEED, 0x1) +#define AN8855_PMSR_SPEED_10 FIELD_PREP_CONST(AN8855_PMSR_SPEED, 0x0) +#define AN8855_PMSR_DPX BIT(25) +#define AN8855_PMSR_LNK BIT(24) +#define AN8855_PMSR_EEE1G BIT(7) +#define AN8855_PMSR_EEE100M BIT(6) +#define AN8855_PMSR_RX_FC BIT(5) +#define AN8855_PMSR_TX_FC BIT(4) + +#define AN8855_PMEEECR_P(x) (0x10210004 + (x) * 0x200) +#define AN8855_LPI_MODE_EN BIT(31) +#define AN8855_WAKEUP_TIME_2500 GENMASK(23, 16) +#define AN8855_WAKEUP_TIME_1000 GENMASK(15, 8) +#define AN8855_WAKEUP_TIME_100 GENMASK(7, 0) +#define AN8855_PMEEECR2_P(x) (0x10210008 + (x) * 0x200) +#define AN8855_WAKEUP_TIME_5000 GENMASK(7, 0) + +#define AN8855_GMACCR 0x10213e00 +#define AN8855_MAX_RX_JUMBO GENMASK(7, 4) +/* 2K for 0x0, 0x1, 0x2 */ +#define AN8855_MAX_RX_JUMBO_2K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x0) +#define AN8855_MAX_RX_JUMBO_3K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x3) +#define AN8855_MAX_RX_JUMBO_4K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x4) +#define AN8855_MAX_RX_JUMBO_5K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x5) +#define AN8855_MAX_RX_JUMBO_6K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x6) +#define AN8855_MAX_RX_JUMBO_7K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x7) +#define AN8855_MAX_RX_JUMBO_8K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x8) +#define AN8855_MAX_RX_JUMBO_9K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0x9) +#define AN8855_MAX_RX_JUMBO_12K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0xa) +#define AN8855_MAX_RX_JUMBO_15K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0xb) +#define AN8855_MAX_RX_JUMBO_16K FIELD_PREP_CONST(AN8855_MAX_RX_JUMBO, 0xc) +#define AN8855_MAX_RX_PKT_LEN GENMASK(1, 0) +#define AN8855_MAX_RX_PKT_1518_1522 FIELD_PREP_CONST(AN8855_MAX_RX_PKT_LEN, 0x0) +#define AN8855_MAX_RX_PKT_1536 FIELD_PREP_CONST(AN8855_MAX_RX_PKT_LEN, 0x1) +#define AN8855_MAX_RX_PKT_1552 FIELD_PREP_CONST(AN8855_MAX_RX_PKT_LEN, 0x2) +#define AN8855_MAX_RX_PKT_JUMBO FIELD_PREP_CONST(AN8855_MAX_RX_PKT_LEN, 0x3) + +#define AN8855_CKGCR 0x10213e1c +#define AN8855_LPI_TXIDLE_THD_MASK GENMASK(31, 14) +#define AN8855_CKG_LNKDN_PORT_STOP BIT(1) +#define AN8855_CKG_LNKDN_GLB_STOP BIT(0) + +/* Register for MIB */ +#define AN8855_PORT_MIB_COUNTER(x) (0x10214000 + (x) * 0x200) +/* Each define is an offset of AN8855_PORT_MIB_COUNTER */ +#define AN8855_PORT_MIB_TX_DROP 0x00 +#define AN8855_PORT_MIB_TX_CRC_ERR 0x04 +#define AN8855_PORT_MIB_TX_UNICAST 0x08 +#define AN8855_PORT_MIB_TX_MULTICAST 0x0c +#define AN8855_PORT_MIB_TX_BROADCAST 0x10 +#define AN8855_PORT_MIB_TX_COLLISION 0x14 +#define AN8855_PORT_MIB_TX_SINGLE_COLLISION 0x18 +#define AN8855_PORT_MIB_TX_MULTIPLE_COLLISION 0x1c +#define AN8855_PORT_MIB_TX_DEFERRED 0x20 +#define AN8855_PORT_MIB_TX_LATE_COLLISION 0x24 +#define AN8855_PORT_MIB_TX_EXCESSIVE_COLLISION 0x28 +#define AN8855_PORT_MIB_TX_PAUSE 0x2c +#define AN8855_PORT_MIB_TX_PKT_SZ_64 0x30 +#define AN8855_PORT_MIB_TX_PKT_SZ_65_TO_127 0x34 +#define AN8855_PORT_MIB_TX_PKT_SZ_128_TO_255 0x38 +#define AN8855_PORT_MIB_TX_PKT_SZ_256_TO_511 0x3 +#define AN8855_PORT_MIB_TX_PKT_SZ_512_TO_1023 0x40 +#define AN8855_PORT_MIB_TX_PKT_SZ_1024_TO_1518 0x44 +#define AN8855_PORT_MIB_TX_PKT_SZ_1519_TO_MAX 0x48 +#define AN8855_PORT_MIB_TX_BYTES 0x4c /* 64 bytes */ +#define AN8855_PORT_MIB_TX_OVERSIZE_DROP 0x54 +#define AN8855_PORT_MIB_TX_BAD_PKT_BYTES 0x58 /* 64 bytes */ +#define AN8855_PORT_MIB_RX_DROP 0x80 +#define AN8855_PORT_MIB_RX_FILTERING 0x84 +#define AN8855_PORT_MIB_RX_UNICAST 0x88 +#define AN8855_PORT_MIB_RX_MULTICAST 0x8c +#define AN8855_PORT_MIB_RX_BROADCAST 0x90 +#define AN8855_PORT_MIB_RX_ALIGN_ERR 0x94 +#define AN8855_PORT_MIB_RX_CRC_ERR 0x98 +#define AN8855_PORT_MIB_RX_UNDER_SIZE_ERR 0x9c +#define AN8855_PORT_MIB_RX_FRAG_ERR 0xa0 +#define AN8855_PORT_MIB_RX_OVER_SZ_ERR 0xa4 +#define AN8855_PORT_MIB_RX_JABBER_ERR 0xa8 +#define AN8855_PORT_MIB_RX_PAUSE 0xac +#define AN8855_PORT_MIB_RX_PKT_SZ_64 0xb0 +#define AN8855_PORT_MIB_RX_PKT_SZ_65_TO_127 0xb4 +#define AN8855_PORT_MIB_RX_PKT_SZ_128_TO_255 0xb8 +#define AN8855_PORT_MIB_RX_PKT_SZ_256_TO_511 0xbc +#define AN8855_PORT_MIB_RX_PKT_SZ_512_TO_1023 0xc0 +#define AN8855_PORT_MIB_RX_PKT_SZ_1024_TO_1518 0xc4 +#define AN8855_PORT_MIB_RX_PKT_SZ_1519_TO_MAX 0xc8 +#define AN8855_PORT_MIB_RX_BYTES 0xcc /* 64 bytes */ +#define AN8855_PORT_MIB_RX_CTRL_DROP 0xd4 +#define AN8855_PORT_MIB_RX_INGRESS_DROP 0xd8 +#define AN8855_PORT_MIB_RX_ARL_DROP 0xdc +#define AN8855_PORT_MIB_FLOW_CONTROL_DROP 0xe0 +#define AN8855_PORT_MIB_WRED_DROP 0xe4 +#define AN8855_PORT_MIB_MIRROR_DROP 0xe8 +#define AN8855_PORT_MIB_RX_BAD_PKT_BYTES 0xec /* 64 bytes */ +#define AN8855_PORT_MIB_RXS_FLOW_SAMPLING_PKT_DROP 0xf4 +#define AN8855_PORT_MIB_RXS_FLOW_TOTAL_PKT_DROP 0xf8 +#define AN8855_PORT_MIB_PORT_CONTROL_DROP 0xfc +#define AN8855_MIB_CCR 0x10213e30 +#define AN8855_CCR_MIB_ENABLE BIT(31) +#define AN8855_CCR_RX_OCT_CNT_GOOD BIT(7) +#define AN8855_CCR_RX_OCT_CNT_BAD BIT(6) +#define AN8855_CCR_TX_OCT_CNT_GOOD BIT(5) +#define AN8855_CCR_TX_OCT_CNT_BAD BIT(4) +#define AN8855_CCR_RX_OCT_CNT_GOOD_2 BIT(3) +#define AN8855_CCR_RX_OCT_CNT_BAD_2 BIT(2) +#define AN8855_CCR_TX_OCT_CNT_GOOD_2 BIT(1) +#define AN8855_CCR_TX_OCT_CNT_BAD_2 BIT(0) +#define AN8855_CCR_MIB_ACTIVATE (AN8855_CCR_MIB_ENABLE | \ + AN8855_CCR_RX_OCT_CNT_GOOD | \ + AN8855_CCR_RX_OCT_CNT_BAD | \ + AN8855_CCR_TX_OCT_CNT_GOOD | \ + AN8855_CCR_TX_OCT_CNT_BAD | \ + AN8855_CCR_RX_OCT_CNT_BAD_2 | \ + AN8855_CCR_TX_OCT_CNT_BAD_2) +#define AN8855_MIB_CLR 0x10213e34 +#define AN8855_MIB_PORT6_CLR BIT(6) +#define AN8855_MIB_PORT5_CLR BIT(5) +#define AN8855_MIB_PORT4_CLR BIT(4) +#define AN8855_MIB_PORT3_CLR BIT(3) +#define AN8855_MIB_PORT2_CLR BIT(2) +#define AN8855_MIB_PORT1_CLR BIT(1) +#define AN8855_MIB_PORT0_CLR BIT(0) + +/* HSGMII/SGMII Configuration register */ +/* AN8855_HSGMII_AN_CSR_BASE 0x10220000 */ +#define AN8855_SGMII_REG_AN0 0x10220000 +/* AN8855_SGMII_AN_ENABLE BMCR_ANENABLE */ +/* AN8855_SGMII_AN_RESTART BMCR_ANRESTART */ +#define AN8855_SGMII_REG_AN_13 0x10220034 +#define AN8855_SGMII_REMOTE_FAULT_DIS BIT(8) +#define AN8855_SGMII_IF_MODE GENMASK(5, 0) +#define AN8855_SGMII_REG_AN_FORCE_CL37 0x10220060 +#define AN8855_RG_FORCE_AN_DONE BIT(0) + +/* AN8855_HSGMII_CSR_PCS_BASE 0x10220000 */ +#define AN8855_RG_HSGMII_PCS_CTROL_1 0x10220a00 +#define AN8855_RG_TBI_10B_MODE BIT(30) +#define AN8855_RG_AN_SGMII_MODE_FORCE 0x10220a24 +#define AN8855_RG_FORCE_CUR_SGMII_MODE GENMASK(5, 4) +#define AN8855_RG_FORCE_CUR_SGMII_SEL BIT(0) + +/* AN8855_MULTI_SGMII_CSR_BASE 0x10224000 */ +#define AN8855_SGMII_STS_CTRL_0 0x10224018 +#define AN8855_RG_LINK_MODE_P0 GENMASK(5, 4) +#define AN8855_RG_LINK_MODE_P0_SPEED_2500 FIELD_PREP_CONST(AN8855_RG_LINK_MODE_P0, 0x3) +#define AN8855_RG_LINK_MODE_P0_SPEED_1000 FIELD_PREP_CONST(AN8855_RG_LINK_MODE_P0, 0x2) +#define AN8855_RG_LINK_MODE_P0_SPEED_100 FIELD_PREP_CONST(AN8855_RG_LINK_MODE_P0, 0x1) +#define AN8855_RG_LINK_MODE_P0_SPEED_10 FIELD_PREP_CONST(AN8855_RG_LINK_MODE_P0, 0x0) +#define AN8855_RG_FORCE_SPD_MODE_P0 BIT(2) +#define AN8855_MSG_RX_CTRL_0 0x10224100 +#define AN8855_MSG_RX_LIK_STS_0 0x10224514 +#define AN8855_RG_DPX_STS_P3 BIT(24) +#define AN8855_RG_DPX_STS_P2 BIT(16) +#define AN8855_RG_EEE1G_STS_P1 BIT(12) +#define AN8855_RG_DPX_STS_P1 BIT(8) +#define AN8855_RG_TXFC_STS_P0 BIT(2) +#define AN8855_RG_RXFC_STS_P0 BIT(1) +#define AN8855_RG_DPX_STS_P0 BIT(0) +#define AN8855_MSG_RX_LIK_STS_2 0x1022451c +#define AN8855_RG_RXFC_AN_BYPASS_P3 BIT(11) +#define AN8855_RG_RXFC_AN_BYPASS_P2 BIT(10) +#define AN8855_RG_RXFC_AN_BYPASS_P1 BIT(9) +#define AN8855_RG_TXFC_AN_BYPASS_P3 BIT(7) +#define AN8855_RG_TXFC_AN_BYPASS_P2 BIT(6) +#define AN8855_RG_TXFC_AN_BYPASS_P1 BIT(5) +#define AN8855_RG_DPX_AN_BYPASS_P3 BIT(3) +#define AN8855_RG_DPX_AN_BYPASS_P2 BIT(2) +#define AN8855_RG_DPX_AN_BYPASS_P1 BIT(1) +#define AN8855_RG_DPX_AN_BYPASS_P0 BIT(0) +#define AN8855_PHY_RX_FORCE_CTRL_0 0x10224520 +#define AN8855_RG_FORCE_TXC_SEL BIT(4) + +/* AN8855_XFI_CSR_PCS_BASE 0x10225000 */ +#define AN8855_RG_USXGMII_AN_CONTROL_0 0x10225bf8 + +/* AN8855_MULTI_PHY_RA_CSR_BASE 0x10226000 */ +#define AN8855_RG_RATE_ADAPT_CTRL_0 0x10226000 +#define AN8855_RG_RATE_ADAPT_RX_BYPASS BIT(27) +#define AN8855_RG_RATE_ADAPT_TX_BYPASS BIT(26) +#define AN8855_RG_RATE_ADAPT_RX_EN BIT(4) +#define AN8855_RG_RATE_ADAPT_TX_EN BIT(0) +#define AN8855_RATE_ADP_P0_CTRL_0 0x10226100 +#define AN8855_RG_P0_DIS_MII_MODE BIT(31) +#define AN8855_RG_P0_MII_MODE BIT(28) +#define AN8855_RG_P0_MII_RA_RX_EN BIT(3) +#define AN8855_RG_P0_MII_RA_TX_EN BIT(2) +#define AN8855_RG_P0_MII_RA_RX_MODE BIT(1) +#define AN8855_RG_P0_MII_RA_TX_MODE BIT(0) +#define AN8855_MII_RA_AN_ENABLE 0x10226300 +#define AN8855_RG_P0_RA_AN_EN BIT(0) + +/* AN8855_QP_DIG_CSR_BASE 0x1022a000 */ +#define AN8855_QP_CK_RST_CTRL_4 0x1022a310 +#define AN8855_QP_DIG_MODE_CTRL_0 0x1022a324 +#define AN8855_RG_SGMII_MODE GENMASK(5, 4) +#define AN8855_RG_SGMII_AN_EN BIT(0) +#define AN8855_QP_DIG_MODE_CTRL_1 0x1022a330 +#define AN8855_RG_TPHY_SPEED GENMASK(3, 2) + +/* AN8855_SERDES_WRAPPER_BASE 0x1022c000 */ +#define AN8855_USGMII_CTRL_0 0x1022c000 + +/* AN8855_QP_PMA_TOP_BASE 0x1022e000 */ +#define AN8855_PON_RXFEDIG_CTRL_0 0x1022e100 +#define AN8855_RG_QP_EQ_RX500M_CK_SEL BIT(12) +#define AN8855_PON_RXFEDIG_CTRL_9 0x1022e124 +#define AN8855_RG_QP_EQ_LEQOSC_DLYCNT GENMASK(2, 0) + +#define AN8855_SS_LCPLL_PWCTL_SETTING_2 0x1022e208 +#define AN8855_RG_NCPO_ANA_MSB GENMASK(17, 16) +#define AN8855_SS_LCPLL_TDC_FLT_2 0x1022e230 +#define AN8855_RG_LCPLL_NCPO_VALUE GENMASK(30, 0) +#define AN8855_SS_LCPLL_TDC_FLT_5 0x1022e23c +#define AN8855_RG_LCPLL_NCPO_CHG BIT(24) +#define AN8855_SS_LCPLL_TDC_PCW_1 0x1022e248 +#define AN8855_RG_LCPLL_PON_HRDDS_PCW_NCPO_GPON GENMASK(30, 0) +#define AN8855_INTF_CTRL_8 0x1022e320 +#define AN8855_INTF_CTRL_9 0x1022e324 +#define AN8855_INTF_CTRL_10 0x1022e328 +#define AN8855_RG_DA_QP_TX_FIR_C2_SEL BIT(29) +#define AN8855_RG_DA_QP_TX_FIR_C2_FORCE GENMASK(28, 24) +#define AN8855_RG_DA_QP_TX_FIR_C1_SEL BIT(21) +#define AN8855_RG_DA_QP_TX_FIR_C1_FORCE GENMASK(20, 16) +#define AN8855_INTF_CTRL_11 0x1022e32c +#define AN8855_RG_DA_QP_TX_FIR_C0B_SEL BIT(6) +#define AN8855_RG_DA_QP_TX_FIR_C0B_FORCE GENMASK(5, 0) +#define AN8855_PLL_CTRL_0 0x1022e400 +#define AN8855_RG_PHYA_AUTO_INIT BIT(0) +#define AN8855_PLL_CTRL_2 0x1022e408 +#define AN8855_RG_DA_QP_PLL_SDM_IFM_INTF BIT(30) +#define AN8855_RG_DA_QP_PLL_RICO_SEL_INTF BIT(29) +#define AN8855_RG_DA_QP_PLL_POSTDIV_EN_INTF BIT(28) +#define AN8855_RG_DA_QP_PLL_PHY_CK_EN_INTF BIT(27) +#define AN8855_RG_DA_QP_PLL_PFD_OFFSET_EN_INTRF BIT(26) +#define AN8855_RG_DA_QP_PLL_PFD_OFFSET_INTF GENMASK(25, 24) +#define AN8855_RG_DA_QP_PLL_PCK_SEL_INTF BIT(22) +#define AN8855_RG_DA_QP_PLL_KBAND_PREDIV_INTF GENMASK(21, 20) +#define AN8855_RG_DA_QP_PLL_IR_INTF GENMASK(19, 16) +#define AN8855_RG_DA_QP_PLL_ICOIQ_EN_INTF BIT(14) +#define AN8855_RG_DA_QP_PLL_FBKSEL_INTF GENMASK(13, 12) +#define AN8855_RG_DA_QP_PLL_BR_INTF GENMASK(10, 8) +#define AN8855_RG_DA_QP_PLL_BPD_INTF GENMASK(7, 6) +#define AN8855_RG_DA_QP_PLL_BPA_INTF GENMASK(4, 2) +#define AN8855_RG_DA_QP_PLL_BC_INTF GENMASK(1, 0) +#define AN8855_PLL_CTRL_3 0x1022e40c +#define AN8855_RG_DA_QP_PLL_SSC_PERIOD_INTF GENMASK(31, 16) +#define AN8855_RG_DA_QP_PLL_SSC_DELTA_INTF GENMASK(15, 0) +#define AN8855_PLL_CTRL_4 0x1022e410 +#define AN8855_RG_DA_QP_PLL_SDM_HREN_INTF GENMASK(4, 3) +#define AN8855_RG_DA_QP_PLL_ICOLP_EN_INTF BIT(2) +#define AN8855_RG_DA_QP_PLL_SSC_DIR_DLY_INTF GENMASK(1, 0) +#define AN8855_PLL_CK_CTRL_0 0x1022e414 +#define AN8855_RG_DA_QP_PLL_TDC_TXCK_SEL_INTF BIT(9) +#define AN8855_RG_DA_QP_PLL_SDM_DI_EN_INTF BIT(8) +#define AN8855_RX_DLY_0 0x1022e614 +#define AN8855_RG_QP_RX_SAOSC_EN_H_DLY GENMASK(13, 8) +#define AN8855_RG_QP_RX_PI_CAL_EN_H_DLY GENMASK(7, 0) +#define AN8855_RX_CTRL_2 0x1022e630 +#define AN8855_RG_QP_RX_EQ_EN_H_DLY GENMASK(28, 16) +#define AN8855_RX_CTRL_5 0x1022e63c +#define AN8855_RG_FREDET_CHK_CYCLE GENMASK(29, 10) +#define AN8855_RX_CTRL_6 0x1022e640 +#define AN8855_RG_FREDET_GOLDEN_CYCLE GENMASK(19, 0) +#define AN8855_RX_CTRL_7 0x1022e644 +#define AN8855_RG_FREDET_TOLERATE_CYCLE GENMASK(19, 0) +#define AN8855_RX_CTRL_8 0x1022e648 +#define AN8855_RG_DA_QP_SAOSC_DONE_TIME GENMASK(27, 16) +#define AN8855_RG_DA_QP_LEQOS_EN_TIME GENMASK(14, 0) +#define AN8855_RX_CTRL_26 0x1022e690 +#define AN8855_RG_QP_EQ_RETRAIN_ONLY_EN BIT(26) +#define AN8855_RG_LINK_NE_EN BIT(24) +#define AN8855_RG_LINK_ERRO_EN BIT(23) +#define AN8855_RX_CTRL_42 0x1022e6d0 +#define AN8855_RG_QP_EQ_EN_DLY GENMASK(12, 0) + +/* AN8855_QP_ANA_CSR_BASE 0x1022f000 */ +#define AN8855_RG_QP_RX_DAC_EN 0x1022f000 +#define AN8855_RG_QP_SIGDET_HF GENMASK(17, 16) +#define AN8855_RG_QP_RXAFE_RESERVE 0x1022f004 +#define AN8855_RG_QP_CDR_PD_10B_EN BIT(11) +#define AN8855_RG_QP_CDR_LPF_BOT_LIM 0x1022f008 +#define AN8855_RG_QP_CDR_LPF_KP_GAIN GENMASK(26, 24) +#define AN8855_RG_QP_CDR_LPF_KI_GAIN GENMASK(22, 20) +#define AN8855_RG_QP_CDR_LPF_MJV_LIM 0x1022f00c +#define AN8855_RG_QP_CDR_LPF_RATIO GENMASK(5, 4) +#define AN8855_RG_QP_CDR_LPF_SETVALUE 0x1022f014 +#define AN8855_RG_QP_CDR_PR_BUF_IN_SR GENMASK(31, 29) +#define AN8855_RG_QP_CDR_PR_BETA_SEL GENMASK(28, 25) +#define AN8855_RG_QP_CDR_PR_CKREF_DIV1 0x1022f018 +#define AN8855_RG_QP_CDR_PR_KBAND_DIV GENMASK(26, 24) +#define AN8855_RG_QP_CDR_PR_DAC_BAND GENMASK(12, 8) +#define AN8855_RG_QP_CDR_PR_KBAND_DIV_PCIE 0x1022f01c +#define AN8855_RG_QP_CDR_PR_XFICK_EN BIT(30) +#define AN8855_RG_QP_CDR_PR_KBAND_PCIE_MODE BIT(6) +#define AN8855_RG_QP_CDR_PR_KBAND_DIV_PCIE_MASK GENMASK(5, 0) +#define AN8855_RG_QP_CDR_FORCE_IBANDLPF_R_OFF 0x1022f020 +#define AN8855_RG_QP_CDR_PHYCK_SEL GENMASK(17, 16) +#define AN8855_RG_QP_CDR_PHYCK_RSTB BIT(13) +#define AN8855_RG_QP_CDR_PHYCK_DIV GENMASK(12, 6) +#define AN8855_RG_QP_TX_MODE 0x1022f028 +#define AN8855_RG_QP_TX_RESERVE GENMASK(31, 16) +#define AN8855_RG_QP_TX_MODE_16B_EN BIT(0) +#define AN8855_RG_QP_PLL_IPLL_DIG_PWR_SEL 0x1022f03c +#define AN8855_RG_QP_PLL_SDM_ORD 0x1022f040 +#define AN8855_RG_QP_PLL_SSC_PHASE_INI BIT(4) +#define AN8855_RG_QP_PLL_SSC_TRI_EN BIT(3) + +/* AN8855_ETHER_SYS_BASE 0x1028c800 */ +#define AN8855_RG_GPHY_AFE_PWD 0x1028c840 +#define AN8855_RG_GPHY_SMI_ADDR 0x1028c848 + +#define MIB_DESC(_s, _o, _n) \ + { \ + .size = (_s), \ + .offset = (_o), \ + .name = (_n), \ + } + +struct an8855_mib_desc { + unsigned int size; + unsigned int offset; + const char *name; +}; + +struct an8855_fdb { + u16 vid; + u8 port_mask; + u16 aging; + u8 mac[6]; + bool noarp; + u8 live; + u8 type; + u8 fid; + u8 ivl; +}; + +struct an8855_priv { + struct device *dev; + struct dsa_switch *ds; + struct regmap *regmap; + struct gpio_desc *reset_gpio; + /* Protect ATU or VLAN table access */ + struct mutex reg_mutex; + + struct phylink_pcs pcs; + + u8 mirror_rx; + u8 mirror_tx; + u8 port_isolated_map; + + bool phy_require_calib; +}; + +#endif /* __AN8855_H */ diff --git a/lede/target/linux/mediatek/files/drivers/net/mdio/mdio-an8855.c b/lede/target/linux/mediatek/files/drivers/net/mdio/mdio-an8855.c new file mode 100644 index 0000000000..5feba72c02 --- /dev/null +++ b/lede/target/linux/mediatek/files/drivers/net/mdio/mdio-an8855.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * MDIO passthrough driver for Airoha AN8855 Switch + */ + +#include +#include +#include +#include + +static int an855_phy_restore_page(struct an8855_mfd_priv *priv, + int phy) __must_hold(&priv->bus->mdio_lock) +{ + /* Check PHY page only for addr shared with switch */ + if (phy != priv->switch_addr) + return 0; + + /* Don't restore page if it's not set to switch page */ + if (priv->current_page != FIELD_GET(AN8855_PHY_PAGE, + AN8855_PHY_PAGE_EXTENDED_4)) + return 0; + + /* Restore page to 0, PHY might change page right after but that + * will be ignored as it won't be a switch page. + */ + return an8855_mii_set_page(priv, phy, AN8855_PHY_PAGE_STANDARD); +} + +static int an8855_phy_read(struct mii_bus *bus, int phy, int regnum) +{ + struct an8855_mfd_priv *priv = bus->priv; + struct mii_bus *real_bus = priv->bus; + int ret; + + mutex_lock_nested(&real_bus->mdio_lock, MDIO_MUTEX_NESTED); + + ret = an855_phy_restore_page(priv, phy); + if (ret) + goto exit; + + ret = __mdiobus_read(real_bus, phy, regnum); +exit: + mutex_unlock(&real_bus->mdio_lock); + + return ret; +} + +static int an8855_phy_write(struct mii_bus *bus, int phy, int regnum, u16 val) +{ + struct an8855_mfd_priv *priv = bus->priv; + struct mii_bus *real_bus = priv->bus; + int ret; + + mutex_lock_nested(&real_bus->mdio_lock, MDIO_MUTEX_NESTED); + + ret = an855_phy_restore_page(priv, phy); + if (ret) + goto exit; + + ret = __mdiobus_write(real_bus, phy, regnum, val); +exit: + mutex_unlock(&real_bus->mdio_lock); + + return ret; +} + +static int an8855_mdio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct an8855_mfd_priv *priv; + struct mii_bus *bus; + int ret; + + /* Get priv of MFD */ + priv = dev_get_drvdata(dev->parent); + + bus = devm_mdiobus_alloc(dev); + if (!bus) + return -ENOMEM; + + bus->priv = priv; + bus->name = KBUILD_MODNAME "-mii"; + snprintf(bus->id, MII_BUS_ID_SIZE, KBUILD_MODNAME "-%d", + priv->switch_addr); + bus->parent = dev; + bus->read = an8855_phy_read; + bus->write = an8855_phy_write; + + ret = devm_of_mdiobus_register(dev, bus, dev->of_node); + if (ret) + return dev_err_probe(dev, ret, "failed to register MDIO bus\n"); + + return ret; +} + +static const struct of_device_id an8855_mdio_of_match[] = { + { .compatible = "airoha,an8855-mdio", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, an8855_mdio_of_match); + +static struct platform_driver an8855_mdio_driver = { + .probe = an8855_mdio_probe, + .driver = { + .name = "an8855-mdio", + .of_match_table = an8855_mdio_of_match, + }, +}; +module_platform_driver(an8855_mdio_driver); + +MODULE_AUTHOR("Christian Marangi "); +MODULE_DESCRIPTION("Driver for AN8855 MDIO passthrough"); +MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/mediatek/files/drivers/net/phy/air_an8855.c b/lede/target/linux/mediatek/files/drivers/net/phy/air_an8855.c new file mode 100644 index 0000000000..7fab0854ef --- /dev/null +++ b/lede/target/linux/mediatek/files/drivers/net/phy/air_an8855.c @@ -0,0 +1,267 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2024 Christian Marangi + */ + +#include +#include +#include +#include + +#define AN8855_PHY_SELECT_PAGE 0x1f +#define AN8855_PHY_PAGE GENMASK(2, 0) +#define AN8855_PHY_PAGE_STANDARD FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x0) +#define AN8855_PHY_PAGE_EXTENDED_1 FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x1) + +/* MII Registers Page 1 */ +#define AN8855_PHY_EXT_REG_14 0x14 +#define AN8855_PHY_EN_DOWN_SHIFT BIT(4) + +/* R50 Calibration regs in MDIO_MMD_VEND1 */ +#define AN8855_PHY_R500HM_RSEL_TX_AB 0x174 +#define AN8855_PHY_R50OHM_RSEL_TX_A_EN BIT(15) +#define AN8855_PHY_R50OHM_RSEL_TX_A GENMASK(14, 8) +#define AN8855_PHY_R50OHM_RSEL_TX_B_EN BIT(7) +#define AN8855_PHY_R50OHM_RSEL_TX_B GENMASK(6, 0) +#define AN8855_PHY_R500HM_RSEL_TX_CD 0x175 +#define AN8855_PHY_R50OHM_RSEL_TX_C_EN BIT(15) +#define AN8855_PHY_R50OHM_RSEL_TX_C GENMASK(14, 8) +#define AN8855_PHY_R50OHM_RSEL_TX_D_EN BIT(7) +#define AN8855_PHY_R50OHM_RSEL_TX_D GENMASK(6, 0) + +#define AN8855_SWITCH_EFUSE_R50O GENMASK(30, 24) + +/* PHY TX PAIR DELAY SELECT Register */ +#define AN8855_PHY_TX_PAIR_DLY_SEL_GBE 0x013 +#define AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_A_GBE GENMASK(14, 12) +#define AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_B_GBE GENMASK(10, 8) +#define AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_C_GBE GENMASK(6, 4) +#define AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_D_GBE GENMASK(2, 0) +/* PHY ADC Register */ +#define AN8855_PHY_RXADC_CTRL 0x0d8 +#define AN8855_PHY_RG_AD_SAMNPLE_PHSEL_A BIT(12) +#define AN8855_PHY_RG_AD_SAMNPLE_PHSEL_B BIT(8) +#define AN8855_PHY_RG_AD_SAMNPLE_PHSEL_C BIT(4) +#define AN8855_PHY_RG_AD_SAMNPLE_PHSEL_D BIT(0) +#define AN8855_PHY_RXADC_REV_0 0x0d9 +#define AN8855_PHY_RG_AD_RESERVE0_A GENMASK(15, 8) +#define AN8855_PHY_RG_AD_RESERVE0_B GENMASK(7, 0) +#define AN8855_PHY_RXADC_REV_1 0x0da +#define AN8855_PHY_RG_AD_RESERVE0_C GENMASK(15, 8) +#define AN8855_PHY_RG_AD_RESERVE0_D GENMASK(7, 0) + +#define AN8855_PHY_ID 0xc0ff0410 + +#define AN8855_PHY_FLAGS_EN_CALIBRATION BIT(0) + +struct air_an8855_priv { + u8 calibration_data[4]; +}; + +static const u8 dsa_r50ohm_table[] = { + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 126, 122, 117, + 112, 109, 104, 101, 97, 94, 90, 88, 84, 80, + 78, 74, 72, 68, 66, 64, 61, 58, 56, 53, + 51, 48, 47, 44, 42, 40, 38, 36, 34, 32, + 31, 28, 27, 24, 24, 22, 20, 18, 16, 16, + 14, 12, 11, 9 +}; + +static int en8855_get_r50ohm_val(struct device *dev, const char *calib_name, + u8 *dest) +{ + u32 shift_sel, val; + int ret; + int i; + + ret = nvmem_cell_read_u32(dev, calib_name, &val); + if (ret) + return ret; + + shift_sel = FIELD_GET(AN8855_SWITCH_EFUSE_R50O, val); + for (i = 0; i < ARRAY_SIZE(dsa_r50ohm_table); i++) + if (dsa_r50ohm_table[i] == shift_sel) + break; + + if (i < 8 || i >= ARRAY_SIZE(dsa_r50ohm_table)) + *dest = dsa_r50ohm_table[25]; + else + *dest = dsa_r50ohm_table[i - 8]; + + return 0; +} + +static int an8855_probe(struct phy_device *phydev) +{ + struct device *dev = &phydev->mdio.dev; + struct device_node *node = dev->of_node; + struct air_an8855_priv *priv; + + /* If we don't have a node, skip calib */ + if (!node) + return 0; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + phydev->priv = priv; + + return 0; +} + +static int an8855_get_downshift(struct phy_device *phydev, u8 *data) +{ + int val; + + val = phy_read_paged(phydev, AN8855_PHY_PAGE_EXTENDED_1, AN8855_PHY_EXT_REG_14); + if (val < 0) + return val; + + *data = val & AN8855_PHY_EN_DOWN_SHIFT ? DOWNSHIFT_DEV_DEFAULT_COUNT : + DOWNSHIFT_DEV_DISABLE; + + return 0; +} + +static int an8855_set_downshift(struct phy_device *phydev, u8 cnt) +{ + u16 ds = cnt != DOWNSHIFT_DEV_DISABLE ? AN8855_PHY_EN_DOWN_SHIFT : 0; + + return phy_modify_paged(phydev, AN8855_PHY_PAGE_EXTENDED_1, + AN8855_PHY_EXT_REG_14, AN8855_PHY_EN_DOWN_SHIFT, + ds); +} + +static int an8855_config_init(struct phy_device *phydev) +{ + struct air_an8855_priv *priv = phydev->priv; + struct device *dev = &phydev->mdio.dev; + int ret; + + /* Enable HW auto downshift */ + ret = an8855_set_downshift(phydev, DOWNSHIFT_DEV_DEFAULT_COUNT); + if (ret) + return ret; + + /* Apply calibration values, if needed. + * AN8855_PHY_FLAGS_EN_CALIBRATION signal this. + */ + if (priv && phydev->dev_flags & AN8855_PHY_FLAGS_EN_CALIBRATION) { + u8 *calibration_data = priv->calibration_data; + + ret = en8855_get_r50ohm_val(dev, "tx_a", &calibration_data[0]); + if (ret) + return ret; + + ret = en8855_get_r50ohm_val(dev, "tx_b", &calibration_data[1]); + if (ret) + return ret; + + ret = en8855_get_r50ohm_val(dev, "tx_c", &calibration_data[2]); + if (ret) + return ret; + + ret = en8855_get_r50ohm_val(dev, "tx_d", &calibration_data[3]); + if (ret) + return ret; + + ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_R500HM_RSEL_TX_AB, + AN8855_PHY_R50OHM_RSEL_TX_A | AN8855_PHY_R50OHM_RSEL_TX_B, + FIELD_PREP(AN8855_PHY_R50OHM_RSEL_TX_A, calibration_data[0]) | + FIELD_PREP(AN8855_PHY_R50OHM_RSEL_TX_B, calibration_data[1])); + if (ret) + return ret; + ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_R500HM_RSEL_TX_CD, + AN8855_PHY_R50OHM_RSEL_TX_C | AN8855_PHY_R50OHM_RSEL_TX_D, + FIELD_PREP(AN8855_PHY_R50OHM_RSEL_TX_C, calibration_data[2]) | + FIELD_PREP(AN8855_PHY_R50OHM_RSEL_TX_D, calibration_data[3])); + if (ret) + return ret; + } + + /* Apply values to reduce signal noise */ + ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_TX_PAIR_DLY_SEL_GBE, + FIELD_PREP(AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_A_GBE, 0x4) | + FIELD_PREP(AN8855_PHY_CR_DA_TX_PAIR_DELKAY_SEL_C_GBE, 0x4)); + if (ret) + return ret; + ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_RXADC_CTRL, + AN8855_PHY_RG_AD_SAMNPLE_PHSEL_A | + AN8855_PHY_RG_AD_SAMNPLE_PHSEL_C); + if (ret) + return ret; + ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_RXADC_REV_0, + FIELD_PREP(AN8855_PHY_RG_AD_RESERVE0_A, 0x1)); + if (ret) + return ret; + ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, AN8855_PHY_RXADC_REV_1, + FIELD_PREP(AN8855_PHY_RG_AD_RESERVE0_C, 0x1)); + if (ret) + return ret; + + return 0; +} + +static int an8855_get_tunable(struct phy_device *phydev, + struct ethtool_tunable *tuna, void *data) +{ + switch (tuna->id) { + case ETHTOOL_PHY_DOWNSHIFT: + return an8855_get_downshift(phydev, data); + default: + return -EOPNOTSUPP; + } +} + +static int an8855_set_tunable(struct phy_device *phydev, + struct ethtool_tunable *tuna, const void *data) +{ + switch (tuna->id) { + case ETHTOOL_PHY_DOWNSHIFT: + return an8855_set_downshift(phydev, *(const u8 *)data); + default: + return -EOPNOTSUPP; + } +} + +static int an8855_read_page(struct phy_device *phydev) +{ + return __phy_read(phydev, AN8855_PHY_SELECT_PAGE); +} + +static int an8855_write_page(struct phy_device *phydev, int page) +{ + return __phy_write(phydev, AN8855_PHY_SELECT_PAGE, page); +} + +static struct phy_driver an8855_driver[] = { +{ + PHY_ID_MATCH_EXACT(AN8855_PHY_ID), + .name = "Airoha AN8855 internal PHY", + /* PHY_GBIT_FEATURES */ + .flags = PHY_IS_INTERNAL, + .probe = an8855_probe, + .config_init = an8855_config_init, + .soft_reset = genphy_soft_reset, + .get_tunable = an8855_get_tunable, + .set_tunable = an8855_set_tunable, + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_page = an8855_read_page, + .write_page = an8855_write_page, +}, }; + +module_phy_driver(an8855_driver); + +static struct mdio_device_id __maybe_unused an8855_tbl[] = { + { PHY_ID_MATCH_EXACT(AN8855_PHY_ID) }, + { } +}; + +MODULE_DEVICE_TABLE(mdio, an8855_tbl); + +MODULE_DESCRIPTION("Airoha AN8855 PHY driver"); +MODULE_AUTHOR("Christian Marangi "); +MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/mediatek/files/drivers/nvmem/an8855-efuse.c b/lede/target/linux/mediatek/files/drivers/nvmem/an8855-efuse.c new file mode 100644 index 0000000000..7940453d6e --- /dev/null +++ b/lede/target/linux/mediatek/files/drivers/nvmem/an8855-efuse.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Airoha AN8855 Switch EFUSE Driver + */ + +#include +#include +#include +#include +#include + +#define AN8855_EFUSE_CELL 50 + +#define AN8855_EFUSE_DATA0 0x1000a500 +#define AN8855_EFUSE_R50O GENMASK(30, 24) + +static int an8855_efuse_read(void *context, unsigned int offset, + void *val, size_t bytes) +{ + struct regmap *regmap = context; + + return regmap_bulk_read(regmap, AN8855_EFUSE_DATA0 + offset, + val, bytes / sizeof(u32)); +} + +static int an8855_efuse_probe(struct platform_device *pdev) +{ + struct nvmem_config an8855_nvmem_config = { + .name = "an8855-efuse", + .size = AN8855_EFUSE_CELL * sizeof(u32), + .stride = sizeof(u32), + .word_size = sizeof(u32), + .reg_read = an8855_efuse_read, + }; + struct device *dev = &pdev->dev; + struct nvmem_device *nvmem; + + /* Assign NVMEM priv to MFD regmap */ + an8855_nvmem_config.priv = dev_get_regmap(dev->parent, NULL); + an8855_nvmem_config.dev = dev; + nvmem = devm_nvmem_register(dev, &an8855_nvmem_config); + + return PTR_ERR_OR_ZERO(nvmem); +} + +static const struct of_device_id an8855_efuse_of_match[] = { + { .compatible = "airoha,an8855-efuse", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, an8855_efuse_of_match); + +static struct platform_driver an8855_efuse_driver = { + .probe = an8855_efuse_probe, + .driver = { + .name = "an8855-efuse", + .of_match_table = an8855_efuse_of_match, + }, +}; +module_platform_driver(an8855_efuse_driver); + +MODULE_AUTHOR("Christian Marangi "); +MODULE_DESCRIPTION("Driver for AN8855 Switch EFUSE"); +MODULE_LICENSE("GPL"); diff --git a/lede/target/linux/mediatek/files/include/linux/mfd/airoha-an8855-mfd.h b/lede/target/linux/mediatek/files/include/linux/mfd/airoha-an8855-mfd.h new file mode 100644 index 0000000000..56061566a0 --- /dev/null +++ b/lede/target/linux/mediatek/files/include/linux/mfd/airoha-an8855-mfd.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * MFD driver for Airoha AN8855 Switch + */ +#ifndef _LINUX_INCLUDE_MFD_AIROHA_AN8855_MFD_H +#define _LINUX_INCLUDE_MFD_AIROHA_AN8855_MFD_H + +#include + +/* MII Registers */ +#define AN8855_PHY_SELECT_PAGE 0x1f +#define AN8855_PHY_PAGE GENMASK(2, 0) +#define AN8855_PHY_PAGE_STANDARD FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x0) +#define AN8855_PHY_PAGE_EXTENDED_1 FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x1) +#define AN8855_PHY_PAGE_EXTENDED_4 FIELD_PREP_CONST(AN8855_PHY_PAGE, 0x4) + +/* MII Registers Page 4 */ +#define AN8855_PBUS_MODE 0x10 +#define AN8855_PBUS_MODE_ADDR_FIXED 0x0 +#define AN8855_PBUS_MODE_ADDR_INCR BIT(15) +#define AN8855_PBUS_WR_ADDR_HIGH 0x11 +#define AN8855_PBUS_WR_ADDR_LOW 0x12 +#define AN8855_PBUS_WR_DATA_HIGH 0x13 +#define AN8855_PBUS_WR_DATA_LOW 0x14 +#define AN8855_PBUS_RD_ADDR_HIGH 0x15 +#define AN8855_PBUS_RD_ADDR_LOW 0x16 +#define AN8855_PBUS_RD_DATA_HIGH 0x17 +#define AN8855_PBUS_RD_DATA_LOW 0x18 + +struct an8855_mfd_priv { + struct device *dev; + struct mii_bus *bus; + + unsigned int switch_addr; + u16 current_page; +}; + +int an8855_mii_set_page(struct an8855_mfd_priv *priv, u8 phy_id, + u8 page); + +#endif diff --git a/lede/target/linux/mediatek/filogic/config-6.6 b/lede/target/linux/mediatek/filogic/config-6.6 index cb36d74e1d..430929d96d 100644 --- a/lede/target/linux/mediatek/filogic/config-6.6 +++ b/lede/target/linux/mediatek/filogic/config-6.6 @@ -1,5 +1,6 @@ CONFIG_64BIT=y # CONFIG_AHCI_MTK is not set +CONFIG_AIR_AN8855_PHY=y CONFIG_AIROHA_EN8801SC_PHY=y CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y @@ -240,12 +241,14 @@ CONFIG_MAXLINEAR_GPHY=y CONFIG_MDIO_BUS=y CONFIG_MDIO_DEVICE=y CONFIG_MDIO_DEVRES=y +CONFIG_MDIO_AN8855=y CONFIG_MEDIATEK_2P5GE_PHY=y CONFIG_MEDIATEK_GE_PHY=y CONFIG_MEDIATEK_GE_SOC_PHY=y CONFIG_MEDIATEK_WATCHDOG=y CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7 CONFIG_MFD_SYSCON=y +CONFIG_MFD_AIROHA_AN8855=y CONFIG_MIGRATION=y # CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY is not set CONFIG_MMC=y @@ -294,6 +297,7 @@ CONFIG_NEED_DMA_MAP_STATE=y CONFIG_NEED_SG_DMA_LENGTH=y CONFIG_NET_DEVLINK=y CONFIG_NET_DSA=y +CONFIG_NET_DSA_AN8855=y CONFIG_NET_DSA_MT7530=y CONFIG_NET_DSA_MT7530_MDIO=y CONFIG_NET_DSA_MT7530_MMIO=y @@ -312,6 +316,7 @@ CONFIG_NO_HZ_COMMON=y CONFIG_NO_HZ_IDLE=y CONFIG_NR_CPUS=4 CONFIG_NVMEM=y +CONFIG_NVMEM_AN8855_EFUSE=y CONFIG_NVMEM_BLOCK=y CONFIG_NVMEM_LAYOUTS=y CONFIG_NVMEM_MTK_EFUSE=y diff --git a/lede/target/linux/mediatek/patches-6.6/737-net-dsa-add-Airoha-AN8855.patch b/lede/target/linux/mediatek/patches-6.6/737-net-dsa-add-Airoha-AN8855.patch new file mode 100644 index 0000000000..bd70bec4b3 --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.6/737-net-dsa-add-Airoha-AN8855.patch @@ -0,0 +1,309 @@ +From: Christian Marangi +To: Christian Marangi , + Lee Jones , Rob Herring , + Krzysztof Kozlowski , + Conor Dooley , + Andrew Lunn , + "David S. Miller" , + Eric Dumazet , + Jakub Kicinski , Paolo Abeni , + Vladimir Oltean , + Srinivas Kandagatla , + Heiner Kallweit , + Russell King , + Matthias Brugger , + AngeloGioacchino Del Regno + , + linux-arm-kernel@lists.infradead.org, + linux-mediatek@lists.infradead.org, netdev@vger.kernel.org, + devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, + upstream@airoha.com +Subject: [net-next PATCH v11 0/9] net: dsa: Add Airoha AN8855 support +Date: Mon, 9 Dec 2024 14:44:17 +0100 [thread overview] +Message-ID: <20241209134459.27110-1-ansuelsmth@gmail.com> (raw) + +This small series add the initial support for the Airoha AN8855 Switch. + +It's a 5 port Gigabit Switch with SGMII/HSGMII upstream port. + +This is starting to get in the wild and there are already some router +having this switch chip. + +It's conceptually similar to mediatek switch but register and bits +are different. And there is that massive Hell that is the PCS +configuration. +Saddly for that part we have absolutely NO documentation currently. + +There is this special thing where PHY needs to be calibrated with values +from the switch efuse. (the thing have a whole cpu timer and MCU) + +Changes v11: +- Address reviews from Christophe (spell mistake + dev_err_probe) +- Fix kconfig dependency for MFD driver (depends on MDIO_DEVICE instead of MDIO) + (indirectly fix link error for mdio APIs) +- Fix copy-paste error for MFD driver of_table +- Fix compilation error for PHY (move NVMEM to .config) +- Drop unneeded NVMEM node from MDIO example schema (from Andrew) +- Adapt MFD example schema to MDIO reg property restrictions +Changes v10: +- Entire rework to MFD + split to MDIO, EFUSE, SWITCH separate drivers +- Drop EEE OPs (while Russell finish RFC for EEE changes) +- Use new pcs_inpand OPs +- Drop AN restart function and move to pcs_config +- Enable assisted_learning and disable CPU learn (preparation for fdb_isolation) +- Move EFUSE read in Internal PHY driver to .config to handle EPROBE_DEFER + (needed now that NVMEM driver is register externally instead of internally to switch + node) +Changes v9: +- Error out on using 5G speed as currently not supported +- Add missing MAC_2500FD in phylink mac_capabilities +- Add comment and improve if condition for an8855_phylink_mac_config +Changes v8: +- Add port Fast Age support +- Add support for Port Isolation +- Use correct register for Learning Disable +- Add support for Ageing Time OP +- Set default PVID to 0 by default +- Add mdb OPs +- Add port change MTU +- Fix support for Upper VLAN +Changes v7: +- Fix devm_dsa_register_switch wrong export symbol +Changes v6: +- Drop standard MIB and handle with ethtool OPs (as requested by Jakub) +- Cosmetic: use bool instead of 0 or 1 +Changes v5: +- Add devm_dsa_register_switch() patch +- Add Reviewed-by tag for DT patch +Changes v4: +- Set regmap readable_table static (mute compilation warning) +- Add support for port_bridge flags (LEARNING, FLOOD) +- Reset fdb struct in fdb_dump +- Drop support_asym_pause in port_enable +- Add define for get_phy_flags +- Fix bug for port not inititially part of a bridge + (in an8855_setup the port matrix was always cleared but + the CPU port was never initially added) +- Disable learning and flood for user port by default +- Set CPU port to flood and learning by default +- Correctly AND force duplex and flow control in an8855_phylink_mac_link_up +- Drop RGMII from pcs_config +- Check ret in "Disable AN if not in autoneg" +- Use devm_mutex_init +- Fix typo for AN8855_PORT_CHECK_MODE +- Better define AN8855_STP_LISTENING = AN8855_STP_BLOCKING +- Fix typo in AN8855_PHY_EN_DOWN_SHIFT +- Use paged helper for PHY +- Skip calibration in config_init if priv not defined +Changes v3: +- Out of RFC +- Switch PHY code to select_page API +- Better describe masks and bits in PHY driver for ADC register +- Drop raw values and use define for mii read/write +- Switch to absolute PHY address +- Replace raw values with mask and bits for pcs_config +- Fix typo for ext-surge property name +- Drop support for relocating Switch base PHY address on the bus +Changes v2: +- Drop mutex guard patch +- Drop guard usage in DSA driver +- Use __mdiobus_write/read +- Check return condition and return errors for mii read/write +- Fix wrong logic for EEE +- Fix link_down (don't force link down with autoneg) +- Fix forcing speed on sgmii autoneg +- Better document link speed for sgmii reg +- Use standard define for sgmii reg +- Imlement nvmem support to expose switch EFUSE +- Rework PHY calibration with the use of NVMEM producer/consumer +- Update DT with new NVMEM property +- Move aneg validation for 2500-basex in pcs_config +- Move r50Ohm table and function to PHY driver + +Christian Marangi (9): + dt-bindings: nvmem: Document support for Airoha AN8855 Switch EFUSE + dt-bindings: net: Document support for Airoha AN8855 Switch Virtual + MDIO + dt-bindings: net: dsa: Document support for Airoha AN8855 DSA Switch + dt-bindings: mfd: Document support for Airoha AN8855 Switch SoC + mfd: an8855: Add support for Airoha AN8855 Switch MFD + net: mdio: Add Airoha AN8855 Switch MDIO Passtrough + nvmem: an8855: Add support for Airoha AN8855 Switch EFUSE + net: dsa: Add Airoha AN8855 5-Port Gigabit DSA Switch driver + net: phy: Add Airoha AN8855 Internal Switch Gigabit PHY + + .../bindings/mfd/airoha,an8855-mfd.yaml | 178 ++ + .../bindings/net/airoha,an8855-mdio.yaml | 56 + + .../net/dsa/airoha,an8855-switch.yaml | 105 + + .../bindings/nvmem/airoha,an8855-efuse.yaml | 123 + + MAINTAINERS | 17 + + drivers/mfd/Kconfig | 10 + + drivers/mfd/Makefile | 1 + + drivers/mfd/airoha-an8855.c | 278 ++ + drivers/net/dsa/Kconfig | 9 + + drivers/net/dsa/Makefile | 1 + + drivers/net/dsa/an8855.c | 2310 +++++++++++++++++ + drivers/net/dsa/an8855.h | 783 ++++++ + drivers/net/mdio/Kconfig | 9 + + drivers/net/mdio/Makefile | 1 + + drivers/net/mdio/mdio-an8855.c | 113 + + drivers/net/phy/Kconfig | 5 + + drivers/net/phy/Makefile | 1 + + drivers/net/phy/air_an8855.c | 267 ++ + drivers/nvmem/Kconfig | 11 + + drivers/nvmem/Makefile | 2 + + drivers/nvmem/an8855-efuse.c | 63 + + include/linux/mfd/airoha-an8855-mfd.h | 41 + + 22 files changed, 4384 insertions(+) + create mode 100644 Documentation/devicetree/bindings/mfd/airoha,an8855-mfd.yaml + create mode 100644 Documentation/devicetree/bindings/net/airoha,an8855-mdio.yaml + create mode 100644 Documentation/devicetree/bindings/net/dsa/airoha,an8855-switch.yaml + create mode 100644 Documentation/devicetree/bindings/nvmem/airoha,an8855-efuse.yaml + create mode 100644 drivers/mfd/airoha-an8855.c + create mode 100644 drivers/net/dsa/an8855.c + create mode 100644 drivers/net/dsa/an8855.h + create mode 100644 drivers/net/mdio/mdio-an8855.c + create mode 100644 drivers/net/phy/air_an8855.c + create mode 100644 drivers/nvmem/an8855-efuse.c + create mode 100644 include/linux/mfd/airoha-an8855-mfd.h + +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -41,6 +41,16 @@ config MFD_ALTERA_SYSMGR + using regmap_mmio accesses for ARM32 parts and SMC calls to + EL3 for ARM64 parts. + ++config MFD_AIROHA_AN8855 ++ tristate "Airoha AN8855 Switch MFD" ++ select MFD_CORE ++ select MDIO_DEVICE ++ depends on NETDEVICES && OF ++ help ++ Support for the Airoha AN8855 Switch MFD. This is a SoC Switch ++ that provides various peripherals. Currently it provides a ++ DSA switch and a NVMEM provider. ++ + config MFD_ACT8945A + tristate "Active-semi ACT8945A" + select MFD_CORE +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -7,6 +7,7 @@ + obj-$(CONFIG_MFD_88PM860X) += 88pm860x.o + obj-$(CONFIG_MFD_88PM800) += 88pm800.o 88pm80x.o + obj-$(CONFIG_MFD_88PM805) += 88pm805.o 88pm80x.o ++obj-$(CONFIG_MFD_AIROHA_AN8855) += airoha-an8855.o + obj-$(CONFIG_MFD_ACT8945A) += act8945a.o + obj-$(CONFIG_MFD_SM501) += sm501.o + obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o +--- a/drivers/net/dsa/Kconfig ++++ b/drivers/net/dsa/Kconfig +@@ -24,6 +24,15 @@ config NET_DSA_LOOP + This enables support for a fake mock-up switch chip which + exercises the DSA APIs. + ++config NET_DSA_AN8855 ++ tristate "Airoha AN8855 Ethernet switch support" ++ depends on MFD_AIROHA_AN8855 ++ depends on NET_DSA ++ select NET_DSA_TAG_MTK ++ help ++ This enables support for the Airoha AN8855 Ethernet switch ++ chip. ++ + source "drivers/net/dsa/hirschmann/Kconfig" + + config NET_DSA_LANTIQ_GSWIP +--- a/drivers/net/dsa/Makefile ++++ b/drivers/net/dsa/Makefile +@@ -5,6 +5,7 @@ obj-$(CONFIG_NET_DSA_LOOP) += dsa_loop.o + ifdef CONFIG_NET_DSA_LOOP + obj-$(CONFIG_FIXED_PHY) += dsa_loop_bdinfo.o + endif ++obj-$(CONFIG_NET_DSA_AN8855) += an8855.o + obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o + obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o + obj-$(CONFIG_NET_DSA_MT7530_MDIO) += mt7530-mdio.o +--- a/drivers/net/mdio/Kconfig ++++ b/drivers/net/mdio/Kconfig +@@ -61,6 +61,15 @@ config MDIO_XGENE + This module provides a driver for the MDIO busses found in the + APM X-Gene SoC's. + ++config MDIO_AN8855 ++ tristate "Airoha AN8855 Switch MDIO bus controller" ++ depends on MFD_AIROHA_AN8855 ++ depends on OF_MDIO ++ help ++ This module provides a driver for the Airoha AN8855 Switch ++ that requires a MDIO passtrough as switch address is shared ++ with the internal PHYs and requires additional page handling. ++ + config MDIO_ASPEED + tristate "ASPEED MDIO bus controller" + depends on ARCH_ASPEED || 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_AN8855) += mdio-an8855.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 +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -147,6 +147,11 @@ config AIROHA_EN8801SC_PHY + help + Currently supports the Airoha EN8801SC PHY. + ++config AIR_AN8855_PHY ++ tristate "Airoha AN8855 Internal Gigabit PHY" ++ help ++ Currently supports the internal Airoha AN8855 Switch PHY. ++ + config AIR_EN8811H_PHY + tristate "Airoha EN8811H 2.5 Gigabit PHY" + help +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -50,6 +50,7 @@ obj-y += $(sfp-obj-y) $(sfp-obj-m) + obj-$(CONFIG_ADIN_PHY) += adin.o + obj-$(CONFIG_ADIN1100_PHY) += adin1100.o + obj-$(CONFIG_AIROHA_EN8801SC_PHY) += en8801sc.o ++obj-$(CONFIG_AIR_AN8855_PHY) += air_an8855.o + obj-$(CONFIG_AIR_EN8811H_PHY) += air_en8811h.o + obj-$(CONFIG_AMD_PHY) += amd.o + obj-$(CONFIG_AQUANTIA_PHY) += aquantia/ +--- a/drivers/nvmem/Kconfig ++++ b/drivers/nvmem/Kconfig +@@ -29,6 +29,17 @@ source "drivers/nvmem/layouts/Kconfig" + + # Devices + ++config NVMEM_AN8855_EFUSE ++ tristate "Airoha AN8855 eFuse support" ++ depends on MFD_AIROHA_AN8855 || COMPILE_TEST ++ help ++ Say y here to enable support for reading eFuses on Airoha AN8855 ++ Switch. These are e.g. used to store factory programmed ++ calibration data required for the PHY. ++ ++ This driver can also be built as a module. If so, the module will ++ be called nvmem-an8855-efuse. ++ + config NVMEM_APPLE_EFUSES + tristate "Apple eFuse support" + depends on ARCH_APPLE || COMPILE_TEST +--- a/drivers/nvmem/Makefile ++++ b/drivers/nvmem/Makefile +@@ -10,6 +10,8 @@ nvmem_layouts-y := layouts.o + obj-y += layouts/ + + # Devices ++obj-$(CONFIG_NVMEM_AN8855_EFUSE) += nvmem-an8855-efuse.o ++nvmem-an8855-efuse-y := an8855-efuse.o + obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvmem-apple-efuses.o + nvmem-apple-efuses-y := apple-efuses.o + obj-$(CONFIG_NVMEM_BCM_OCOTP) += nvmem-bcm-ocotp.o diff --git a/lede/target/linux/mediatek/patches-6.6/738-net-phylink-move-phylink_pcs_neg_mode.patch b/lede/target/linux/mediatek/patches-6.6/738-net-phylink-move-phylink_pcs_neg_mode.patch new file mode 100644 index 0000000000..27be419f6f --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.6/738-net-phylink-move-phylink_pcs_neg_mode.patch @@ -0,0 +1,166 @@ +From 5e5401d6612ef599ad45785b941eebda7effc90f Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Thu, 4 Jan 2024 09:47:36 +0000 +Subject: [PATCH] net: phylink: move phylink_pcs_neg_mode() into phylink.c + +Move phylink_pcs_neg_mode() from the header file into the .c file since +nothing should be using it. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/phy/phylink.c | 66 +++++++++++++++++++++++++++++++++++++++ + include/linux/phylink.h | 66 --------------------------------------- + 2 files changed, 66 insertions(+), 66 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -1150,6 +1150,72 @@ static void phylink_pcs_an_restart(struc + pl->pcs->ops->pcs_an_restart(pl->pcs); + } + ++/** ++ * phylink_pcs_neg_mode() - helper to determine PCS inband mode ++ * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND. ++ * @interface: interface mode to be used ++ * @advertising: adertisement ethtool link mode mask ++ * ++ * Determines the negotiation mode to be used by the PCS, and returns ++ * one of: ++ * ++ * - %PHYLINK_PCS_NEG_NONE: interface mode does not support inband ++ * - %PHYLINK_PCS_NEG_OUTBAND: an out of band mode (e.g. reading the PHY) ++ * will be used. ++ * - %PHYLINK_PCS_NEG_INBAND_DISABLED: inband mode selected but autoneg ++ * disabled ++ * - %PHYLINK_PCS_NEG_INBAND_ENABLED: inband mode selected and autoneg enabled ++ * ++ * Note: this is for cases where the PCS itself is involved in negotiation ++ * (e.g. Clause 37, SGMII and similar) not Clause 73. ++ */ ++static unsigned int phylink_pcs_neg_mode(unsigned int mode, ++ phy_interface_t interface, ++ const unsigned long *advertising) ++{ ++ unsigned int neg_mode; ++ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_QSGMII: ++ case PHY_INTERFACE_MODE_QUSGMII: ++ case PHY_INTERFACE_MODE_USXGMII: ++ /* These protocols are designed for use with a PHY which ++ * communicates its negotiation result back to the MAC via ++ * inband communication. Note: there exist PHYs that run ++ * with SGMII but do not send the inband data. ++ */ ++ if (!phylink_autoneg_inband(mode)) ++ neg_mode = PHYLINK_PCS_NEG_OUTBAND; ++ else ++ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; ++ break; ++ ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ /* 1000base-X is designed for use media-side for Fibre ++ * connections, and thus the Autoneg bit needs to be ++ * taken into account. We also do this for 2500base-X ++ * as well, but drivers may not support this, so may ++ * need to override this. ++ */ ++ if (!phylink_autoneg_inband(mode)) ++ neg_mode = PHYLINK_PCS_NEG_OUTBAND; ++ else if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, ++ advertising)) ++ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; ++ else ++ neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED; ++ break; ++ ++ default: ++ neg_mode = PHYLINK_PCS_NEG_NONE; ++ break; ++ } ++ ++ return neg_mode; ++} ++ + static void phylink_major_config(struct phylink *pl, bool restart, + const struct phylink_link_state *state) + { +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -99,72 +99,6 @@ static inline bool phylink_autoneg_inban + } + + /** +- * phylink_pcs_neg_mode() - helper to determine PCS inband mode +- * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND. +- * @interface: interface mode to be used +- * @advertising: adertisement ethtool link mode mask +- * +- * Determines the negotiation mode to be used by the PCS, and returns +- * one of: +- * +- * - %PHYLINK_PCS_NEG_NONE: interface mode does not support inband +- * - %PHYLINK_PCS_NEG_OUTBAND: an out of band mode (e.g. reading the PHY) +- * will be used. +- * - %PHYLINK_PCS_NEG_INBAND_DISABLED: inband mode selected but autoneg +- * disabled +- * - %PHYLINK_PCS_NEG_INBAND_ENABLED: inband mode selected and autoneg enabled +- * +- * Note: this is for cases where the PCS itself is involved in negotiation +- * (e.g. Clause 37, SGMII and similar) not Clause 73. +- */ +-static inline unsigned int phylink_pcs_neg_mode(unsigned int mode, +- phy_interface_t interface, +- const unsigned long *advertising) +-{ +- unsigned int neg_mode; +- +- switch (interface) { +- case PHY_INTERFACE_MODE_SGMII: +- case PHY_INTERFACE_MODE_QSGMII: +- case PHY_INTERFACE_MODE_QUSGMII: +- case PHY_INTERFACE_MODE_USXGMII: +- /* These protocols are designed for use with a PHY which +- * communicates its negotiation result back to the MAC via +- * inband communication. Note: there exist PHYs that run +- * with SGMII but do not send the inband data. +- */ +- if (!phylink_autoneg_inband(mode)) +- neg_mode = PHYLINK_PCS_NEG_OUTBAND; +- else +- neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; +- break; +- +- case PHY_INTERFACE_MODE_1000BASEX: +- case PHY_INTERFACE_MODE_2500BASEX: +- /* 1000base-X is designed for use media-side for Fibre +- * connections, and thus the Autoneg bit needs to be +- * taken into account. We also do this for 2500base-X +- * as well, but drivers may not support this, so may +- * need to override this. +- */ +- if (!phylink_autoneg_inband(mode)) +- neg_mode = PHYLINK_PCS_NEG_OUTBAND; +- else if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, +- advertising)) +- neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; +- else +- neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED; +- break; +- +- default: +- neg_mode = PHYLINK_PCS_NEG_NONE; +- break; +- } +- +- return neg_mode; +-} +- +-/** + * struct phylink_link_state - link state structure + * @advertising: ethtool bitmask containing advertised link modes + * @lp_advertising: ethtool bitmask containing link partner advertised link diff --git a/lede/target/linux/mediatek/patches-6.6/739-net-add-negotiation-of-in-band-capabilities.patch b/lede/target/linux/mediatek/patches-6.6/739-net-add-negotiation-of-in-band-capabilities.patch new file mode 100644 index 0000000000..44a6aad7f5 --- /dev/null +++ b/lede/target/linux/mediatek/patches-6.6/739-net-add-negotiation-of-in-band-capabilities.patch @@ -0,0 +1,1233 @@ +From: "Russell King (Oracle)" +To: Andrew Lunn , Heiner Kallweit +Cc: Alexander Couzens , + Andrew Lunn , + AngeloGioacchino Del Regno + , + Broadcom internal kernel review list + , + Daniel Golle , + "David S. Miller" , + Eric Dumazet , + Florian Fainelli , + Ioana Ciornei , + Jakub Kicinski , + Jose Abreu , + linux-arm-kernel@lists.infradead.org, + linux-mediatek@lists.infradead.org, + Marcin Wojtas , + Matthias Brugger , + netdev@vger.kernel.org, Paolo Abeni +Subject: [PATCH RFC net-next 00/16] net: add negotiation of in-band capabilities +Date: Tue, 26 Nov 2024 09:23:48 +0000 [thread overview] +Message-ID: (raw) + +Hi, + +Yes, this is one patch over the limit of 15 for netdev - but I think it's +important to include the last patch to head off review comments like "why +don't you remove phylink_phy_no_inband() in this series?" + +Phylink's handling of in-band has been deficient for a long time, and +people keep hitting problems with it. Notably, situations with the way- +to-late standardized 2500Base-X and whether that should or should not +have in-band enabled. We have also been carrying a hack in the form of +phylink_phy_no_inband() for a PHY that has been used on a SFP module, +but has no in-band capabilities, not even for SGMII. + +When phylink is trying to operate in in-band mode, this series will look +at the capabilities of the MAC-side PCS and PHY, and work out whether +in-band can or should be used, programming the PHY as appropriate. This +includes in-band bypass mode at the PHY. + +We don't... yet... support that on the MAC side PCS, because that +requires yet more complexity. + +Patch 1 passes struct phylink and struct phylink_pcs into +phylink_pcs_neg_mode() so we can look at more state in this function in +a future patch. + +Patch 2 splits "cur_link_an_mode" (the MLO_AN_* mode) into two separate +purposes - a requested and an active mode. The active mode is the one +we will be using for the MAC, which becomes dependent on the result of +in-band negotiation. + +Patch 3 adds debug to phylink_major_config() so we can see what is going +on with the requested and active AN modes. + +Patch 4 adds to phylib a method to get the in-band capabilities of the +PHY from phylib. Patches 5 and 6 add implementations for BCM84881 and +some Marvell PHYs found on SFPs. + +Patch 7 adds to phylib a method to configure the PHY in-band signalling, +and patch 8 implements it for those Marvell PHYs that support the method +in patch 4. + +Patch 9 does the same as patch 4 but for the MAC-side PCS, with patches +10 through 14 adding support to several PCS. + +Patch 15 adds the code to phylink_pcs_neg_mode() which looks at the +capabilities, and works out whether to use in-band or out-band mode for +driving the link between the MAC PCS and PHY. + +Patch 16 removes the phylink_phy_no_inband() hack now that we are +publishing the in-band capabilities from the BCM84881 PHY driver. + + drivers/net/ethernet/marvell/mvneta.c | 27 +- + drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 25 +- + drivers/net/pcs/pcs-lynx.c | 22 ++ + drivers/net/pcs/pcs-mtk-lynxi.c | 16 ++ + drivers/net/pcs/pcs-xpcs.c | 28 ++ + drivers/net/phy/bcm84881.c | 10 + + drivers/net/phy/marvell.c | 48 ++++ + drivers/net/phy/phy.c | 52 ++++ + drivers/net/phy/phylink.c | 352 +++++++++++++++++++----- + include/linux/phy.h | 34 +++ + include/linux/phylink.h | 17 ++ + 11 files changed, 539 insertions(+), 92 deletions(-) + +--- a/drivers/net/phy/phylink.c ++++ b/drivers/net/phy/phylink.c +@@ -56,7 +56,8 @@ struct phylink { + struct phy_device *phydev; + phy_interface_t link_interface; /* PHY_INTERFACE_xxx */ + u8 cfg_link_an_mode; /* MLO_AN_xxx */ +- u8 cur_link_an_mode; ++ u8 req_link_an_mode; /* Requested MLO_AN_xxx mode */ ++ u8 act_link_an_mode; /* Active MLO_AN_xxx mode */ + u8 link_port; /* The current non-phy ethtool port */ + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); + +@@ -74,6 +75,7 @@ struct phylink { + + struct mutex state_mutex; + struct phylink_link_state phy_state; ++ unsigned int phy_ib_mode; + struct work_struct resolve; + unsigned int pcs_neg_mode; + unsigned int pcs_state; +@@ -175,6 +177,24 @@ static const char *phylink_an_mode_str(u + return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown"; + } + ++static const char *phylink_pcs_mode_str(unsigned int mode) ++{ ++ if (!mode) ++ return "none"; ++ ++ if (mode & PHYLINK_PCS_NEG_OUTBAND) ++ return "outband"; ++ ++ if (mode & PHYLINK_PCS_NEG_INBAND) { ++ if (mode & PHYLINK_PCS_NEG_ENABLED) ++ return "inband,an-enabled"; ++ else ++ return "inband,an-disabled"; ++ } ++ ++ return "unknown"; ++} ++ + static unsigned int phylink_interface_signal_rate(phy_interface_t interface) + { + switch (interface) { +@@ -1053,6 +1073,15 @@ static void phylink_resolve_an_pause(str + } + } + ++static unsigned int phylink_pcs_inband_caps(struct phylink_pcs *pcs, ++ phy_interface_t interface) ++{ ++ if (pcs && pcs->ops->pcs_inband_caps) ++ return pcs->ops->pcs_inband_caps(pcs, interface); ++ ++ return 0; ++} ++ + static void phylink_pcs_pre_config(struct phylink_pcs *pcs, + phy_interface_t interface) + { +@@ -1106,6 +1135,24 @@ static void phylink_pcs_link_up(struct p + pcs->ops->pcs_link_up(pcs, neg_mode, interface, speed, duplex); + } + ++/* Query inband for a specific interface mode, asking the MAC for the ++ * PCS which will be used to handle the interface mode. ++ */ ++static unsigned int phylink_inband_caps(struct phylink *pl, ++ phy_interface_t interface) ++{ ++ struct phylink_pcs *pcs; ++ ++ if (!pl->mac_ops->mac_select_pcs) ++ return 0; ++ ++ pcs = pl->mac_ops->mac_select_pcs(pl->config, interface); ++ if (!pcs) ++ return 0; ++ ++ return phylink_pcs_inband_caps(pcs, interface); ++} ++ + static void phylink_pcs_poll_stop(struct phylink *pl) + { + if (pl->cfg_link_an_mode == MLO_AN_INBAND) +@@ -1132,13 +1179,13 @@ static void phylink_mac_config(struct ph + + phylink_dbg(pl, + "%s: mode=%s/%s/%s adv=%*pb pause=%02x\n", +- __func__, phylink_an_mode_str(pl->cur_link_an_mode), ++ __func__, phylink_an_mode_str(pl->act_link_an_mode), + phy_modes(st.interface), + phy_rate_matching_to_str(st.rate_matching), + __ETHTOOL_LINK_MODE_MASK_NBITS, st.advertising, + st.pause); + +- pl->mac_ops->mac_config(pl->config, pl->cur_link_an_mode, &st); ++ pl->mac_ops->mac_config(pl->config, pl->act_link_an_mode, &st); + } + + static void phylink_pcs_an_restart(struct phylink *pl) +@@ -1146,13 +1193,14 @@ static void phylink_pcs_an_restart(struc + if (pl->pcs && linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, + pl->link_config.advertising) && + phy_interface_mode_is_8023z(pl->link_config.interface) && +- phylink_autoneg_inband(pl->cur_link_an_mode)) ++ phylink_autoneg_inband(pl->act_link_an_mode)) + pl->pcs->ops->pcs_an_restart(pl->pcs); + } + + /** + * phylink_pcs_neg_mode() - helper to determine PCS inband mode +- * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND. ++ * @pl: a pointer to a &struct phylink returned from phylink_create() ++ * @pcs: a pointer to &struct phylink_pcs + * @interface: interface mode to be used + * @advertising: adertisement ethtool link mode mask + * +@@ -1169,11 +1217,21 @@ static void phylink_pcs_an_restart(struc + * Note: this is for cases where the PCS itself is involved in negotiation + * (e.g. Clause 37, SGMII and similar) not Clause 73. + */ +-static unsigned int phylink_pcs_neg_mode(unsigned int mode, +- phy_interface_t interface, +- const unsigned long *advertising) ++static void phylink_pcs_neg_mode(struct phylink *pl, struct phylink_pcs *pcs, ++ phy_interface_t interface, ++ const unsigned long *advertising) + { +- unsigned int neg_mode; ++ unsigned int pcs_ib_caps = 0; ++ unsigned int phy_ib_caps = 0; ++ unsigned int neg_mode, mode; ++ enum { ++ INBAND_CISCO_SGMII, ++ INBAND_BASEX, ++ } type; ++ ++ mode = pl->req_link_an_mode; ++ ++ pl->phy_ib_mode = 0; + + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: +@@ -1185,10 +1243,7 @@ static unsigned int phylink_pcs_neg_mode + * inband communication. Note: there exist PHYs that run + * with SGMII but do not send the inband data. + */ +- if (!phylink_autoneg_inband(mode)) +- neg_mode = PHYLINK_PCS_NEG_OUTBAND; +- else +- neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; ++ type = INBAND_CISCO_SGMII; + break; + + case PHY_INTERFACE_MODE_1000BASEX: +@@ -1199,21 +1254,143 @@ static unsigned int phylink_pcs_neg_mode + * as well, but drivers may not support this, so may + * need to override this. + */ +- if (!phylink_autoneg_inband(mode)) ++ type = INBAND_BASEX; ++ break; ++ ++ default: ++ pl->pcs_neg_mode = PHYLINK_PCS_NEG_NONE; ++ pl->act_link_an_mode = mode; ++ return; ++ } ++ ++ if (pcs) ++ pcs_ib_caps = phylink_pcs_inband_caps(pcs, interface); ++ ++ if (pl->phydev) ++ phy_ib_caps = phy_inband_caps(pl->phydev, interface); ++ ++ phylink_dbg(pl, "interface %s inband modes: pcs=%02x phy=%02x\n", ++ phy_modes(interface), pcs_ib_caps, phy_ib_caps); ++ ++ if (!phylink_autoneg_inband(mode)) { ++ bool pcs_ib_only = false; ++ bool phy_ib_only = false; ++ ++ if (pcs_ib_caps && pcs_ib_caps != LINK_INBAND_DISABLE) { ++ /* PCS supports reporting in-band capabilities, and ++ * supports more than disable mode. ++ */ ++ if (pcs_ib_caps & LINK_INBAND_DISABLE) ++ neg_mode = PHYLINK_PCS_NEG_OUTBAND; ++ else if (pcs_ib_caps & LINK_INBAND_ENABLE) ++ pcs_ib_only = true; ++ } ++ ++ if (phy_ib_caps && phy_ib_caps != LINK_INBAND_DISABLE) { ++ /* PHY supports in-band capabilities, and supports ++ * more than disable mode. ++ */ ++ if (phy_ib_caps & LINK_INBAND_DISABLE) ++ pl->phy_ib_mode = LINK_INBAND_DISABLE; ++ else if (phy_ib_caps & LINK_INBAND_BYPASS) ++ pl->phy_ib_mode = LINK_INBAND_BYPASS; ++ else if (phy_ib_caps & LINK_INBAND_ENABLE) ++ phy_ib_only = true; ++ } ++ ++ /* If either the PCS or PHY requires inband to be enabled, ++ * this is an invalid configuration. Provide a diagnostic ++ * message for this case, but don't try to force the issue. ++ */ ++ if (pcs_ib_only || phy_ib_only) ++ phylink_warn(pl, ++ "firmware wants %s mode, but %s%s%s requires inband\n", ++ phylink_an_mode_str(mode), ++ pcs_ib_only ? "PCS" : "", ++ pcs_ib_only && phy_ib_only ? " and " : "", ++ phy_ib_only ? "PHY" : ""); ++ ++ neg_mode = PHYLINK_PCS_NEG_OUTBAND; ++ } else if (type == INBAND_CISCO_SGMII || pl->phydev) { ++ /* For SGMII modes which are designed to be used with PHYs, or ++ * Base-X with a PHY, we try to use in-band mode where-ever ++ * possible. However, there are some PHYs e.g. BCM84881 which ++ * do not support in-band. ++ */ ++ const unsigned int inband_ok = LINK_INBAND_ENABLE | ++ LINK_INBAND_BYPASS; ++ const unsigned int outband_ok = LINK_INBAND_DISABLE | ++ LINK_INBAND_BYPASS; ++ /* PCS PHY ++ * D E D E ++ * 0 0 0 0 no information inband enabled ++ * 1 0 0 0 pcs doesn't support outband ++ * 0 1 0 0 pcs required inband enabled ++ * 1 1 0 0 pcs optional inband enabled ++ * 0 0 1 0 phy doesn't support outband ++ * 1 0 1 0 pcs+phy doesn't support outband ++ * 0 1 1 0 pcs required, phy doesn't support, invalid ++ * 1 1 1 0 pcs optional, phy doesn't support, outband ++ * 0 0 0 1 phy required inband enabled ++ * 1 0 0 1 pcs doesn't support, phy required, invalid ++ * 0 1 0 1 pcs+phy required inband enabled ++ * 1 1 0 1 pcs optional, phy required inband enabled ++ * 0 0 1 1 phy optional inband enabled ++ * 1 0 1 1 pcs doesn't support, phy optional, outband ++ * 0 1 1 1 pcs required, phy optional inband enabled ++ * 1 1 1 1 pcs+phy optional inband enabled ++ */ ++ if ((!pcs_ib_caps || pcs_ib_caps & inband_ok) && ++ (!phy_ib_caps || phy_ib_caps & inband_ok)) { ++ /* In-band supported or unknown at both ends. Enable ++ * in-band mode with or without bypass at the PHY. ++ */ ++ if (phy_ib_caps & LINK_INBAND_ENABLE) ++ pl->phy_ib_mode = LINK_INBAND_ENABLE; ++ else if (phy_ib_caps & LINK_INBAND_BYPASS) ++ pl->phy_ib_mode = LINK_INBAND_BYPASS; ++ ++ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; ++ } else if ((!pcs_ib_caps || pcs_ib_caps & outband_ok) && ++ (!phy_ib_caps || phy_ib_caps & outband_ok)) { ++ /* Either in-band not supported at at least one end. ++ * In-band bypass at the other end is possible. ++ */ ++ if (phy_ib_caps & LINK_INBAND_DISABLE) ++ pl->phy_ib_mode = LINK_INBAND_DISABLE; ++ else if (phy_ib_caps & LINK_INBAND_BYPASS) ++ pl->phy_ib_mode = LINK_INBAND_BYPASS; ++ + neg_mode = PHYLINK_PCS_NEG_OUTBAND; ++ if (pl->phydev) ++ mode = MLO_AN_PHY; ++ } else { ++ /* invalid */ ++ phylink_warn(pl, "%s: incompatible in-band capabilities, trying in-band", ++ phy_modes(interface)); ++ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; ++ } ++ } else { ++ /* For Base-X without a PHY */ ++ if (pcs_ib_caps == LINK_INBAND_DISABLE) ++ /* If the PCS doesn't support inband, then inband must ++ * be disabled. ++ */ ++ neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED; ++ else if (pcs_ib_caps == LINK_INBAND_ENABLE) ++ /* If the PCS requires inband, then inband must always ++ * be enabled. ++ */ ++ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; + else if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, + advertising)) + neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED; + else + neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED; +- break; +- +- default: +- neg_mode = PHYLINK_PCS_NEG_NONE; +- break; + } + +- return neg_mode; ++ pl->pcs_neg_mode = neg_mode; ++ pl->act_link_an_mode = mode; + } + + static void phylink_major_config(struct phylink *pl, bool restart, +@@ -1225,11 +1402,9 @@ static void phylink_major_config(struct + unsigned int neg_mode; + int err; + +- phylink_dbg(pl, "major config %s\n", phy_modes(state->interface)); +- +- pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode, +- state->interface, +- state->advertising); ++ phylink_dbg(pl, "major config, requested %s/%s\n", ++ phylink_an_mode_str(pl->req_link_an_mode), ++ phy_modes(state->interface)); + + if (pl->using_mac_select_pcs) { + pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface); +@@ -1243,10 +1418,17 @@ static void phylink_major_config(struct + pcs_changed = pcs && pl->pcs != pcs; + } + ++ phylink_pcs_neg_mode(pl, pcs, state->interface, state->advertising); ++ ++ phylink_dbg(pl, "major config, active %s/%s/%s\n", ++ phylink_an_mode_str(pl->act_link_an_mode), ++ phylink_pcs_mode_str(pl->pcs_neg_mode), ++ phy_modes(state->interface)); ++ + phylink_pcs_poll_stop(pl); + + if (pl->mac_ops->mac_prepare) { +- err = pl->mac_ops->mac_prepare(pl->config, pl->cur_link_an_mode, ++ err = pl->mac_ops->mac_prepare(pl->config, pl->act_link_an_mode, + state->interface); + if (err < 0) { + phylink_err(pl, "mac_prepare failed: %pe\n", +@@ -1280,7 +1462,7 @@ static void phylink_major_config(struct + if (pl->pcs_state == PCS_STATE_STARTING || pcs_changed) + phylink_pcs_enable(pl->pcs); + +- neg_mode = pl->cur_link_an_mode; ++ neg_mode = pl->act_link_an_mode; + if (pl->pcs && pl->pcs->neg_mode) + neg_mode = pl->pcs_neg_mode; + +@@ -1296,13 +1478,20 @@ static void phylink_major_config(struct + phylink_pcs_an_restart(pl); + + if (pl->mac_ops->mac_finish) { +- err = pl->mac_ops->mac_finish(pl->config, pl->cur_link_an_mode, ++ err = pl->mac_ops->mac_finish(pl->config, pl->act_link_an_mode, + state->interface); + if (err < 0) + phylink_err(pl, "mac_finish failed: %pe\n", + ERR_PTR(err)); + } + ++ if (pl->phydev && pl->phy_ib_mode) { ++ err = phy_config_inband(pl->phydev, pl->phy_ib_mode); ++ if (err < 0) ++ phylink_err(pl, "phy_config_inband: %pe\n", ++ ERR_PTR(err)); ++ } ++ + if (pl->sfp_bus) { + rate_kbd = phylink_interface_signal_rate(state->interface); + if (rate_kbd) +@@ -1327,17 +1516,16 @@ static int phylink_change_inband_advert( + return 0; + + phylink_dbg(pl, "%s: mode=%s/%s adv=%*pb pause=%02x\n", __func__, +- phylink_an_mode_str(pl->cur_link_an_mode), ++ phylink_an_mode_str(pl->req_link_an_mode), + phy_modes(pl->link_config.interface), + __ETHTOOL_LINK_MODE_MASK_NBITS, pl->link_config.advertising, + pl->link_config.pause); + + /* Recompute the PCS neg mode */ +- pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode, +- pl->link_config.interface, +- pl->link_config.advertising); ++ phylink_pcs_neg_mode(pl, pl->pcs, pl->link_config.interface, ++ pl->link_config.advertising); + +- neg_mode = pl->cur_link_an_mode; ++ neg_mode = pl->act_link_an_mode; + if (pl->pcs->neg_mode) + neg_mode = pl->pcs_neg_mode; + +@@ -1402,7 +1590,7 @@ static void phylink_mac_initial_config(s + { + struct phylink_link_state link_state; + +- switch (pl->cur_link_an_mode) { ++ switch (pl->req_link_an_mode) { + case MLO_AN_PHY: + link_state = pl->phy_state; + break; +@@ -1476,14 +1664,14 @@ static void phylink_link_up(struct phyli + + pl->cur_interface = link_state.interface; + +- neg_mode = pl->cur_link_an_mode; ++ neg_mode = pl->act_link_an_mode; + if (pl->pcs && pl->pcs->neg_mode) + neg_mode = pl->pcs_neg_mode; + + phylink_pcs_link_up(pl->pcs, neg_mode, pl->cur_interface, speed, + duplex); + +- pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->cur_link_an_mode, ++ pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->act_link_an_mode, + pl->cur_interface, speed, duplex, + !!(link_state.pause & MLO_PAUSE_TX), rx_pause); + +@@ -1503,7 +1691,7 @@ static void phylink_link_down(struct phy + + if (ndev) + netif_carrier_off(ndev); +- pl->mac_ops->mac_link_down(pl->config, pl->cur_link_an_mode, ++ pl->mac_ops->mac_link_down(pl->config, pl->act_link_an_mode, + pl->cur_interface); + phylink_info(pl, "Link is Down\n"); + } +@@ -1530,7 +1718,7 @@ static void phylink_resolve(struct work_ + link_state.link = false; + retrigger = true; + } else { +- switch (pl->cur_link_an_mode) { ++ switch (pl->act_link_an_mode) { + case MLO_AN_PHY: + link_state = pl->phy_state; + phylink_apply_manual_flow(pl, &link_state); +@@ -1773,7 +1961,7 @@ struct phylink *phylink_create(struct ph + } + } + +- pl->cur_link_an_mode = pl->cfg_link_an_mode; ++ pl->req_link_an_mode = pl->cfg_link_an_mode; + + ret = phylink_register_sfp(pl, fwnode); + if (ret < 0) { +@@ -2236,7 +2424,7 @@ void phylink_start(struct phylink *pl) + ASSERT_RTNL(); + + phylink_info(pl, "configuring for %s/%s link mode\n", +- phylink_an_mode_str(pl->cur_link_an_mode), ++ phylink_an_mode_str(pl->req_link_an_mode), + phy_modes(pl->link_config.interface)); + + /* Always set the carrier off */ +@@ -2495,7 +2683,7 @@ int phylink_ethtool_ksettings_get(struct + + linkmode_copy(kset->link_modes.supported, pl->supported); + +- switch (pl->cur_link_an_mode) { ++ switch (pl->act_link_an_mode) { + case MLO_AN_FIXED: + /* We are using fixed settings. Report these as the + * current link settings - and note that these also +@@ -2526,6 +2714,26 @@ int phylink_ethtool_ksettings_get(struct + } + EXPORT_SYMBOL_GPL(phylink_ethtool_ksettings_get); + ++static bool phylink_validate_pcs_inband_autoneg(struct phylink *pl, ++ phy_interface_t interface, ++ unsigned long *adv) ++{ ++ unsigned int inband = phylink_inband_caps(pl, interface); ++ unsigned int mask; ++ ++ /* If the PCS doesn't implement inband support, be permissive. */ ++ if (!inband) ++ return true; ++ ++ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, adv)) ++ mask = LINK_INBAND_ENABLE; ++ else ++ mask = LINK_INBAND_DISABLE; ++ ++ /* Check whether the PCS implements the required mode */ ++ return !!(inband & mask); ++} ++ + /** + * phylink_ethtool_ksettings_set() - set the link settings + * @pl: a pointer to a &struct phylink returned from phylink_create() +@@ -2587,7 +2795,7 @@ int phylink_ethtool_ksettings_set(struct + /* If we have a fixed link, refuse to change link parameters. + * If the link parameters match, accept them but do nothing. + */ +- if (pl->cur_link_an_mode == MLO_AN_FIXED) { ++ if (pl->req_link_an_mode == MLO_AN_FIXED) { + if (s->speed != pl->link_config.speed || + s->duplex != pl->link_config.duplex) + return -EINVAL; +@@ -2603,7 +2811,7 @@ int phylink_ethtool_ksettings_set(struct + * is our default case) but do not allow the advertisement to + * be changed. If the advertisement matches, simply return. + */ +- if (pl->cur_link_an_mode == MLO_AN_FIXED) { ++ if (pl->req_link_an_mode == MLO_AN_FIXED) { + if (!linkmode_equal(config.advertising, + pl->link_config.advertising)) + return -EINVAL; +@@ -2643,7 +2851,7 @@ int phylink_ethtool_ksettings_set(struct + linkmode_copy(support, pl->supported); + if (phylink_validate(pl, support, &config)) { + phylink_err(pl, "validation of %s/%s with support %*pb failed\n", +- phylink_an_mode_str(pl->cur_link_an_mode), ++ phylink_an_mode_str(pl->req_link_an_mode), + phy_modes(config.interface), + __ETHTOOL_LINK_MODE_MASK_NBITS, support); + return -EINVAL; +@@ -2661,6 +2869,13 @@ int phylink_ethtool_ksettings_set(struct + phylink_is_empty_linkmode(config.advertising)) + return -EINVAL; + ++ /* Validate the autonegotiation state. We don't have a PHY in this ++ * situation, so the PCS is the media-facing entity. ++ */ ++ if (!phylink_validate_pcs_inband_autoneg(pl, config.interface, ++ config.advertising)) ++ return -EINVAL; ++ + mutex_lock(&pl->state_mutex); + pl->link_config.speed = config.speed; + pl->link_config.duplex = config.duplex; +@@ -2743,7 +2958,7 @@ int phylink_ethtool_set_pauseparam(struc + + ASSERT_RTNL(); + +- if (pl->cur_link_an_mode == MLO_AN_FIXED) ++ if (pl->req_link_an_mode == MLO_AN_FIXED) + return -EOPNOTSUPP; + + if (!phylink_test(pl->supported, Pause) && +@@ -3007,7 +3222,7 @@ static int phylink_mii_read(struct phyli + struct phylink_link_state state; + int val = 0xffff; + +- switch (pl->cur_link_an_mode) { ++ switch (pl->act_link_an_mode) { + case MLO_AN_FIXED: + if (phy_id == 0) { + phylink_get_fixed_state(pl, &state); +@@ -3032,7 +3247,7 @@ static int phylink_mii_read(struct phyli + static int phylink_mii_write(struct phylink *pl, unsigned int phy_id, + unsigned int reg, unsigned int val) + { +- switch (pl->cur_link_an_mode) { ++ switch (pl->act_link_an_mode) { + case MLO_AN_FIXED: + break; + +@@ -3202,10 +3417,11 @@ static phy_interface_t phylink_choose_sf + return interface; + } + +-static void phylink_sfp_set_config(struct phylink *pl, u8 mode, ++static void phylink_sfp_set_config(struct phylink *pl, + unsigned long *supported, + struct phylink_link_state *state) + { ++ u8 mode = MLO_AN_INBAND; + bool changed = false; + + phylink_dbg(pl, "requesting link mode %s/%s with support %*pb\n", +@@ -3222,9 +3438,9 @@ static void phylink_sfp_set_config(struc + changed = true; + } + +- if (pl->cur_link_an_mode != mode || ++ if (pl->req_link_an_mode != mode || + pl->link_config.interface != state->interface) { +- pl->cur_link_an_mode = mode; ++ pl->req_link_an_mode = mode; + pl->link_config.interface = state->interface; + + changed = true; +@@ -3239,8 +3455,7 @@ static void phylink_sfp_set_config(struc + phylink_mac_initial_config(pl, false); + } + +-static int phylink_sfp_config_phy(struct phylink *pl, u8 mode, +- struct phy_device *phy) ++static int phylink_sfp_config_phy(struct phylink *pl, struct phy_device *phy) + { + __ETHTOOL_DECLARE_LINK_MODE_MASK(support1); + __ETHTOOL_DECLARE_LINK_MODE_MASK(support); +@@ -3279,8 +3494,7 @@ static int phylink_sfp_config_phy(struct + ret = phylink_validate(pl, support1, &config); + if (ret) { + phylink_err(pl, +- "validation of %s/%s with support %*pb failed: %pe\n", +- phylink_an_mode_str(mode), ++ "validation of %s with support %*pb failed: %pe\n", + phy_modes(config.interface), + __ETHTOOL_LINK_MODE_MASK_NBITS, support, + ERR_PTR(ret)); +@@ -3289,7 +3503,7 @@ static int phylink_sfp_config_phy(struct + + pl->link_port = pl->sfp_port; + +- phylink_sfp_set_config(pl, mode, support, &config); ++ phylink_sfp_set_config(pl, support, &config); + + return 0; + } +@@ -3345,6 +3559,12 @@ static int phylink_sfp_config_optical(st + phylink_dbg(pl, "optical SFP: chosen %s interface\n", + phy_modes(interface)); + ++ if (!phylink_validate_pcs_inband_autoneg(pl, interface, ++ config.advertising)) { ++ phylink_err(pl, "autoneg setting not compatible with PCS"); ++ return -EINVAL; ++ } ++ + config.interface = interface; + + /* Ignore errors if we're expecting a PHY to attach later */ +@@ -3358,7 +3578,7 @@ static int phylink_sfp_config_optical(st + + pl->link_port = pl->sfp_port; + +- phylink_sfp_set_config(pl, MLO_AN_INBAND, pl->sfp_support, &config); ++ phylink_sfp_set_config(pl, pl->sfp_support, &config); + + return 0; + } +@@ -3429,20 +3649,10 @@ static void phylink_sfp_link_up(void *up + phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_LINK); + } + +-/* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII +- * or 802.3z control word, so inband will not work. +- */ +-static bool phylink_phy_no_inband(struct phy_device *phy) +-{ +- return phy->is_c45 && phy_id_compare(phy->c45_ids.device_ids[1], +- 0xae025150, 0xfffffff0); +-} +- + static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy) + { + struct phylink *pl = upstream; + phy_interface_t interface; +- u8 mode; + int ret; + + /* +@@ -3454,17 +3664,12 @@ static int phylink_sfp_connect_phy(void + */ + phy_support_asym_pause(phy); + +- if (phylink_phy_no_inband(phy)) +- mode = MLO_AN_PHY; +- else +- mode = MLO_AN_INBAND; +- + /* Set the PHY's host supported interfaces */ + phy_interface_and(phy->host_interfaces, phylink_sfp_interfaces, + pl->config->supported_interfaces); + + /* Do the initial configuration */ +- ret = phylink_sfp_config_phy(pl, mode, phy); ++ ret = phylink_sfp_config_phy(pl, phy); + if (ret < 0) + return ret; + +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -973,6 +973,58 @@ static int phy_check_link_status(struct + } + + /** ++ * phy_inband_caps - query which in-band signalling modes are supported ++ * @phydev: a pointer to a &struct phy_device ++ * @interface: the interface mode for the PHY ++ * ++ * Returns zero if it is unknown what in-band signalling is supported by the ++ * PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise, ++ * returns a bit mask of the LINK_INBAND_* values from ++ * &enum link_inband_signalling to describe which inband modes are supported ++ * by the PHY for this interface mode. ++ */ ++unsigned int phy_inband_caps(struct phy_device *phydev, ++ phy_interface_t interface) ++{ ++ if (phydev->drv && phydev->drv->inband_caps) ++ return phydev->drv->inband_caps(phydev, interface); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(phy_inband_caps); ++ ++/** ++ * phy_config_inband - configure the desired PHY in-band mode ++ * @phydev: the phy_device struct ++ * @modes: in-band modes to configure ++ * ++ * Description: disables, enables or enables-with-bypass in-band signalling ++ * between the PHY and host system. ++ * ++ * Returns: zero on success, or negative errno value. ++ */ ++int phy_config_inband(struct phy_device *phydev, unsigned int modes) ++{ ++ int err; ++ ++ if (!!(modes & LINK_INBAND_DISABLE) + ++ !!(modes & LINK_INBAND_ENABLE) + ++ !!(modes & LINK_INBAND_BYPASS) != 1) ++ return -EINVAL; ++ ++ mutex_lock(&phydev->lock); ++ if (!phydev->drv) ++ err = -EIO; ++ else if (!phydev->drv->config_inband) ++ err = -EOPNOTSUPP; ++ else ++ err = phydev->drv->config_inband(phydev, modes); ++ mutex_unlock(&phydev->lock); ++ ++ return err; ++} ++ ++/** + * _phy_start_aneg - start auto-negotiation for this PHY device + * @phydev: the phy_device struct + * +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -800,6 +800,24 @@ struct phy_tdr_config { + #define PHY_PAIR_ALL -1 + + /** ++ * enum link_inband_signalling - in-band signalling modes that are supported ++ * ++ * @LINK_INBAND_DISABLE: in-band signalling can be disabled ++ * @LINK_INBAND_ENABLE: in-band signalling can be enabled without bypass ++ * @LINK_INBAND_BYPASS: in-band signalling can be enabled with bypass ++ * ++ * The possible and required bits can only be used if the valid bit is set. ++ * If possible is clear, that means inband signalling can not be used. ++ * Required is only valid when possible is set, and means that inband ++ * signalling must be used. ++ */ ++enum link_inband_signalling { ++ LINK_INBAND_DISABLE = BIT(0), ++ LINK_INBAND_ENABLE = BIT(1), ++ LINK_INBAND_BYPASS = BIT(2), ++}; ++ ++/** + * struct phy_plca_cfg - Configuration of the PLCA (Physical Layer Collision + * Avoidance) Reconciliation Sublayer. + * +@@ -939,6 +957,19 @@ struct phy_driver { + int (*get_features)(struct phy_device *phydev); + + /** ++ * @inband_caps: query whether in-band is supported for the given PHY ++ * interface mode. Returns a bitmask of bits defined by enum ++ * link_inband_signalling. ++ */ ++ unsigned int (*inband_caps)(struct phy_device *phydev, ++ phy_interface_t interface); ++ ++ /** ++ * @config_inband: configure in-band mode for the PHY ++ */ ++ int (*config_inband)(struct phy_device *phydev, unsigned int modes); ++ ++ /** + * @get_rate_matching: Get the supported type of rate matching for a + * particular phy interface. This is used by phy consumers to determine + * whether to advertise lower-speed modes for that interface. It is +@@ -1774,6 +1805,9 @@ void phy_stop(struct phy_device *phydev) + int phy_config_aneg(struct phy_device *phydev); + int phy_start_aneg(struct phy_device *phydev); + int phy_aneg_done(struct phy_device *phydev); ++unsigned int phy_inband_caps(struct phy_device *phydev, ++ phy_interface_t interface); ++int phy_config_inband(struct phy_device *phydev, unsigned int modes); + int phy_speed_down(struct phy_device *phydev, bool sync); + int phy_speed_up(struct phy_device *phydev); + bool phy_check_valid(int speed, int duplex, unsigned long *features); +--- a/drivers/net/phy/bcm84881.c ++++ b/drivers/net/phy/bcm84881.c +@@ -223,11 +223,21 @@ static int bcm84881_read_status(struct p + return genphy_c45_read_mdix(phydev); + } + ++/* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII ++ * or 802.3z control word, so inband will not work. ++ */ ++static unsigned int bcm84881_inband_caps(struct phy_device *phydev, ++ phy_interface_t interface) ++{ ++ return LINK_INBAND_DISABLE; ++} ++ + static struct phy_driver bcm84881_drivers[] = { + { + .phy_id = 0xae025150, + .phy_id_mask = 0xfffffff0, + .name = "Broadcom BCM84881", ++ .inband_caps = bcm84881_inband_caps, + .config_init = bcm84881_config_init, + .probe = bcm84881_probe, + .get_features = bcm84881_get_features, +--- a/drivers/net/phy/marvell.c ++++ b/drivers/net/phy/marvell.c +@@ -673,6 +673,48 @@ static int marvell_config_aneg_fiber(str + return genphy_check_and_restart_aneg(phydev, changed); + } + ++static unsigned int m88e1111_inband_caps(struct phy_device *phydev, ++ phy_interface_t interface) ++{ ++ /* In 1000base-X and SGMII modes, the inband mode can be changed ++ * through the Fibre page BMCR ANENABLE bit. ++ */ ++ if (interface == PHY_INTERFACE_MODE_1000BASEX || ++ interface == PHY_INTERFACE_MODE_SGMII) ++ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE | ++ LINK_INBAND_BYPASS; ++ ++ return 0; ++} ++ ++static int m88e1111_config_inband(struct phy_device *phydev, unsigned int modes) ++{ ++ u16 extsr, bmcr; ++ int err; ++ ++ if (phydev->interface != PHY_INTERFACE_MODE_1000BASEX && ++ phydev->interface != PHY_INTERFACE_MODE_SGMII) ++ return -EINVAL; ++ ++ if (modes == LINK_INBAND_BYPASS) ++ extsr = MII_M1111_HWCFG_SERIAL_AN_BYPASS; ++ else ++ extsr = 0; ++ ++ if (modes == LINK_INBAND_DISABLE) ++ bmcr = 0; ++ else ++ bmcr = BMCR_ANENABLE; ++ ++ err = phy_modify(phydev, MII_M1111_PHY_EXT_SR, ++ MII_M1111_HWCFG_SERIAL_AN_BYPASS, extsr); ++ if (err < 0) ++ return extsr; ++ ++ return phy_modify_paged(phydev, MII_MARVELL_FIBER_PAGE, MII_BMCR, ++ BMCR_ANENABLE, bmcr); ++} ++ + static int m88e1111_config_aneg(struct phy_device *phydev) + { + int extsr = phy_read(phydev, MII_M1111_PHY_EXT_SR); +@@ -3292,6 +3334,8 @@ static struct phy_driver marvell_drivers + .name = "Marvell 88E1112", + /* PHY_GBIT_FEATURES */ + .probe = marvell_probe, ++ .inband_caps = m88e1111_inband_caps, ++ .config_inband = m88e1111_config_inband, + .config_init = m88e1112_config_init, + .config_aneg = marvell_config_aneg, + .config_intr = marvell_config_intr, +@@ -3312,6 +3356,8 @@ static struct phy_driver marvell_drivers + .name = "Marvell 88E1111", + /* PHY_GBIT_FEATURES */ + .probe = marvell_probe, ++ .inband_caps = m88e1111_inband_caps, ++ .config_inband = m88e1111_config_inband, + .config_init = m88e1111gbe_config_init, + .config_aneg = m88e1111_config_aneg, + .read_status = marvell_read_status, +@@ -3333,6 +3379,8 @@ static struct phy_driver marvell_drivers + .name = "Marvell 88E1111 (Finisar)", + /* PHY_GBIT_FEATURES */ + .probe = marvell_probe, ++ .inband_caps = m88e1111_inband_caps, ++ .config_inband = m88e1111_config_inband, + .config_init = m88e1111gbe_config_init, + .config_aneg = m88e1111_config_aneg, + .read_status = marvell_read_status, +--- a/include/linux/phylink.h ++++ b/include/linux/phylink.h +@@ -432,6 +432,7 @@ struct phylink_pcs { + /** + * struct phylink_pcs_ops - MAC PCS operations structure. + * @pcs_validate: validate the link configuration. ++ * @pcs_inband_caps: query inband support for interface mode. + * @pcs_enable: enable the PCS. + * @pcs_disable: disable the PCS. + * @pcs_pre_config: pre-mac_config method (for errata) +@@ -445,6 +446,8 @@ struct phylink_pcs { + struct phylink_pcs_ops { + int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported, + const struct phylink_link_state *state); ++ unsigned int (*pcs_inband_caps)(struct phylink_pcs *pcs, ++ phy_interface_t interface); + int (*pcs_enable)(struct phylink_pcs *pcs); + void (*pcs_disable)(struct phylink_pcs *pcs); + void (*pcs_pre_config)(struct phylink_pcs *pcs, +@@ -481,6 +484,20 @@ int pcs_validate(struct phylink_pcs *pcs + const struct phylink_link_state *state); + + /** ++ * pcs_inband_caps - query PCS in-band capabilities for interface mode. ++ * @pcs: a pointer to a &struct phylink_pcs. ++ * @interface: interface mode to be queried ++ * ++ * Returns zero if it is unknown what in-band signalling is supported by the ++ * PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise, ++ * returns a bit mask of the LINK_INBAND_* values from ++ * &enum link_inband_signalling to describe which inband modes are supported ++ * for this interface mode. ++ */ ++unsigned int pcs_inband_caps(struct phylink_pcs *pcs, ++ phy_interface_t interface); ++ ++/** + * pcs_enable() - enable the PCS. + * @pcs: a pointer to a &struct phylink_pcs. + */ +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -3959,20 +3959,27 @@ static struct mvneta_port *mvneta_pcs_to + return container_of(pcs, struct mvneta_port, phylink_pcs); + } + +-static int mvneta_pcs_validate(struct phylink_pcs *pcs, +- unsigned long *supported, +- const struct phylink_link_state *state) ++static unsigned int mvneta_pcs_inband_caps(struct phylink_pcs *pcs, ++ phy_interface_t interface) + { +- /* We only support QSGMII, SGMII, 802.3z and RGMII modes. +- * When in 802.3z mode, we must have AN enabled: ++ /* When operating in an 802.3z mode, we must have AN enabled: + * "Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ... + * When = 1 (1000BASE-X) this field must be set to 1." ++ * Therefore, inband is "required". + */ +- if (phy_interface_mode_is_8023z(state->interface) && +- !phylink_test(state->advertising, Autoneg)) +- return -EINVAL; ++ if (phy_interface_mode_is_8023z(interface)) ++ return LINK_INBAND_ENABLE; + +- return 0; ++ /* QSGMII, SGMII and RGMII can be configured to use inband ++ * signalling of the AN result. Indicate these as "possible". ++ */ ++ if (interface == PHY_INTERFACE_MODE_SGMII || ++ interface == PHY_INTERFACE_MODE_QSGMII || ++ phy_interface_mode_is_rgmii(interface)) ++ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; ++ ++ /* For any other modes, indicate that inband is not supported. */ ++ return LINK_INBAND_DISABLE; + } + + static void mvneta_pcs_get_state(struct phylink_pcs *pcs, +@@ -4070,7 +4077,7 @@ static void mvneta_pcs_an_restart(struct + } + + static const struct phylink_pcs_ops mvneta_phylink_pcs_ops = { +- .pcs_validate = mvneta_pcs_validate, ++ .pcs_inband_caps = mvneta_pcs_inband_caps, + .pcs_get_state = mvneta_pcs_get_state, + .pcs_config = mvneta_pcs_config, + .pcs_an_restart = mvneta_pcs_an_restart, +--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c ++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +@@ -6214,19 +6214,26 @@ static const struct phylink_pcs_ops mvpp + .pcs_config = mvpp2_xlg_pcs_config, + }; + +-static int mvpp2_gmac_pcs_validate(struct phylink_pcs *pcs, +- unsigned long *supported, +- const struct phylink_link_state *state) ++static unsigned int mvpp2_gmac_pcs_inband_caps(struct phylink_pcs *pcs, ++ phy_interface_t interface) + { +- /* When in 802.3z mode, we must have AN enabled: ++ /* When operating in an 802.3z mode, we must have AN enabled: + * Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ... + * When = 1 (1000BASE-X) this field must be set to 1. ++ * Therefore, inband is "required". + */ +- if (phy_interface_mode_is_8023z(state->interface) && +- !phylink_test(state->advertising, Autoneg)) +- return -EINVAL; ++ if (phy_interface_mode_is_8023z(interface)) ++ return LINK_INBAND_ENABLE; + +- return 0; ++ /* SGMII and RGMII can be configured to use inband signalling of the ++ * AN result. Indicate these as "possible". ++ */ ++ if (interface == PHY_INTERFACE_MODE_SGMII || ++ phy_interface_mode_is_rgmii(interface)) ++ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; ++ ++ /* For any other modes, indicate that inband is not supported. */ ++ return LINK_INBAND_DISABLE; + } + + static void mvpp2_gmac_pcs_get_state(struct phylink_pcs *pcs, +@@ -6333,7 +6340,7 @@ static void mvpp2_gmac_pcs_an_restart(st + } + + static const struct phylink_pcs_ops mvpp2_phylink_gmac_pcs_ops = { +- .pcs_validate = mvpp2_gmac_pcs_validate, ++ .pcs_inband_caps = mvpp2_gmac_pcs_inband_caps, + .pcs_get_state = mvpp2_gmac_pcs_get_state, + .pcs_config = mvpp2_gmac_pcs_config, + .pcs_an_restart = mvpp2_gmac_pcs_an_restart, +--- a/drivers/net/pcs/pcs-lynx.c ++++ b/drivers/net/pcs/pcs-lynx.c +@@ -35,6 +35,27 @@ enum sgmii_speed { + #define phylink_pcs_to_lynx(pl_pcs) container_of((pl_pcs), struct lynx_pcs, pcs) + #define lynx_to_phylink_pcs(lynx) (&(lynx)->pcs) + ++static unsigned int lynx_pcs_inband_caps(struct phylink_pcs *pcs, ++ phy_interface_t interface) ++{ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_QSGMII: ++ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; ++ ++ case PHY_INTERFACE_MODE_10GBASER: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ return LINK_INBAND_DISABLE; ++ ++ case PHY_INTERFACE_MODE_USXGMII: ++ return LINK_INBAND_ENABLE; ++ ++ default: ++ return 0; ++ } ++} ++ + static void lynx_pcs_get_state_usxgmii(struct mdio_device *pcs, + struct phylink_link_state *state) + { +@@ -307,6 +328,7 @@ static void lynx_pcs_link_up(struct phyl + } + + static const struct phylink_pcs_ops lynx_pcs_phylink_ops = { ++ .pcs_inband_caps = lynx_pcs_inband_caps, + .pcs_get_state = lynx_pcs_get_state, + .pcs_config = lynx_pcs_config, + .pcs_an_restart = lynx_pcs_an_restart, +--- a/drivers/net/pcs/pcs-mtk-lynxi.c ++++ b/drivers/net/pcs/pcs-mtk-lynxi.c +@@ -110,6 +110,21 @@ static struct mtk_pcs_lynxi *pcs_to_mtk_ + return container_of(pcs, struct mtk_pcs_lynxi, pcs); + } + ++static unsigned int mtk_pcs_lynxi_inband_caps(struct phylink_pcs *pcs, ++ phy_interface_t interface) ++{ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_1000BASEX: ++ case PHY_INTERFACE_MODE_2500BASEX: ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_QSGMII: ++ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; ++ ++ default: ++ return 0; ++ } ++} ++ + static void mtk_pcs_lynxi_get_state(struct phylink_pcs *pcs, + struct phylink_link_state *state) + { +@@ -302,6 +317,7 @@ static void mtk_pcs_lynxi_disable(struct + } + + static const struct phylink_pcs_ops mtk_pcs_lynxi_ops = { ++ .pcs_inband_caps = mtk_pcs_lynxi_inband_caps, + .pcs_get_state = mtk_pcs_lynxi_get_state, + .pcs_config = mtk_pcs_lynxi_config, + .pcs_an_restart = mtk_pcs_lynxi_restart_an, +--- a/drivers/net/pcs/pcs-xpcs.c ++++ b/drivers/net/pcs/pcs-xpcs.c +@@ -628,6 +628,33 @@ static int xpcs_validate(struct phylink_ + return 0; + } + ++static unsigned int xpcs_inband_caps(struct phylink_pcs *pcs, ++ phy_interface_t interface) ++{ ++ struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs); ++ const struct dw_xpcs_compat *compat; ++ ++ compat = xpcs_find_compat(xpcs, interface); ++ if (!compat) ++ return 0; ++ ++ switch (compat->an_mode) { ++ case DW_AN_C73: ++ return LINK_INBAND_ENABLE; ++ ++ case DW_AN_C37_SGMII: ++ case DW_AN_C37_1000BASEX: ++ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE; ++ ++ case DW_10GBASER: ++ case DW_2500BASEX: ++ return LINK_INBAND_DISABLE; ++ ++ default: ++ return 0; ++ } ++} ++ + void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces) + { + int i, j; +@@ -1331,6 +1358,7 @@ static const struct xpcs_id xpcs_id_list + + static const struct phylink_pcs_ops xpcs_phylink_ops = { + .pcs_validate = xpcs_validate, ++ .pcs_inband_caps = xpcs_inband_caps, + .pcs_config = xpcs_config, + .pcs_get_state = xpcs_get_state, + .pcs_an_restart = xpcs_an_restart, diff --git a/lede/target/linux/mvebu/Makefile b/lede/target/linux/mvebu/Makefile index 6a1e0f63f7..98bb4ef4f3 100644 --- a/lede/target/linux/mvebu/Makefile +++ b/lede/target/linux/mvebu/Makefile @@ -9,7 +9,7 @@ BOARDNAME:=Marvell EBU Armada FEATURES:=fpu usb pci pcie gpio nand squashfs ramdisk boot-part rootfs-part legacy-sdcard targz SUBTARGETS:=cortexa9 cortexa53 cortexa72 -KERNEL_PATCHVER:=5.10 +KERNEL_PATCHVER:=6.6 KERNEL_TESTING_PATCHVER:=5.15 include $(INCLUDE_DIR)/target.mk diff --git a/lede/target/linux/mvebu/config-6.6 b/lede/target/linux/mvebu/config-6.6 new file mode 100644 index 0000000000..939514e13f --- /dev/null +++ b/lede/target/linux/mvebu/config-6.6 @@ -0,0 +1,439 @@ +CONFIG_AHCI_MVEBU=y +CONFIG_ALIGNMENT_TRAP=y +CONFIG_ARCH_32BIT_OFF_T=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y +CONFIG_ARCH_MULTIPLATFORM=y +CONFIG_ARCH_MULTI_V6_V7=y +CONFIG_ARCH_MULTI_V7=y +CONFIG_ARCH_MVEBU=y +CONFIG_ARCH_NR_GPIO=0 +CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM=y +CONFIG_ARMADA_370_CLK=y +CONFIG_ARMADA_370_XP_IRQ=y +CONFIG_ARMADA_370_XP_TIMER=y +# CONFIG_ARMADA_37XX_WATCHDOG is not set +CONFIG_ARMADA_38X_CLK=y +CONFIG_ARMADA_THERMAL=y +CONFIG_ARMADA_XP_CLK=y +CONFIG_ARM_APPENDED_DTB=y +# CONFIG_ARM_ARMADA_37XX_CPUFREQ is not set +# CONFIG_ARM_ARMADA_8K_CPUFREQ is not set +CONFIG_ARM_ATAG_DTB_COMPAT=y +# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER is not set +CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE=y +CONFIG_ARM_CPU_SUSPEND=y +CONFIG_ARM_ERRATA_720789=y +CONFIG_ARM_ERRATA_764369=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GLOBAL_TIMER=y +CONFIG_ARM_GT_INITIAL_PRESCALER_VAL=1 +CONFIG_ARM_HEAVY_MB=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_MVEBU_V7_CPUIDLE=y +CONFIG_ARM_PATCH_IDIV=y +CONFIG_ARM_PATCH_PHYS_VIRT=y +CONFIG_ARM_THUMB=y +CONFIG_ARM_UNWIND=y +CONFIG_ARM_VIRT_EXT=y +CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH=y +CONFIG_ATA=y +CONFIG_ATAGS=y +CONFIG_ATA_LEDS=y +CONFIG_AUTO_ZRELADDR=y +CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_NVME=y +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BOUNCE=y +# CONFIG_CACHE_FEROCEON_L2 is not set +CONFIG_CACHE_L2X0=y +CONFIG_CC_HAVE_STACKPROTECTOR_TLS=y +CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK=y +CONFIG_CLKSRC_MMIO=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_COMMON_CLK=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=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 is not set +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_PJ4B=y +CONFIG_CPU_PM=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_SPECTRE=y +CONFIG_CPU_THERMAL=y +CONFIG_CPU_THUMB_CAPABLE=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_V7=y +CONFIG_CRC16=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_AES_ARM_BS=y +CONFIG_CRYPTO_AUTHENC=y +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CRC32=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_CRYPTD=y +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_DEV_MARVELL=y +CONFIG_CRYPTO_DEV_MARVELL_CESA=y +CONFIG_CRYPTO_ESSIV=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_DES=y +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_LZO=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM=y +CONFIG_CRYPTO_SHA1_ARM_NEON=y +CONFIG_CRYPTO_SHA256_ARM=y +CONFIG_CRYPTO_SHA512_ARM=y +CONFIG_CRYPTO_SIMD=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_ALIGN_RODATA=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_LL=y +CONFIG_DEBUG_LL_INCLUDE="debug/8250.S" +CONFIG_DEBUG_MVEBU_UART0=y +# CONFIG_DEBUG_MVEBU_UART0_ALTERNATE is not set +# CONFIG_DEBUG_MVEBU_UART1_ALTERNATE is not set +CONFIG_DEBUG_UART_8250=y +CONFIG_DEBUG_UART_8250_SHIFT=2 +CONFIG_DEBUG_UART_PHYS=0xd0012000 +CONFIG_DEBUG_UART_VIRT=0xfec12000 +CONFIG_DEBUG_USER=y +CONFIG_DMADEVICES=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_ENGINE_RAID=y +CONFIG_DMA_OF=y +CONFIG_DMA_OPS=y +CONFIG_DTC=y +CONFIG_EARLY_PRINTK=y +CONFIG_EDAC_ATOMIC_SCRUB=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_EXT4_FS=y +CONFIG_EXTCON=y +CONFIG_F2FS_FS=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FWNODE_MDIO=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_GENERIC_IRQ_MULTI_HANDLER=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_MSI_IRQ_DOMAIN=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=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_GENERIC_VDSO_32=y +CONFIG_GLOB=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_GENERIC=y +CONFIG_GPIO_GENERIC_PLATFORM=y +CONFIG_GPIO_MVEBU=y +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_PCA953X_IRQ=y +CONFIG_GRO_CELLS=y +CONFIG_HARDEN_BRANCH_PREDICTOR=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAVE_SMP=y +CONFIG_HIGHMEM=y +CONFIG_HIGHPTE=y +CONFIG_HOTPLUG_CPU=y +CONFIG_HWBM=y +CONFIG_HWMON=y +CONFIG_HW_RANDOM=y +CONFIG_HZ_FIXED=0 +CONFIG_HZ_PERIODIC=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MV64XXX=y +# CONFIG_I2C_PXA is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_WORK=y +# CONFIG_IWMMXT is not set +CONFIG_JBD2=y +CONFIG_KMAP_LOCAL=y +CONFIG_KMAP_LOCAL_NON_LINEAR_PTE_ARRAY=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_PCA963X=y +CONFIG_LEDS_TLC591XX=y +CONFIG_LEDS_TRIGGER_DISK=y +CONFIG_LIBFDT=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_MACH_ARMADA_370=y +# CONFIG_MACH_ARMADA_375 is not set +CONFIG_MACH_ARMADA_38X=y +# CONFIG_MACH_ARMADA_39X is not set +CONFIG_MACH_ARMADA_XP=y +# CONFIG_MACH_DOVE is not set +CONFIG_MACH_MVEBU_ANY=y +CONFIG_MACH_MVEBU_V7=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_MANGLE_BOOTARGS=y +CONFIG_MARVELL_PHY=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y +CONFIG_MDIO_I2C=y +CONFIG_MEMFD_CREATE=y +CONFIG_MEMORY=y +CONFIG_MIGHT_HAVE_CACHE_L2X0=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_MVSDIO=y +CONFIG_MMC_SDHCI=y +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_PXAV3=y +CONFIG_MODULES_USE_ELF_REL=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_NAND_CORE=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_NAND_ECC_SW_HAMMING=y +CONFIG_MTD_NAND_MARVELL=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y +CONFIG_MTD_SPLIT_FIRMWARE=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_MVEBU_CLK_COMMON=y +CONFIG_MVEBU_CLK_COREDIV=y +CONFIG_MVEBU_CLK_CPU=y +CONFIG_MVEBU_DEVBUS=y +CONFIG_MVEBU_MBUS=y +CONFIG_MVMDIO=y +CONFIG_MVNETA=y +CONFIG_MVNETA_BM=y +CONFIG_MVNETA_BM_ENABLE=y +# CONFIG_MVPP2 is not set +CONFIG_MV_XOR=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEON=y +CONFIG_NET_DEVLINK=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_SELFTESTS=y +CONFIG_NLS=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_NR_CPUS=4 +CONFIG_NVMEM=y +CONFIG_NVME_CORE=y +# CONFIG_NVME_HWMON is not set +# CONFIG_NVME_MULTIPATH is not set +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OLD_SIGACTION=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_ORION_WATCHDOG=y +CONFIG_OUTER_CACHE=y +CONFIG_OUTER_CACHE_SYNC=y +CONFIG_PADATA=y +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PAGE_POOL=y +CONFIG_PAGE_POOL_STATS=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PCI=y +CONFIG_PCI_BRIDGE_EMUL=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PCI_MVEBU=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHYLIB=y +CONFIG_PHYLINK=y +# CONFIG_PHY_MVEBU_A3700_COMPHY is not set +# CONFIG_PHY_MVEBU_A3700_UTMI is not set +# CONFIG_PHY_MVEBU_A38X_COMPHY is not set +# CONFIG_PHY_MVEBU_CP110_COMPHY is not set +CONFIG_PINCTRL=y +CONFIG_PINCTRL_ARMADA_370=y +CONFIG_PINCTRL_ARMADA_38X=y +CONFIG_PINCTRL_ARMADA_XP=y +CONFIG_PINCTRL_MVEBU=y +# CONFIG_PINCTRL_SINGLE is not set +CONFIG_PJ4B_ERRATA_4742=y +CONFIG_PL310_ERRATA_753970=y +CONFIG_PLAT_ORION=y +CONFIG_PM_OPP=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_PREEMPT_NONE_BUILD=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_PWM=y +CONFIG_PWM_SYSFS=y +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RATIONAL=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_RFS_ACCEL=y +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_ARMADA38X=y +# CONFIG_RTC_DRV_MV is not set +CONFIG_RTC_I2C_AND_SPI=y +CONFIG_RTC_MC146818_LIB=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_SATA_HOST=y +CONFIG_SATA_MV=y +CONFIG_SATA_PMP=y +CONFIG_SCSI=y +CONFIG_SCSI_COMMON=y +CONFIG_SENSORS_PWM_FAN=y +CONFIG_SENSORS_TMP421=y +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_8250_DWLIB=y +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_MVEBU_CONSOLE=y +CONFIG_SERIAL_MVEBU_UART=y +CONFIG_SFP=y +CONFIG_SGL_ALLOC=y +CONFIG_SG_POOL=y +CONFIG_SMP=y +CONFIG_SMP_ON_UP=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SOC_BUS=y +CONFIG_SOFTIRQ_ON_OWN_STACK=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +# CONFIG_SPI_ARMADA_3700 is not set +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPI_ORION=y +CONFIG_SRAM=y +CONFIG_SRAM_EXEC=y +CONFIG_SRCU=y +CONFIG_SWPHY=y +CONFIG_SWP_EMULATE=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=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_HWMON=y +CONFIG_THERMAL_OF=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_UBIFS_FS=y +CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" +CONFIG_UNWINDER_ARM=y +CONFIG_USB=y +CONFIG_USB_COMMON=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_HCD_ORION=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_USB_LEDS_TRIGGER_USBPORT=y +CONFIG_USB_PHY=y +CONFIG_USB_STORAGE=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_MVEBU=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USE_OF=y +CONFIG_VFP=y +CONFIG_VFPv3=y +CONFIG_WATCHDOG_CORE=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_BCJ=y +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZSTD_COMMON=y +CONFIG_ZSTD_COMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y diff --git a/lede/target/linux/mvebu/cortexa53/config-6.6 b/lede/target/linux/mvebu/cortexa53/config-6.6 new file mode 100644 index 0000000000..9679d30ddf --- /dev/null +++ b/lede/target/linux/mvebu/cortexa53/config-6.6 @@ -0,0 +1,95 @@ +CONFIG_64BIT=y +CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y +CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=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_STACKWALK=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_ARCH_WANTS_THP_SWAP=y +CONFIG_ARM64=y +CONFIG_ARM64_4K_PAGES=y +CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y +CONFIG_ARM64_PAGE_SHIFT=12 +CONFIG_ARM64_PA_BITS=48 +CONFIG_ARM64_PA_BITS_48=y +CONFIG_ARM64_TAGGED_ADDR_ABI=y +CONFIG_ARM64_VA_BITS=39 +CONFIG_ARM64_VA_BITS_39=y +CONFIG_ARMADA_37XX_CLK=y +CONFIG_ARMADA_37XX_RWTM_MBOX=y +CONFIG_ARMADA_37XX_WATCHDOG=y +CONFIG_ARMADA_AP806_SYSCON=y +CONFIG_ARMADA_AP_CP_HELPER=y +CONFIG_ARMADA_CP110_SYSCON=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +# CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set +CONFIG_ARM_ARMADA_37XX_CPUFREQ=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_GIC_V3_ITS_PCI=y +# CONFIG_ARM_MHU_V2 is not set +# CONFIG_ARM_PL172_MPMC is not set +CONFIG_ARM_PSCI_FW=y +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_CC_HAVE_SHADOW_CALL_STACK=y +CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_F2FS_FS_COMPRESSION=y +# CONFIG_F2FS_FS_LZ4 is not set +# CONFIG_F2FS_FS_LZO is not set +CONFIG_F2FS_FS_ZSTD=y +CONFIG_FRAME_POINTER=y +CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_REGS=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_IOREMAP=y +CONFIG_GENERIC_PINCONF=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_MAILBOX=y +# CONFIG_MAILBOX_TEST is not set +CONFIG_MFD_SYSCON=y +CONFIG_MMC_SDHCI_XENON=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MVEBU_GICP=y +CONFIG_MVEBU_ICU=y +CONFIG_MVEBU_ODMI=y +CONFIG_MVEBU_PIC=y +CONFIG_MVEBU_SEI=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_PARTITION_PERCPU=y +CONFIG_PCI_AARDVARK=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PHY_MVEBU_A3700_COMPHY=y +CONFIG_PHY_MVEBU_A3700_UTMI=y +CONFIG_PINCTRL_AC5=y +CONFIG_PINCTRL_ARMADA_37XX=y +CONFIG_PINCTRL_ARMADA_AP806=y +CONFIG_PINCTRL_ARMADA_CP110=y +CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_POWER_SUPPLY=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_REGULATOR_GPIO=y +CONFIG_RODATA_FULL_DEFAULT_ENABLED=y +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPI_ARMADA_3700=y +CONFIG_SWIOTLB=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y +CONFIG_TURRIS_MOX_RWTM=y +CONFIG_UNMAP_KERNEL_AT_EL0=y +CONFIG_VMAP_STACK=y +CONFIG_ZONE_DMA32=y diff --git a/lede/target/linux/mvebu/cortexa72/config-6.6 b/lede/target/linux/mvebu/cortexa72/config-6.6 new file mode 100644 index 0000000000..d6aaa8d0bd --- /dev/null +++ b/lede/target/linux/mvebu/cortexa72/config-6.6 @@ -0,0 +1,121 @@ +CONFIG_64BIT=y +CONFIG_AQUANTIA_PHY=y +CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y +CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=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_STACKWALK=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_ARCH_WANTS_THP_SWAP=y +CONFIG_ARM64=y +CONFIG_ARM64_4K_PAGES=y +CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y +CONFIG_ARM64_PAGE_SHIFT=12 +CONFIG_ARM64_PA_BITS=48 +CONFIG_ARM64_PA_BITS_48=y +CONFIG_ARM64_SVE=y +# CONFIG_ARM64_TAGGED_ADDR_ABI is not set +CONFIG_ARM64_VA_BITS=39 +CONFIG_ARM64_VA_BITS_39=y +CONFIG_ARMADA_37XX_CLK=y +CONFIG_ARMADA_AP806_SYSCON=y +CONFIG_ARMADA_AP_CPU_CLK=y +CONFIG_ARMADA_AP_CP_HELPER=y +CONFIG_ARMADA_CP110_SYSCON=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +# CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set +CONFIG_ARM_ARMADA_8K_CPUFREQ=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_GIC_V3_ITS_PCI=y +# CONFIG_ARM_PL172_MPMC is not set +CONFIG_ARM_PSCI_FW=y +CONFIG_ARM_SBSA_WATCHDOG=y +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_CC_HAVE_SHADOW_CALL_STACK=y +CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CRC_CCITT=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_EEPROM_AT24=y +CONFIG_FRAME_POINTER=y +CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_REGS=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_IOREMAP=y +CONFIG_GENERIC_PINCONF=y +CONFIG_HW_RANDOM_OMAP=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_LEDS_IEI_WT61P803_PUZZLE=y +CONFIG_LEDS_IS31FL319X=y +CONFIG_MARVELL_10G_PHY=y +CONFIG_MFD_CORE=y +CONFIG_MFD_IEI_WT61P803_PUZZLE=y +CONFIG_MFD_SYSCON=y +CONFIG_MIKROTIK=y +CONFIG_MIKROTIK_RB_SYSFS=y +# CONFIG_MIKROTIK_WLAN_DECOMPRESS_LZ77 is not set +CONFIG_MMC_SDHCI_XENON=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MTD_ROUTERBOOT_PARTS=y +CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y +CONFIG_MVEBU_GICP=y +CONFIG_MVEBU_ICU=y +CONFIG_MVEBU_ODMI=y +CONFIG_MVEBU_PIC=y +CONFIG_MVEBU_SEI=y +CONFIG_MVPP2=y +CONFIG_MV_XOR_V2=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NVMEM_LAYOUTS=y +CONFIG_NVMEM_LAYOUT_MIKROTIK=y +CONFIG_NVMEM_LAYOUT_ONIE_TLV=y +CONFIG_NVMEM_SYSFS=y +CONFIG_NVMEM_U_BOOT_ENV=y +CONFIG_PARTITION_PERCPU=y +CONFIG_PCIEAER=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_ARMADA_8K=y +CONFIG_PCIE_DW=y +CONFIG_PCIE_DW_HOST=y +# CONFIG_PCI_AARDVARK is not set +CONFIG_PGTABLE_LEVELS=3 +CONFIG_PHYLIB_LEDS=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PHY_MVEBU_CP110_COMPHY=y +CONFIG_PHY_MVEBU_CP110_UTMI=y +CONFIG_PINCTRL_AC5=y +CONFIG_PINCTRL_ARMADA_37XX=y +CONFIG_PINCTRL_ARMADA_AP806=y +CONFIG_PINCTRL_ARMADA_CP110=y +CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_POWER_SUPPLY=y +CONFIG_QCA808X_PHY=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_RAS=y +# CONFIG_RAVE_SP_CORE is not set +CONFIG_REGULATOR_GPIO=y +CONFIG_REGULATOR_USERSPACE_CONSUMER=y +# CONFIG_RODATA_FULL_DEFAULT_ENABLED is not set +CONFIG_SENSORS_IEI_WT61P803_PUZZLE_HWMON=y +CONFIG_SERIAL_DEV_BUS=y +CONFIG_SERIAL_DEV_CTRL_TTYPORT=y +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SWIOTLB=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y +CONFIG_UNMAP_KERNEL_AT_EL0=y +CONFIG_VMAP_STACK=y +CONFIG_ZONE_DMA32=y diff --git a/lede/target/linux/mvebu/cortexa9/config-6.6 b/lede/target/linux/mvebu/cortexa9/config-6.6 new file mode 100644 index 0000000000..7f825a806b --- /dev/null +++ b/lede/target/linux/mvebu/cortexa9/config-6.6 @@ -0,0 +1,12 @@ +CONFIG_ARM_HAS_GROUP_RELOCS=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CURRENT_POINTER_IN_TPIDRURO=y +CONFIG_IRQSTACKS=y +CONFIG_LED_TRIGGER_PHY=y +CONFIG_MTD_SPLIT_SEIL_FW=y +CONFIG_MTD_SPLIT_UIMAGE_FW=y +CONFIG_MTD_VIRT_CONCAT=y +CONFIG_PHY_MVEBU_A38X_COMPHY=y +CONFIG_POWER_RESET_QNAP=y +CONFIG_RTC_DRV_MV=y +CONFIG_THREAD_INFO_IN_TASK=y diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-370-buffalo-ls220de.dts b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-370-buffalo-ls220de.dts new file mode 100644 index 0000000000..8740cb32d9 --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-370-buffalo-ls220de.dts @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT) +/* + * Device Tree file for Buffalo LinkStation LS220DE + * + * Copyright (C) 2023 Daniel González Cabanelas + */ + +/dts-v1/; + +#include "armada-370.dtsi" +#include "mvebu-linkstation-fan.dtsi" +#include +#include +#include +#include + +/ { + model = "Buffalo LinkStation LS220DE"; + compatible = "buffalo,ls220de", "marvell,armada370", "marvell,armada-370-xp"; + + aliases { + led-boot = &led_boot; + led-failsafe = &led_failsafe; + led-running = &led_power; + led-upgrade = &led_upgrade; + }; + + chosen { + bootargs = "earlycon"; + stdout-path = "serial0:115200n8"; + append-rootblock = "nullparameter="; /* override the bootloader args */ + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x10000000>; /* 256 MB */ + }; + + soc { + ranges = ; + }; + + system_fan: gpio_fan { + gpios = <&gpio0 13 GPIO_ACTIVE_HIGH + &gpio0 14 GPIO_ACTIVE_HIGH>; + alarm-gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>; + + #cooling-cells = <2>; + }; + + thermal-zones { + hdd-thermal { + polling-delay = <20000>; + polling-delay-passive = <2000>; + + thermal-sensors = <&hdd0_temp>; /* only one drivetemp sensor is supported */ + + trips { + hdd_alert1: trip1 { + temperature = <34000>; + hysteresis = <2000>; + type = "active"; + }; + hdd_alert2: trip2 { + temperature = <40000>; + hysteresis = <2000>; + type = "active"; + }; + hdd_alert3: trip3 { + temperature = <45000>; + hysteresis = <2000>; + type = "passive"; + }; + hdd_hot { + temperature = <50000>; + hysteresis = <2000>; + type = "hot"; + }; + hdd_crit { + temperature = <60000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + + cooling-maps { + map1 { + trip = <&hdd_alert1>; + cooling-device = <&system_fan THERMAL_NO_LIMIT 1>; + }; + map2 { + trip = <&hdd_alert2>; + cooling-device = <&system_fan 2 2>; + }; + map3 { + trip = <&hdd_alert3>; + cooling-device = <&system_fan 3 THERMAL_NO_LIMIT>; + }; + }; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + pinctrl-0 = <&pmx_buttons>; + pinctrl-names = "default"; + + power { + label = "Power Switch"; + linux,code = ; + linux,input-type = ; + gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + }; + + function { + label = "Function Button"; + linux,code = ; + gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + }; + }; + + gpio_leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pmx_leds1 &pmx_leds2>; + + indicator_red { + function = LED_FUNCTION_INDICATOR; + color = ; + gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; + panic-indicator; + }; + + led_power: power_white { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + + led_failsafe: power_red { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; + }; + + led_upgrade: power_orange { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&gpio1 25 GPIO_ACTIVE_HIGH>; + }; + + led_boot: indicator_white { + function = LED_FUNCTION_INDICATOR; + color = ; + gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>; + }; + + hdd1_red { + function = LED_FUNCTION_DISK; + color = ; + gpios = <&gpio1 29 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "ata1"; + function-enumerator = <1>; + }; + + hdd2_red { + function = LED_FUNCTION_DISK; + color = ; + gpios = <&gpio1 30 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "ata2"; + function-enumerator = <2>; + }; + }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-0 = <&pmx_power_hdd1 &pmx_power_hdd2>; + pinctrl-names = "default"; + + sata1_power: regulator@1 { + compatible = "regulator-fixed"; + reg = <1>; + regulator-name = "HDD1"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + startup-delay-us = <2000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; + }; + + sata2_power: regulator@2 { + compatible = "regulator-fixed"; + reg = <2>; + regulator-name = "HDD2"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + startup-delay-us = <4000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&coherencyfab { + broken-idle; +}; + +ð1 { + pinctrl-0 = <&ge1_rgmii_pins>; + pinctrl-names = "default"; + status = "okay"; + phy-handle = <ðphy0>; + phy-connection-type = "rgmii-id"; +}; + +&mdio { + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + + ethphy0: ethernet-phy@0 { /* Marvell 88E1318 */ + reg = <0>; + marvell,reg-init = <0x3 0x10 0xf000 0x091A>, /* LED function */ + <0x3 0x11 0x0000 0x4401>, /* LED polarity */ + <0x3 0x12 0x0000 0x4905>; /* LED timer */ + #thermal-sensor-cells = <0>; + }; +}; + +&nand_controller { + status = "okay"; + + nand@0 { + reg = <0>; + label = "pxa3xx_nand-0"; + nand-rb = <0>; + marvell,nand-keep-config; + nand-on-flash-bbt; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "ubi_kernel"; + reg = <0x00000000 0x02000000>; /* 32 MiB */ + }; + + partition@2000000 { + label = "ubi"; + reg = <0x02000000 0x1df00000>; /* 479 MiB */ + }; + }; + }; +}; + +&sata { + nr-ports = <2>; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + hdd0_temp: sata-port@0 { + reg = <0>; + #thermal-sensor-cells = <0>; + }; + + hdd1_temp: sata-port@1 { + reg = <1>; + #thermal-sensor-cells = <0>; + }; +}; + +&spi0 { + status = "okay"; + pinctrl-0 = <&spi0_pins2>; + pinctrl-names = "default"; + + spi-flash@0 { + compatible = "mxicy,mx25l8005", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x00000 0xf0000>; /* 960 KiB*/ + label = "u-boot"; + read-only; + }; + partition@f0000 { + reg = <0xf0000 0x10000>; /* 64 KiB */ + label = "u-boot-env"; + }; + }; + }; +}; + +&pmsu { + pinctrl-0 = <&pmx_power_cpu>; + pinctrl-names = "default"; +}; + +&uart0 { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&pinctrl { + pmx_power_hdd2: pmx-power-hdd2 { + marvell,pins = "mpp2"; + marvell,function = "gpio"; + }; + + pmx_power_cpu: pmx-power-cpu { + marvell,pins = "mpp4"; + marvell,function = "vdd"; + }; + + pmx_power_hdd1: pmx-power-hdd1 { + marvell,pins = "mpp8"; + marvell,function = "gpio"; + }; + + pmx_fan_lock: pmx-fan-lock { + marvell,pins = "mpp10"; + marvell,function = "gpio"; + }; + + pmx_hdd_present: pmx-hdd-present { + marvell,pins = "mpp11", "mpp12"; + marvell,function = "gpio"; + }; + + pmx_fan_high: pmx-fan-high { + marvell,pins = "mpp13"; + marvell,function = "gpio"; + }; + + pmx_fan_low: pmx-fan-low { + marvell,pins = "mpp14"; + marvell,function = "gpio"; + }; + + pmx_buttons: pmx-buttons { + marvell,pins = "mpp15", "mpp16"; + marvell,function = "gpio"; + }; + + pmx_leds1: pmx-leds { + marvell,pins = "mpp7", "mpp54", "mpp59", "mpp61"; + marvell,function = "gpo"; + }; + + pmx_leds2: pmx-leds { + marvell,pins = "mpp55", "mpp57", "mpp62"; + marvell,function = "gpio"; + }; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-370-buffalo-ls421de.dts b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-370-buffalo-ls421de.dts new file mode 100644 index 0000000000..13cc8efa2d --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-370-buffalo-ls421de.dts @@ -0,0 +1,448 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT) +/* + * Device Tree file for Buffalo LinkStation LS421DE + * + * Copyright (C) 2020 Daniel González Cabanelas + */ + +/dts-v1/; + +#include "armada-370.dtsi" +#include "mvebu-linkstation-fan.dtsi" +#include +#include +#include + +/ { + model = "Buffalo LinkStation LS421DE"; + compatible = "buffalo,ls421de", "marvell,armada370", "marvell,armada-370-xp"; + + aliases { + led-boot = &led_boot; + led-failsafe = &led_failsafe; + led-running = &led_power; + led-upgrade = &led_upgrade; + }; + + chosen { + bootargs = "earlycon"; + stdout-path = "serial0:115200n8"; + append-rootblock = "nullparameter="; /* override the bootloader args */ + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x20000000>; /* 512 MB */ + }; + + soc { + ranges = ; + }; + + system_fan: gpio_fan { + gpios = <&gpio0 13 GPIO_ACTIVE_HIGH + &gpio0 14 GPIO_ACTIVE_HIGH>; + alarm-gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>; + + #cooling-cells = <2>; + }; + + thermal-zones { + hdd-thermal { + polling-delay = <20000>; + polling-delay-passive = <2000>; + + thermal-sensors = <&hdd0_temp>; /* only one drivetemp sensor is supported */ + + trips { + hdd_alert1: trip1 { + temperature = <36000>; + hysteresis = <2000>; + type = "active"; + }; + hdd_alert2: trip2 { + temperature = <44000>; + hysteresis = <2000>; + type = "active"; + }; + hdd_alert3: trip3 { + temperature = <52000>; + hysteresis = <2000>; + type = "passive"; + }; + hdd_crit: trip4 { + temperature = <60000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + + cooling-maps { + map1 { + trip = <&hdd_alert1>; + cooling-device = <&system_fan THERMAL_NO_LIMIT 1>; + }; + map2 { + trip = <&hdd_alert2>; + cooling-device = <&system_fan 2 2>; + }; + map3 { + trip = <&hdd_alert3>; + cooling-device = <&system_fan 3 THERMAL_NO_LIMIT>; + }; + }; + }; + + ethphy-thermal { + polling-delay = <20000>; + polling-delay-passive = <2000>; + + thermal-sensors = <ðphy0>; + + trips { + ethphy_alert1: trip1 { + temperature = <65000>; + hysteresis = <4000>; + type = "passive"; + }; + + ethphy_crit: trip2 { + temperature = <100000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + + cooling-maps { + map1 { + trip = <ðphy_alert1>; + cooling-device = <&system_fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + + }; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + pinctrl-0 = <&pmx_buttons>; + pinctrl-names = "default"; + + power { + label = "Power Switch"; + linux,code = ; + linux,input-type = ; + gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + }; + + function { + label = "Function Button"; + linux,code = ; + gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + }; + }; + + gpio_leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pmx_leds1 &pmx_leds2>; + + system_red { + label = "ls421de:red:system"; + gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; + }; + + led_power: power_white { + label = "ls421de:white:power"; + gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + + led_failsafe: power_red { + label = "ls421de:red:power"; + gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; + }; + + led_upgrade: power_orange { + label = "ls421de:orange:power"; + gpios = <&gpio1 25 GPIO_ACTIVE_HIGH>; + }; + + led_boot: system_white { + label = "ls421de:white:system"; + gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>; + }; + + hdd1_red { + label = "ls421de:red:hdd1"; + gpios = <&gpio1 29 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "ata1"; + }; + + hdd2_red { + label = "ls421de:red:hdd2"; + gpios = <&gpio1 30 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "ata2"; + }; + }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-0 = <&pmx_power_usb &pmx_power_hdd1 &pmx_power_hdd2>; + pinctrl-names = "default"; + + usb_power: regulator@0 { + compatible = "regulator-fixed"; + reg = <0>; + regulator-name = "USB"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>; + }; + + sata1_power: regulator@1 { + compatible = "regulator-fixed"; + reg = <1>; + regulator-name = "HDD1"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + startup-delay-us = <2000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; + }; + + sata2_power: regulator@2 { + compatible = "regulator-fixed"; + reg = <2>; + regulator-name = "HDD2"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + startup-delay-us = <4000000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&coherencyfab { + broken-idle; +}; + +ð1 { + pinctrl-0 = <&ge1_rgmii_pins>; + pinctrl-names = "default"; + status = "okay"; + phy-handle = <ðphy0>; + phy-connection-type = "rgmii-id"; +}; + +&i2c0 { + pinctrl-0 = <&i2c0_pins>; + pinctrl-names = "default"; + clock-frequency = <100000>; + status = "okay"; + + rs5c372a: rs5c372a@32 { + compatible = "ricoh,rs5c372a"; + reg = <0x32>; + wakeup-source; + }; +}; + +&mdio { + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + + ethphy0: ethernet-phy@0 { /* Marvell 88E1518 */ + reg = <0>; + marvell,reg-init = <0x2 0x10 0xffff 0x0006>, /* disable CLK125 */ + <0x3 0x10 0x0000 0x1991>, /* LED function */ + <0x3 0x11 0x0000 0x4401>, /* LED polarity */ + <0x3 0x12 0x0000 0x4905>; /* LED timer */ + #thermal-sensor-cells = <0>; + }; +}; + +&pciec { + status = "okay"; + pinctrl-0 = <&pmx_pcie>; + pinctrl-names = "default"; + + /* Connected to uPD720202 USB 3.0 Host */ + pcie@1,0 { + status = "okay"; + }; +}; + +&pmsu { + pinctrl-0 = <&pmx_power_cpu>; + pinctrl-names = "default"; +}; + +&rtc { + status = "disabled"; +}; + +&sata { + nr-ports = <2>; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + hdd0_temp: sata-port@0 { + reg = <0>; + #thermal-sensor-cells = <0>; + }; + + hdd1_temp: sata-port@1 { + reg = <1>; + #thermal-sensor-cells = <0>; + }; +}; + +&sdio { + pinctrl-0 = <&sdio_pins2>; + pinctrl-names = "default"; + status = "okay"; + /* No CD or WP GPIOs */ + broken-cd; +}; + +&uart0 { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&nand_controller { + status = "okay"; + + nand@0 { + reg = <0>; + label = "pxa3xx_nand-0"; + nand-rb = <0>; + marvell,nand-keep-config; + nand-on-flash-bbt; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "kernel"; + reg = <0x00000000 0x02000000>; /* 32 MiB */ + }; + + partition@2000000 { + label = "ubi"; + reg = <0x02000000 0x1e000000>; /* 480 MiB */ + }; + }; + }; +}; + +&spi0 { + status = "okay"; + pinctrl-0 = <&spi0_pins2>; + pinctrl-names = "default"; + + spi-flash@0 { + compatible = "mxicy,mx25l8005", "jedec,spi-nor"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <50000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x00000 0xf0000>; /* 960 KiB*/ + label = "u-boot"; + read-only; + }; + partition@f0000 { + reg = <0xf0000 0x10000>; /* 64 KiB */ + label = "u-boot-env"; + }; + }; + }; +}; + +&pinctrl { + pmx_power_cpu: pmx-power-cpu { + marvell,pins = "mpp4"; + marvell,function = "vdd"; + }; + + pmx_power_usb: pmx-power-usb { + marvell,pins = "mpp5"; + marvell,function = "gpo"; + }; + + pmx_power_hdd1: pmx-power-hdd1 { + marvell,pins = "mpp8"; + marvell,function = "gpio"; + }; + + pmx_power_hdd2: pmx-power-hdd2 { + marvell,pins = "mpp9"; + marvell,function = "gpo"; + }; + + pmx_fan_lock: pmx-fan-lock { + marvell,pins = "mpp10"; + marvell,function = "gpio"; + }; + + pmx_hdd_present: pmx-hdd-present { + marvell,pins = "mpp11", "mpp12"; + marvell,function = "gpio"; + }; + + pmx_fan_high: pmx-fan-high { + marvell,pins = "mpp13"; + marvell,function = "gpio"; + }; + + pmx_fan_low: pmx-fan-low { + marvell,pins = "mpp14"; + marvell,function = "gpio"; + }; + + pmx_buttons: pmx-buttons { + marvell,pins = "mpp15", "mpp16"; + marvell,function = "gpio"; + }; + + pmx_leds1: pmx-leds { + marvell,pins = "mpp7", "mpp54", "mpp59", "mpp61"; + marvell,function = "gpo"; + }; + + pmx_leds2: pmx-leds { + marvell,pins = "mpp55", "mpp57", "mpp62"; + marvell,function = "gpio"; + }; + + pmx_pcie: pmx-pcie { + marvell,pins = "mpp56", "mpp60"; + marvell,function = "pcie"; + }; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-370-c200-v2.dts b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-370-c200-v2.dts new file mode 100644 index 0000000000..0d5ec567ea --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-370-c200-v2.dts @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT) +/* + * Device Tree file for Ctera C200-V2 + * + * Copyright (C) 2021 Pawel Dembicki + */ + +/dts-v1/; + +#include "armada-370.dtsi" +#include +#include +#include +#include + +/ { + model = "Ctera C200 V2"; + compatible = "ctera,c200-v2", "marvell,armada370", "marvell,armada-370-xp"; + + aliases { + led-boot = &led_status_green; + led-failsafe = &led_status_red; + led-running = &led_status_green; + led-upgrade = &led_status_red; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x40000000>; /* 1024 MB */ + }; + + soc { + ranges = ; + }; + + thermal-zones { + ethphy-thermal { + polling-delay = <20000>; + polling-delay-passive = <2000>; + + thermal-sensors = <ðphy0>; + + trips { + ethphy_alert1: trip1 { + temperature = <65000>; + hysteresis = <4000>; + type = "passive"; + }; + + ethphy_crit: trip2 { + temperature = <100000>; + hysteresis = <2000>; + type = "critical"; + }; + }; + }; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-0 = <&pmx_buttons>; + pinctrl-names = "default"; + + power { + label = "Power Button"; + linux,code = ; + gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>; + }; + + reset { + label = "Reset Button"; + linux,code = ; + gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + }; + + usb1 { + label = "USB1 Button"; + linux,code = ; + gpios = <&gpio1 0 GPIO_ACTIVE_LOW>; + }; + + usb2 { + label = "USB2 Button"; + linux,code = ; + gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-poweroff { + compatible = "gpio-poweroff"; + pinctrl-0 = <&pmx_poweroff>; + pinctrl-names = "default"; + gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-0 = <&pmx_leds1 &pmx_leds2>; + pinctrl-names = "default"; + + led-0 { + function = LED_FUNCTION_USB; + function-enumerator = <2>; + color = ; + gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; + }; + + led-1 { + function = LED_FUNCTION_USB; + function-enumerator = <2>; + color = ; + gpios = <&gpio0 13 GPIO_ACTIVE_LOW>; + linux,default-trigger = "usbport"; + trigger-sources = <&usb1_port 1>, <&usb2_port 1>; + }; + + led-2 { + function = LED_FUNCTION_USB; + function-enumerator = <1>; + color = ; + gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + }; + + led-3 { + function = LED_FUNCTION_USB; + function-enumerator = <1>; + color = ; + gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + linux,default-trigger = "usbport"; + trigger-sources = <&usb1_port 2>, <&usb2_port 2>; + }; + + led-4 { + function = LED_FUNCTION_DISK; + function-enumerator = <2>; + color = ; + gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; + linux,default-trigger = "ata2"; + }; + + led-5 { + function = LED_FUNCTION_DISK; + function-enumerator = <1>; + color = ; + gpios = <&gpio1 18 GPIO_ACTIVE_LOW>; + }; + + led-6 { + function = LED_FUNCTION_DISK; + function-enumerator = <2>; + color = ; + gpios = <&gpio1 19 GPIO_ACTIVE_LOW>; + }; + + led-7 { + function = LED_FUNCTION_INDICATOR; + color = ; + gpios = <&gpio1 20 GPIO_ACTIVE_HIGH>; + }; + + led-8 { + function = LED_FUNCTION_DISK_ERR; + color = ; + gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; + }; + + led-9 { + function = LED_FUNCTION_DISK_ERR; + color = ; + gpios = <&gpio1 23 GPIO_ACTIVE_LOW>; + }; + + led_status_red: led-10 { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&gpio1 24 GPIO_ACTIVE_LOW>; + }; + + led-11 { + function = LED_FUNCTION_DISK; + function-enumerator = <1>; + color = ; + gpios = <&gpio1 25 GPIO_ACTIVE_LOW>; + linux,default-trigger = "ata1"; + }; + + led_status_green: led-12 { + function = LED_FUNCTION_STATUS; + color = ; + gpios = <&gpio1 26 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&coherencyfab { + broken-idle; +}; + +ð1 { + pinctrl-0 = <&ge1_rgmii_pins>; + pinctrl-names = "default"; + status = "okay"; + phy-handle = <ðphy0>; + phy-connection-type = "rgmii-id"; +}; + +&i2c0 { + pinctrl-0 = <&i2c0_pins>; + pinctrl-names = "default"; + clock-frequency = <100000>; + status = "okay"; + + hwmon@2a { + compatible = "nuvoton,nct7802"; + reg = <0x2a>; + }; + + rtc@30 { + compatible = "sii,s35390a"; + reg = <0x30>; + }; +}; + +&mdio { + pinctrl-0 = <&mdio_pins>; + pinctrl-names = "default"; + + ethphy0: ethernet-phy@0 { /* Marvell 88E1318 */ + reg = <0>; + #thermal-sensor-cells = <0>; + }; +}; + +&nand_controller { + status = "okay"; + + nand@0 { + reg = <0>; + label = "pxa3xx_nand-0"; + nand-rb = <0>; + marvell,nand-keep-config; + nand-on-flash-bbt; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "uboot"; + reg = <0x0000000 0x200000>; + read-only; + }; + + partition@200000 { + label = "certificate"; + reg = <0x0200000 0x100000>; + read-only; + }; + + partition@300000 { + label = "preset_cfg"; + reg = <0x0300000 0x100000>; + read-only; + }; + + partition@400000 { + label = "dev_params"; + reg = <0x0400000 0x100000>; + read-only; + }; + partition@500000 { + label = "active_bank"; + reg = <0x0500000 0x0100000>; + }; + + partition@600000 { + label = "magic"; + reg = <0x0600000 0x0100000>; + read-only; + }; + + partition@700000 { + label = "bank1"; + reg = <0x0700000 0x2800000>; + }; + + partition@2f00000 { + label = "bank2"; + reg = <0x2f00000 0x2800000>; + }; + + /* 0x5700000-0x5a00000 undefined in vendor firmware */ + + partition@5a00000 { + label = "reserved"; + reg = <0x5a00000 0x2000000>; + }; + + partition@7a00000 { + label = "ubi"; + reg = <0x7a00000 0x8600000>; + }; + }; + }; +}; + +&pciec { + status = "okay"; + + pcie@1,0 { + pinctrl-0 = <&pmx_pcie>; + pinctrl-names = "default"; + status = "okay"; + reset-gpios = <&gpio1 27 GPIO_ACTIVE_LOW>; + + /* -[0000:00]---01.0-[01]----00.0 */ + /* usbport trigger won't work */ + bridge@0,1 { + compatible = "pci11ab,6710"; + reg = <0x3800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + + usb@1,0 { + /* Renesas uPD720202 */ + compatible = "pci1912,0015"; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + + usb1_port: port@1 { + reg = <1>; + #trigger-source-cells = <1>; + }; + + usb2_port: port@2 { + reg = <2>; + #trigger-source-cells = <1>; + }; + }; + }; + }; +}; + +&pinctrl { + pmx_poweroff: pmx-poweroff { + marvell,pins = "mpp7"; + marvell,function = "gpo"; + }; + + pmx_power_cpu: pmx-power-cpu { + marvell,pins = "mpp4"; + marvell,function = "vdd"; + }; + + pmx_buttons: pmx-buttons { + marvell,pins = "mpp6", "mpp10", "mpp14", "mpp32"; + marvell,function = "gpio"; + }; + + pmx_leds1: pmx-leds1 { + marvell,pins = "mpp47"; + marvell,function = "gpo"; + }; + + pmx_leds2: pmx-leds2 { + marvell,pins = "mpp12", "mpp13", "mpp15", "mpp16", "mpp50", "mpp51", + "mpp52", "mpp53", "mpp55", "mpp56", "mpp57", "mpp58"; + marvell,function = "gpio"; + }; + + pmx_pcie: pmx-pcie { + marvell,pins = "mpp59"; + marvell,function = "gpio"; + }; + + /* this gpio is connected to the pin of buzzer + * leave it as is due lack of proper driver + */ + pmx_buzzer: pmx-buzzer { + marvell,pins = "mpp63"; + marvell,function = "gpio"; + }; +}; + +&pmsu { + pinctrl-0 = <&pmx_power_cpu>; + pinctrl-names = "default"; +}; + +&rtc { + status = "disabled"; +}; + +&sata { + nr-ports = <2>; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + hdd0_temp: sata-port@0 { + reg = <0>; + #thermal-sensor-cells = <0>; + }; + + hdd1_temp: sata-port@1 { + reg = <1>; + #thermal-sensor-cells = <0>; + }; +}; + +&uart0 { + status = "okay"; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-380-iij-sa-w2.dts b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-380-iij-sa-w2.dts new file mode 100644 index 0000000000..86029d3629 --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-380-iij-sa-w2.dts @@ -0,0 +1,389 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include +#include +#include +#include "armada-380.dtsi" + +/ { + model = "IIJ SA-W2"; + compatible = "iij,sa-w2", "marvell,armada380"; + + aliases { + led-boot = &led_power_green; + led-failsafe = &led_power_red; + led-running = &led_power_green; + led-upgrade = &led_power_green; + label-mac-device = &ge0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x10000000>; /* 256MB */ + }; + + soc { + ranges = ; + + pcie { + status = "okay"; + + pcie@1,0 { + status = "okay"; + }; + + pcie@3,0 { + status = "okay"; + }; + }; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&pmx_keys_pins>; + + button-init { + label = "init"; + linux,code = ; + gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pmx_leds_pins>; + + led-0 { + gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_WLAN_5GHZ; + linux,default-trigger = "phy0tpt"; + }; + + led-1 { + gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_WLAN_5GHZ; + }; + + led-2 { + gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_STATUS; + }; + + led-3 { + gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_STATUS; + }; + + led-4 { + gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_MOBILE; + }; + + led-5 { + gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_MOBILE; + }; + + led-6 { + gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_WLAN_2GHZ; + linux,default-trigger = "phy1tpt"; + }; + + led-7 { + gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_WLAN_2GHZ; + }; + + led_power_green: led-8 { + gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_POWER; + }; + + led_power_red: led-9 { + gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_POWER; + }; + + led-10 { + gpios = <&gpio1 22 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_USB; + function-enumerator = <1>; + linux,default-trigger = "usbport"; + trigger-sources = <&hub_port2>; + }; + + led-11 { + gpios = <&gpio1 23 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_USB; + function-enumerator = <0>; + linux,default-trigger = "usbport"; + trigger-sources = <&hub_port1>; + }; + }; + + regulator-vbus-usb0 { + compatible = "regulator-fixed"; + regulator-name = "vbus-usb0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpios = <&gpio1 20 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-always-on; + }; + + regulator-vbus-usb1 { + compatible = "regulator-fixed"; + regulator-name = "vbus-usb1"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-always-on; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; +}; + +&pinctrl { + pmx_usb_pins: usb-pins { + marvell,pins = "mpp2", /* smsc usb2514b reset */ + "mpp48", "mpp49", /* port over current */ + "mpp52", "mpp53"; /* port vbus */ + marvell,function = "gpio"; + }; + + pmx_keys_pins: keys-pins { + marvell,pins = "mpp18"; + marvell,function = "gpio"; + }; + + pmx_leds_pins: leds-pins { + marvell,pins = "mpp19", "mpp20", "mpp33", "mpp34", "mpp35", + "mpp36", "mpp44", "mpp45", "mpp46", "mpp47", + "mpp54", "mpp55"; + marvell,function = "gpio"; + }; +}; + +&gpio0 { + usb-hub-reset { + gpio-hog; + gpios = <2 GPIO_ACTIVE_HIGH>; + output-high; + }; +}; + +&usb0 { + pinctrl-names = "default"; + pinctrl-0 = <&pmx_usb_pins>; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + /* SMSC USB2514B on PCB */ + hub@1 { + compatible = "usb424,2514"; + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + + hub_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; + + hub_port2: port@2 { + reg = <2>; + #trigger-source-cells = <0>; + }; + }; +}; + +&bm { + status = "okay"; +}; + +&bm_bppi { + status = "okay"; +}; + +ð1 { + pinctrl-names = "default"; + pinctrl-0 = <&ge1_rgmii_pins>; + status = "okay"; + + phy-connection-type = "rgmii-id"; + buffer-manager = <&bm>; + bm,pool-long = <2>; + bm,pool-short = <3>; + + nvmem-cells = <&macaddr_bdinfo_6 1>; + nvmem-cell-names = "mac-address"; + + fixed-link { + speed = <1000>; + full-duplex; + }; +}; + +&mdio { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + status = "okay"; + + /* Marvell 88E6172 */ + switch@0 { + compatible = "marvell,mv88e6085"; + reg = <0x0>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&gpio1>; + interrupts = <10 IRQ_TYPE_LEVEL_LOW>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "ge1_0"; + }; + + port@1 { + reg = <1>; + label = "ge1_1"; + }; + + port@2 { + reg = <2>; + label = "ge1_2"; + }; + + port@3 { + reg = <3>; + label = "ge1_3"; + }; + + ge0: port@4 { + reg = <4>; + label = "ge0"; + nvmem-cells = <&macaddr_bdinfo_6 0>; + nvmem-cell-names = "mac-address"; + }; + + /* + * eth0 is connected to port5 for WAN connection + * on port4 ("GE0") + */ + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <ð1>; + phy-connection-type = "rgmii-id"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; + }; +}; + +&rtc { + status = "disabled"; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spi1_pins>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <40000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x0 0x100000>; + label = "bootloader"; + read-only; + }; + + partition@100000 { + reg = <0x100000 0x10000>; + label = "bootloader-env"; + read-only; + }; + + partition@110000 { + reg = <0x110000 0xf0000>; + label = "board_info"; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_bdinfo_6: macaddr@6 { + compatible = "mac-base"; + reg = <0x6 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@200000 { + compatible = "iij,seil-firmware"; + reg = <0x200000 0xf00000>; + label = "firmware"; + iij,bootdev-name = "flash"; + iij,seil-id = <0x5345494c 0x32303135>; + }; + + partition@1100000 { + compatible = "iij,seil-firmware"; + reg = <0x1100000 0xf00000>; + label = "rescue"; + iij,bootdev-name = "rescue"; + iij,seil-id = <0x5345494c 0x32303135>; + }; + }; + }; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-30e.dts b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-30e.dts new file mode 100644 index 0000000000..e9e6c29213 --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-30e.dts @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "armada-385-fortinet-fg-3xe.dtsi" + +/ { + model = "Fortinet FortiGate 30E"; + compatible = "fortinet,fg-30e", "marvell,armada385", "marvell,armada380"; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-3xe.dtsi b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-3xe.dtsi new file mode 100644 index 0000000000..6d835332d2 --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-3xe.dtsi @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "armada-385-fortinet-fg-xxe.dtsi" + +/ { + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x40000000>; /* 1GB */ + }; +}; + +&gpio_leds { + led-14 { + gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_SPEED_WAN; + linux,default-trigger = "mv88e6xxx-0:00:100Mbps"; + }; + + led-15 { + gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_SPEED_WAN; + linux,default-trigger = "mv88e6xxx-0:00:1Gbps"; + }; +}; + +&pinctrl { + pmx_switch_pins: switch-pins { + marvell,pins = "mpp19"; + marvell,function = "gpio"; + }; +}; + +&mdio { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>, <&pmx_switch_pins>; + + /* Marvell 88E6176 */ + switch@2 { + compatible = "marvell,mv88e6085"; + reg = <0x2>; + reset-gpios = <&gpio0 19 GPIO_ACTIVE_LOW>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "wan"; + nvmem-cells = <&macaddr_bdinfo_d880 1>; + nvmem-cell-names = "mac-address"; + }; + + port@1 { + reg = <1>; + label = "lan4"; + nvmem-cells = <&macaddr_bdinfo_d880 5>; + nvmem-cell-names = "mac-address"; + }; + + port@2 { + reg = <2>; + label = "lan3"; + nvmem-cells = <&macaddr_bdinfo_d880 4>; + nvmem-cell-names = "mac-address"; + }; + + port@3 { + reg = <3>; + label = "lan2"; + nvmem-cells = <&macaddr_bdinfo_d880 3>; + nvmem-cell-names = "mac-address"; + }; + + port@4 { + reg = <4>; + label = "lan1"; + nvmem-cells = <&macaddr_bdinfo_d880 2>; + nvmem-cell-names = "mac-address"; + }; + + port@6 { + reg = <6>; + ethernet = <ð0>; + phy-connection-type = "rgmii-id"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; + }; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-50e.dts b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-50e.dts new file mode 100644 index 0000000000..01a9e36826 --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-50e.dts @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "armada-385-fortinet-fg-5xe.dtsi" + +/ { + model = "Fortinet FortiGate 50E"; + compatible = "fortinet,fg-50e", "marvell,armada385", "marvell,armada380"; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-51e.dts b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-51e.dts new file mode 100644 index 0000000000..7bb61113c5 --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-51e.dts @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "armada-385-fortinet-fg-5xe.dtsi" + +/ { + model = "Fortinet FortiGate 51E"; + compatible = "fortinet,fg-51e", "marvell,armada385", "marvell,armada380"; +}; + +&ahci0 { + status = "okay"; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-52e.dts b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-52e.dts new file mode 100644 index 0000000000..bcb0d05627 --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-52e.dts @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "armada-385-fortinet-fg-5xe.dtsi" + +/ { + model = "Fortinet FortiGate 52E"; + compatible = "fortinet,fg-52e", "marvell,armada385", "marvell,armada380"; +}; + +&ahci0 { + status = "okay"; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-5xe.dtsi b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-5xe.dtsi new file mode 100644 index 0000000000..bf1daa3bc6 --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-5xe.dtsi @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "armada-385-fortinet-fg-xxe.dtsi" + +/ { + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x80000000>; /* 2GB */ + }; +}; + +&gpio_leds { + led-14 { + gpios = <&gpio2 0 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_SPEED_WAN; + function-enumerator = <1>; + linux,default-trigger = "f1072004.mdio-mii:00:1Gbps"; + }; + + led-15 { + gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_SPEED_WAN; + function-enumerator = <2>; + linux,default-trigger = "f1072004.mdio-mii:01:1Gbps"; + }; + + led-16 { + gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_SPEED_LAN; + function-enumerator = <5>; + linux,default-trigger = "mv88e6xxx-0:00:100Mbps"; + }; + + led-17 { + gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>; + color = ; + function = LED_FUNCTION_SPEED_LAN; + function-enumerator = <5>; + linux,default-trigger = "mv88e6xxx-0:00:1Gbps"; + }; +}; + +&pinctrl { + pmx_phy_switch_pins: phy-switch-pins { + marvell,pins = "mpp19", "mpp20", "mpp23", "mpp34", "mpp41"; + marvell,function = "gpio"; + }; +}; + +ð1 { + status = "okay"; + + phy-handle = <ðphy0>; + phy-connection-type = "sgmii"; + buffer-manager = <&bm>; + bm,pool-long = <2>; + nvmem-cells = <&macaddr_bdinfo_d880 1>; + nvmem-cell-names = "mac-address"; +}; + +ð2 { + status = "okay"; + + phy-handle = <ðphy1>; + phy-connection-type = "sgmii"; + buffer-manager = <&bm>; + bm,pool-long = <3>; + nvmem-cells = <&macaddr_bdinfo_d880 2>; + nvmem-cell-names = "mac-address"; +}; + +&mdio { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>, <&pmx_phy_switch_pins>; + + /* Marvell 88E1512 */ + ethphy0: ethernet-phy@0 { + compatible = "ethernet-phy-id0141,0dd1", + "ethernet-phy-ieee802.3-c22"; + reg = <0x0>; + interrupt-parent = <&gpio0>; + interrupts = <20 IRQ_TYPE_LEVEL_LOW>; + reset-gpios = <&gpio0 23 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <10000>; + /* + * LINK/ACT (Green): LED[0], Active Low + * SPEED 100M (Amber): LED[1], Active High + */ + marvell,reg-init = <3 16 0 0x71>, + <3 17 0 0x4>; + }; + + /* Marvell 88E1512 */ + ethphy1: ethernet-phy@1 { + compatible = "ethernet-phy-id0141,0dd1", + "ethernet-phy-ieee802.3-c22"; + reg = <0x1>; + interrupt-parent = <&gpio1>; + interrupts = <9 IRQ_TYPE_LEVEL_LOW>; + reset-gpios = <&gpio1 2 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <10000>; + /* + * LINK/ACT (Green): LED[0], Active Low + * SPEED 100M (Amber): LED[1], Active High + */ + marvell,reg-init = <3 16 0 0x71>, + <3 17 0 0x4>; + }; + + /* Marvell 88E6176 */ + switch@2 { + compatible = "marvell,mv88e6085"; + reg = <0x2>; + reset-gpios = <&gpio0 19 GPIO_ACTIVE_LOW>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan5"; + nvmem-cells = <&macaddr_bdinfo_d880 7>; + nvmem-cell-names = "mac-address"; + }; + + port@1 { + reg = <1>; + label = "lan4"; + nvmem-cells = <&macaddr_bdinfo_d880 6>; + nvmem-cell-names = "mac-address"; + }; + + port@2 { + reg = <2>; + label = "lan3"; + nvmem-cells = <&macaddr_bdinfo_d880 5>; + nvmem-cell-names = "mac-address"; + }; + + port@3 { + reg = <3>; + label = "lan2"; + nvmem-cells = <&macaddr_bdinfo_d880 4>; + nvmem-cell-names = "mac-address"; + }; + + port@4 { + reg = <4>; + label = "lan1"; + nvmem-cells = <&macaddr_bdinfo_d880 3>; + nvmem-cell-names = "mac-address"; + }; + + port@6 { + reg = <6>; + ethernet = <ð0>; + phy-connection-type = "rgmii-id"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; + }; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-xxe.dtsi b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-xxe.dtsi new file mode 100644 index 0000000000..a1adddc4e0 --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fg-xxe.dtsi @@ -0,0 +1,346 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include +#include +#include +#include "armada-385.dtsi" + +/ { + aliases { + led-boot = &led_status_green; + led-failsafe = &led_status_red; + led-running = &led_status_green; + led-upgrade = &led_status_green; + label-mac-device = ð0; + }; + + chosen { + stdout-path = "serial0:9600n8"; + }; + + soc { + ranges = ; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&pmx_gpio_keys_pins>; + + reset { + label = "reset"; + linux,code = ; + gpios = <&gpio1 22 GPIO_ACTIVE_LOW>; + }; + }; + + gpio_leds: gpio-leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pmx_gpio_leds_pins>; + + led-0 { + gpios = <&gpio0 30 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_ALARM; + }; + + led-1 { + gpios = <&gpio1 0 GPIO_ACTIVE_LOW>; + color = ; + function = "ha"; + }; + + led_status_green: led-2 { + gpios = <&gpio1 1 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_STATUS; + }; + + led-3 { + gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; + color = ; + function = "ha"; + }; + + led-4 { + gpios = <&gpio1 13 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_ALARM; + }; + + led_status_red: led-5 { + gpios = <&gpio1 15 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_STATUS; + }; + + led-6 { + gpios = <&gpio2 4 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_SPEED_LAN; + function-enumerator = <4>; + linux,default-trigger = "mv88e6xxx-0:01:1Gbps"; + }; + + led-7 { + gpios = <&gpio2 5 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_SPEED_LAN; + function-enumerator = <4>; + linux,default-trigger = "mv88e6xxx-0:01:100Mbps"; + }; + + led-8 { + gpios = <&gpio2 6 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_SPEED_LAN; + function-enumerator = <3>; + linux,default-trigger = "mv88e6xxx-0:02:100Mbps"; + }; + + led-9 { + gpios = <&gpio2 7 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_SPEED_LAN; + function-enumerator = <3>; + linux,default-trigger = "mv88e6xxx-0:02:1Gbps"; + }; + + led-10 { + gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_SPEED_LAN; + function-enumerator = <1>; + linux,default-trigger = "mv88e6xxx-0:04:1Gbps"; + }; + + led-11 { + gpios = <&gpio2 13 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_SPEED_LAN; + function-enumerator = <1>; + linux,default-trigger = "mv88e6xxx-0:04:100Mbps"; + }; + + led-12 { + gpios = <&gpio2 14 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_SPEED_LAN; + function-enumerator = <2>; + linux,default-trigger = "mv88e6xxx-0:03:1Gbps"; + }; + + led-13 { + gpios = <&gpio2 15 GPIO_ACTIVE_LOW>; + color = ; + function = LED_FUNCTION_SPEED_LAN; + function-enumerator = <2>; + linux,default-trigger = "mv88e6xxx-0:03:100Mbps"; + }; + }; + + reg_usb_vbus: regulator-usb-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb-vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; + regulator-always-on; + }; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + gpio2: gpio@24 { + compatible = "nxp,pca9555"; + reg = <0x24>; + gpio-controller; + #gpio-cells = <0x2>; + }; + + hwmon@28 { + compatible = "nuvoton,nct7802"; + reg = <0x28>; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; +}; + +&pinctrl { + pmx_gpio_leds_pins: gpio-leds-pins { + marvell,pins = "mpp30", "mpp32", "mpp33", "mpp35", + "mpp45", "mpp47"; + marvell,function = "gpio"; + }; + + pmx_usb_pins: usb-pins { + marvell,pins = "mpp53"; + marvell,function = "gpio"; + }; + + pmx_gpio_keys_pins: gpio-keys-pins { + marvell,pins = "mpp54"; + marvell,function = "gpio"; + }; +}; + +&bm { + status = "okay"; +}; + +&bm_bppi { + status = "okay"; +}; + +ð0 { + pinctrl-names = "default"; + pinctrl-0 = <&ge0_rgmii_pins>; + status = "okay"; + + phy-connection-type = "rgmii-id"; + buffer-manager = <&bm>; + bm,pool-long = <0>; + bm,pool-short = <1>; + nvmem-cells = <&macaddr_bdinfo_d880 0>; + nvmem-cell-names = "mac-address"; + + fixed-link { + speed = <1000>; + full-duplex; + }; +}; + +&usb3_0 { + pinctrl-names = "default"; + pinctrl-0 = <&pmx_usb_pins>; + status = "okay"; + + vbus-supply = <®_usb_vbus>; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spi1_pins>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x0 0x1c0000>; + label = "u-boot"; + read-only; + }; + + partition@1c0000 { + reg = <0x1c0000 0x10000>; + label = "firmware-info"; + + /* + * 0x10 - 0x2f : image name (image1) + * 0x30 - 0x4f : image name (image2) + * 0x170 (1byte): active image (0x0/0x1) + * 0x184 - 0x185: kernel block count (image1) + * 0x18c - 0x18d: rootfs block count (image1) + * 0x194 - 0x195: kernel block count (image2) + * 0x19c - 0x19d: rootfs block count (image2) + * 0x1be (1byte): bit7 -> active flag (image1)? + * 0x1ce (1byte): bit7 -> active flag (image2)? + * + * Note: block size --> 0x200 (512 bytes) + */ + }; + + partition@1d0000 { + reg = <0x1d0000 0x10000>; + label = "dtb"; + read-only; + }; + + partition@1e0000 { + reg = <0x1e0000 0x10000>; + label = "u-boot-env"; + read-only; + }; + + partition@1f0000 { + reg = <0x1f0000 0x10000>; + label = "board-info"; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_bdinfo_d880: macaddr@d880 { + compatible = "mac-base"; + reg = <0xd880 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@200000 { + reg = <0x200000 0x600000>; + label = "kernel"; + }; + + partition@800000 { + reg = <0x800000 0x1800000>; + label = "rootfs"; + }; + + partition@2000000 { + reg = <0x2000000 0x600000>; + label = "kn2"; + read-only; + }; + + partition@2600000 { + reg = <0x2600000 0x1800000>; + label = "rfs2"; + read-only; + }; + + partition@3e00000 { + reg = <0x3e00000 0x1200000>; + label = "part1"; + read-only; + }; + + partition@5000000 { + reg = <0x5000000 0x1200000>; + label = "part2"; + read-only; + }; + + partition@6200000 { + reg = <0x6200000 0x1e00000>; + label = "config"; + read-only; + }; + }; + }; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fwf-50e-2r.dts b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fwf-50e-2r.dts new file mode 100644 index 0000000000..eee9e6d942 --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fwf-50e-2r.dts @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "armada-385-fortinet-fg-5xe.dtsi" + +/ { + model = "Fortinet FortiWiFi 50E-2R"; + compatible = "fortinet,fwf-50e-2r", "marvell,armada385", "marvell,armada380"; +}; + +&pciec { + status = "okay"; +}; + +&pcie1 { + status = "okay"; +}; + +&pcie2 { + status = "okay"; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fwf-51e.dts b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fwf-51e.dts new file mode 100644 index 0000000000..d9ebd9f815 --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-fortinet-fwf-51e.dts @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "armada-385-fortinet-fg-5xe.dtsi" + +/ { + model = "Fortinet FortiWiFi 51E"; + compatible = "fortinet,fwf-51e", "marvell,armada385", "marvell,armada380"; +}; + +&ahci0 { + status = "okay"; +}; + +&pciec { + status = "okay"; +}; + +&pcie2 { + status = "okay"; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-linksys-venom.dts b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-linksys-venom.dts new file mode 100644 index 0000000000..63d25701c9 --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-linksys-venom.dts @@ -0,0 +1,213 @@ +/* + * Device Tree file for the Linksys WRT32X (Venom) + * + * Copyright (C) 2017 Imre Kaloz + * + * + * This file is dual-licensed: you can use it either under the terms + * of the GPL or the X11 license, at your option. Note that this dual + * licensing only applies to this file, and not this project as a + * whole. + * + * a) This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without + * any warranty of any kind, whether express or implied. + * + * Or, alternatively, + * + * b) Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/dts-v1/; +#include +#include +#include "armada-385-linksys.dtsi" + +/ { + model = "Linksys WRT32X"; + compatible = "linksys,wrt32x", "linksys,venom", "linksys,armada385", + "marvell,armada385", "marvell,armada380"; + + chosen { + bootargs = "console=ttyS0,115200"; + stdout-path = "serial0:115200n8"; + append-rootblock = "root=/dev/mtdblock"; + }; +}; + +&expander0 { + wan_amber@0 { + label = "venom:amber:wan"; + reg = <0x0>; + }; + + wan_blue@1 { + label = "venom:blue:wan"; + reg = <0x1>; + }; + + usb2@5 { + label = "venom:blue:usb2"; + reg = <0x5>; + }; + + usb3_1@6 { + label = "venom:blue:usb3_1"; + reg = <0x6>; + }; + + usb3_2@7 { + label = "venom:blue:usb3_2"; + reg = <0x7>; + }; + + wps_blue@8 { + label = "venom:blue:wps"; + reg = <0x8>; + }; + + wps_amber@9 { + label = "venom:amber:wps"; + reg = <0x9>; + }; +}; + +&gpio_leds { + power { + gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>; + label = "venom:blue:power"; + }; + + sata { + gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; + label = "venom:blue:sata"; + }; + + wlan_2g { + gpios = <&gpio1 13 GPIO_ACTIVE_LOW>; + label = "venom:blue:wlan_2g"; + }; + + wlan_5g { + gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; + label = "venom:blue:wlan_5g"; + }; +}; + +&gpio_leds_pins { + marvell,pins = "mpp21", "mpp45", "mpp46", "mpp56"; +}; + +&nand { + /* Spansion S34ML02G2 256MiB, OEM Layout */ + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0000000 0x200000>; /* 2MB */ + read-only; + }; + + partition@200000 { + label = "u_env"; + reg = <0x200000 0x20000>; /* 128KB */ + }; + + partition@220000 { + label = "s_env"; + reg = <0x220000 0x40000>; /* 256KB */ + }; + + partition@180000 { + label = "unused_area"; + reg = <0x260000 0x5c0000>; /* 5.75MB */ + }; + + partition@7e0000 { + label = "devinfo"; + reg = <0x7e0000 0x40000>; /* 256KB */ + read-only; + }; + + /* kernel1 overlaps with rootfs1 by design */ + partition@900000 { + label = "kernel1"; + reg = <0x900000 0x7b00000>; /* 123MB */ + }; + + partition@f00000 { + label = "rootfs1"; + reg = <0xf00000 0x7500000>; /* 117MB */ + }; + + /* kernel2 overlaps with rootfs2 by design */ + partition@8400000 { + label = "kernel2"; + reg = <0x8400000 0x7b00000>; /* 123MB */ + }; + + partition@8a00000 { + label = "rootfs2"; + reg = <0x8a00000 0x7500000>; /* 117MB */ + }; + + /* last MB is for the BBT, not writable */ + partition@ff00000 { + label = "BBT"; + reg = <0xff00000 0x100000>; + }; + }; +}; + + +&pcie1 { + mwlwifi { + marvell,chainmask = <4 4>; + }; +}; + +&pcie2 { + mwlwifi { + marvell,chainmask = <4 4>; + }; +}; + +&sdhci { + pinctrl-names = "default"; + pinctrl-0 = <&sdhci_pins>; + no-1-8-v; + non-removable; + wp-inverted; + bus-width = <8>; + status = "okay"; +}; + +&usb3_1_vbus { + gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>; +}; + +&usb3_1_vbus_pins { + marvell,pins = "mpp44"; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-nas1dual.dts b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-nas1dual.dts new file mode 100644 index 0000000000..b3dca335c9 --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-nas1dual.dts @@ -0,0 +1,322 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR MIT) +/* + * Device Tree file for ipTIME NAS1dual + * + * Copyright (C) 2020 Sungbo Eo + * + * Based on armada-385-linksys.dtsi + * Copyright (C) 2015 Imre Kaloz + */ + +/dts-v1/; + +#include +#include +#include +#include "armada-385.dtsi" + +/ { + model = "ipTIME NAS1dual"; + compatible = "iptime,nas1dual", "marvell,armada385", "marvell,armada380"; + + aliases { + led-boot = &led_ready; + led-failsafe = &led_ready; + led-running = &led_ready; + led-upgrade = &led_ready; + label-mac-device = ð0; + }; + + chosen { + bootargs = "console=ttyS0,115200n8"; + stdout-path = "serial0:115200n8"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x80000000>; /* 2GB */ + }; + + soc { + ranges = ; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&gpio_keys_pins>; + + power { + label = "Power Button"; + linux,input-type = ; + linux,code = ; + gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + }; + + reset { + label = "Reset Button"; + linux,code = ; + gpios = <&gpio0 26 GPIO_ACTIVE_LOW>; + }; + + copy { + label = "USB Copy Button"; + linux,code = ; + gpios = <&gpio1 16 GPIO_ACTIVE_LOW>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&gpio_leds_pins>; + + led_ready: ready { + label = "blue:ready"; + gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + }; + + hdd { + label = "blue:hdd"; + gpios = <&gpio0 20 GPIO_ACTIVE_LOW>; + linux,default-trigger = "disk-activity"; + }; + + usb { + function = LED_FUNCTION_USB; + color = ; + gpios = <&gpio1 19 GPIO_ACTIVE_HIGH>; + trigger-sources = <&usb3_0_port1 &usb3_0_port2>; + linux,default-trigger = "usbport"; + }; + }; + + gpio-fan { + compatible = "gpio-fan"; + pinctrl-names = "default"; + pinctrl-0 = <&gpio_fan_pins>; + gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>, + <&gpio1 18 GPIO_ACTIVE_HIGH>; + /* We don't know the exact rpm, just use dummy values here. */ + gpio-fan,speed-map = <0 0>, <1 1>, <2 2>; + #cooling-cells = <2>; + }; + + gpio-poweroff { + compatible = "gpio-poweroff"; + gpios = <&pca9536 1 GPIO_ACTIVE_LOW>; + }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&sata_power_pins>; + + reg_sata_power: regulator@1 { + compatible = "regulator-fixed"; + reg = <1>; + regulator-name = "sata-power"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + gpios = <&gpio1 20 GPIO_ACTIVE_LOW>; + regulator-always-on; + }; + }; +}; + +&ahci0 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + sata-port@0 { + reg = <0>; + target-supply = <®_sata_power>; + #thermal-sensor-cells = <0>; + }; +}; + +&bm { + status = "okay"; +}; + +&bm_bppi { + status = "okay"; +}; + +ð0 { + pinctrl-names = "default"; + pinctrl-0 = <&ge0_rgmii_pins>; + status = "okay"; + phy-handle = <ðphy1>; + phy-connection-type = "rgmii-id"; + buffer-manager = <&bm>; + bm,pool-long = <0>; + bm,pool-short = <1>; + nvmem-cells = <&macaddr_uboot_fffa8>; + nvmem-cell-names = "mac-address"; +}; + +ð1 { + pinctrl-names = "default"; + pinctrl-0 = <&ge1_rgmii_pins>; + status = "okay"; + phy-handle = <ðphy0>; + phy-connection-type = "rgmii-id"; + buffer-manager = <&bm>; + bm,pool-long = <2>; + bm,pool-short = <3>; + nvmem-cells = <&macaddr_uboot_fffa8>; + nvmem-cell-names = "mac-address"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + pca9536: gpio@41 { + compatible = "nxp,pca9536"; + reg = <0x41>; + gpio-controller; + #gpio-cells = <2>; + gpio-line-names = "power-led", "power-board"; + }; +}; + +&mdio { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + + /* LED1: On - Link, Blink - Activity, Off - No Link */ + + ethphy0: ethernet-phy@0 { + reg = <0>; + marvell,reg-init = <3 16 0 0x1017>; + }; + + ethphy1: ethernet-phy@1 { + reg = <1>; + marvell,reg-init = <3 16 0 0x1017>; + }; +}; + +&pinctrl { + gpio_keys_pins: gpio-keys-pins { + marvell,pins = "mpp24", "mpp26", "mpp48"; + marvell,function = "gpio"; + }; + + gpio_leds_pins: gpio-leds-pins { + marvell,pins = "mpp18", "mpp20", "mpp51"; + marvell,function = "gpio"; + }; + + gpio_fan_pins: gpio-fan-pins { + marvell,pins = "mpp25", "mpp50"; + marvell,function = "gpio"; + }; + + sata_power_pins: sata-power-pins { + marvell,pins = "mpp52"; + marvell,function = "gpio"; + }; + + uart1_pins_alt: uart-pins-1-alt { + marvell,pins = "mpp45", "mpp46"; + marvell,function = "ua1"; + }; +}; + +&spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&spi1_pins>; + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <40000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x00000000 0x00100000>; + label = "u-boot"; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_uboot_fffa8: macaddr@fffa8 { + reg = <0xfffa8 0x6>; + }; + }; + }; + + partition@100000 { + reg = <0x00100000 0x03ec0000>; + label = "firmware"; + + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x00000000 0x00600000>; + label = "kernel"; + }; + + partition@600000 { + reg = <0x00600000 0x038c0000>; + label = "rootfs"; + }; + }; + + partition@3fc0000 { + reg = <0x03fc0000 0x00040000>; + label = "config"; + read-only; + }; + }; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins_alt>; + status = "okay"; +}; + +&usb3_0 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + usb3_0_port1: port@1 { + reg = <1>; + #trigger-source-cells = <0>; + }; + + usb3_0_port2: port@2 { + reg = <2>; + #trigger-source-cells = <0>; + }; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-wd_cloud-mirror-gen2.dts b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-wd_cloud-mirror-gen2.dts new file mode 100644 index 0000000000..50936e72ad --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm/boot/dts/marvell/armada-385-wd_cloud-mirror-gen2.dts @@ -0,0 +1,368 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree file for Western Digital My Cloud Mirror Gen 2 + * (BWVZ/Grand Teton) + * + * Copyright (C) 2020 + * + * Based on the code from: + * + * Copyright (C) 2019 Evgeny Kolesnikov + * Copyright (C) 2016 Martin Mueller + * Copyright (C) 2013 Gregory CLEMENT + * Copyright (C) 2014 Thomas Petazzoni + * + */ + +/dts-v1/; +#include +#include +#include +#include "armada-385.dtsi" + +/ { + model = "WD MyCloud Mirror Gen 2 (BWVZ/Grand Teton)"; + compatible = "wd,cloud-mirror-gen2", "marvell,armada385", "marvell,armada380"; + + aliases { + led-boot = &led_boot; + led-failsafe = &led_boot; + led-upgrade = &led_boot; + }; + + chosen { + stdout-path = "serial0:115200n8"; + append-rootblock = "nullparameter="; /* override the bootloader args */ + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x20000000>; /* 512 MB */ + }; + + soc { + ranges = ; + + internal-regs { + timer@c200 { + status = "okay"; + }; + + i2c0: i2c@11000 { + status = "okay"; + clock-frequency = <100000>; + }; + + i2c1: i2c@11100 { + status = "okay"; + clock-frequency = <100000>; + }; + + serial@12000 { + status = "okay"; + }; + + /* Connected to Welltrend 6703F-OG240WT MCU + * which controls power, fan and other things + */ + serial@12100 { + status = "okay"; + }; + + pinctrl@18000 { + /* use only one pin for UART1, as mpp20 is used by sata0 */ + uart1_pins: uart-pins-1 { + marvell,pins = "mpp19"; + marvell,function = "ua1"; + }; + + xhci0_vbus_pins: xhci0-vbus-pins { + marvell,pins = "mpp26"; + marvell,function = "gpio"; + }; + + xhci1_vbus_pins: xhci1-vbus-pins { + marvell,pins = "mpp27"; + marvell,function = "gpio"; + }; + + sata0_pins: sata-pins-0 { + marvell,pins = "mpp55"; + marvell,function = "sata0"; + }; + + sata1_pins: sata-pins-1 { + marvell,pins = "mpp56"; + marvell,function = "sata1"; + }; + + sata_leds: sata-leds { + marvell,pins = "mpp43", "mpp52", "mpp53", "mpp54"; + marvell,function = "gpio"; + }; + + btn_pins: btn-pins { + marvell,pins = "mpp50"; + marvell,function = "gpio"; + }; + }; + + usb@58000 { + status = "okay"; + }; + + phy: mdio@72004 { + phy0: ethernet-phy@0 { + /* Init ETH LEDs */ + marvell,reg-init = <3 16 0 0x101e>; + reg = <0>; + }; + }; + + sata@a8000 { + status = "okay"; + }; + + nand-controller@d0000 { + status = "okay"; + + nand: nand@0 { + reg = <0>; + label = "pxa3xx_nand-0"; + nand-rb = <0>; + marvell,nand-keep-config; + #marvell,nand-enable-arbiter; //optional + nand-on-flash-bbt; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@00000000 { + label = "U-Boot"; + reg = <0x00000000 0x00500000>; /* 5 MB */ + read-only; + }; + + partition@00500000 { + label = "kernel"; + reg = <0x00500000 0x00500000>; /* 5 MB */ + }; + + partition@00a00000 { + label = "uRamdisk"; + reg = <0x00a00000 0x00500000>; /* 5 MB */ + read-only; + }; + + partition@00f00000 { + label = "ubi"; + reg = <0x00f00000 0x0b900000>; /* 185 MB */ + }; + + partition@c800000 { + label = "rescue fw"; + reg = <0x0c800000 0x00f00000>; /* 15 MB */ + read-only; + }; + + partition@d70000 { + label = "config"; + reg = <0x0d700000 0x01400000>; /* 20 MB */ + read-only; + }; + + partition@eb00000 { + label = "reserve1"; + reg = <0x0eb00000 0x00a00000>; /* 10 MB */ + read-only; + }; + + partition@f500000 { + label = "reserve2"; + reg = <0x0f500000 0x00a00000>; /* 10 MB */ + read-only; + }; + }; + }; + }; + + usb3@f0000 { + usb-phy = <&usb3_0_phy>; + status = "okay"; + }; + + usb3@f8000 { + usb-phy = <&usb3_1_phy>; + status = "okay"; + }; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&sata_leds>; + + led_boot: s1red { + label = "red:hdd1"; + gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>; + }; + s2red { + label = "red:hdd2"; + gpios = <&gpio1 20 GPIO_ACTIVE_HIGH>; + }; + s1blue { + label = "blue:hdd1"; + gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; + linux,default-trigger = "ata1"; + }; + s2blue { + label = "blue:hdd2"; + gpios = <&gpio1 22 GPIO_ACTIVE_LOW>; + linux,default-trigger = "ata2"; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&btn_pins>; + + reset { + label = "reset"; + linux,code = ; // Restart=0x198, Power=0x116 + gpios = <&gpio1 18 GPIO_ACTIVE_LOW>; + debounce-interval = <60>; + wakeup-source; + }; + }; + + usb3_0_phy: usb3_0_phy { + compatible = "usb-nop-xceiv"; + vcc-supply = <®_usb3_0_vbus>; + }; + + usb3_1_phy: usb3_1_phy { + compatible = "usb-nop-xceiv"; + vcc-supply = <®_usb3_1_vbus>; + }; + + reg_usb3_0_vbus: usb3-vbus0 { + compatible = "regulator-fixed"; + regulator-name = "usb3-vbus0"; + pinctrl-names = "default"; + pinctrl-0 = <&xhci0_vbus_pins>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + gpio = <&gpio0 26 GPIO_ACTIVE_HIGH>; + }; + + reg_usb3_1_vbus: usb3-vbus1 { + compatible = "regulator-fixed"; + regulator-name = "usb3-vbus1"; + pinctrl-names = "default"; + pinctrl-0 = <&xhci1_vbus_pins>; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + regulator-always-on; + gpio = <&gpio0 27 GPIO_ACTIVE_HIGH>; + }; + + reg_sata0: pwr-sata0 { + compatible = "regulator-fixed"; + regulator-name = "pwr_en_sata0"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + regulator-boot-on; + gpio = <&gpio1 23 GPIO_ACTIVE_HIGH>; + }; + + reg_5v_sata0: v5-sata0 { + compatible = "regulator-fixed"; + regulator-name = "v5.0-sata0"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <®_sata0>; + }; + + reg_12v_sata0: v12-sata0 { + compatible = "regulator-fixed"; + regulator-name = "v12.0-sata0"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + vin-supply = <®_sata0>; + }; + + reg_sata1: pwr-sata1 { + compatible = "regulator-fixed"; + regulator-name = "pwr_en_sata1"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + enable-active-high; + regulator-boot-on; + gpio = <&gpio1 24 GPIO_ACTIVE_HIGH>; + }; + + reg_5v_sata1: v5-sata1 { + compatible = "regulator-fixed"; + regulator-name = "v5.0-sata1"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <®_sata1>; + }; + + reg_12v_sata1: v12-sata1 { + compatible = "regulator-fixed"; + regulator-name = "v12.0-sata1"; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + vin-supply = <®_sata1>; + }; +}; + +&bm { + status = "okay"; +}; + +&bm_bppi { + status = "okay"; +}; + +ð2 { + status = "okay"; + phy = <&phy0>; + phy-mode = "sgmii"; + buffer-manager = <&bm>; + bm,pool-long = <0>; + bm,pool-short = <1>; +}; + +&ahci0 { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + sata-port@0 { + reg = <0>; + target-supply = <®_sata0>; + #thermal-sensor-cells = <0>; + }; + + sata-port@1 { + reg = <1>; + target-supply = <®_sata1>; + #thermal-sensor-cells = <1>; + }; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-3720-eDPU.dts b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-3720-eDPU.dts new file mode 100644 index 0000000000..35f107b63b --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-3720-eDPU.dts @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include "armada-3720-uDPU.dtsi" + +/ { + model = "Methode eDPU Board"; + compatible = "methode,edpu", "marvell,armada3720", "marvell,armada3710"; +}; + +/* PHY mode is set to 1000Base-X despite Maxlinear IC being capable of + * 2500Base-X since until 5.15 support for mvebu is available trying to + * use 2500Base-X will cause buffer overruns for which the fix is not + * easily backportable. + */ +ð0 { + phy-mode = "1000base-x"; +}; + +/* + * External MV88E6361 switch is only available on v2 of the board. + * U-Boot will enable the MDIO bus and switch nodes. + */ +&mdio { + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <&smi_pins>; + + /* Actual device is MV88E6361 */ + switch: switch@0 { + compatible = "marvell,mv88e6190"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "cpu"; + phy-mode = "2500base-x"; + managed = "in-band-status"; + ethernet = <ð0>; + }; + + port@9 { + reg = <9>; + label = "downlink"; + phy-mode = "2500base-x"; + managed = "in-band-status"; + }; + + port@a { + reg = <10>; + label = "uplink"; + phy-mode = "2500base-x"; + managed = "in-band-status"; + sfp = <&sfp_eth1>; + }; + }; + }; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-3720-espressobin-ultra.dts b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-3720-espressobin-ultra.dts new file mode 100644 index 0000000000..063eb86992 --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-3720-espressobin-ultra.dts @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device Tree file for ESPRESSObin-Ultra + * Copyright (C) 2019 Globalscale technologies, Inc. + * + * Jason Hung + */ + +/dts-v1/; + +#include +#include "armada-372x.dtsi" + +/ { + model = "Globalscale Marvell ESPRESSOBin Ultra Board"; + compatible = "globalscale,espressobin-ultra", "marvell,armada3720", + "marvell,armada3710"; + + aliases { + /* for dsa slave device */ + ethernet1 = &switch0port1; + ethernet2 = &switch0port2; + ethernet3 = &switch0port3; + ethernet4 = &switch0port4; + ethernet5 = &switch0port5; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x00000000 0x00000000 0x20000000>; + }; + + reg_usb3_vbus: usb3-vbus { + compatible = "regulator-fixed"; + regulator-name = "usb3-vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpios = <&gpionb 19 GPIO_ACTIVE_HIGH>; + }; + + usb3_phy: usb3-phy { + compatible = "usb-nop-xceiv"; + vcc-supply = <®_usb3_vbus>; + }; + + leds { + pinctrl-names = "default"; + compatible = "gpio-leds"; + /* No assigned functions to the LEDs by default */ + led1 { + label = "ebin-ultra:blue:led1"; + gpios = <&gpionb 11 GPIO_ACTIVE_LOW>; + }; + led2 { + label = "ebin-ultra:green:led2"; + gpios = <&gpionb 12 GPIO_ACTIVE_LOW>; + }; + led3 { + label = "ebin-ultra:red:led3"; + gpios = <&gpionb 13 GPIO_ACTIVE_LOW>; + }; + led4 { + label = "ebin-ultra:yellow:led4"; + gpios = <&gpionb 14 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&pcie0 { + status = "okay"; +}; + +&sata { + status = "okay"; +}; + +&sdhci0 { + status = "okay"; + non-removable; + bus-width = <8>; + mmc-ddr-1_8v; + mmc-hs400-1_8v; + marvell,pad-type = "fixed-1-8v"; +}; + +&spi0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spi_quad_pins>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <108000000>; + spi-rx-bus-width = <4>; + spi-tx-bus-width = <4>; + m25p,fast-read; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "firmware"; + reg = <0x0 0x3e0000>; + }; + partition@3e0000 { + label = "hw-info"; + reg = <0x3e0000 0x10000>; + read-only; + }; + partition@3f0000 { + label = "u-boot-env"; + reg = <0x3f0000 0x10000>; + }; + }; + }; +}; + +&uart0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; +}; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + + clock-frequency = <100000>; + + rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + }; +}; + +&usb3 { + status = "okay"; + usb-phy = <&usb3_phy>; +}; + +&usb2 { + status = "okay"; +}; + +ð0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>; + phy-mode = "rgmii-id"; + + fixed-link { + speed = <1000>; + full-duplex; + }; +}; + +&mdio { + status = "okay"; + + extphy: ethernet-phy@0 { + reg = <1>; + }; + + switch0: switch0@1 { + compatible = "marvell,mv88e6085"; + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + dsa,member = <0 0>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + switch0port0: port@0 { + reg = <0>; + ethernet = <ð0>; + }; + + switch0port1: port@1 { + reg = <1>; + label = "lan0"; + phy-handle = <&switch0phy1>; + }; + + switch0port2: port@2 { + reg = <2>; + label = "lan1"; + phy-handle = <&switch0phy2>; + }; + + switch0port3: port@3 { + reg = <3>; + label = "lan2"; + phy-handle = <&switch0phy3>; + }; + + switch0port4: port@4 { + reg = <4>; + label = "lan3"; + phy-handle = <&switch0phy4>; + }; + + switch0port5: port@5 { + reg = <5>; + label = "wan"; + phy-handle = <&extphy>; + phy-mode = "sgmii"; + }; + }; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + switch0phy1: switch0phy1@11 { + reg = <0x11>; + }; + switch0phy2: switch0phy2@12 { + reg = <0x12>; + }; + switch0phy3: switch0phy3@13 { + reg = <0x13>; + }; + switch0phy4: switch0phy4@14 { + reg = <0x14>; + }; + }; + }; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-3720-gl-mv1000.dts b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-3720-gl-mv1000.dts new file mode 100644 index 0000000000..e098ede75f --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-3720-gl-mv1000.dts @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT) + +/dts-v1/; +#include +#include +#include +#include "armada-372x.dtsi" + +/ { + model = "GL.iNet GL-MV1000"; + compatible = "glinet,gl-mv1000", "marvell,armada3720"; + + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x00000000 0x00000000 0x20000000>; + }; + + vcc_sd_reg1: regulator { + compatible = "regulator-gpio"; + regulator-name = "vcc_sd1"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + + gpios-states = <0>; + states = <1800000 0x1 + 3300000 0x0>; + enable-active-high; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + linux,code = ; + gpios = <&gpionb 14 GPIO_ACTIVE_LOW>; + }; + + switch { + label = "switch"; + linux,code = ; + gpios = <&gpiosb 22 GPIO_ACTIVE_LOW>; + }; + }; + + leds { + compatible = "gpio-leds"; + + vpn { + label = "green:vpn"; + gpios = <&gpionb 11 GPIO_ACTIVE_LOW>; + }; + + wan { + function = LED_FUNCTION_WAN; + color = ; + gpios = <&gpionb 12 GPIO_ACTIVE_LOW>; + }; + + led_power: power { + function = LED_FUNCTION_POWER; + color = ; + gpios = <&gpionb 13 GPIO_ACTIVE_LOW>; + default-state = "on"; + }; + }; +}; + +&spi0 { + status = "okay"; + + flash@0 { + reg = <0>; + compatible = "jedec,spi-nor"; + spi-max-frequency = <104000000>; + m25p,fast-read; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0 0xf0000>; + read-only; + }; + + partition@f0000 { + label = "u-boot-env"; + reg = <0xf0000 0x8000>; + }; + + factory: partition@f8000 { + label = "factory"; + reg = <0xf8000 0x8000>; + read-only; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_factory_0: macaddr@0 { + reg = <0x0 0x6>; + }; + + macaddr_factory_6: macaddr@6 { + reg = <0x6 0x6>; + }; + }; + }; + + partition@100000 { + label = "gl-firmware-dtb"; + reg = <0x100000 0x10000>; + read-only; + }; + + partition@110000 { + label = "gl-firmware"; + reg = <0x110000 0xef0000>; + read-only; + }; + + partition@ef0000 { + label = "gl-firmware-jffs2"; + reg = <0xef0000 0x110000>; + read-only; + }; + }; + }; +}; + +&sdhci1 { + wp-inverted; + bus-width = <4>; + cd-gpios = <&gpionb 17 GPIO_ACTIVE_LOW>; + marvell,pad-type = "sd"; + no-1-8-v; + vqmmc-supply = <&vcc_sd_reg1>; + status = "okay"; +}; + +&sdhci0 { + bus-width = <8>; + mmc-ddr-1_8v; + mmc-hs400-1_8v; + non-removable; + no-sd; + no-sdio; + marvell,pad-type = "fixed-1-8v"; + status = "okay"; +}; + +&usb3 { + status = "okay"; +}; + +&usb2 { + status = "okay"; +}; + +&uart0 { + status = "okay"; +}; + +&mdio { + switch0: switch0@1 { + compatible = "marvell,mv88e6085"; + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + + dsa,member = <0 0>; + + ports: ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + ethernet = <ð0>; + }; + + port@1 { + reg = <1>; + label = "wan"; + phy-handle = <&switch0phy0>; + }; + + port@2 { + reg = <2>; + label = "lan0"; + phy-handle = <&switch0phy1>; + + nvmem-cells = <&macaddr_factory_6>; + nvmem-cell-names = "mac-address"; + }; + + port@3 { + reg = <3>; + label = "lan1"; + phy-handle = <&switch0phy2>; + + nvmem-cells = <&macaddr_factory_6>; + nvmem-cell-names = "mac-address"; + }; + }; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + switch0phy0: switch0phy0@11 { + reg = <0x11>; + }; + switch0phy1: switch0phy1@12 { + reg = <0x12>; + }; + switch0phy2: switch0phy2@13 { + reg = <0x13>; + }; + }; + }; +}; + +ð0 { + nvmem-cells = <&macaddr_factory_0>; + nvmem-cell-names = "mac-address"; + phy-mode = "rgmii-id"; + status = "okay"; + + fixed-link { + speed = <1000>; + full-duplex; + }; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-3720-uDPU.dts b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-3720-uDPU.dts new file mode 100644 index 0000000000..186a5e7d7d --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-3720-uDPU.dts @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) + +/dts-v1/; + +#include "armada-3720-uDPU.dtsi" + +/ { + model = "Methode uDPU Board"; + compatible = "methode,udpu", "marvell,armada3720", "marvell,armada3710"; + + sfp_eth0: sfp-eth0 { + compatible = "sff,sfp"; + i2c-bus = <&i2c0>; + los-gpio = <&gpiosb 2 GPIO_ACTIVE_HIGH>; + mod-def0-gpio = <&gpiosb 3 GPIO_ACTIVE_LOW>; + tx-disable-gpio = <&gpiosb 4 GPIO_ACTIVE_HIGH>; + tx-fault-gpio = <&gpiosb 5 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <3000>; + }; +}; + +&pinctrl_nb { + i2c1_recovery_pins: i2c1-recovery-pins { + groups = "i2c1"; + function = "gpio"; + }; +}; + +&i2c0 { + status = "okay"; + pinctrl-names = "default", "recovery"; + pinctrl-0 = <&i2c1_pins>; + pinctrl-1 = <&i2c1_recovery_pins>; + /delete-property/mrvl,i2c-fast-mode; + scl-gpios = <&gpionb 0 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpionb 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; +}; + +ð0 { + phy-mode = "2500base-x"; + sfp = <&sfp_eth0>; +}; + +ð1 { + phy-mode = "2500base-x"; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-3720-uDPU.dtsi b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-3720-uDPU.dtsi new file mode 100644 index 0000000000..bc8d1f1020 --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-3720-uDPU.dtsi @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Device tree for the uDPU board. + * Based on Marvell Armada 3720 development board (DB-88F3720-DDR3) + * Copyright (C) 2016 Marvell + * Copyright (C) 2019 Methode Electronics + * Copyright (C) 2019 Telus + * + * Vladimir Vid + */ + +/dts-v1/; + +#include +#include "armada-372x.dtsi" + +/ { + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x00000000 0x00000000 0x00000000 0x20000000>; + }; + + aliases { + ethernet0 = ð0; + ethernet1 = ð1; + }; + + leds { + compatible = "gpio-leds"; + + led-power1 { + label = "udpu:green:power"; + gpios = <&gpionb 11 GPIO_ACTIVE_LOW>; + }; + + led-power2 { + label = "udpu:red:power"; + gpios = <&gpionb 12 GPIO_ACTIVE_LOW>; + }; + + led-network1 { + label = "udpu:green:network"; + gpios = <&gpionb 13 GPIO_ACTIVE_LOW>; + }; + + led-network2 { + label = "udpu:red:network"; + gpios = <&gpionb 14 GPIO_ACTIVE_LOW>; + }; + + led-alarm1 { + label = "udpu:green:alarm"; + gpios = <&gpionb 15 GPIO_ACTIVE_LOW>; + }; + + led-alarm2 { + label = "udpu:red:alarm"; + gpios = <&gpionb 16 GPIO_ACTIVE_LOW>; + }; + }; + + sfp_eth1: sfp-eth1 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1>; + los-gpio = <&gpiosb 7 GPIO_ACTIVE_HIGH>; + mod-def0-gpio = <&gpiosb 8 GPIO_ACTIVE_LOW>; + tx-disable-gpio = <&gpiosb 9 GPIO_ACTIVE_HIGH>; + tx-fault-gpio = <&gpiosb 10 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <3000>; + }; +}; + +&sdhci0 { + status = "okay"; + bus-width = <8>; + mmc-ddr-1_8v; + mmc-hs400-1_8v; + marvell,pad-type = "fixed-1-8v"; + non-removable; + no-sd; + no-sdio; +}; + +&spi0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spi_quad_pins>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <54000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "firmware"; + reg = <0x0 0x180000>; + }; + + partition@180000 { + label = "u-boot-env"; + reg = <0x180000 0x10000>; + }; + }; + }; +}; + +&pinctrl_nb { + i2c2_recovery_pins: i2c2-recovery-pins { + groups = "i2c2"; + function = "gpio"; + }; +}; + +&i2c1 { + status = "okay"; + pinctrl-names = "default", "recovery"; + pinctrl-0 = <&i2c2_pins>; + pinctrl-1 = <&i2c2_recovery_pins>; + /delete-property/mrvl,i2c-fast-mode; + scl-gpios = <&gpionb 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpionb 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + + temp-sensor@48 { + compatible = "ti,tmp75c"; + reg = <0x48>; + }; + + temp-sensor@49 { + compatible = "ti,tmp75c"; + reg = <0x49>; + }; +}; + +ð0 { + status = "okay"; + managed = "in-band-status"; + phys = <&comphy1 0>; +}; + +ð1 { + phy-mode = "sgmii"; + status = "okay"; + managed = "in-band-status"; + phys = <&comphy0 1>; + sfp = <&sfp_eth1>; +}; + +&usb3 { + status = "okay"; + phys = <&usb2_utmi_otg_phy>; + phy-names = "usb2-utmi-otg-phy"; +}; + +&uart0 { + status = "okay"; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-7040-mochabin.dts b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-7040-mochabin.dts new file mode 100644 index 0000000000..26804a4875 --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-7040-mochabin.dts @@ -0,0 +1,448 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Device Tree file for Globalscale MOCHAbin + * Copyright (C) 2019 Globalscale technologies, Inc. + * Copyright (C) 2021 Sartura Ltd. + * + */ + +/dts-v1/; + +#include +#include "armada-7040.dtsi" + +/ { + model = "Globalscale MOCHAbin"; + compatible = "globalscale,mochabin", "marvell,armada7040", + "marvell,armada-ap806-quad", "marvell,armada-ap806"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + ethernet0 = &cp0_eth0; + ethernet1 = &cp0_eth1; + ethernet2 = &cp0_eth2; + ethernet3 = &swport1; + ethernet4 = &swport2; + ethernet5 = &swport3; + ethernet6 = &swport4; + }; + + /* SFP+ 10G */ + sfp_eth0: sfp-eth0 { + compatible = "sff,sfp"; + i2c-bus = <&cp0_i2c1>; + los-gpio = <&sfp_gpio 3 GPIO_ACTIVE_HIGH>; + mod-def0-gpio = <&sfp_gpio 2 GPIO_ACTIVE_LOW>; + tx-disable-gpio = <&sfp_gpio 1 GPIO_ACTIVE_HIGH>; + tx-fault-gpio = <&sfp_gpio 0 GPIO_ACTIVE_HIGH>; + }; + + /* SFP 1G */ + sfp_eth2: sfp-eth2 { + compatible = "sff,sfp"; + i2c-bus = <&cp0_i2c0>; + los-gpio = <&sfp_gpio 7 GPIO_ACTIVE_HIGH>; + mod-def0-gpio = <&sfp_gpio 6 GPIO_ACTIVE_LOW>; + tx-disable-gpio = <&sfp_gpio 5 GPIO_ACTIVE_HIGH>; + tx-fault-gpio = <&sfp_gpio 4 GPIO_ACTIVE_HIGH>; + }; +}; + +/* microUSB UART console */ +&uart0 { + status = "okay"; + + pinctrl-0 = <&uart0_pins>; + pinctrl-names = "default"; +}; + +/* eMMC */ +&ap_sdhci0 { + status = "okay"; + + bus-width = <4>; + non-removable; + /delete-property/ marvell,xenon-phy-slow-mode; + no-1-8-v; +}; + +&cp0_pinctrl { + cp0_uart0_pins: cp0-uart0-pins { + marvell,pins = "mpp6", "mpp7"; + marvell,function = "uart0"; + }; + + cp0_spi0_pins: cp0-spi0-pins { + marvell,pins = "mpp56", "mpp57", "mpp58", "mpp59"; + marvell,function = "spi0"; + }; + + cp0_spi1_pins: cp0-spi1-pins { + marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16"; + marvell,function = "spi1"; + }; + + cp0_i2c0_pins: cp0-i2c0-pins { + marvell,pins = "mpp37", "mpp38"; + marvell,function = "i2c0"; + }; + + cp0_i2c1_pins: cp0-i2c1-pins { + marvell,pins = "mpp2", "mpp3"; + marvell,function = "i2c1"; + }; + + pca9554_int_pins: pca9554-int-pins { + marvell,pins = "mpp27"; + marvell,function = "gpio"; + }; + + cp0_rgmii1_pins: cp0-rgmii1-pins { + marvell,pins = "mpp44", "mpp45", "mpp46", "mpp47", "mpp48", "mpp49", + "mpp50", "mpp51", "mpp52", "mpp53", "mpp54", "mpp55"; + marvell,function = "ge1"; + }; + + is31_sdb_pins: is31-sdb-pins { + marvell,pins = "mpp30"; + marvell,function = "gpio"; + }; + + cp0_pcie_reset_pins: cp0-pcie-reset-pins { + marvell,pins = "mpp9"; + marvell,function = "gpio"; + }; + + cp0_switch_pins: cp0-switch-pins { + marvell,pins = "mpp0", "mpp1"; + marvell,function = "gpio"; + }; + + cp0_phy_pins: cp0-phy-pins { + marvell,pins = "mpp12"; + marvell,function = "gpio"; + }; +}; + +/* mikroBUS UART */ +&cp0_uart0 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&cp0_uart0_pins>; +}; + +/* mikroBUS SPI */ +&cp0_spi0 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&cp0_spi0_pins>; +}; + +/* SPI-NOR */ +&cp0_spi1{ + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&cp0_spi1_pins>; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <20000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x3e0000>; + read-only; + }; + + partition@3e0000 { + label = "hw-info"; + reg = <0x3e0000 0x10000>; + read-only; + }; + + partition@3f0000 { + label = "u-boot-env"; + reg = <0x3f0000 0x10000>; + }; + }; + }; +}; + +/* mikroBUS, 1G SFP and GPIO expander */ +&cp0_i2c0 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&cp0_i2c0_pins>; + clock-frequency = <100000>; + + sfp_gpio: pca9554@39 { + compatible = "nxp,pca9554"; + pinctrl-names = "default"; + pinctrl-0 = <&pca9554_int_pins>; + reg = <0x39>; + + interrupt-parent = <&cp0_gpio1>; + interrupts = <27 IRQ_TYPE_LEVEL_LOW>; + interrupt-controller; + #interrupt-cells = <2>; + + gpio-controller; + #gpio-cells = <2>; + + /* + * IO0_0: SFP+_TX_FAULT + * IO0_1: SFP+_TX_DISABLE + * IO0_2: SFP+_PRSNT + * IO0_3: SFP+_LOSS + * IO0_4: SFP_TX_FAULT + * IO0_5: SFP_TX_DISABLE + * IO0_6: SFP_PRSNT + * IO0_7: SFP_LOSS + */ + }; +}; + +/* IS31FL3199, mini-PCIe and 10G SFP+ */ +&cp0_i2c1 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&cp0_i2c1_pins>; + clock-frequency = <100000>; + + leds@64 { + compatible = "issi,is31fl3199"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&is31_sdb_pins>; + shutdown-gpios = <&cp0_gpio1 30 GPIO_ACTIVE_HIGH>; + reg = <0x64>; + + led1_red: led@1 { + label = "red:led1"; + reg = <1>; + led-max-microamp = <20000>; + }; + + led1_green: led@2 { + label = "green:led1"; + reg = <2>; + }; + + led1_blue: led@3 { + label = "blue:led1"; + reg = <3>; + }; + + led2_red: led@4 { + label = "red:led2"; + reg = <4>; + }; + + led2_green: led@5 { + label = "green:led2"; + reg = <5>; + }; + + led2_blue: led@6 { + label = "blue:led2"; + reg = <6>; + }; + + led3_red: led@7 { + label = "red:led3"; + reg = <7>; + }; + + led3_green: led@8 { + label = "green:led3"; + reg = <8>; + }; + + led3_blue: led@9 { + label = "blue:led3"; + reg = <9>; + }; + }; +}; + +&cp0_mdio { + status = "okay"; + + /* 88E1512 PHY */ + eth2phy: ethernet-phy@1 { + reg = <1>; + sfp = <&sfp_eth2>; + + pinctrl-names = "default"; + pinctrl-0 = <&cp0_phy_pins>; + reset-gpios = <&cp0_gpio1 12 GPIO_ACTIVE_LOW>; + }; + + /* 88E6141 Topaz switch */ + switch: switch@3 { + compatible = "marvell,mv88e6085"; + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; + + pinctrl-names = "default"; + pinctrl-0 = <&cp0_switch_pins>; + reset-gpios = <&cp0_gpio1 0 GPIO_ACTIVE_LOW>; + + interrupt-parent = <&cp0_gpio1>; + interrupts = <1 IRQ_TYPE_LEVEL_LOW>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + swport1: port@1 { + reg = <1>; + label = "lan0"; + phy-handle = <&swphy1>; + }; + + swport2: port@2 { + reg = <2>; + label = "lan1"; + phy-handle = <&swphy2>; + }; + + swport3: port@3 { + reg = <3>; + label = "lan2"; + phy-handle = <&swphy3>; + }; + + swport4: port@4 { + reg = <4>; + label = "lan3"; + phy-handle = <&swphy4>; + }; + + port@5 { + reg = <5>; + ethernet = <&cp0_eth1>; + phy-mode = "2500base-x"; + managed = "in-band-status"; + }; + }; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + swphy1: swphy1@17 { + reg = <17>; + }; + + swphy2: swphy2@18 { + reg = <18>; + }; + + swphy3: swphy3@19 { + reg = <19>; + }; + + swphy4: swphy4@20 { + reg = <20>; + }; + }; + }; +}; + +&cp0_ethernet { + status = "okay"; +}; + +/* 10G SFP+ */ +&cp0_eth0 { + status = "okay"; + + phy-mode = "10gbase-r"; + phys = <&cp0_comphy4 0>; + managed = "in-band-status"; + sfp = <&sfp_eth0>; +}; + +/* Topaz switch uplink */ +&cp0_eth1 { + status = "okay"; + + phy-mode = "2500base-x"; + phys = <&cp0_comphy0 1>; + + fixed-link { + speed = <2500>; + full-duplex; + }; +}; + +/* 1G SFP or 1G RJ45 */ +&cp0_eth2 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&cp0_rgmii1_pins>; + + phy = <ð2phy>; + phy-mode = "rgmii-id"; +}; + +/* SMSC USB5434B hub */ +&cp0_usb3_0 { + status = "okay"; + + phys = <&cp0_comphy1 0>; + phy-names = "cp0-usb3h0-comphy"; +}; + +/* miniPCI-E USB */ +&cp0_usb3_1 { + status = "okay"; +}; + +&cp0_sata0 { + status = "okay"; + + /* 7 + 12 SATA connector (J24) */ + sata-port@0 { + phys = <&cp0_comphy2 0>; + phy-names = "cp0-sata0-0-phy"; + }; + + /* M.2-2250 B-key (J39) */ + sata-port@1 { + phys = <&cp0_comphy3 1>; + phy-names = "cp0-sata0-1-phy"; + }; +}; + +/* miniPCI-E (J5) */ +&cp0_pcie2 { + status = "okay"; + + pinctrl-names = "default"; + pinctrl-0 = <&cp0_pcie_reset_pins>; + phys = <&cp0_comphy5 2>; + phy-names = "cp0-pcie2-x1-phy"; + reset-gpio = <&cp0_gpio1 9 GPIO_ACTIVE_LOW>; + ranges = <0x82000000 0x0 0xc0000000 0x0 0xc0000000 0x0 0x8000000>; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-7040-rb5009.dts b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-7040-rb5009.dts new file mode 100644 index 0000000000..023370a678 --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/armada-7040-rb5009.dts @@ -0,0 +1,406 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +/dts-v1/; + +#include "armada-7040.dtsi" +#include +#include +#include + +/ { + model = "MikroTik RB5009"; + compatible = "mikrotik,rb5009", "marvell,armada7040", + "marvell,armada-ap806-quad", "marvell,armada-ap806"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x40000000>; + }; + + aliases { + led-boot = &led_user; + led-failsafe = &led_user; + led-running = &led_user; + led-upgrade = &led_user; + label-mac-device = &p1; + }; + + usb3_vbus: regulator-usb3-vbus0 { + compatible = "regulator-fixed"; + regulator-name = "usb3_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&cp0_gpio2 23 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + + reg_leds: regulator-leds { + compatible = "regulator-fixed"; + regulator-name = "LED-power"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&cp0_gpio2 27 GPIO_ACTIVE_HIGH>; + enable-active-high; + regulator-boot-on; + }; + + output-led-power { + compatible = "regulator-output"; + vout-supply = <®_leds>; + }; + + sfp_i2c: sfp-i2c { + compatible = "i2c-gpio"; + sda-gpios = <&cp0_gpio1 0 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + scl-gpios = <&cp0_gpio1 1 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&cp0_gpio1 28 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_user: user { + function = "user"; + gpios = <&cp0_gpio2 26 GPIO_ACTIVE_LOW>; + color = ; + }; + + sfp { + function = "sfp"; + gpios = <&cp0_gpio2 25 GPIO_ACTIVE_LOW>; + color = ; + }; + + hdr1 { + function = "hdr1"; + gpios = <&cp0_gpio1 4 GPIO_ACTIVE_LOW>; + color = ; + }; + + hdr2 { + function = "hdr2"; + gpios = <&cp0_gpio2 19 GPIO_ACTIVE_LOW>; + color = ; + }; + }; + + sfp: sfp { + compatible = "sff,sfp"; + i2c-bus = <&sfp_i2c>; + mod-def0-gpios = <&cp0_gpio1 11 GPIO_ACTIVE_LOW>; + los-gpios = <&cp0_gpio1 2 GPIO_ACTIVE_HIGH>; + tx-fault-gpios = <&cp0_gpio1 6 GPIO_ACTIVE_HIGH>; + tx-disable-gpios = <&cp0_gpio1 5 GPIO_ACTIVE_HIGH>; + rate-select0-gpios = <&cp0_gpio1 3 GPIO_ACTIVE_HIGH>; + }; +}; + +&uart0 { + status = "okay"; + + pinctrl-0 = <&uart0_pins>; + pinctrl-names = "default"; +}; + + +&spi0 { + status = "okay"; + + flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <20000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + compatible = "mikrotik,routerboot-partitions"; + #address-cells = <1>; + #size-cells = <1>; + label = "MikroTik"; + reg = <0x0 0xfe0000>; + + hard_config: hard_config { + read-only; + + nvmem-layout { + compatible = "mikrotik,routerboot-nvmem"; + + macaddr_hard: base-mac-address { + #nvmem-cell-cells = <1>; + }; + }; + }; + + soft_config { + }; + + dtb_config { + read-only; + }; + }; + + partition@b0000 { + label = "RouterBOOT-primary"; + reg = <0xb0000 0x10000>; + }; + + /* Empty space on NOR repurposed for U-Boot environment */ + partition@fe0000 { + label = "u-boot-env"; + reg = <0xfe0000 0x20000>; + + nvmem-layout { + compatible = "u-boot,env"; + }; + }; + }; + }; +}; + +&cp0_nand_controller { + status = "okay"; + + nand@0 { + reg = <0>; + nand-rb = <0>; + nand-ecc-mode = "hw"; + nand-ecc-strength = <4>; + nand-ecc-step-size = <512>; + nand-on-flash-bbt; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "YAFFS"; + reg = <0x0 0x800000>; + }; + + partition@800000 { + label = "ubi"; + reg = <0x800000 0x3f800000>; + }; + }; + }; +}; + +&cp0_utmi { + status = "okay"; +}; + +&cp0_comphy3 { + connector { + compatible = "usb-a-connector"; + phy-supply = <&usb3_vbus>; + }; +}; + +&cp0_usb3_1 { + status = "okay"; + phys = <&cp0_comphy3 1>, <&cp0_utmi1>; + phy-names = "cp0-usb3h1-comphy", "utmi"; + dr_mode = "host"; +}; + +&cp0_i2c0 { + status = "okay"; + clock-frequency = <100000>; +}; + +&cp0_mdio { + status = "okay"; +}; + +&cp0_ethernet { + status = "okay"; +}; + +&cp0_eth0 { + /* This port is connected to 88E6393X switch */ + status = "okay"; + phy-mode = "10gbase-r"; + phys = <&cp0_comphy2 0>; + managed = "in-band-status"; + nvmem-cells = <&macaddr_hard 0>; + nvmem-cell-names = "mac-address"; +}; + +&cp0_mdio { + status = "okay"; + + switch@0 { + /* Actual device is MV88E6393X */ + compatible = "marvell,mv88e6190"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + /* LED config is lost if switch is reset */ + //reset-gpios = <&cp0_gpio2 2 GPIO_ACTIVE_HIGH>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "cpu"; + ethernet = <&cp0_eth0>; + phy-mode = "10gbase-r"; + managed = "in-band-status"; + }; + + port@1 { + reg = <1>; + label = "p8"; + phy-handle = <&switch0phy1>; + nvmem-cells = <&macaddr_hard 7>; + nvmem-cell-names = "mac-address"; + }; + + port@2 { + reg = <2>; + label = "p7"; + phy-handle = <&switch0phy2>; + nvmem-cells = <&macaddr_hard 6>; + nvmem-cell-names = "mac-address"; + }; + + port@3 { + reg = <3>; + label = "p6"; + phy-handle = <&switch0phy3>; + nvmem-cells = <&macaddr_hard 5>; + nvmem-cell-names = "mac-address"; + }; + + port@4 { + reg = <4>; + label = "p5"; + phy-handle = <&switch0phy4>; + nvmem-cells = <&macaddr_hard 4>; + nvmem-cell-names = "mac-address"; + }; + + port@5 { + reg = <5>; + label = "p4"; + phy-handle = <&switch0phy5>; + nvmem-cells = <&macaddr_hard 3>; + nvmem-cell-names = "mac-address"; + }; + + port@6 { + reg = <6>; + label = "p3"; + phy-handle = <&switch0phy6>; + nvmem-cells = <&macaddr_hard 2>; + nvmem-cell-names = "mac-address"; + }; + + port@7 { + reg = <7>; + label = "p2"; + phy-handle = <&switch0phy7>; + nvmem-cells = <&macaddr_hard 1>; + nvmem-cell-names = "mac-address"; + }; + + p1: port@9 { + reg = <9>; + label = "p1"; + phy-mode = "sgmii"; + phy-handle = <&qca8081>; + managed = "in-band-status"; + nvmem-cells = <&macaddr_hard 0>; + nvmem-cell-names = "mac-address"; + }; + + port@a { + reg = <10>; + label = "sfp"; + phy-mode = "10gbase-r"; + managed = "in-band-status"; + sfp = <&sfp>; + nvmem-cells = <&macaddr_hard 8>; + nvmem-cell-names = "mac-address"; + }; + }; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + switch0phy1: switch0phy1@1 { + reg = <0x1>; + }; + + switch0phy2: switch0phy2@2 { + reg = <0x2>; + }; + + switch0phy3: switch0phy3@3 { + reg = <0x3>; + }; + + switch0phy4: switch0phy4@4 { + reg = <0x4>; + }; + + switch0phy5: switch0phy5@5 { + reg = <0x5>; + }; + + switch0phy6: switch0phy6@6 { + reg = <0x6>; + }; + + switch0phy7: switch0phy7@7 { + reg = <0x7>; + }; + }; + + mdio1 { + compatible = "marvell,mv88e6xxx-mdio-external"; + #address-cells = <1>; + #size-cells = <0>; + + qca8081: qca8081@0 { + reg = <0>; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@1 { + reg = <1>; + color = ; + function = LED_FUNCTION_WAN; + default-state = "keep"; + active-low; + }; + }; + }; + }; + }; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/cn9130-clearfog-pro.dts b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/cn9130-clearfog-pro.dts new file mode 100644 index 0000000000..15e19fb932 --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/cn9130-clearfog-pro.dts @@ -0,0 +1,513 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright SolidRun Ltd. + * Copyright (C) 2024 Tobias Schramm + * + * Device tree for the CN9130-based ClearFog Pro + */ + +#include "cn9130.dtsi" + +#include +#include + +/ { + model = "SolidRun ClearFog Pro"; + compatible = "solidrun,clearfog-pro", "marvell,armada-ap807-quad", + "marvell,armada-ap807"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + gpio1 = &cp0_gpio1; + gpio2 = &cp0_gpio2; + i2c0 = &cp0_i2c0; + ethernet0 = &cp0_eth0; + ethernet1 = &cp0_eth1; + ethernet2 = &cp0_eth2; + spi1 = &cp0_spi1; + }; + + memory@00000000 { + reg = <0x0 0x0 0x1 0x0>; + device_type = "memory"; + }; + + /* Virtual regulator, root of power tree */ + vin: regulator-vin { + compatible = "regulator-fixed"; + regulator-name = "vin"; + regulator-always-on; + regulator-min-microvolt = <12000000>; + regulator-max-microvolt = <12000000>; + }; + + /* Regulators supplied by vin */ + v_5v0: regulator-v_5v0 { + compatible = "regulator-fixed"; + regulator-name = "v_5v0"; + regulator-always-on; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + vin-supply = <&vin>; + }; + + v_3v3: regulator-v_3v3 { + compatible = "regulator-fixed"; + regulator-name = "v_3v3"; + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <&vin>; + }; + + /* Regulators supplied by v_5v0 */ + v_1v8: regulator-v_1v8 { + compatible = "regulator-fixed"; + regulator-name = "v_1v8"; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&v_5v0>; + }; + + v_5v0_usb3_hst_vbus: regulator-v_5v0_usb3_hst_vbus { + compatible = "regulator-fixed"; + regulator-name = "v_5v0_usb3_hst_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpios = <&expander0 6 GPIO_ACTIVE_LOW>; + vin-supply = <&v_5v0>; + }; + + /* Regulators internal to SOM */ + vqmmc: regulator-vqmmc { + compatible = "regulator-fixed"; + regulator-name = "vqmmc"; + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&v_5v0>; + }; + + cp0_usb3_0_phy1: cp0_usb3_phy@1 { + compatible = "usb-nop-xceiv"; + vbus-supply = <&v_5v0_usb3_hst_vbus>; + }; + + cp0_sfp_eth0: sfp-eth@0 { + compatible = "sff,sfp"; + i2c-bus = <&cp0_i2c1>; + los-gpio = <&expander0 12 GPIO_ACTIVE_HIGH>; + mod-def0-gpio = <&expander0 15 GPIO_ACTIVE_LOW>; + tx-disable-gpio = <&expander0 14 GPIO_ACTIVE_HIGH>; + tx-fault-gpio = <&expander0 13 GPIO_ACTIVE_HIGH>; + maximum-power-milliwatt = <2000>; + }; + + keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&cp0_button_pin>; + + reset { + label = "Reset"; + linux,code = ; + gpios = <&cp0_gpio2 0 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +/* on-board eMMC */ +&ap_sdhci0 { + bus-width = <8>; + pinctrl-names = "default"; + vqmmc-supply = <&vqmmc>; + status = "okay"; +}; + +&cp0_crypto { + status = "okay"; +}; + +&cp0_ethernet { + status = "okay"; +}; + +&cp0_gpio1 { + status = "okay"; +}; + +&cp0_gpio2 { + status = "okay"; +}; + +&cp0_i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&cp0_i2c0_pins>; + clock-frequency = <100000>; + + /* + * PCA9655 GPIO expander, up to 1MHz clock. + * 0-CON3 CLKREQ# + * 1-CON3 PERST# + * 2-CON2 PERST# + * 3-CON3 W_DISABLE + * 4-CON2 CLKREQ# + * 5-USB3 overcurrent + * 6-USB3 power + * 7-CON2 W_DISABLE + * 8-JP4 P1 + * 9-JP4 P4 + * 10-JP4 P5 + * 11-m.2 DEVSLP + * 12-SFP_LOS + * 13-SFP_TX_FAULT + * 14-SFP_TX_DISABLE + * 15-SFP_MOD_DEF0 + */ + expander0: gpio-expander@20 { + compatible = "nxp,pca9555"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&cp0_gpio1>; + interrupts = <4 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&cp0_expander0_pins>; + vcc-supply = <&v_3v3>; + + pcie1_0_clkreq { + gpio-hog; + gpios = <0 GPIO_ACTIVE_LOW>; + input; + line-name = "pcie1.0-clkreq"; + }; + + pcie1_0_w_disable { + gpio-hog; + gpios = <3 GPIO_ACTIVE_LOW>; + output-low; + line-name = "pcie1.0-w-disable"; + }; + + pcie2_0_clkreq { + gpio-hog; + gpios = <4 GPIO_ACTIVE_LOW>; + input; + line-name = "pcie2.0-clkreq"; + }; + + pcie2_0_w_disable { + gpio-hog; + gpios = <7 GPIO_ACTIVE_LOW>; + output-low; + line-name = "pcie2.0-w-disable"; + }; + + usb3_ilimit { + gpio-hog; + gpios = <5 GPIO_ACTIVE_LOW>; + input; + line-name = "usb3-current-limit"; + }; + + m2_devslp { + gpio-hog; + gpios = <11 GPIO_ACTIVE_HIGH>; + output-low; + line-name = "m.2 devslp"; + }; + }; + + /* ADC only for mikroBUS connector */ + mcp3021@4c { + compatible = "microchip,mcp3021"; + reg = <0x4c>; + }; + + /* EEPROM on the SOM */ + eeprom@53 { + compatible = "atmel,24c02"; + reg = <0x53>; + pagesize = <16>; + read-only; + + nvmem-layout { + compatible = "onie,tlv-layout"; + + onie_tlv_macaddr: mac-address { + #nvmem-cell-cells = <1>; + }; + }; + }; +}; + +/* SMBUS on mini PCIe sockets */ +&cp0_i2c1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&cp0_i2c1_pins>; + clock-frequency = <100000>; +}; + +&cp0_mdio { + status = "okay"; + + phy0: ethernet-phy@0 { + reg = <0>; + /* Green led blinks on activity, orange LED on link */ + marvell,reg-init = <3 16 0 0x0064>; + }; + + switch@4 { + compatible = "marvell,mv88e6085"; + reg = <4>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&cp0_gpio1>; + interrupts = <29 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&cp0_dsa0_pins>; + reset-gpios = <&cp0_gpio1 27 GPIO_ACTIVE_LOW>; + + mdio-external { + compatible = "marvell,mv88e6xxx-mdio-external"; + #address-cells = <1>; + #size-cells = <0>; + + /* 88E1512 PHY */ + port6_phy: ethernet-phy@1 { + reg = <1>; + }; + }; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan5"; + }; + + port@1 { + reg = <1>; + label = "lan4"; + }; + + port@2 { + reg = <2>; + label = "lan3"; + }; + + port@3 { + reg = <3>; + label = "lan2"; + }; + + port@4 { + reg = <4>; + label = "lan1"; + }; + + port@5 { + reg = <5>; + ethernet = <&cp0_eth1>; + label = "cpu"; + phy-mode = "rgmii-id"; + + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + + port@6 { + /* 88E1512 external phy */ + reg = <6>; + label = "lan6"; + phy-handle = <&port6_phy>; + phy-mode = "rgmii-id"; + }; + }; + }; +}; + +/* SRDS #0 - SATA on bottom M.2 B-Key connector */ +&cp0_sata0 { + status = "okay"; + + sata-port@0 { + status = "disabled"; + }; + + sata-port@1 { + phys = <&cp0_comphy0 1>; + target-supply = <&v_3v3>; + }; +}; + +&cp0_utmi { + status = "okay"; +}; + +/* mini PCIe slot far from SOM, USB 2.0 only, SS lanes unused */ +&cp0_usb3_0 { + status = "okay"; + phys = <&cp0_utmi0>; + phy-names = "utmi"; + dr_mode = "host"; +}; + +/* SRDS #1 - USB-A 3.0 host port */ +&cp0_usb3_1 { + status = "okay"; + phys = <&cp0_utmi1>, <&cp0_comphy1 0>; + phy-names = "utmi", "usb"; + usb-phy = <&cp0_usb3_0_phy1>; + dr_mode = "host"; +}; + +/* SRDS #2 - SFP+ 10GE */ +&cp0_eth0 { + status = "okay"; + phy-mode = "10gbase-r"; + phys = <&cp0_comphy2 0>; + managed = "in-band-status"; + nvmem-cells = <&onie_tlv_macaddr 0>; + nvmem-cell-names = "mac-address"; + sfp = <&cp0_sfp_eth0>; +}; + +/* SRDS #3 - SGMII 1GE to L2 switch */ +&cp0_eth1 { + status = "okay"; + phys = <&cp0_comphy3 1>; + phy-mode = "sgmii"; + nvmem-cells = <&onie_tlv_macaddr 1>; + nvmem-cell-names = "mac-address"; + + fixed-link { + speed = <1000>; + full-duplex; + }; +}; + +/* SRDS #4 - mini PCIe slot near SOM */ +&cp0_pcie1 { + status = "okay"; + phys = <&cp0_comphy4 1>; + num-lanes = <1>; + reset-gpios = <&expander0 2 GPIO_ACTIVE_LOW>; +}; + +/* SRDS #5 - mini PCIe slot far from SOM */ +&cp0_pcie2 { + status = "okay"; + phys = <&cp0_comphy5 2>; + num-lanes = <1>; + reset-gpios = <&expander0 1 GPIO_ACTIVE_LOW>; +}; + +/* GE PHY RGMII */ +&cp0_eth2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&cp0_ge2_rgmii_pins>; + phy = <&phy0>; + phy-mode = "rgmii-id"; + nvmem-cells = <&onie_tlv_macaddr 2>; + nvmem-cell-names = "mac-address"; +}; + +/* micro SD card slot */ +&cp0_sdhci0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&cp0_sdhci_pins &cp0_sdhci_cd_pins>; + bus-width = <4>; + cd-gpios = <&cp0_gpio2 11 GPIO_ACTIVE_LOW>; + no-1-8-v; + vqmmc-supply = <&v_3v3>; + vmmc-supply = <&v_3v3>; +}; + +&cp0_spi1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&cp0_spi1_pins>; + + spi-flash@0 { + compatible = "jedec,spi-nor"; + reg = <0x0>; + #address-cells = <0x1>; + #size-cells = <0x1>; + spi-max-frequency = <10000000>; + }; +}; + +&cp0_syscon0 { + cp0_pinctrl: pinctrl { + compatible = "marvell,cp115-standalone-pinctrl"; + + cp0_i2c0_pins: cp0-i2c0-pins { + marvell,pins = "mpp37", "mpp38"; + marvell,function = "i2c0"; + }; + + cp0_i2c1_pins: cp0-i2c1-pins { + marvell,pins = "mpp35", "mpp36"; + marvell,function = "i2c1"; + }; + + cp0_ge2_rgmii_pins: cp0-ge2-rgmii-pins { + marvell,pins = "mpp44", "mpp45", "mpp46", + "mpp47", "mpp48", "mpp49", + "mpp50", "mpp51", "mpp52", + "mpp53", "mpp54", "mpp55"; + marvell,function = "ge1"; + }; + + cp0_sdhci_cd_pins: cp0-sdhci-cd-pins { + marvell,pins = "mpp43"; + marvell,function = "sdio"; + }; + + cp0_sdhci_pins: cp0-sdhci-pins { + marvell,pins = "mpp56", "mpp57", "mpp58", + "mpp59", "mpp60", "mpp61"; + marvell,function = "sdio"; + }; + + cp0_spi1_pins: cp0-spi1-pins { + marvell,pins = "mpp12", "mpp13", "mpp14", + "mpp15", "mpp16"; + marvell,function = "spi1"; + }; + + cp0_dsa0_pins: cp0-dsa0-pins { + marvell,pins = "mpp27", "mpp29"; + marvell,function = "gpio"; + }; + + cp0_button_pin: cp0-button-pin { + marvell,pins = "mpp32"; + marvell,function = "gpio"; + }; + + cp0_expander0_pins: cp0-expander0-pins { + marvell,pins = "mpp4"; + marvell,function = "gpio"; + }; + }; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/cn9131-puzzle-m901.dts b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/cn9131-puzzle-m901.dts new file mode 100644 index 0000000000..90d6e855be --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/cn9131-puzzle-m901.dts @@ -0,0 +1,447 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT) +/* + * Copyright (C) 2019 Marvell International Ltd. + * + * Device tree for the CN9131-DB board. + */ + +#include "cn9130.dtsi" +#include "puzzle-thermal.dtsi" + +#include +#include +#include + +/ { + model = "iEi Puzzle-M901"; + compatible = "iei,puzzle-m901", + "marvell,armada-ap807-quad", "marvell,armada-ap807"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + i2c0 = &cp1_i2c0; + i2c1 = &cp0_i2c0; + ethernet0 = &cp0_eth0; + ethernet1 = &cp0_eth1; + ethernet2 = &cp0_eth2; + ethernet3 = &cp1_eth0; + ethernet4 = &cp1_eth1; + ethernet5 = &cp1_eth2; + gpio1 = &cp0_gpio1; + gpio2 = &cp0_gpio2; + gpio3 = &cp1_gpio1; + gpio4 = &cp1_gpio2; + led-boot = &led_power; + led-failsafe = &led_info; + led-running = &led_power; + led-upgrade = &led_info; + }; + + memory@00000000 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x80000000>; + }; + + gpio_keys { + compatible = "gpio-keys"; + + reset { + label = "Reset"; + linux,code = ; + gpios = <&cp0_gpio2 4 GPIO_ACTIVE_LOW>; + }; + }; + + thermal-zones { + chassis0-thermal { + thermal-sensors = <&puzzle_hwmon 0>; + PUZZLE_FAN_CHASSIS_THERMAL(chassis0, &chassis_fan_group0); + }; + + chassis1-thermal { + thermal-sensors = <&puzzle_hwmon 1>; + PUZZLE_FAN_CHASSIS_THERMAL(chassis1, &chassis_fan_group0); + }; + + cp0-phy0-thermal { + thermal-sensors = <&cp0_nbaset_phy0>; + PUZZLE_FAN_THERMAL(cp0_phy0, &chassis_fan_group0); + }; + + cp0-phy1-thermal { + thermal-sensors = <&cp0_nbaset_phy1>; + PUZZLE_FAN_THERMAL(cp0_phy1, &chassis_fan_group0); + }; + + cp0-phy2-thermal { + thermal-sensors = <&cp0_nbaset_phy2>; + PUZZLE_FAN_THERMAL(cp0_phy2, &chassis_fan_group0); + }; + + cp1-phy0-thermal { + thermal-sensors = <&cp1_nbaset_phy0>; + PUZZLE_FAN_THERMAL(cp1_phy0, &chassis_fan_group0); + }; + + cp1-phy1-thermal { + thermal-sensors = <&cp1_nbaset_phy1>; + PUZZLE_FAN_THERMAL(cp1_phy1, &chassis_fan_group0); + }; + + cp1-phy2-thermal { + thermal-sensors = <&cp1_nbaset_phy2>; + PUZZLE_FAN_THERMAL(cp1_phy2, &chassis_fan_group0); + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&cp0_uart0 { + status = "okay"; + + puzzle-mcu { + compatible = "iei,wt61p803-puzzle"; + #address-cells = <1>; + #size-cells = <1>; + current-speed = <115200>; + enable-beep; + status = "okay"; + + leds { + compatible = "iei,wt61p803-puzzle-leds"; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + led@0 { + reg = <0>; + label = "white:network"; + active-low; + }; + + led@1 { + reg = <1>; + label = "green:cloud"; + active-low; + }; + + led_info: led@2 { + reg = <2>; + label = "orange:info"; + active-low; + }; + + led_power: led@3 { + reg = <3>; + function = LED_FUNCTION_POWER; + color = ; + active-low; + default-state = "on"; + }; + }; + + puzzle_hwmon: hwmon { + compatible = "iei,wt61p803-puzzle-hwmon"; + #address-cells = <1>; + #size-cells = <0>; + #thermal-sensor-cells = <1>; + + chassis_fan_group0: fan-group@0 { + #cooling-cells = <2>; + reg = <0x00>; + cooling-levels = <0 159 195 211 223 241 255>; + }; + }; + }; +}; + +/* on-board eMMC - U9 */ +&ap_sdhci0 { + pinctrl-names = "default"; + bus-width = <8>; + status = "okay"; + mmc-ddr-1_8v; + mmc-hs400-1_8v; +}; + +&cp0_crypto { + status = "okay"; +}; + +&cp0_xmdio { + status = "okay"; + cp0_nbaset_phy0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <2>; + #thermal-sensor-cells = <0>; + }; + cp0_nbaset_phy1: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <0>; + #thermal-sensor-cells = <0>; + }; + cp0_nbaset_phy2: ethernet-phy@2 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <8>; + #thermal-sensor-cells = <0>; + }; +}; + +&cp0_ethernet { + status = "okay"; +}; + +/* SLM-1521-V2, CON9 */ +&cp0_eth0 { + status = "okay"; + phy-mode = "2500base-x"; + phys = <&cp0_comphy2 0>; + phy = <&cp0_nbaset_phy0>; +}; + +&cp0_eth1 { + status = "okay"; + phy-mode = "2500base-x"; + phys = <&cp0_comphy4 1>; + phy = <&cp0_nbaset_phy1>; +}; + +&cp0_eth2 { + status = "okay"; + phy-mode = "2500base-x"; + phys = <&cp0_comphy5 2>; + phy = <&cp0_nbaset_phy2>; +}; + +&cp0_gpio1 { + status = "okay"; +}; + +&cp0_gpio2 { + status = "okay"; +}; + +&cp0_i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&cp0_i2c0_pins>; + status = "okay"; + clock-frequency = <100000>; + rtc@32 { + compatible = "epson,rx8130"; + reg = <0x32>; + wakeup-source; + }; +}; + +/* SLM-1521-V2, CON6 */ +&cp0_pcie0 { + status = "okay"; + num-lanes = <2>; + num-viewport = <8>; + phys = <&cp0_comphy0 0>, <&cp0_comphy1 0>; +}; + +/* U55 */ +&cp0_spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&cp0_spi0_pins>; + reg = <0x700680 0x50>, /* control */ + <0x2000000 0x1000000>; /* CS0 */ + status = "okay"; + spi-flash@0 { + #address-cells = <0x1>; + #size-cells = <0x1>; + compatible = "jedec,spi-nor"; + reg = <0x0>; + spi-max-frequency = <40000000>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + partition@0 { + label = "U-Boot"; + reg = <0x0 0x1f0000>; + }; + partition@1f0000 { + label = "U-Boot ENV Factory"; + reg = <0x1f0000 0x10000>; + }; + partition@200000 { + label = "Reserved"; + reg = <0x200000 0x1f0000>; + }; + partition@3f0000 { + label = "U-Boot ENV"; + reg = <0x3f0000 0x10000>; + }; + }; + }; +}; + +&cp0_rtc { + status = "disabled"; +}; + +&cp0_syscon0 { + cp0_pinctrl: pinctrl { + compatible = "marvell,cp115-standalone-pinctrl"; + cp0_i2c0_pins: cp0-i2c-pins-0 { + marvell,pins = "mpp37", "mpp38"; + marvell,function = "i2c0"; + }; + cp0_i2c1_pins: cp0-i2c-pins-1 { + marvell,pins = "mpp35", "mpp36"; + marvell,function = "i2c1"; + }; + cp0_ge1_rgmii_pins: cp0-ge-rgmii-pins-0 { + marvell,pins = "mpp0", "mpp1", "mpp2", + "mpp3", "mpp4", "mpp5", + "mpp6", "mpp7", "mpp8", + "mpp9", "mpp10", "mpp11"; + marvell,function = "ge0"; + }; + cp0_ge2_rgmii_pins: cp0-ge-rgmii-pins-1 { + marvell,pins = "mpp44", "mpp45", "mpp46", + "mpp47", "mpp48", "mpp49", + "mpp50", "mpp51", "mpp52", + "mpp53", "mpp54", "mpp55"; + marvell,function = "ge1"; + }; + cp0_spi0_pins: cp0-spi-pins-0 { + marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16"; + marvell,function = "spi1"; + }; + }; +}; + +/* + * Instantiate the first connected CP115 + */ + +#define CP11X_NAME cp1 +#define CP11X_BASE f6000000 +#define CP11X_PCIEx_MEM_BASE(iface) (0xe2000000 + (iface * 0x1000000)) +#define CP11X_PCIEx_MEM_SIZE(iface) 0xf00000 +#define CP11X_PCIE0_BASE f6600000 +#define CP11X_PCIE1_BASE f6620000 +#define CP11X_PCIE2_BASE f6640000 + +#include "armada-cp115.dtsi" + +#undef CP11X_NAME +#undef CP11X_BASE +#undef CP11X_PCIEx_MEM_BASE +#undef CP11X_PCIEx_MEM_SIZE +#undef CP11X_PCIE0_BASE +#undef CP11X_PCIE1_BASE +#undef CP11X_PCIE2_BASE + +&cp1_crypto { + status = "okay"; +}; + +&cp1_xmdio { + status = "okay"; + cp1_nbaset_phy0: ethernet-phy@3 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <2>; + #thermal-sensor-cells = <0>; + }; + cp1_nbaset_phy1: ethernet-phy@4 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <0>; + #thermal-sensor-cells = <0>; + }; + cp1_nbaset_phy2: ethernet-phy@5 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <8>; + #thermal-sensor-cells = <0>; + }; +}; + +&cp1_ethernet { + status = "okay"; +}; + +/* CON50 */ +&cp1_eth0 { + status = "okay"; + phy-mode = "2500base-x"; + phys = <&cp1_comphy2 0>; + phy = <&cp1_nbaset_phy0>; +}; + +&cp1_eth1 { + status = "okay"; + phy-mode = "2500base-x"; + phys = <&cp1_comphy4 1>; + phy = <&cp1_nbaset_phy1>; +}; + +&cp1_eth2 { + status = "okay"; + phy-mode = "2500base-x"; + phys = <&cp1_comphy5 2>; + phy = <&cp1_nbaset_phy2>; +}; + +&cp1_sata0 { + status = "okay"; + sata-port@1 { + status = "okay"; + phys = <&cp1_comphy0 1>; + }; +}; + +&cp1_gpio1 { + status = "okay"; +}; + +&cp1_gpio2 { + status = "okay"; +}; + +&cp1_i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&cp1_i2c0_pins>; + clock-frequency = <100000>; +}; + +&cp1_rtc { + status = "disabled"; +}; + +&cp1_syscon0 { + cp1_pinctrl: pinctrl { + compatible = "marvell,cp115-standalone-pinctrl"; + cp1_i2c0_pins: cp1-i2c-pins-0 { + marvell,pins = "mpp37", "mpp38"; + marvell,function = "i2c0"; + }; + cp1_spi0_pins: cp1-spi-pins-0 { + marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16"; + marvell,function = "spi1"; + }; + cp1_xhci0_vbus_pins: cp1-xhci0-vbus-pins { + marvell,pins = "mpp3"; + marvell,function = "gpio"; + }; + cp1_sfp_pins: sfp-pins { + marvell,pins = "mpp8", "mpp9", "mpp10", "mpp11"; + marvell,function = "gpio"; + }; + }; +}; + +&cp1_usb3_1 { + status = "okay"; + phys = <&cp1_comphy3 1>; + phy-names = "usb"; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/cn9132-puzzle-m902.dts b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/cn9132-puzzle-m902.dts new file mode 100644 index 0000000000..0c042f12de --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/cn9132-puzzle-m902.dts @@ -0,0 +1,631 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT) +/* + * Copyright (C) 2019 Marvell International Ltd. + * + * Device tree for the CN9132-DB board. + */ + +#include "cn9130.dtsi" +#include "puzzle-thermal.dtsi" + +#include +#include +#include + +/ { + model = "iEi Puzzle-M902"; + compatible = "iei,puzzle-m902", + "marvell,armada-ap807-quad", "marvell,armada-ap807"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + i2c0 = &cp1_i2c0; + i2c1 = &cp0_i2c0; + gpio1 = &cp0_gpio1; + gpio2 = &cp0_gpio2; + gpio3 = &cp1_gpio1; + gpio4 = &cp1_gpio2; + gpio5 = &cp2_gpio1; + gpio6 = &cp2_gpio2; + ethernet0 = &cp0_eth0; + ethernet1 = &cp0_eth1; + ethernet2 = &cp0_eth2; + ethernet3 = &cp1_eth0; + ethernet4 = &cp1_eth1; + ethernet5 = &cp1_eth2; + ethernet6 = &cp2_eth0; + ethernet7 = &cp2_eth1; + ethernet8 = &cp2_eth2; + spi1 = &cp0_spi0; + spi2 = &cp0_spi1; + led-boot = &led_power; + led-failsafe = &led_info; + led-running = &led_power; + led-upgrade = &led_info; + }; + + memory@00000000 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x80000000>; + }; + + gpio_keys { + compatible = "gpio-keys"; + + reset { + label = "Reset"; + linux,code = ; + gpios = <&cp0_gpio2 4 GPIO_ACTIVE_LOW>; + }; + }; + + cp2_reg_usb3_vbus0: cp2_usb3_vbus@0 { + compatible = "regulator-fixed"; + regulator-name = "cp2-xhci0-vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpios = <&cp2_gpio1 2 GPIO_ACTIVE_HIGH>; + }; + + cp2_usb3_0_phy0: cp2_usb3_phy0 { + compatible = "usb-nop-xceiv"; + vcc-supply = <&cp2_reg_usb3_vbus0>; + }; + + cp2_reg_usb3_vbus1: cp2_usb3_vbus@1 { + compatible = "regulator-fixed"; + regulator-name = "cp2-xhci1-vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + enable-active-high; + gpios = <&cp2_gpio1 3 GPIO_ACTIVE_HIGH>; + }; + + cp2_usb3_0_phy1: cp2_usb3_phy1 { + compatible = "usb-nop-xceiv"; + vcc-supply = <&cp2_reg_usb3_vbus1>; + }; + + cp2_sfp_eth0: sfp-eth0 { + compatible = "sff,sfp"; + i2c-bus = <&cp2_sfpp0_i2c>; + los-gpio = <&cp2_module_expander1 11 GPIO_ACTIVE_HIGH>; + mod-def0-gpio = <&cp2_module_expander1 10 GPIO_ACTIVE_LOW>; + tx-disable-gpio = <&cp2_module_expander1 9 GPIO_ACTIVE_HIGH>; + tx-fault-gpio = <&cp2_module_expander1 8 GPIO_ACTIVE_HIGH>; + status = "disabled"; + }; + + thermal-zones { + chassis0-thermal { + thermal-sensors = <&puzzle_hwmon 0>; + PUZZLE_FAN_CHASSIS_THERMAL(chassis0, &chassis_fan_group0); + }; + + chassis1-thermal { + thermal-sensors = <&puzzle_hwmon 1>; + PUZZLE_FAN_CHASSIS_THERMAL(chassis1, &chassis_fan_group0); + }; + + cp0-phy0-thermal { + thermal-sensors = <&cp0_nbaset_phy0>; + PUZZLE_FAN_THERMAL(cp0_phy0, &chassis_fan_group0); + }; + + cp0-phy1-thermal { + thermal-sensors = <&cp0_nbaset_phy1>; + PUZZLE_FAN_THERMAL(cp0_phy1, &chassis_fan_group0); + }; + + cp0-phy2-thermal { + thermal-sensors = <&cp0_nbaset_phy2>; + PUZZLE_FAN_THERMAL(cp0_phy2, &chassis_fan_group0); + }; + + cp1-phy0-thermal { + thermal-sensors = <&cp1_nbaset_phy0>; + PUZZLE_FAN_THERMAL(cp1_phy0, &chassis_fan_group0); + }; + + cp1-phy1-thermal { + thermal-sensors = <&cp1_nbaset_phy1>; + PUZZLE_FAN_THERMAL(cp1_phy1, &chassis_fan_group0); + }; + + cp1-phy2-thermal { + thermal-sensors = <&cp1_nbaset_phy2>; + PUZZLE_FAN_THERMAL(cp1_phy2, &chassis_fan_group0); + }; + + cp2-phy0-thermal { + thermal-sensors = <&cp2_nbaset_phy0>; + PUZZLE_FAN_THERMAL(cp2_phy0, &chassis_fan_group0); + }; + + cp2-phy1-thermal { + thermal-sensors = <&cp2_nbaset_phy1>; + PUZZLE_FAN_THERMAL(cp2_phy1, &chassis_fan_group0); + }; + + cp2-phy2-thermal { + thermal-sensors = <&cp2_nbaset_phy2>; + PUZZLE_FAN_THERMAL(cp2_phy2, &chassis_fan_group0); + }; + }; + +}; + +&uart0 { + status = "okay"; +}; + +&cp0_uart0 { + status = "okay"; + + puzzle-mcu { + compatible = "iei,wt61p803-puzzle"; + #address-cells = <1>; + #size-cells = <1>; + current-speed = <115200>; + enable-beep; + status = "okay"; + + leds { + compatible = "iei,wt61p803-puzzle-leds"; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + led@0 { + reg = <0>; + label = "white:network"; + active-low; + }; + + led@1 { + reg = <1>; + label = "green:cloud"; + active-low; + }; + + led_info: led@2 { + reg = <2>; + label = "orange:info"; + active-low; + }; + + led_power: led@3 { + reg = <3>; + function = LED_FUNCTION_POWER; + color = ; + active-low; + default-state = "on"; + }; + }; + + puzzle_hwmon: hwmon { + compatible = "iei,wt61p803-puzzle-hwmon"; + #address-cells = <1>; + #size-cells = <0>; + #thermal-sensor-cells = <1>; + + chassis_fan_group0: fan-group@0 { + #cooling-cells = <2>; + reg = <0x00>; + cooling-levels = <0 159 195 211 223 241 255>; + }; + }; + }; +}; + +/* on-board eMMC - U9 */ +&ap_sdhci0 { + pinctrl-names = "default"; + bus-width = <8>; + status = "okay"; + mmc-ddr-1_8v; + mmc-hs400-1_8v; +}; + +&cp0_crypto { + status = "okay"; +}; + +&cp0_xmdio { + status = "okay"; + cp0_nbaset_phy0: ethernet-phy@2 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <2>; + #thermal-sensor-cells = <0>; + }; + cp0_nbaset_phy1: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <0>; + #thermal-sensor-cells = <0>; + }; + cp0_nbaset_phy2: ethernet-phy@8 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <8>; + #thermal-sensor-cells = <0>; + }; +}; + +&cp0_ethernet { + status = "okay"; +}; + +/* SLM-1521-V2, CON9 */ +&cp0_eth0 { + status = "okay"; + phy-mode = "10gbase-kr"; + phys = <&cp0_comphy2 0>; + phy = <&cp0_nbaset_phy0>; +}; + +&cp0_eth1 { + status = "okay"; + phy-mode = "2500base-x"; + phys = <&cp0_comphy4 1>; + phy = <&cp0_nbaset_phy1>; +}; + +&cp0_eth2 { + status = "okay"; + phy-mode = "2500base-x"; + phys = <&cp0_comphy1 2>; + phy = <&cp0_nbaset_phy2>; +}; + +&cp0_gpio1 { + status = "okay"; +}; + +&cp0_gpio2 { + status = "okay"; +}; + +&cp0_i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&cp0_i2c0_pins>; + status = "okay"; + clock-frequency = <100000>; + rtc@32 { + compatible = "epson,rx8130"; + reg = <0x32>; + wakeup-source; + }; +}; + +&cp0_i2c1 { + clock-frequency = <100000>; +}; + +/* SLM-1521-V2, CON6 */ +&cp0_sata0 { + status = "okay"; + sata-port@1 { + status = "okay"; + phys = <&cp0_comphy0 1>; + }; +}; + +&cp0_pcie2 { + status = "okay"; + num-lanes = <1>; + num-viewport = <8>; + phys = <&cp0_comphy5 2>; +}; + +/* U55 */ +&cp0_spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&cp0_spi0_pins>; + reg = <0x700680 0x50>, /* control */ + <0x2000000 0x1000000>; /* CS0 */ + status = "okay"; + spi-flash@0 { + #address-cells = <0x1>; + #size-cells = <0x1>; + compatible = "jedec,spi-nor"; + reg = <0x0>; + spi-max-frequency = <40000000>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + partition@0 { + label = "U-Boot"; + reg = <0x0 0x1f0000>; + }; + partition@1f0000 { + label = "U-Boot ENV Factory"; + reg = <0x1f0000 0x10000>; + }; + partition@200000 { + label = "Reserved"; + reg = <0x200000 0x1f0000>; + }; + partition@3f0000 { + label = "U-Boot ENV"; + reg = <0x3f0000 0x10000>; + }; + }; + }; +}; + +&cp0_rtc { + status = "disabled"; +}; + +&cp0_syscon0 { + cp0_pinctrl: pinctrl { + compatible = "marvell,cp115-standalone-pinctrl"; + cp0_i2c0_pins: cp0-i2c-pins-0 { + marvell,pins = "mpp37", "mpp38"; + marvell,function = "i2c0"; + }; + cp0_i2c1_pins: cp0-i2c-pins-1 { + marvell,pins = "mpp35", "mpp36"; + marvell,function = "i2c1"; + }; + cp0_ge1_rgmii_pins: cp0-ge-rgmii-pins-0 { + marvell,pins = "mpp0", "mpp1", "mpp2", + "mpp3", "mpp4", "mpp5", + "mpp6", "mpp7", "mpp8", + "mpp9", "mpp10", "mpp11"; + marvell,function = "ge0"; + }; + cp0_ge2_rgmii_pins: cp0-ge-rgmii-pins-1 { + marvell,pins = "mpp44", "mpp45", "mpp46", + "mpp47", "mpp48", "mpp49", + "mpp50", "mpp51", "mpp52", + "mpp53", "mpp54", "mpp55"; + marvell,function = "ge1"; + }; + cp0_spi0_pins: cp0-spi-pins-0 { + marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16"; + marvell,function = "spi1"; + }; + }; +}; + +&cp0_usb3_1 { + status = "okay"; + phys = <&cp0_comphy3 1>; + phy-names = "usb"; +}; + +/* + * Instantiate the first connected CP115 + */ + +#define CP11X_NAME cp1 +#define CP11X_BASE f4000000 +#define CP11X_PCIEx_MEM_BASE(iface) (0xe2000000 + (iface * 0x1000000)) +#define CP11X_PCIEx_MEM_SIZE(iface) 0xf00000 +#define CP11X_PCIE0_BASE f4600000 +#define CP11X_PCIE1_BASE f4620000 +#define CP11X_PCIE2_BASE f4640000 + +#include "armada-cp115.dtsi" + +#undef CP11X_NAME +#undef CP11X_BASE +#undef CP11X_PCIEx_MEM_BASE +#undef CP11X_PCIEx_MEM_SIZE +#undef CP11X_PCIE0_BASE +#undef CP11X_PCIE1_BASE +#undef CP11X_PCIE2_BASE + +&cp1_crypto { + status = "okay"; +}; + +&cp1_xmdio { + status = "okay"; + cp1_nbaset_phy0: ethernet-phy@2 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <2>; + #thermal-sensor-cells = <0>; + }; + cp1_nbaset_phy1: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <0>; + #thermal-sensor-cells = <0>; + }; + cp1_nbaset_phy2: ethernet-phy@8 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <8>; + #thermal-sensor-cells = <0>; + }; +}; + +&cp1_ethernet { + status = "okay"; +}; + +/* CON50 */ +&cp1_eth0 { + status = "okay"; + phy-mode = "10gbase-kr"; + phys = <&cp1_comphy2 0>; + phy = <&cp1_nbaset_phy0>; +}; + +&cp1_eth1 { + status = "okay"; + phy-mode = "2500base-x"; + phys = <&cp1_comphy4 1>; + phy = <&cp1_nbaset_phy1>; +}; + +&cp1_eth2 { + status = "okay"; + phy-mode = "2500base-x"; + phys = <&cp1_comphy1 2>; + phy = <&cp1_nbaset_phy2>; +}; + +&cp1_gpio1 { + status = "okay"; +}; + +&cp1_gpio2 { + status = "okay"; +}; + +&cp1_i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&cp1_i2c0_pins>; + clock-frequency = <100000>; +}; + +&cp1_rtc { + status = "disabled"; +}; + +&cp1_syscon0 { + cp1_pinctrl: pinctrl { + compatible = "marvell,cp115-standalone-pinctrl"; + cp1_i2c0_pins: cp1-i2c-pins-0 { + marvell,pins = "mpp37", "mpp38"; + marvell,function = "i2c0"; + }; + cp1_spi0_pins: cp1-spi-pins-0 { + marvell,pins = "mpp13", "mpp14", "mpp15", "mpp16"; + marvell,function = "spi1"; + }; + cp1_xhci0_vbus_pins: cp1-xhci0-vbus-pins { + marvell,pins = "mpp3"; + marvell,function = "gpio"; + }; + }; +}; + +/* + * Instantiate the second connected CP115 + */ + +#define CP11X_NAME cp2 +#define CP11X_BASE f6000000 +#define CP11X_PCIEx_MEM_BASE(iface) (0xe5000000 + (iface * 0x1000000)) +#define CP11X_PCIEx_MEM_SIZE(iface) 0xf00000 +#define CP11X_PCIE0_BASE f6600000 +#define CP11X_PCIE1_BASE f6620000 +#define CP11X_PCIE2_BASE f6640000 + +#include "armada-cp115.dtsi" + +#undef CP11X_NAME +#undef CP11X_BASE +#undef CP11X_PCIEx_MEM_BASE +#undef CP11X_PCIEx_MEM_SIZE +#undef CP11X_PCIE0_BASE +#undef CP11X_PCIE1_BASE +#undef CP11X_PCIE2_BASE + +&cp2_crypto { + status = "okay"; +}; + +&cp2_ethernet { + status = "okay"; +}; + +&cp2_xmdio { + status = "okay"; + cp2_nbaset_phy0: ethernet-phy@2 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <2>; + #thermal-sensor-cells = <0>; + }; + cp2_nbaset_phy1: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <0>; + #thermal-sensor-cells = <0>; + }; + cp2_nbaset_phy2: ethernet-phy@8 { + compatible = "ethernet-phy-ieee802.3-c45"; + reg = <8>; + #thermal-sensor-cells = <0>; + }; +}; + +/* SLM-1521-V2, CON9 */ +&cp2_eth0 { + status = "okay"; + phy-mode = "10gbase-kr"; + phys = <&cp2_comphy2 0>; + phy = <&cp2_nbaset_phy0>; +}; + +&cp2_eth1 { + status = "okay"; + phy-mode = "2500base-x"; + phys = <&cp2_comphy4 1>; + phy = <&cp2_nbaset_phy1>; +}; + +&cp2_eth2 { + status = "okay"; + phy-mode = "2500base-x"; + phys = <&cp2_comphy1 2>; + phy = <&cp2_nbaset_phy2>; +}; + +&cp2_gpio1 { + status = "okay"; +}; + +&cp2_gpio2 { + status = "okay"; +}; + +&cp2_i2c0 { + clock-frequency = <100000>; + /* SLM-1521-V2 - U3 */ + i2c-mux@72 { + compatible = "nxp,pca9544"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x72>; + cp2_sfpp0_i2c: i2c@0 { + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; + }; + + i2c@1 { + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; + /* U12 */ + cp2_module_expander1: pca9555@21 { + compatible = "nxp,pca9555"; + pinctrl-names = "default"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x21>; + }; + }; + }; +}; + +&cp2_rtc { + status = "disabled"; +}; + +&cp2_syscon0 { + cp2_pinctrl: pinctrl { + compatible = "marvell,cp115-standalone-pinctrl"; + cp2_i2c0_pins: cp2-i2c-pins-0 { + marvell,pins = "mpp37", "mpp38"; + marvell,function = "i2c0"; + }; + }; +}; diff --git a/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/puzzle-thermal.dtsi b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/puzzle-thermal.dtsi new file mode 100644 index 0000000000..eb8682b297 --- /dev/null +++ b/lede/target/linux/mvebu/files-6.6/arch/arm64/boot/dts/marvell/puzzle-thermal.dtsi @@ -0,0 +1,98 @@ +#define PUZZLE_FAN_THERMAL(_cname, _fan) \ + polling-delay-passive = <0>; \ + polling-delay = <1000>; \ + \ + trips { \ + _cname##_active_full: trip-point5 { \ + temperature = <70000>; \ + hysteresis = <3000>; \ + type = "active"; \ + }; \ + _cname##_active_very_high: trip-point4 { \ + temperature = <67500>; \ + hysteresis = <3000>; \ + type = "active"; \ + }; \ + _cname##_active_high: trip-point3 { \ + temperature = <65000>; \ + hysteresis = <5000>; \ + type = "active"; \ + }; \ + _cname##_active_med: trip-point2 { \ + temperature = <62500>; \ + hysteresis = <3000>; \ + type = "active"; \ + }; \ + _cname##_active_low: trip-point1 { \ + temperature = <60000>; \ + hysteresis = <3000>; \ + type = "active"; \ + }; \ + _cname##_active_min: trip-point0 { \ + temperature = <55000>; \ + hysteresis = <5000>; \ + type = "active"; \ + }; \ + }; \ + cooling-maps { \ + map5 { \ + trip = <&_cname##_active_full>; \ + cooling-device = <_fan 6 6>; \ + }; \ + map4 { \ + trip = <&_cname##_active_very_high>; \ + cooling-device = <_fan 5 5>; \ + }; \ + map3 { \ + trip = <&_cname##_active_high>; \ + cooling-device = <_fan 4 4>; \ + }; \ + map2 { \ + trip = <&_cname##_active_med>; \ + cooling-device = <_fan 3 3>; \ + }; \ + map1 { \ + trip = <&_cname##_active_low>; \ + cooling-device = <_fan 2 2>; \ + }; \ + map0 { \ + trip = <&_cname##_active_min>; \ + cooling-device = <_fan 1 1>; \ + }; \ + } + +#define PUZZLE_FAN_CHASSIS_THERMAL(_cname, _fan) \ + polling-delay-passive = <0>; \ + polling-delay = <5000>; \ + \ + trips { \ + _cname##_active_full: trip-point2 { \ + temperature = <70000>; \ + hysteresis = <3000>; \ + type = "active"; \ + }; \ + _cname##_active_med: trip-point1 { \ + temperature = <62500>; \ + hysteresis = <3000>; \ + type = "active"; \ + }; \ + _cname##_active_min: trip-point0 { \ + temperature = <55000>; \ + hysteresis = <5000>; \ + type = "active"; \ + }; \ + }; \ + cooling-maps { \ + map2 { \ + trip = <&_cname##_active_full>; \ + cooling-device = <_fan 6 6>; \ + }; \ + map1 { \ + trip = <&_cname##_active_med>; \ + cooling-device = <_fan 3 3>; \ + }; \ + map0 { \ + trip = <&_cname##_active_min>; \ + cooling-device = <_fan 1 1>; \ + }; \ + } diff --git a/lede/target/linux/mvebu/patches-6.6/100-aardvark-workaround-PCIe.patch b/lede/target/linux/mvebu/patches-6.6/100-aardvark-workaround-PCIe.patch new file mode 100644 index 0000000000..4936f6ad16 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/100-aardvark-workaround-PCIe.patch @@ -0,0 +1,81 @@ +Subject: [PATCH v2] PCI: aardvark: Implement workaround for PCIe Completion Timeout +Date: Tue, 2 Aug 2022 14:38:16 +0200 +Message-Id: <20220802123816.21817-1-pali@kernel.org> +X-Mailer: git-send-email 2.20.1 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Precedence: bulk +List-ID: +X-Mailing-List: linux-pci@vger.kernel.org + +Marvell Armada 3700 Functional Errata, Guidelines, and Restrictions +document describes in erratum 3.12 PCIe Completion Timeout (Ref #: 251), +that PCIe IP does not support a strong-ordered model for inbound posted vs. +outbound completion. + +As a workaround for this erratum, DIS_ORD_CHK flag in Debug Mux Control +register must be set. It disables the ordering check in the core between +Completions and Posted requests received from the link. + +Marvell also suggests to do full memory barrier at the beginning of +aardvark summary interrupt handler before calling interrupt handlers of +endpoint drivers in order to minimize the risk for the race condition +documented in the Erratum between the DMA done status reading and the +completion of writing to the host memory. + +More details about this issue and suggested workarounds are in discussion: +https://lore.kernel.org/linux-pci/BN9PR18MB425154FE5019DCAF2028A1D5DB8D9@BN9PR18MB4251.namprd18.prod.outlook.com/t/#u + +It was reported that enabling this workaround fixes instability issues and +"Unhandled fault" errors when using 60 GHz WiFi 802.11ad card with Qualcomm +QCA6335 chip under significant load which were caused by interrupt status +stuck in the outbound CMPLT queue traced back to this erratum. + +This workaround fixes also kernel panic triggered after some minutes of +usage 5 GHz WiFi 802.11ax card with Mediatek MT7915 chip: + + Internal error: synchronous external abort: 96000210 [#1] SMP + Kernel panic - not syncing: Fatal exception in interrupt + +Signed-off-by: Thomas Petazzoni +Signed-off-by: Pali Rohár +Fixes: 8c39d710363c ("PCI: aardvark: Add Aardvark PCI host controller driver") +Cc: stable@vger.kernel.org +--- + drivers/pci/controller/pci-aardvark.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/pci/controller/pci-aardvark.c ++++ b/drivers/pci/controller/pci-aardvark.c +@@ -212,6 +212,8 @@ enum { + }; + + #define VENDOR_ID_REG (LMI_BASE_ADDR + 0x44) ++#define DEBUG_MUX_CTRL_REG (LMI_BASE_ADDR + 0x208) ++#define DIS_ORD_CHK BIT(30) + + /* PCIe core controller registers */ + #define CTRL_CORE_BASE_ADDR 0x18000 +@@ -560,6 +562,11 @@ static void advk_pcie_setup_hw(struct ad + PCIE_CORE_CTRL2_TD_ENABLE; + advk_writel(pcie, reg, PCIE_CORE_CTRL2_REG); + ++ /* Disable ordering checks, workaround for erratum 3.12 "PCIe completion timeout" */ ++ reg = advk_readl(pcie, DEBUG_MUX_CTRL_REG); ++ reg |= DIS_ORD_CHK; ++ advk_writel(pcie, reg, DEBUG_MUX_CTRL_REG); ++ + /* Set lane X1 */ + reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG); + reg &= ~LANE_CNT_MSK; +@@ -1661,6 +1668,9 @@ static irqreturn_t advk_pcie_irq_handler + struct advk_pcie *pcie = arg; + u32 status; + ++ /* Full memory barrier (ARM dsb sy), workaround for erratum 3.12 "PCIe completion timeout" */ ++ mb(); ++ + status = advk_readl(pcie, HOST_CTRL_INT_STATUS_REG); + if (!(status & PCIE_IRQ_CORE_INT)) + return IRQ_NONE; diff --git a/lede/target/linux/mvebu/patches-6.6/105-power-reset-linkstation-poweroff-add-ls220de.patch b/lede/target/linux/mvebu/patches-6.6/105-power-reset-linkstation-poweroff-add-ls220de.patch new file mode 100644 index 0000000000..3223861234 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/105-power-reset-linkstation-poweroff-add-ls220de.patch @@ -0,0 +1,15 @@ +--- a/drivers/power/reset/linkstation-poweroff.c ++++ b/drivers/power/reset/linkstation-poweroff.c +@@ -142,6 +142,12 @@ static void linkstation_poweroff(void) + } + + static const struct of_device_id ls_poweroff_of_match[] = { ++ { .compatible = "buffalo,ls220d", ++ .data = &linkstation_power_off_cfg, ++ }, ++ { .compatible = "buffalo,ls220de", ++ .data = &linkstation_power_off_cfg, ++ }, + { .compatible = "buffalo,ls421d", + .data = &linkstation_power_off_cfg, + }, diff --git a/lede/target/linux/mvebu/patches-6.6/300-mvebu-Mangle-bootloader-s-kernel-arguments.patch b/lede/target/linux/mvebu/patches-6.6/300-mvebu-Mangle-bootloader-s-kernel-arguments.patch new file mode 100644 index 0000000000..8f5b9dee40 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/300-mvebu-Mangle-bootloader-s-kernel-arguments.patch @@ -0,0 +1,279 @@ +From 71270226b14733a4b1f2cde58ea9265caa50b38d Mon Sep 17 00:00:00 2001 +From: Adrian Panella +Date: Thu, 9 Mar 2017 09:37:17 +0100 +Subject: [PATCH 67/69] generic: Mangle bootloader's kernel arguments + +The command-line arguments provided by the boot loader will be +appended to a new device tree property: bootloader-args. +If there is a property "append-rootblock" in DT under /chosen +and a root= option in bootloaders command line it will be parsed +and added to DT bootargs with the form: XX. +Only command line ATAG will be processed, the rest of the ATAGs +sent by bootloader will be ignored. +This is usefull in dual boot systems, to get the current root partition +without afecting the rest of the system. + +Signed-off-by: Adrian Panella + +This patch has been modified to be mvebu specific. The original patch +did not pass the bootloader cmdline on if no append-rootblock stanza +was found, resulting in blank cmdline and failure to boot. + +Signed-off-by: Michael Gray +--- + arch/arm/Kconfig | 11 ++++ + arch/arm/boot/compressed/atags_to_fdt.c | 85 ++++++++++++++++++++++++- + init/main.c | 16 +++++ + 3 files changed, 111 insertions(+), 1 deletion(-) + +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -1566,6 +1566,17 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN + The command-line arguments provided by the boot loader will be + appended to the the device tree bootargs property. + ++config ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE ++ bool "Append rootblock parsing bootloader's kernel arguments" ++ help ++ The command-line arguments provided by the boot loader will be ++ appended to a new device tree property: bootloader-args. ++ If there is a property "append-rootblock" in DT under /chosen ++ and a root= option in bootloaders command line it will be parsed ++ and added to DT bootargs with the form: XX. ++ Only command line ATAG will be processed, the rest of the ATAGs ++ sent by bootloader will be ignored. ++ + endchoice + + config CMDLINE +--- a/arch/arm/boot/compressed/atags_to_fdt.c ++++ b/arch/arm/boot/compressed/atags_to_fdt.c +@@ -6,6 +6,8 @@ + + #if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND) + #define do_extend_cmdline 1 ++#elif defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) ++#define do_extend_cmdline 1 + #else + #define do_extend_cmdline 0 + #endif +@@ -21,6 +23,7 @@ static int node_offset(void *fdt, const + return offset; + } + ++#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE + static int setprop(void *fdt, const char *node_path, const char *property, + void *val_array, int size) + { +@@ -29,6 +32,7 @@ static int setprop(void *fdt, const char + return offset; + return fdt_setprop(fdt, offset, property, val_array, size); + } ++#endif + + static int setprop_string(void *fdt, const char *node_path, + const char *property, const char *string) +@@ -39,6 +43,7 @@ static int setprop_string(void *fdt, con + return fdt_setprop_string(fdt, offset, property, string); + } + ++#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE + static int setprop_cell(void *fdt, const char *node_path, + const char *property, uint32_t val) + { +@@ -47,6 +52,7 @@ static int setprop_cell(void *fdt, const + return offset; + return fdt_setprop_cell(fdt, offset, property, val); + } ++#endif + + static const void *getprop(const void *fdt, const char *node_path, + const char *property, int *len) +@@ -59,6 +65,7 @@ static const void *getprop(const void *f + return fdt_getprop(fdt, offset, property, len); + } + ++#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE + static uint32_t get_cell_size(const void *fdt) + { + int len; +@@ -70,6 +77,74 @@ static uint32_t get_cell_size(const void + return cell_size; + } + ++#endif ++ ++#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) ++ ++static char *append_rootblock(char *dest, const char *str, int len, void *fdt) ++{ ++ const char *ptr, *end; ++ const char *root="root="; ++ int i, l; ++ const char *rootblock; ++ ++ //ARM doesn't have __HAVE_ARCH_STRSTR, so search manually ++ ptr = str - 1; ++ ++ do { ++ //first find an 'r' at the begining or after a space ++ do { ++ ptr++; ++ ptr = strchr(ptr, 'r'); ++ if (!ptr) ++ goto no_append; ++ ++ } while (ptr != str && *(ptr-1) != ' '); ++ ++ //then check for the rest ++ for(i = 1; i <= 4; i++) ++ if(*(ptr+i) != *(root+i)) break; ++ ++ } while (i != 5); ++ ++ end = strchr(ptr, ' '); ++ end = end ? (end - 1) : (strchr(ptr, 0) - 1); ++ ++ //find partition number (assumes format root=/dev/mtdXX | /dev/mtdblockXX | yy:XX ) ++ for( i = 0; end >= ptr && *end >= '0' && *end <= '9'; end--, i++); ++ ptr = end + 1; ++ ++ /* if append-rootblock property is set use it to append to command line */ ++ rootblock = getprop(fdt, "/chosen", "append-rootblock", &l); ++ if (rootblock == NULL) ++ goto no_append; ++ ++ if (*dest != ' ') { ++ *dest = ' '; ++ dest++; ++ len++; ++ } ++ ++ if (len + l + i <= COMMAND_LINE_SIZE) { ++ memcpy(dest, rootblock, l); ++ dest += l - 1; ++ memcpy(dest, ptr, i); ++ dest += i; ++ } ++ ++ return dest; ++ ++no_append: ++ len = strlen(str); ++ if (len + 1 < COMMAND_LINE_SIZE) { ++ memcpy(dest, str, len); ++ dest += len; ++ } ++ ++ return dest; ++} ++#endif ++ + static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline) + { + char cmdline[COMMAND_LINE_SIZE]; +@@ -89,18 +164,28 @@ static void merge_fdt_bootargs(void *fdt + + /* and append the ATAG_CMDLINE */ + if (fdt_cmdline) { ++ ++#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) ++ //save original bootloader args ++ //and append ubi.mtd with root partition number to current cmdline ++ setprop_string(fdt, "/chosen", "bootloader-args", fdt_cmdline); ++ ptr = append_rootblock(ptr, fdt_cmdline, len, fdt); ++ ++#else + len = strlen(fdt_cmdline); + if (ptr - cmdline + len + 2 < COMMAND_LINE_SIZE) { + *ptr++ = ' '; + memcpy(ptr, fdt_cmdline, len); + ptr += len; + } ++#endif + } + *ptr = '\0'; + + setprop_string(fdt, "/chosen", "bootargs", cmdline); + } + ++#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE + static void hex_str(char *out, uint32_t value) + { + uint32_t digit; +@@ -118,6 +203,7 @@ static void hex_str(char *out, uint32_t + } + *out = '\0'; + } ++#endif + + /* + * Convert and fold provided ATAGs into the provided FDT. +@@ -132,9 +218,11 @@ int atags_to_fdt(void *atag_list, void * + struct tag *atag = atag_list; + /* In the case of 64 bits memory size, need to reserve 2 cells for + * address and size for each bank */ ++#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE + __be32 mem_reg_property[2 * 2 * NR_BANKS]; +- int memcount = 0; +- int ret, memsize; ++ int memsize, memcount = 0; ++#endif ++ int ret; + + /* make sure we've got an aligned pointer */ + if ((u32)atag_list & 0x3) +@@ -169,7 +257,9 @@ int atags_to_fdt(void *atag_list, void * + else + setprop_string(fdt, "/chosen", "bootargs", + atag->u.cmdline.cmdline); +- } else if (atag->hdr.tag == ATAG_MEM) { ++ } ++#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE ++ else if (atag->hdr.tag == ATAG_MEM) { + if (memcount >= sizeof(mem_reg_property)/4) + continue; + if (!atag->u.mem.size) +@@ -213,6 +303,10 @@ int atags_to_fdt(void *atag_list, void * + setprop(fdt, "/memory", "reg", mem_reg_property, + 4 * memcount * memsize); + } ++#else ++ ++ } ++#endif + + return fdt_pack(fdt); + } +--- a/init/main.c ++++ b/init/main.c +@@ -112,6 +112,10 @@ + + #include + ++#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) ++#include ++#endif ++ + static int kernel_init(void *); + + /* +@@ -929,6 +933,18 @@ void start_kernel(void) + boot_cpu_hotplug_init(); + + pr_notice("Kernel command line: %s\n", saved_command_line); ++ ++#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE) ++ //Show bootloader's original command line for reference ++ if(of_chosen) { ++ const char *prop = of_get_property(of_chosen, "bootloader-args", NULL); ++ if(prop) ++ pr_notice("Bootloader command line (ignored): %s\n", prop); ++ else ++ pr_notice("Bootloader command line not present\n"); ++ } ++#endif ++ + /* parameters may set static keys */ + jump_label_init(); + parse_early_param(); diff --git a/lede/target/linux/mvebu/patches-6.6/301-mvebu-armada-38x-enable-libata-leds.patch b/lede/target/linux/mvebu/patches-6.6/301-mvebu-armada-38x-enable-libata-leds.patch new file mode 100644 index 0000000000..b75dcf596a --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/301-mvebu-armada-38x-enable-libata-leds.patch @@ -0,0 +1,10 @@ +--- a/arch/arm/mach-mvebu/Kconfig ++++ b/arch/arm/mach-mvebu/Kconfig +@@ -66,6 +66,7 @@ config MACH_ARMADA_38X + select HAVE_ARM_TWD if SMP + select MACH_MVEBU_V7 + select PINCTRL_ARMADA_38X ++ select ARCH_WANT_LIBATA_LEDS + help + Say 'Y' here if you want your kernel to support boards based + on the Marvell Armada 380/385 SoC with device tree. diff --git a/lede/target/linux/mvebu/patches-6.6/302-add_powertables.patch b/lede/target/linux/mvebu/patches-6.6/302-add_powertables.patch new file mode 100644 index 0000000000..36117d0cd1 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/302-add_powertables.patch @@ -0,0 +1,770 @@ +--- a/arch/arm/boot/dts/marvell/armada-385-linksys.dtsi ++++ b/arch/arm/boot/dts/marvell/armada-385-linksys.dtsi +@@ -214,11 +214,19 @@ + &pcie1 { + /* Marvell 88W8864, 5GHz-only */ + status = "okay"; ++ ++ mwlwifi { ++ marvell,2ghz = <0>; ++ }; + }; + + &pcie2 { + /* Marvell 88W8864, 2GHz-only */ + status = "okay"; ++ ++ mwlwifi { ++ marvell,5ghz = <0>; ++ }; + }; + + &pinctrl { +--- a/arch/arm/boot/dts/marvell/armada-385-linksys-caiman.dts ++++ b/arch/arm/boot/dts/marvell/armada-385-linksys-caiman.dts +@@ -142,3 +142,205 @@ + }; + }; + }; ++ ++&pcie1 { ++ mwlwifi { ++ marvell,chainmask = <2 2>; ++ marvell,powertable { ++ AU = ++ <36 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <40 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <44 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <48 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <100 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <104 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <108 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <112 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <116 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <120 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <124 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <128 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <132 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <136 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <140 0 0x17 0x17 0x17 0x17 0x17 0x17 0x17 0x15 0x17 0x17 0x17 0x14 0x17 0x17 0x17 0x14 0 0xf>, ++ <149 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>, ++ <153 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>, ++ <157 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>, ++ <161 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>, ++ <165 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x1a 0x1a 0x17 0x14 0 0xf>; ++ CA = ++ <36 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0 0xf>, ++ <40 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0 0xf>, ++ <44 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0 0xf>, ++ <48 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <149 0 0x1a 0x1a 0x18 0x17 0x19 0x19 0x17 0x15 0x18 0x18 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <153 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <157 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <161 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <165 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>; ++ CN = ++ <36 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <40 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <44 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <48 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <100 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <149 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x11 0x11 0x11 0x11 0 0xf>, ++ <153 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0 0xf>, ++ <157 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0 0xf>, ++ <161 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0 0xf>, ++ <165 0 0x15 0x15 0x15 0x15 0x16 0x16 0x16 0x15 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0 0xf>; ++ ETSI = ++ <36 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <40 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <44 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <48 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <100 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>, ++ <149 0 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0 0xf>; ++ FCC = ++ <36 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <40 0 0x19 0x19 0x18 0x17 0x19 0x19 0x17 0x15 0x17 0x17 0x17 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <44 0 0x19 0x19 0x18 0x17 0x19 0x19 0x17 0x15 0x17 0x17 0x17 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <48 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x17 0x17 0x17 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <149 0 0x1a 0x1a 0x18 0x17 0x19 0x19 0x17 0x15 0x18 0x18 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <153 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <157 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <161 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>, ++ <165 0 0x1a 0x1a 0x18 0x17 0x1a 0x1a 0x17 0x15 0x1a 0x1a 0x17 0x14 0x15 0x15 0x15 0x14 0 0xf>; ++ }; ++ }; ++}; ++ ++&pcie2 { ++ mwlwifi { ++ marvell,chainmask = <2 2>; ++ marvell,powertable { ++ AU = ++ <1 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>; ++ CA = ++ <1 0 0x19 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x10 0x10 0x10 0x10 0x00 0x00 0x00 0x00 0 0xf>, ++ <2 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <3 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <4 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <5 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <6 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <7 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <8 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <9 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <10 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x00 0x00 0x00 0x00 0 0xf>, ++ <11 0 0x19 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x00 0x00 0x00 0x00 0 0xf>; ++ CN = ++ <1 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <14 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>; ++ ETSI = ++ <1 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0x0 0x0 0x0 0x0 0 0xf>; ++ FCC = ++ <1 0 0x19 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0x1a 0x19 0x18 0x17 0x19 0x19 0x17 0x16 0x14 0x14 0x14 0x14 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0x19 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x0 0x0 0x0 0x0 0 0xf>; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/marvell/armada-385-linksys-cobra.dts ++++ b/arch/arm/boot/dts/marvell/armada-385-linksys-cobra.dts +@@ -142,3 +142,205 @@ + }; + }; + }; ++ ++&pcie1 { ++ mwlwifi { ++ marvell,chainmask = <4 4>; ++ marvell,powertable { ++ AU = ++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <100 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <104 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <108 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <112 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <116 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <120 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <124 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <128 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <132 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <136 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <140 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <149 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <153 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <157 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <161 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <165 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>; ++ CA = ++ <36 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <40 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <44 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <48 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <149 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <165 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>; ++ CN = ++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <100 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <104 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <108 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <112 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <116 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <120 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <124 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <128 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <132 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <136 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <140 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <149 0 0x14 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <165 0 0x13 0x13 0x13 0x13 0x13 0x13 0x13 0x13 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>; ++ ETSI = ++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <100 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <104 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <108 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <112 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <116 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <120 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <124 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <128 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <132 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <136 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <140 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <149 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>; ++ FCC = ++ <36 0 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0 0xf>, ++ <40 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, ++ <44 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, ++ <48 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <149 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <165 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>; ++ }; ++ }; ++}; ++ ++&pcie2 { ++ mwlwifi { ++ marvell,chainmask = <4 4>; ++ marvell,powertable { ++ AU = ++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; ++ CA = ++ <1 0 0x17 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0xe 0xe 0xe 0xe 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0x17 0x12 0x12 0x12 0x13 0x13 0x13 0x13 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>; ++ CN = ++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <14 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; ++ ETSI = ++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; ++ FCC = ++ <1 0 0x17 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0xe 0xe 0xe 0xe 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0x17 0x12 0x12 0x12 0x13 0x13 0x13 0x13 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/marvell/armada-385-linksys-shelby.dts ++++ b/arch/arm/boot/dts/marvell/armada-385-linksys-shelby.dts +@@ -142,3 +142,205 @@ + }; + }; + }; ++ ++&pcie1 { ++ mwlwifi { ++ marvell,chainmask = <4 4>; ++ marvell,powertable { ++ AU = ++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <100 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <104 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <108 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <112 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <116 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <120 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <124 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <128 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <132 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <136 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <140 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <149 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <153 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <157 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <161 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>, ++ <165 0 0x19 0x19 0x19 0x17 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0x19 0x19 0x16 0x15 0 0xf>; ++ CA = ++ <36 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <40 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <44 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <48 0 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <149 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <165 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>; ++ CN = ++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <100 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <104 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <108 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <112 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <116 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <120 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <124 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <128 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <132 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <136 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <140 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <149 0 0x14 0x14 0x14 0x14 0x13 0x13 0x13 0x13 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>, ++ <165 0 0x13 0x13 0x13 0x13 0x13 0x13 0x13 0x13 0x14 0x14 0x14 0x14 0x10 0x10 0x10 0x10 0 0xf>; ++ ETSI = ++ <36 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <40 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <44 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <48 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <52 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <56 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <60 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <64 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <100 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <104 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <108 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <112 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <116 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <120 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <124 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <128 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <132 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <136 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <140 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>, ++ <149 0 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xd 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0xe 0 0xf>; ++ FCC = ++ <36 0 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0 0xf>, ++ <40 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, ++ <44 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, ++ <48 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0xf 0xf 0xf 0xf 0 0xf>, ++ <52 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <56 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <60 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <64 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <100 0 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <104 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x12 0x12 0x12 0x12 0x10 0x10 0x10 0x10 0 0xf>, ++ <108 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <112 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <116 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <120 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <124 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <128 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <132 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <136 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <140 0 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0 0xf>, ++ <149 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <153 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <157 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <161 0 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>, ++ <165 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0 0xf>; ++ }; ++ }; ++}; ++ ++&pcie2 { ++ mwlwifi { ++ marvell,chainmask = <4 4>; ++ marvell,powertable { ++ AU = ++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; ++ CA = ++ <1 0 0x17 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0xe 0xe 0xe 0xe 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0x17 0x12 0x12 0x12 0x13 0x13 0x13 0x13 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>; ++ CN = ++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <14 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; ++ ETSI = ++ <1 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0xa 0x0 0x0 0x0 0x0 0 0xf>; ++ FCC = ++ <1 0 0x17 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0xe 0xe 0xe 0xe 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0x18 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x11 0x11 0x11 0x11 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0x17 0x12 0x12 0x12 0x13 0x13 0x13 0x13 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>; ++ }; ++ }; ++}; +--- a/arch/arm/boot/dts/marvell/armada-385-linksys-rango.dts ++++ b/arch/arm/boot/dts/marvell/armada-385-linksys-rango.dts +@@ -157,6 +157,18 @@ + }; + }; + ++&pcie1 { ++ mwlwifi { ++ marvell,chainmask = <4 4>; ++ }; ++}; ++ ++&pcie2 { ++ mwlwifi { ++ marvell,chainmask = <4 4>; ++ }; ++}; ++ + &sdhci { + pinctrl-names = "default"; + pinctrl-0 = <&sdhci_pins>; +--- a/arch/arm/boot/dts/marvell/armada-xp-linksys-mamba.dts ++++ b/arch/arm/boot/dts/marvell/armada-xp-linksys-mamba.dts +@@ -223,12 +223,100 @@ + pcie@2,0 { + /* Port 0, Lane 1 */ + status = "okay"; ++ ++ mwlwifi { ++ marvell,5ghz = <0>; ++ marvell,chainmask = <4 4>; ++ marvell,powertable { ++ FCC = ++ <1 0 0x17 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0xf 0xf 0xf 0xf 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0x17 0x16 0x16 0x16 0x16 0x16 0x16 0x14 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0x17 0x11 0x11 0x11 0x11 0x11 0x11 0x11 0x10 0x10 0x10 0x10 0x0 0x0 0x0 0x0 0 0xf>; ++ ++ ETSI = ++ <1 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <2 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <3 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <4 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <5 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <6 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <7 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <8 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <9 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <10 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <11 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <12 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>, ++ <13 0 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0xb 0x0 0x0 0x0 0x0 0 0xf>; ++ }; ++ }; + }; + + /* Second mini-PCIe port */ + pcie@3,0 { + /* Port 0, Lane 3 */ + status = "okay"; ++ ++ mwlwifi { ++ marvell,2ghz = <0>; ++ marvell,chainmask = <4 4>; ++ marvell,powertable { ++ FCC = ++ <36 0 0x8 0x8 0x8 0x8 0x8 0x8 0x8 0x8 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <40 0 0x8 0x8 0x8 0x8 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <44 0 0x8 0x8 0x8 0x8 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <48 0 0x8 0x8 0x8 0x8 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0x9 0 0xf>, ++ <52 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0 0xf>, ++ <56 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0 0xf>, ++ <60 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0 0xf>, ++ <64 0 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0xf 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0x12 0 0xf>, ++ <100 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <104 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <108 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <112 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <116 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <120 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <124 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <128 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <132 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <136 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <140 0 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0x14 0 0xf>, ++ <149 0 0x16 0x16 0x16 0x16 0x14 0x14 0x14 0x14 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>, ++ <153 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>, ++ <157 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>, ++ <161 0 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>, ++ <165 0 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x16 0x15 0x15 0x15 0x15 0x14 0x14 0x14 0x14 0 0xf>; ++ ++ ETSI = ++ <36 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <40 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <44 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <48 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <52 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <56 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <60 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <64 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <100 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <104 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <108 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <112 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <116 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <120 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <124 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <128 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <132 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <136 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <140 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>, ++ <149 0 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xc 0xd 0xd 0xd 0xd 0xc 0xc 0xc 0xc 0 0xf>; ++ }; ++ }; + }; + }; + diff --git a/lede/target/linux/mvebu/patches-6.6/304-revert_i2c_delay.patch b/lede/target/linux/mvebu/patches-6.6/304-revert_i2c_delay.patch new file mode 100644 index 0000000000..3802b0f16e --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/304-revert_i2c_delay.patch @@ -0,0 +1,15 @@ +--- a/arch/arm/boot/dts/marvell/armada-xp.dtsi ++++ b/arch/arm/boot/dts/marvell/armada-xp.dtsi +@@ -237,12 +237,10 @@ + }; + + &i2c0 { +- compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c"; + reg = <0x11000 0x100>; + }; + + &i2c1 { +- compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c"; + reg = <0x11100 0x100>; + }; + diff --git a/lede/target/linux/mvebu/patches-6.6/305-armada-385-rd-mtd-partitions.patch b/lede/target/linux/mvebu/patches-6.6/305-armada-385-rd-mtd-partitions.patch new file mode 100644 index 0000000000..6fd4fa0e20 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/305-armada-385-rd-mtd-partitions.patch @@ -0,0 +1,19 @@ +--- a/arch/arm/boot/dts/marvell/armada-388-rd.dts ++++ b/arch/arm/boot/dts/marvell/armada-388-rd.dts +@@ -103,6 +103,16 @@ + compatible = "st,m25p128", "jedec,spi-nor"; + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <108000000>; ++ ++ partition@0 { ++ label = "uboot"; ++ reg = <0 0x400000>; ++ }; ++ ++ partition@1 { ++ label = "firmware"; ++ reg = <0x400000 0xc00000>; ++ }; + }; + }; + diff --git a/lede/target/linux/mvebu/patches-6.6/306-ARM-mvebu-385-ap-Add-partitions.patch b/lede/target/linux/mvebu/patches-6.6/306-ARM-mvebu-385-ap-Add-partitions.patch new file mode 100644 index 0000000000..fbdab2fb94 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/306-ARM-mvebu-385-ap-Add-partitions.patch @@ -0,0 +1,35 @@ +From 9861f93a59142a3131870df2521eb2deb73026d7 Mon Sep 17 00:00:00 2001 +From: Maxime Ripard +Date: Tue, 13 Jan 2015 11:14:09 +0100 +Subject: [PATCH 2/2] ARM: mvebu: 385-ap: Add partitions + +Signed-off-by: Maxime Ripard +--- + arch/arm/boot/dts/marvell/armada-385-db-ap.dts | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/arm/boot/dts/marvell/armada-385-db-ap.dts ++++ b/arch/arm/boot/dts/marvell/armada-385-db-ap.dts +@@ -218,19 +218,19 @@ + #size-cells = <1>; + + partition@0 { +- label = "U-Boot"; ++ label = "u-boot"; + reg = <0x00000000 0x00800000>; + read-only; + }; + + partition@800000 { +- label = "uImage"; ++ label = "kernel"; + reg = <0x00800000 0x00400000>; + read-only; + }; + + partition@c00000 { +- label = "Root"; ++ label = "ubi"; + reg = <0x00c00000 0x3f400000>; + }; + }; diff --git a/lede/target/linux/mvebu/patches-6.6/307-armada-xp-linksys-mamba-broken-idle.patch b/lede/target/linux/mvebu/patches-6.6/307-armada-xp-linksys-mamba-broken-idle.patch new file mode 100644 index 0000000000..b801b54435 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/307-armada-xp-linksys-mamba-broken-idle.patch @@ -0,0 +1,10 @@ +--- a/arch/arm/boot/dts/marvell/armada-xp-linksys-mamba.dts ++++ b/arch/arm/boot/dts/marvell/armada-xp-linksys-mamba.dts +@@ -483,3 +483,7 @@ + }; + }; + }; ++ ++&coherencyfab { ++ broken-idle; ++}; diff --git a/lede/target/linux/mvebu/patches-6.6/308-armada-xp-linksys-mamba-wan.patch b/lede/target/linux/mvebu/patches-6.6/308-armada-xp-linksys-mamba-wan.patch new file mode 100644 index 0000000000..5d8c5811b6 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/308-armada-xp-linksys-mamba-wan.patch @@ -0,0 +1,11 @@ +--- a/arch/arm/boot/dts/marvell/armada-xp-linksys-mamba.dts ++++ b/arch/arm/boot/dts/marvell/armada-xp-linksys-mamba.dts +@@ -385,7 +385,7 @@ + + port@4 { + reg = <4>; +- label = "internet"; ++ label = "wan"; + }; + + port@5 { diff --git a/lede/target/linux/mvebu/patches-6.6/309-linksys-status-led.patch b/lede/target/linux/mvebu/patches-6.6/309-linksys-status-led.patch new file mode 100644 index 0000000000..270937a924 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/309-linksys-status-led.patch @@ -0,0 +1,50 @@ +--- a/arch/arm/boot/dts/marvell/armada-385-linksys.dtsi ++++ b/arch/arm/boot/dts/marvell/armada-385-linksys.dtsi +@@ -14,6 +14,13 @@ + compatible = "linksys,armada385", "marvell,armada385", + "marvell,armada380"; + ++ aliases { ++ led-boot = &led_power; ++ led-failsafe = &led_power; ++ led-running = &led_power; ++ led-upgrade = &led_power; ++ }; ++ + chosen { + stdout-path = "serial0:115200n8"; + }; +@@ -71,7 +78,7 @@ + pinctrl-0 = <&gpio_leds_pins>; + pinctrl-names = "default"; + +- led-power { ++ led_power: led-power { + gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; +--- a/arch/arm/boot/dts/marvell/armada-xp-linksys-mamba.dts ++++ b/arch/arm/boot/dts/marvell/armada-xp-linksys-mamba.dts +@@ -26,6 +26,13 @@ + compatible = "linksys,mamba", "marvell,armadaxp-mv78230", + "marvell,armadaxp", "marvell,armada-370-xp"; + ++ aliases { ++ led-boot = &led_power; ++ led-failsafe = &led_power; ++ led-running = &led_power; ++ led-upgrade = &led_power; ++ }; ++ + chosen { + bootargs = "console=ttyS0,115200"; + stdout-path = &uart0; +@@ -195,7 +202,7 @@ + pinctrl-0 = <&power_led_pin>; + pinctrl-names = "default"; + +- led-power { ++ led_power: led-power { + label = "mamba:white:power"; + gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>; + default-state = "on"; diff --git a/lede/target/linux/mvebu/patches-6.6/310-linksys-use-eth0-as-cpu-port.patch b/lede/target/linux/mvebu/patches-6.6/310-linksys-use-eth0-as-cpu-port.patch new file mode 100644 index 0000000000..683a5ebe51 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/310-linksys-use-eth0-as-cpu-port.patch @@ -0,0 +1,25 @@ +--- a/arch/arm/boot/dts/marvell/armada-385-linksys.dtsi ++++ b/arch/arm/boot/dts/marvell/armada-385-linksys.dtsi +@@ -116,7 +116,7 @@ + }; + + ð2 { +- status = "okay"; ++ status = "disabled"; + phy-mode = "sgmii"; + buffer-manager = <&bm>; + bm,pool-long = <2>; +@@ -200,10 +200,10 @@ + label = "wan"; + }; + +- port@5 { +- reg = <5>; ++ port@6 { ++ reg = <6>; + phy-mode = "sgmii"; +- ethernet = <ð2>; ++ ethernet = <ð0>; + + fixed-link { + speed = <1000>; diff --git a/lede/target/linux/mvebu/patches-6.6/311-adjust-compatible-for-linksys.patch b/lede/target/linux/mvebu/patches-6.6/311-adjust-compatible-for-linksys.patch new file mode 100644 index 0000000000..6722248df7 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/311-adjust-compatible-for-linksys.patch @@ -0,0 +1,68 @@ +--- a/arch/arm/boot/dts/marvell/armada-385-linksys-rango.dts ++++ b/arch/arm/boot/dts/marvell/armada-385-linksys-rango.dts +@@ -12,8 +12,8 @@ + + / { + model = "Linksys WRT3200ACM"; +- compatible = "linksys,rango", "linksys,armada385", "marvell,armada385", +- "marvell,armada380"; ++ compatible = "linksys,wrt3200acm", "linksys,rango", "linksys,armada385", ++ "marvell,armada385", "marvell,armada380"; + }; + + &expander0 { +--- a/arch/arm/boot/dts/marvell/armada-xp-linksys-mamba.dts ++++ b/arch/arm/boot/dts/marvell/armada-xp-linksys-mamba.dts +@@ -22,9 +22,10 @@ + #include "armada-xp-mv78230.dtsi" + + / { +- model = "Linksys WRT1900AC"; +- compatible = "linksys,mamba", "marvell,armadaxp-mv78230", +- "marvell,armadaxp", "marvell,armada-370-xp"; ++ model = "Linksys WRT1900AC v1"; ++ compatible = "linksys,wrt1900ac-v1", "linksys,mamba", ++ "marvell,armadaxp-mv78230", "marvell,armadaxp", ++ "marvell,armada-370-xp"; + + aliases { + led-boot = &led_power; +--- a/arch/arm/boot/dts/marvell/armada-385-linksys-cobra.dts ++++ b/arch/arm/boot/dts/marvell/armada-385-linksys-cobra.dts +@@ -9,8 +9,9 @@ + #include "armada-385-linksys.dtsi" + + / { +- model = "Linksys WRT1900ACv2"; +- compatible = "linksys,cobra", "linksys,armada385", "marvell,armada385", ++ model = "Linksys WRT1900AC v2"; ++ compatible = "linksys,wrt1900ac-v2", "linksys,cobra", ++ "linksys,armada385", "marvell,armada385", + "marvell,armada380"; + }; + +--- a/arch/arm/boot/dts/marvell/armada-385-linksys-caiman.dts ++++ b/arch/arm/boot/dts/marvell/armada-385-linksys-caiman.dts +@@ -10,8 +10,8 @@ + + / { + model = "Linksys WRT1200AC"; +- compatible = "linksys,caiman", "linksys,armada385", "marvell,armada385", +- "marvell,armada380"; ++ compatible = "linksys,wrt1200ac", "linksys,caiman", "linksys,armada385", ++ "marvell,armada385", "marvell,armada380"; + }; + + &expander0 { +--- a/arch/arm/boot/dts/marvell/armada-385-linksys-shelby.dts ++++ b/arch/arm/boot/dts/marvell/armada-385-linksys-shelby.dts +@@ -10,7 +10,8 @@ + + / { + model = "Linksys WRT1900ACS"; +- compatible = "linksys,shelby", "linksys,armada385", "marvell,armada385", ++ compatible = "linksys,wrt1900acs", "linksys,shelby", ++ "linksys,armada385", "marvell,armada385", + "marvell,armada380"; + }; + diff --git a/lede/target/linux/mvebu/patches-6.6/312-ARM-dts-armada388-clearfog-emmc-on-clearfog-base.patch b/lede/target/linux/mvebu/patches-6.6/312-ARM-dts-armada388-clearfog-emmc-on-clearfog-base.patch new file mode 100644 index 0000000000..5f84a34769 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/312-ARM-dts-armada388-clearfog-emmc-on-clearfog-base.patch @@ -0,0 +1,87 @@ +From 8137da20701c776ad3481115305a5e8e410871ba Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Tue, 29 Nov 2016 10:15:45 +0000 +Subject: ARM: dts: armada388-clearfog: emmc on clearfog base + +Signed-off-by: Russell King +--- + .../arm/boot/dts/marvell/armada-388-clearfog-base.dts | 1 + + .../armada-38x-solidrun-microsom-emmc.dtsi | 62 +++++++++++++++++++ + 2 files changed, 63 insertions(+) + create mode 100644 arch/arm/boot/dts/marvell/armada-38x-solidrun-microsom-emmc.dtsi + +--- a/arch/arm/boot/dts/marvell/armada-388-clearfog-base.dts ++++ b/arch/arm/boot/dts/marvell/armada-388-clearfog-base.dts +@@ -7,6 +7,7 @@ + + /dts-v1/; + #include "armada-388-clearfog.dtsi" ++#include "armada-38x-solidrun-microsom-emmc.dtsi" + + / { + model = "SolidRun Clearfog Base A1"; +--- /dev/null ++++ b/arch/arm/boot/dts/marvell/armada-38x-solidrun-microsom-emmc.dtsi +@@ -0,0 +1,62 @@ ++/* ++ * Device Tree file for SolidRun Armada 38x Microsom add-on for eMMC ++ * ++ * Copyright (C) 2015 Russell King ++ * ++ * This board is in development; the contents of this file work with ++ * the A1 rev 2.0 of the board, which does not represent final ++ * production board. Things will change, don't expect this file to ++ * remain compatible info the future. ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPL or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This file is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 as published by the Free Software Foundation. ++ * ++ * This file is distributed in the hope that it will be useful ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++/ { ++ soc { ++ internal-regs { ++ sdhci@d8000 { ++ bus-width = <4>; ++ no-1-8-v; ++ non-removable; ++ pinctrl-0 = <µsom_sdhci_pins>; ++ pinctrl-names = "default"; ++ status = "okay"; ++ wp-inverted; ++ }; ++ }; ++ }; ++}; diff --git a/lede/target/linux/mvebu/patches-6.6/313-helios4-dts-status-led-alias.patch b/lede/target/linux/mvebu/patches-6.6/313-helios4-dts-status-led-alias.patch new file mode 100644 index 0000000000..50b970aabb --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/313-helios4-dts-status-led-alias.patch @@ -0,0 +1,28 @@ +--- a/arch/arm/boot/dts/marvell/armada-388-helios4.dts ++++ b/arch/arm/boot/dts/marvell/armada-388-helios4.dts +@@ -15,6 +15,13 @@ + model = "Helios4"; + compatible = "kobol,helios4", "marvell,armada388", + "marvell,armada385", "marvell,armada380"; ++ ++ aliases { ++ led-boot = &led_status; ++ led-failsafe = &led_status; ++ led-running = &led_status; ++ led-upgrade = &led_status; ++ }; + + memory { + device_type = "memory"; +@@ -73,10 +80,9 @@ + pinctrl-names = "default"; + pinctrl-0 = <&helios_system_led_pins>; + +- status-led { ++ led_status: status-led { + label = "helios4:green:status"; + gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; +- linux,default-trigger = "heartbeat"; + default-state = "on"; + }; + diff --git a/lede/target/linux/mvebu/patches-6.6/314-arm64-dts-marvell-enable-heartbeat-LED-by-default.patch b/lede/target/linux/mvebu/patches-6.6/314-arm64-dts-marvell-enable-heartbeat-LED-by-default.patch new file mode 100644 index 0000000000..7221e04de1 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/314-arm64-dts-marvell-enable-heartbeat-LED-by-default.patch @@ -0,0 +1,22 @@ +From: Tomasz Maciej Nowak +Date: Fri, 7 Jul 2023 19:06:05 +0200 +Subject: [PATCH] arm64: dts: marvell: enable heartbeat LED by default + +Some boards could be placed in an enclosure, so enable LED18 by default, +since that'll be the only visible indicator that the board is operating. + +Signed-off-by: Tomasz Maciej Nowak +--- + arch/arm64/boot/dts/marvell/armada-8040-mcbin-singleshot.dts | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm64/boot/dts/marvell/armada-8040-mcbin-singleshot.dts ++++ b/arch/arm64/boot/dts/marvell/armada-8040-mcbin-singleshot.dts +@@ -25,6 +25,7 @@ + function = LED_FUNCTION_HEARTBEAT; + color = ; + linux,default-trigger = "heartbeat"; ++ default-state = "on"; + }; + }; + }; diff --git a/lede/target/linux/mvebu/patches-6.6/315-armada-xp-linksys-mamba-resize-kernel.patch b/lede/target/linux/mvebu/patches-6.6/315-armada-xp-linksys-mamba-resize-kernel.patch new file mode 100644 index 0000000000..d36fe7441c --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/315-armada-xp-linksys-mamba-resize-kernel.patch @@ -0,0 +1,37 @@ +From 258233f00bcd013050efee00c5d9128ef8cd62dd Mon Sep 17 00:00:00 2001 +From: Tad +Date: Fri, 5 Feb 2021 22:32:11 -0500 +Subject: [PATCH] ARM: dts: armada-xp-linksys-mamba: Increase kernel + partition to 4MB + +Signed-off-by: Tad Davanzo +--- + arch/arm/boot/dts/marvell/armada-xp-linksys-mamba.dts | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/arch/arm/boot/dts/marvell/armada-xp-linksys-mamba.dts ++++ b/arch/arm/boot/dts/marvell/armada-xp-linksys-mamba.dts +@@ -454,9 +454,9 @@ + reg = <0xa00000 0x2800000>; /* 40MB */ + }; + +- partition@d00000 { ++ partition@e00000 { + label = "rootfs1"; +- reg = <0xd00000 0x2500000>; /* 37MB */ ++ reg = <0xe00000 0x2400000>; /* 36MB */ + }; + + /* kernel2 overlaps with rootfs2 by design */ +@@ -465,9 +465,9 @@ + reg = <0x3200000 0x2800000>; /* 40MB */ + }; + +- partition@3500000 { ++ partition@3600000 { + label = "rootfs2"; +- reg = <0x3500000 0x2500000>; /* 37MB */ ++ reg = <0x3600000 0x2400000>; /* 36MB */ + }; + + /* diff --git a/lede/target/linux/mvebu/patches-6.6/316-armada-370-dts-fix-crypto-engine.patch b/lede/target/linux/mvebu/patches-6.6/316-armada-370-dts-fix-crypto-engine.patch new file mode 100644 index 0000000000..653c2b0a18 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/316-armada-370-dts-fix-crypto-engine.patch @@ -0,0 +1,29 @@ +--- a/arch/arm/boot/dts/marvell/armada-370.dtsi ++++ b/arch/arm/boot/dts/marvell/armada-370.dtsi +@@ -254,7 +254,7 @@ + clocks = <&gateclk 23>; + clock-names = "cesa0"; + marvell,crypto-srams = <&crypto_sram>; +- marvell,crypto-sram-size = <0x7e0>; ++ marvell,crypto-sram-size = <0x800>; + }; + }; + +@@ -275,12 +275,17 @@ + * cpuidle workaround. + */ + idle-sram@0 { ++ status = "disabled"; + reg = <0x0 0x20>; + }; + }; + }; + }; + ++&coherencyfab { ++ broken-idle; ++}; ++ + /* + * Default UART pinctrl setting without RTS/CTS, can be overwritten on + * board level if a different configuration is used. diff --git a/lede/target/linux/mvebu/patches-6.6/320-arm-dts-armada-370-synology-ds213j-mtd-parts.patch b/lede/target/linux/mvebu/patches-6.6/320-arm-dts-armada-370-synology-ds213j-mtd-parts.patch new file mode 100644 index 0000000000..135952ee5f --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/320-arm-dts-armada-370-synology-ds213j-mtd-parts.patch @@ -0,0 +1,132 @@ +--- a/arch/arm/boot/dts/marvell/armada-370-synology-ds213j.dts ++++ b/arch/arm/boot/dts/marvell/armada-370-synology-ds213j.dts +@@ -31,6 +31,7 @@ + + chosen { + stdout-path = "serial0:115200n8"; ++ append-rootblock = "nullparameter="; /* override the bootloader args */ + }; + + memory@0 { +@@ -94,6 +95,8 @@ + status = "okay"; + phy = <&phy1>; + phy-mode = "sgmii"; ++ nvmem-cells = <&macaddr_vendor_0>; ++ nvmem-cell-names = "mac-address"; + }; + + sata@a0000 { +@@ -175,6 +178,24 @@ + phy1: ethernet-phy@1 { /* Marvell 88E1512 */ + reg = <1>; + }; ++ ++ virtual_flash { ++ compatible = "mtd-concat"; ++ ++ devices = <&mtd_kernel &mtd_gap &mtd_gap2>; ++ ++ partitions { ++ compatible = "fixed-partitions"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ partition@0 { ++ compatible = "openwrt,uimage", "denx,uimage"; ++ label = "firmware"; ++ reg = <0x0 0x0>; ++ }; ++ }; ++ }; + }; + + &pinctrl { +@@ -259,48 +280,50 @@ + reg = <0>; /* Chip select 0 */ + spi-max-frequency = <20000000>; + +- /* +- * Warning! +- * +- * Synology u-boot uses its compiled-in environment +- * and it seems Synology did not care to change u-boot +- * default configuration in order to allow saving a +- * modified environment at a sensible location. So, +- * if you do a 'saveenv' under u-boot, your modified +- * environment will be saved at 1MB after the start +- * of the flash, i.e. in the middle of the uImage. +- * For that reason, it is strongly advised not to +- * change the default environment, unless you know +- * what you are doing. +- */ +- partition@0 { /* u-boot */ +- label = "RedBoot"; +- reg = <0x00000000 0x000c0000>; /* 768KB */ +- }; ++ partitions { ++ compatible = "fixed-partitions"; + +- partition@c0000 { /* uImage */ +- label = "zImage"; +- reg = <0x000c0000 0x002d0000>; /* 2880KB */ +- }; ++ partition@0 { /* u-boot */ ++ label = "u-boot"; ++ reg = <0x00000000 0x000c0000>; /* 768KB */ ++ read-only; ++ }; + +- partition@390000 { /* uInitramfs */ +- label = "rd.gz"; +- reg = <0x00390000 0x00440000>; /* 4250KB */ +- }; ++ mtd_gap: partition@c0000 { /* gap */ ++ label = "gap"; ++ reg = <0x000c0000 0x00040000>; /* 256KB */ ++ }; + +- partition@7d0000 { /* MAC address and serial number */ +- label = "vendor"; +- reg = <0x007d0000 0x00010000>; /* 64KB */ +- }; ++ partition@100000 { /* u-boot-env */ ++ label = "u-boot-env"; ++ reg = <0x00100000 0x00010000>; /* 64KB */ ++ }; + +- partition@7e0000 { +- label = "RedBoot config"; +- reg = <0x007e0000 0x00010000>; /* 64KB */ +- }; ++ mtd_kernel: partition@110000 { ++ label = "kernel"; ++ reg = <0x00110000 0x006c0000>; /* 6912KB */ ++ }; + +- partition@7f0000 { +- label = "FIS directory"; +- reg = <0x007f0000 0x00010000>; /* 64KB */ ++ partition@7d0000 { /* MAC address and serial number */ ++ reg = <0x007d0000 0x00010000>; /* 64KB */ ++ label = "vendor"; ++ read-only; ++ ++ nvmem-layout { ++ compatible = "fixed-layout"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ macaddr_vendor_0: macaddr@0 { ++ reg = <0x0 0x6>; ++ }; ++ }; ++ }; ++ ++ mtd_gap2: partition@7e0000 { ++ label = "gap2"; ++ reg = <0x007e0000 0x00020000>; /* 128KB */ ++ }; + }; + }; + }; diff --git a/lede/target/linux/mvebu/patches-6.6/350-drivers-thermal-step_wise-add-support-for-hysteresis.patch b/lede/target/linux/mvebu/patches-6.6/350-drivers-thermal-step_wise-add-support-for-hysteresis.patch new file mode 100644 index 0000000000..e7332b6df0 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/350-drivers-thermal-step_wise-add-support-for-hysteresis.patch @@ -0,0 +1,65 @@ +From 9685ce100f0d302501117113ef0a526ad1acca1d Mon Sep 17 00:00:00 2001 +From: Ram Chandrasekar +Date: Mon, 7 May 2018 11:54:08 -0600 +Subject: [PATCH] drivers: thermal: step_wise: add support for hysteresis + +Step wise governor increases the mitigation level when the temperature +goes above a threshold and will decrease the mitigation when the +temperature falls below the threshold. If it were a case, where the +temperature hovers around a threshold, the mitigation will be applied +and removed at every iteration. This reaction to the temperature is +inefficient for performance. + +The use of hysteresis temperature could avoid this ping-pong of +mitigation by relaxing the mitigation to happen only when the +temperature goes below this lower hysteresis value. + +Signed-off-by: Ram Chandrasekar +Signed-off-by: Lina Iyer +[forward-ported for Linux 6.6, as stop-gap downstream solution] +Signed-off-by: Daniel Golle +--- + drivers/thermal/gov_step_wise.c | 23 ++++++++++++++++------- + 1 file changed, 16 insertions(+), 7 deletions(-) + +--- a/drivers/thermal/gov_step_wise.c ++++ b/drivers/thermal/gov_step_wise.c +@@ -86,22 +86,31 @@ static void thermal_zone_trip_update(str + struct thermal_instance *instance; + bool throttle = false; + int old_target; ++ int hyst_temp; + + trend = get_tz_trend(tz, trip_id); + +- if (tz->temperature >= trip->temperature) { +- throttle = true; +- trace_thermal_zone_trip(tz, trip_id, trip->type); +- } +- +- dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d]:trend=%d,throttle=%d\n", +- trip_id, trip->type, trip->temperature, trend, throttle); ++ hyst_temp = trip->temperature - trip->hysteresis; ++ dev_dbg(&tz->device, "Trip%d[type=%d,temp=%d,hyst=%d]:trend=%d,throttle=%d\n", ++ trip_id, trip->type, trip->temperature, hyst_temp, trend, throttle); + + list_for_each_entry(instance, &tz->thermal_instances, tz_node) { + if (instance->trip != trip) + continue; + + old_target = instance->target; ++ throttle = false; ++ /* ++ * Lower the mitigation only if the temperature ++ * goes below the hysteresis temperature. ++ */ ++ if (tz->temperature >= trip->temperature || ++ (tz->temperature >= hyst_temp && ++ old_target != THERMAL_NO_TARGET)) { ++ throttle = true; ++ trace_thermal_zone_trip(tz, trip_id, trip->type); ++ } ++ + instance->target = get_target_state(instance, trend, throttle); + dev_dbg(&instance->cdev->device, "old_target=%d, target=%d\n", + old_target, (int)instance->target); diff --git a/lede/target/linux/mvebu/patches-6.6/400-find_active_root.patch b/lede/target/linux/mvebu/patches-6.6/400-find_active_root.patch new file mode 100644 index 0000000000..90164adcd4 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/400-find_active_root.patch @@ -0,0 +1,60 @@ +The WRT1900AC among other Linksys routers uses a dual-firmware layout. +Dynamically rename the active partition to "ubi". + +Signed-off-by: Imre Kaloz + +--- a/drivers/mtd/parsers/ofpart_core.c ++++ b/drivers/mtd/parsers/ofpart_core.c +@@ -38,6 +38,8 @@ static bool node_has_compatible(struct d + return of_get_property(pp, "compatible", NULL); + } + ++static int mangled_rootblock; ++ + static int parse_fixed_partitions(struct mtd_info *master, + const struct mtd_partition **pparts, + struct mtd_part_parser_data *data) +@@ -48,6 +50,7 @@ static int parse_fixed_partitions(struct + struct device_node *mtd_node; + struct device_node *ofpart_node; + const char *partname; ++ const char *owrtpart = "ubi"; + struct device_node *pp; + int nr_parts, i, ret = 0; + bool dedicated = true; +@@ -152,9 +155,13 @@ static int parse_fixed_partitions(struct + parts[i].size = of_read_number(reg + a_cells, s_cells); + parts[i].of_node = pp; + +- partname = of_get_property(pp, "label", &len); +- if (!partname) +- partname = of_get_property(pp, "name", &len); ++ if (mangled_rootblock && (i == mangled_rootblock)) { ++ partname = owrtpart; ++ } else { ++ partname = of_get_property(pp, "label", &len); ++ if (!partname) ++ partname = of_get_property(pp, "name", &len); ++ } + parts[i].name = partname; + + if (of_get_property(pp, "read-only", &len)) +@@ -271,6 +278,18 @@ static int __init ofpart_parser_init(voi + return 0; + } + ++static int __init active_root(char *str) ++{ ++ get_option(&str, &mangled_rootblock); ++ ++ if (!mangled_rootblock) ++ return 1; ++ ++ return 1; ++} ++ ++__setup("mangled_rootblock=", active_root); ++ + static void __exit ofpart_parser_exit(void) + { + deregister_mtd_parser(&ofpart_parser); diff --git a/lede/target/linux/mvebu/patches-6.6/700-mvneta-tx-queue-workaround.patch b/lede/target/linux/mvebu/patches-6.6/700-mvneta-tx-queue-workaround.patch new file mode 100644 index 0000000000..099281e048 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/700-mvneta-tx-queue-workaround.patch @@ -0,0 +1,43 @@ +From: Felix Fietkau +Subject: mvneta: tx queue workaround + +The hardware queue scheduling is apparently configured with fixed +priorities, which creates a nasty fairness issue where traffic from one +CPU can starve traffic from all other CPUs. + +Work around this issue by forcing all tx packets to go through one CPU, +until this issue is fixed properly. + +Ref: https://github.com/openwrt/openwrt/issues/5411 + +Signed-off-by: Felix Fietkau +--- +--- a/drivers/net/ethernet/marvell/mvneta.c ++++ b/drivers/net/ethernet/marvell/mvneta.c +@@ -5294,6 +5294,16 @@ static int mvneta_setup_tc(struct net_de + } + } + ++#ifndef CONFIG_ARM64 ++static u16 mvneta_select_queue(struct net_device *dev, struct sk_buff *skb, ++ struct net_device *sb_dev) ++{ ++ /* XXX: hardware queue scheduling is broken, ++ * use only one queue until it is fixed */ ++ return 0; ++} ++#endif ++ + static const struct net_device_ops mvneta_netdev_ops = { + .ndo_open = mvneta_open, + .ndo_stop = mvneta_stop, +@@ -5304,6 +5314,9 @@ static const struct net_device_ops mvnet + .ndo_fix_features = mvneta_fix_features, + .ndo_get_stats64 = mvneta_get_stats64, + .ndo_eth_ioctl = mvneta_ioctl, ++#ifndef CONFIG_ARM64 ++ .ndo_select_queue = mvneta_select_queue, ++#endif + .ndo_bpf = mvneta_xdp, + .ndo_xdp_xmit = mvneta_xdp_xmit, + .ndo_setup_tc = mvneta_setup_tc, diff --git a/lede/target/linux/mvebu/patches-6.6/701-mvpp2-read-mac-address-from-nvmem.patch b/lede/target/linux/mvebu/patches-6.6/701-mvpp2-read-mac-address-from-nvmem.patch new file mode 100644 index 0000000000..69ee10c3f2 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/701-mvpp2-read-mac-address-from-nvmem.patch @@ -0,0 +1,27 @@ +From: Tobias Schramm +Subject: mvpp2: support fetching mac address from nvmem + +The mvpp2 driver did not query nvmem for hardware mac addresses. This +patch adds querying of mac addresses stored in nvmem cells as a further +fallback option before assigning a random address. +Purposely added separately to fwnode_get_mac_address() above to maintain +existing behaviour with builtin adapter mac address still taking +precedence. + +Signed-off-by: Tobias Schramm +--- +--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c ++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +@@ -6156,6 +6156,12 @@ static int mvpp2_port_copy_mac_addr(stru + return 0; + } + ++ if (!of_get_mac_address(to_of_node(fwnode), hw_mac_addr)) { ++ *mac_from = "nvmem cell"; ++ eth_hw_addr_set(dev, hw_mac_addr); ++ return 0; ++ } ++ + *mac_from = "random"; + eth_hw_addr_random(dev); + diff --git a/lede/target/linux/mvebu/patches-6.6/800-cpuidle-mvebu-indicate-failure-to-enter-deeper-sleep.patch b/lede/target/linux/mvebu/patches-6.6/800-cpuidle-mvebu-indicate-failure-to-enter-deeper-sleep.patch new file mode 100644 index 0000000000..5df5aca5dc --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/800-cpuidle-mvebu-indicate-failure-to-enter-deeper-sleep.patch @@ -0,0 +1,40 @@ +From c28b2d367da8a471482e6a4aa8337ab6369a80c2 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Sat, 3 Oct 2015 09:13:05 +0100 +Subject: cpuidle: mvebu: indicate failure to enter deeper sleep states + +The cpuidle ->enter method expects the return value to be the sleep +state we entered. Returning negative numbers or other codes is not +permissible since coupled CPU idle was merged. + +At least some of the mvebu_v7_cpu_suspend() implementations return the +value from cpu_suspend(), which returns zero if the CPU vectors back +into the kernel via cpu_resume() (the success case), or the non-zero +return value of the suspend actor, or one (failure cases). + +We do not want to be returning the failure case value back to CPU idle +as that indicates that we successfully entered one of the deeper idle +states. Always return zero instead, indicating that we slept for the +shortest amount of time. + +Signed-off-by: Russell King +--- + drivers/cpuidle/cpuidle-mvebu-v7.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/cpuidle/cpuidle-mvebu-v7.c ++++ b/drivers/cpuidle/cpuidle-mvebu-v7.c +@@ -42,8 +42,12 @@ static __cpuidle int mvebu_v7_enter_idle + + cpu_pm_exit(); + ++ /* ++ * If we failed to enter the desired state, indicate that we ++ * slept lightly. ++ */ + if (ret) +- return ret; ++ return 0; + + return index; + } diff --git a/lede/target/linux/mvebu/patches-6.6/801-pci-mvebu-time-out-reset-on-link-up.patch b/lede/target/linux/mvebu/patches-6.6/801-pci-mvebu-time-out-reset-on-link-up.patch new file mode 100644 index 0000000000..f1832c8940 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/801-pci-mvebu-time-out-reset-on-link-up.patch @@ -0,0 +1,60 @@ +From 287b9df160b6159f8d385424904f8bac501280c1 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Sat, 9 Jul 2016 10:58:16 +0100 +Subject: pci: mvebu: time out reset on link up + +If the port reports that the link is up while we are resetting, there's +little point in waiting for the full duration. + +Signed-off-by: Russell King +--- + drivers/pci/controller/pci-mvebu.c | 20 ++++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +--- a/drivers/pci/controller/pci-mvebu.c ++++ b/drivers/pci/controller/pci-mvebu.c +@@ -1397,6 +1397,7 @@ static int mvebu_pcie_powerup(struct mve + + if (port->reset_gpio) { + u32 reset_udelay = PCI_PM_D3COLD_WAIT * 1000; ++ unsigned int i; + + of_property_read_u32(port->dn, "reset-delay-us", + &reset_udelay); +@@ -1404,7 +1405,13 @@ static int mvebu_pcie_powerup(struct mve + udelay(100); + + gpiod_set_value_cansleep(port->reset_gpio, 0); +- msleep(reset_udelay / 1000); ++ for (i = 0; i < reset_udelay; i += 1000) { ++ if (mvebu_pcie_link_up(port)) ++ break; ++ msleep(1); ++ } ++ ++ printk("%s: reset completed in %dus\n", port->name, i); + } + + return 0; +@@ -1521,15 +1528,16 @@ static int mvebu_pcie_probe(struct platf + if (!child) + continue; + +- ret = mvebu_pcie_powerup(port); +- if (ret < 0) +- continue; +- + port->base = mvebu_pcie_map_registers(pdev, child, port); + if (IS_ERR(port->base)) { + dev_err(dev, "%s: cannot map registers\n", port->name); + port->base = NULL; +- mvebu_pcie_powerdown(port); ++ continue; ++ } ++ ++ ret = mvebu_pcie_powerup(port); ++ if (ret < 0) { ++ port->base = NULL; + continue; + } + diff --git a/lede/target/linux/mvebu/patches-6.6/820-v6.11-01-dt-bindings-firmware-add-cznic-turris-omnia-mcu-bind.patch b/lede/target/linux/mvebu/patches-6.6/820-v6.11-01-dt-bindings-firmware-add-cznic-turris-omnia-mcu-bind.patch new file mode 100644 index 0000000000..4d6d8e82c2 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/820-v6.11-01-dt-bindings-firmware-add-cznic-turris-omnia-mcu-bind.patch @@ -0,0 +1,125 @@ +From cdfed4d05780450817ef96567e2cd8d355ca9e70 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 1 Jul 2024 13:30:03 +0200 +Subject: [PATCH 01/11] dt-bindings: firmware: add cznic,turris-omnia-mcu + binding +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add binding for cznic,turris-omnia-mcu, the device-tree node +representing the system-controller features provided by the MCU on the +Turris Omnia router. + +Signed-off-by: Marek Behún +Reviewed-by: Krzysztof Kozlowski +Reviewed-by: Conor Dooley +Reviewed-by: Andy Shevchenko +Acked-by: Bartosz Golaszewski +Link: https://lore.kernel.org/r/20240701113010.16447-2-kabel@kernel.org +Signed-off-by: Arnd Bergmann +--- + .../firmware/cznic,turris-omnia-mcu.yaml | 86 +++++++++++++++++++ + MAINTAINERS | 1 + + 2 files changed, 87 insertions(+) + create mode 100644 Documentation/devicetree/bindings/firmware/cznic,turris-omnia-mcu.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/firmware/cznic,turris-omnia-mcu.yaml +@@ -0,0 +1,86 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/firmware/cznic,turris-omnia-mcu.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: CZ.NIC's Turris Omnia MCU ++ ++maintainers: ++ - Marek Behún ++ ++description: ++ The MCU on Turris Omnia acts as a system controller providing additional ++ GPIOs, interrupts, watchdog, system power off and wakeup configuration. ++ ++properties: ++ compatible: ++ const: cznic,turris-omnia-mcu ++ ++ reg: ++ description: MCU I2C slave address ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 1 ++ ++ interrupt-controller: true ++ ++ '#interrupt-cells': ++ const: 2 ++ description: | ++ The first cell specifies the interrupt number (0 to 63), the second cell ++ specifies interrupt type (which can be one of IRQ_TYPE_EDGE_RISING, ++ IRQ_TYPE_EDGE_FALLING or IRQ_TYPE_EDGE_BOTH). ++ The interrupt numbers correspond sequentially to GPIO numbers, taking the ++ GPIO banks into account: ++ IRQ number GPIO bank GPIO pin within bank ++ 0 - 15 0 0 - 15 ++ 16 - 47 1 0 - 31 ++ 48 - 63 2 0 - 15 ++ There are several exceptions: ++ IRQ number meaning ++ 11 LED panel brightness changed by button press ++ 13 TRNG entropy ready ++ 14 ECDSA message signature computation done ++ ++ gpio-controller: true ++ ++ '#gpio-cells': ++ const: 3 ++ description: ++ The first cell is bank number (0, 1 or 2), the second cell is pin number ++ within the bank (0 to 15 for banks 0 and 2, 0 to 31 for bank 1), and the ++ third cell specifies consumer flags. ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ - interrupt-controller ++ - gpio-controller ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ ++ i2c { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ system-controller@2a { ++ compatible = "cznic,turris-omnia-mcu"; ++ reg = <0x2a>; ++ ++ interrupt-parent = <&gpio1>; ++ interrupts = <11 IRQ_TYPE_NONE>; ++ ++ gpio-controller; ++ #gpio-cells = <3>; ++ ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ }; +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -2104,6 +2104,7 @@ F: Documentation/ABI/testing/sysfs-bus-m + F: Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm + F: Documentation/devicetree/bindings/bus/moxtet.txt + F: Documentation/devicetree/bindings/firmware/cznic,turris-mox-rwtm.txt ++F: Documentation/devicetree/bindings/firmware/cznic,turris-omnia-mcu.yaml + F: Documentation/devicetree/bindings/gpio/gpio-moxtet.txt + F: Documentation/devicetree/bindings/leds/cznic,turris-omnia-leds.yaml + F: Documentation/devicetree/bindings/watchdog/armada-37xx-wdt.txt diff --git a/lede/target/linux/mvebu/patches-6.6/820-v6.11-02-platform-cznic-Add-preliminary-support-for-Turris-Om.patch b/lede/target/linux/mvebu/patches-6.6/820-v6.11-02-platform-cznic-Add-preliminary-support-for-Turris-Om.patch new file mode 100644 index 0000000000..72bd18d144 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/820-v6.11-02-platform-cznic-Add-preliminary-support-for-Turris-Om.patch @@ -0,0 +1,922 @@ +From 4a63f684c8badfc43f384df2291ed2566909a3bc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 1 Jul 2024 13:30:04 +0200 +Subject: [PATCH 02/11] platform: cznic: Add preliminary support for Turris + Omnia MCU +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add the basic skeleton for a new platform driver for the microcontroller +found on the Turris Omnia board. + +Signed-off-by: Marek Behún +Reviewed-by: Andy Shevchenko +Acked-by: Bartosz Golaszewski +Link: https://lore.kernel.org/r/20240701113010.16447-3-kabel@kernel.org +Signed-off-by: Arnd Bergmann +--- + .../sysfs-bus-i2c-devices-turris-omnia-mcu | 81 ++++ + MAINTAINERS | 3 + + drivers/platform/Kconfig | 2 + + drivers/platform/Makefile | 1 + + drivers/platform/cznic/Kconfig | 25 ++ + drivers/platform/cznic/Makefile | 4 + + .../platform/cznic/turris-omnia-mcu-base.c | 393 ++++++++++++++++++ + drivers/platform/cznic/turris-omnia-mcu.h | 74 ++++ + include/linux/turris-omnia-mcu-interface.h | 249 +++++++++++ + 9 files changed, 832 insertions(+) + create mode 100644 Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu + create mode 100644 drivers/platform/cznic/Kconfig + create mode 100644 drivers/platform/cznic/Makefile + create mode 100644 drivers/platform/cznic/turris-omnia-mcu-base.c + create mode 100644 drivers/platform/cznic/turris-omnia-mcu.h + create mode 100644 include/linux/turris-omnia-mcu-interface.h + +--- /dev/null ++++ b/Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu +@@ -0,0 +1,81 @@ ++What: /sys/bus/i2c/devices//board_revision ++Date: September 2024 ++KernelVersion: 6.11 ++Contact: Marek Behún ++Description: (RO) Contains board revision number. ++ ++ Only available if board information is burned in the MCU (older ++ revisions have board information burned in the ATSHA204-A chip). ++ ++ Format: %u. ++ ++What: /sys/bus/i2c/devices//first_mac_address ++Date: September 2024 ++KernelVersion: 6.11 ++Contact: Marek Behún ++Description: (RO) Contains device first MAC address. Each Turris Omnia is ++ allocated 3 MAC addresses. The two additional addresses are ++ computed from the first one by incrementing it. ++ ++ Only available if board information is burned in the MCU (older ++ revisions have board information burned in the ATSHA204-A chip). ++ ++ Format: %pM. ++ ++What: /sys/bus/i2c/devices//fw_features ++Date: September 2024 ++KernelVersion: 6.11 ++Contact: Marek Behún ++Description: (RO) Newer versions of the microcontroller firmware report the ++ features they support. These can be read from this file. If the ++ MCU firmware is too old, this file reads 0x0. ++ ++ Format: 0x%x. ++ ++What: /sys/bus/i2c/devices//fw_version_hash_application ++Date: September 2024 ++KernelVersion: 6.11 ++Contact: Marek Behún ++Description: (RO) Contains the version hash (commit hash) of the application ++ part of the microcontroller firmware. ++ ++ Format: %s. ++ ++What: /sys/bus/i2c/devices//fw_version_hash_bootloader ++Date: September 2024 ++KernelVersion: 6.11 ++Contact: Marek Behún ++Description: (RO) Contains the version hash (commit hash) of the bootloader ++ part of the microcontroller firmware. ++ ++ Format: %s. ++ ++What: /sys/bus/i2c/devices//mcu_type ++Date: September 2024 ++KernelVersion: 6.11 ++Contact: Marek Behún ++Description: (RO) Contains the microcontroller type (STM32, GD32, MKL). ++ ++ Format: %s. ++ ++What: /sys/bus/i2c/devices//reset_selector ++Date: September 2024 ++KernelVersion: 6.11 ++Contact: Marek Behún ++Description: (RO) Contains the selected factory reset level, determined by ++ how long the rear reset button was held by the user during board ++ reset. ++ ++ Format: %i. ++ ++What: /sys/bus/i2c/devices//serial_number ++Date: September 2024 ++KernelVersion: 6.11 ++Contact: Marek Behún ++Description: (RO) Contains the 64-bit board serial number in hexadecimal ++ format. ++ ++ Only available if board information is burned in the MCU (older ++ revisions have board information burned in the ATSHA204-A chip). ++ ++ Format: %016X. +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -2100,6 +2100,7 @@ M: Marek Behún + S: Maintained + W: https://www.turris.cz/ + F: Documentation/ABI/testing/debugfs-moxtet ++F: Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu + F: Documentation/ABI/testing/sysfs-bus-moxtet-devices + F: Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm + F: Documentation/devicetree/bindings/bus/moxtet.txt +@@ -2113,10 +2114,12 @@ F: drivers/firmware/turris-mox-rwtm.c + F: drivers/gpio/gpio-moxtet.c + F: drivers/leds/leds-turris-omnia.c + F: drivers/mailbox/armada-37xx-rwtm-mailbox.c ++F: drivers/platform/cznic/ + F: drivers/watchdog/armada_37xx_wdt.c + F: include/dt-bindings/bus/moxtet.h + F: include/linux/armada-37xx-rwtm-mailbox.h + F: include/linux/moxtet.h ++F: include/linux/turris-omnia-mcu-interface.h + + ARM/FARADAY FA526 PORT + M: Hans Ulli Kroll +--- a/drivers/platform/Kconfig ++++ b/drivers/platform/Kconfig +@@ -7,6 +7,8 @@ source "drivers/platform/goldfish/Kconfi + + source "drivers/platform/chrome/Kconfig" + ++source "drivers/platform/cznic/Kconfig" ++ + source "drivers/platform/mellanox/Kconfig" + + source "drivers/platform/olpc/Kconfig" +--- a/drivers/platform/Makefile ++++ b/drivers/platform/Makefile +@@ -10,5 +10,6 @@ obj-$(CONFIG_MIPS) += mips/ + obj-$(CONFIG_OLPC_EC) += olpc/ + obj-$(CONFIG_GOLDFISH) += goldfish/ + obj-$(CONFIG_CHROME_PLATFORMS) += chrome/ ++obj-$(CONFIG_CZNIC_PLATFORMS) += cznic/ + obj-$(CONFIG_SURFACE_PLATFORMS) += surface/ + obj-$(CONFIG_MIKROTIK) += mikrotik/ +--- /dev/null ++++ b/drivers/platform/cznic/Kconfig +@@ -0,0 +1,25 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++# ++# For a description of the syntax of this configuration file, ++# see Documentation/kbuild/kconfig-language.rst. ++# ++ ++menuconfig CZNIC_PLATFORMS ++ bool "Platform support for CZ.NIC's Turris hardware" ++ help ++ Say Y here to be able to choose driver support for CZ.NIC's Turris ++ devices. This option alone does not add any kernel code. ++ ++if CZNIC_PLATFORMS ++ ++config TURRIS_OMNIA_MCU ++ tristate "Turris Omnia MCU driver" ++ depends on MACH_ARMADA_38X || COMPILE_TEST ++ depends on I2C ++ help ++ Say Y here to add support for the features implemented by the ++ microcontroller on the CZ.NIC's Turris Omnia SOHO router. ++ To compile this driver as a module, choose M here; the module will be ++ called turris-omnia-mcu. ++ ++endif # CZNIC_PLATFORMS +--- /dev/null ++++ b/drivers/platform/cznic/Makefile +@@ -0,0 +1,4 @@ ++# SPDX-License-Identifier: GPL-2.0-only ++ ++obj-$(CONFIG_TURRIS_OMNIA_MCU) += turris-omnia-mcu.o ++turris-omnia-mcu-y := turris-omnia-mcu-base.o +--- /dev/null ++++ b/drivers/platform/cznic/turris-omnia-mcu-base.c +@@ -0,0 +1,393 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * CZ.NIC's Turris Omnia MCU driver ++ * ++ * 2024 by Marek Behún ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "turris-omnia-mcu.h" ++ ++#define OMNIA_FW_VERSION_LEN 20 ++#define OMNIA_FW_VERSION_HEX_LEN (2 * OMNIA_FW_VERSION_LEN + 1) ++#define OMNIA_BOARD_INFO_LEN 16 ++ ++int omnia_cmd_write_read(const struct i2c_client *client, ++ void *cmd, unsigned int cmd_len, ++ void *reply, unsigned int reply_len) ++{ ++ struct i2c_msg msgs[2]; ++ int ret, num; ++ ++ msgs[0].addr = client->addr; ++ msgs[0].flags = 0; ++ msgs[0].len = cmd_len; ++ msgs[0].buf = cmd; ++ num = 1; ++ ++ if (reply_len) { ++ msgs[1].addr = client->addr; ++ msgs[1].flags = I2C_M_RD; ++ msgs[1].len = reply_len; ++ msgs[1].buf = reply; ++ num++; ++ } ++ ++ ret = i2c_transfer(client->adapter, msgs, num); ++ if (ret < 0) ++ return ret; ++ if (ret != num) ++ return -EIO; ++ ++ return 0; ++} ++ ++static int omnia_get_version_hash(struct omnia_mcu *mcu, bool bootloader, ++ char version[static OMNIA_FW_VERSION_HEX_LEN]) ++{ ++ u8 reply[OMNIA_FW_VERSION_LEN]; ++ char *p; ++ int err; ++ ++ err = omnia_cmd_read(mcu->client, ++ bootloader ? OMNIA_CMD_GET_FW_VERSION_BOOT ++ : OMNIA_CMD_GET_FW_VERSION_APP, ++ reply, sizeof(reply)); ++ if (err) ++ return err; ++ ++ p = bin2hex(version, reply, OMNIA_FW_VERSION_LEN); ++ *p = '\0'; ++ ++ return 0; ++} ++ ++static ssize_t fw_version_hash_show(struct device *dev, char *buf, ++ bool bootloader) ++{ ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ char version[OMNIA_FW_VERSION_HEX_LEN]; ++ int err; ++ ++ err = omnia_get_version_hash(mcu, bootloader, version); ++ if (err) ++ return err; ++ ++ return sysfs_emit(buf, "%s\n", version); ++} ++ ++static ssize_t fw_version_hash_application_show(struct device *dev, ++ struct device_attribute *a, ++ char *buf) ++{ ++ return fw_version_hash_show(dev, buf, false); ++} ++static DEVICE_ATTR_RO(fw_version_hash_application); ++ ++static ssize_t fw_version_hash_bootloader_show(struct device *dev, ++ struct device_attribute *a, ++ char *buf) ++{ ++ return fw_version_hash_show(dev, buf, true); ++} ++static DEVICE_ATTR_RO(fw_version_hash_bootloader); ++ ++static ssize_t fw_features_show(struct device *dev, struct device_attribute *a, ++ char *buf) ++{ ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ ++ return sysfs_emit(buf, "0x%x\n", mcu->features); ++} ++static DEVICE_ATTR_RO(fw_features); ++ ++static ssize_t mcu_type_show(struct device *dev, struct device_attribute *a, ++ char *buf) ++{ ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ ++ return sysfs_emit(buf, "%s\n", mcu->type); ++} ++static DEVICE_ATTR_RO(mcu_type); ++ ++static ssize_t reset_selector_show(struct device *dev, ++ struct device_attribute *a, char *buf) ++{ ++ u8 reply; ++ int err; ++ ++ err = omnia_cmd_read_u8(to_i2c_client(dev), OMNIA_CMD_GET_RESET, ++ &reply); ++ if (err) ++ return err; ++ ++ return sysfs_emit(buf, "%d\n", reply); ++} ++static DEVICE_ATTR_RO(reset_selector); ++ ++static ssize_t serial_number_show(struct device *dev, ++ struct device_attribute *a, char *buf) ++{ ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ ++ return sysfs_emit(buf, "%016llX\n", mcu->board_serial_number); ++} ++static DEVICE_ATTR_RO(serial_number); ++ ++static ssize_t first_mac_address_show(struct device *dev, ++ struct device_attribute *a, char *buf) ++{ ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ ++ return sysfs_emit(buf, "%pM\n", mcu->board_first_mac); ++} ++static DEVICE_ATTR_RO(first_mac_address); ++ ++static ssize_t board_revision_show(struct device *dev, ++ struct device_attribute *a, char *buf) ++{ ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ ++ return sysfs_emit(buf, "%u\n", mcu->board_revision); ++} ++static DEVICE_ATTR_RO(board_revision); ++ ++static struct attribute *omnia_mcu_base_attrs[] = { ++ &dev_attr_fw_version_hash_application.attr, ++ &dev_attr_fw_version_hash_bootloader.attr, ++ &dev_attr_fw_features.attr, ++ &dev_attr_mcu_type.attr, ++ &dev_attr_reset_selector.attr, ++ &dev_attr_serial_number.attr, ++ &dev_attr_first_mac_address.attr, ++ &dev_attr_board_revision.attr, ++ NULL ++}; ++ ++static umode_t omnia_mcu_base_attrs_visible(struct kobject *kobj, ++ struct attribute *a, int n) ++{ ++ struct device *dev = kobj_to_dev(kobj); ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ ++ if ((a == &dev_attr_serial_number.attr || ++ a == &dev_attr_first_mac_address.attr || ++ a == &dev_attr_board_revision.attr) && ++ !(mcu->features & OMNIA_FEAT_BOARD_INFO)) ++ return 0; ++ ++ return a->mode; ++} ++ ++static const struct attribute_group omnia_mcu_base_group = { ++ .attrs = omnia_mcu_base_attrs, ++ .is_visible = omnia_mcu_base_attrs_visible, ++}; ++ ++static const struct attribute_group *omnia_mcu_groups[] = { ++ &omnia_mcu_base_group, ++ NULL ++}; ++ ++static void omnia_mcu_print_version_hash(struct omnia_mcu *mcu, bool bootloader) ++{ ++ const char *type = bootloader ? "bootloader" : "application"; ++ struct device *dev = &mcu->client->dev; ++ char version[OMNIA_FW_VERSION_HEX_LEN]; ++ int err; ++ ++ err = omnia_get_version_hash(mcu, bootloader, version); ++ if (err) { ++ dev_err(dev, "Cannot read MCU %s firmware version: %d\n", ++ type, err); ++ return; ++ } ++ ++ dev_info(dev, "MCU %s firmware version hash: %s\n", type, version); ++} ++ ++static const char *omnia_status_to_mcu_type(u16 status) ++{ ++ switch (status & OMNIA_STS_MCU_TYPE_MASK) { ++ case OMNIA_STS_MCU_TYPE_STM32: ++ return "STM32"; ++ case OMNIA_STS_MCU_TYPE_GD32: ++ return "GD32"; ++ case OMNIA_STS_MCU_TYPE_MKL: ++ return "MKL"; ++ default: ++ return "unknown"; ++ } ++} ++ ++static void omnia_info_missing_feature(struct device *dev, const char *feature) ++{ ++ dev_info(dev, ++ "Your board's MCU firmware does not support the %s feature.\n", ++ feature); ++} ++ ++static int omnia_mcu_read_features(struct omnia_mcu *mcu) ++{ ++ static const struct { ++ u16 mask; ++ const char *name; ++ } features[] = { ++#define _DEF_FEAT(_n, _m) { OMNIA_FEAT_ ## _n, _m } ++ _DEF_FEAT(EXT_CMDS, "extended control and status"), ++ _DEF_FEAT(WDT_PING, "watchdog pinging"), ++ _DEF_FEAT(LED_STATE_EXT_MASK, "peripheral LED pins reading"), ++ _DEF_FEAT(NEW_INT_API, "new interrupt API"), ++ _DEF_FEAT(POWEROFF_WAKEUP, "poweroff and wakeup"), ++ _DEF_FEAT(TRNG, "true random number generator"), ++#undef _DEF_FEAT ++ }; ++ struct i2c_client *client = mcu->client; ++ struct device *dev = &client->dev; ++ bool suggest_fw_upgrade = false; ++ u16 status; ++ int err; ++ ++ /* status word holds MCU type, which we need below */ ++ err = omnia_cmd_read_u16(client, OMNIA_CMD_GET_STATUS_WORD, &status); ++ if (err) ++ return err; ++ ++ /* ++ * Check whether MCU firmware supports the OMNIA_CMD_GET_FEATURES ++ * command. ++ */ ++ if (status & OMNIA_STS_FEATURES_SUPPORTED) { ++ /* try read 32-bit features */ ++ err = omnia_cmd_read_u32(client, OMNIA_CMD_GET_FEATURES, ++ &mcu->features); ++ if (err) { ++ /* try read 16-bit features */ ++ u16 features16; ++ ++ err = omnia_cmd_read_u16(client, OMNIA_CMD_GET_FEATURES, ++ &features16); ++ if (err) ++ return err; ++ ++ mcu->features = features16; ++ } else { ++ if (mcu->features & OMNIA_FEAT_FROM_BIT_16_INVALID) ++ mcu->features &= GENMASK(15, 0); ++ } ++ } else { ++ dev_info(dev, ++ "Your board's MCU firmware does not support feature reading.\n"); ++ suggest_fw_upgrade = true; ++ } ++ ++ mcu->type = omnia_status_to_mcu_type(status); ++ dev_info(dev, "MCU type %s%s\n", mcu->type, ++ (mcu->features & OMNIA_FEAT_PERIPH_MCU) ? ++ ", with peripheral resets wired" : ""); ++ ++ omnia_mcu_print_version_hash(mcu, true); ++ ++ if (mcu->features & OMNIA_FEAT_BOOTLOADER) ++ dev_warn(dev, ++ "MCU is running bootloader firmware. Was firmware upgrade interrupted?\n"); ++ else ++ omnia_mcu_print_version_hash(mcu, false); ++ ++ for (unsigned int i = 0; i < ARRAY_SIZE(features); i++) { ++ if (mcu->features & features[i].mask) ++ continue; ++ ++ omnia_info_missing_feature(dev, features[i].name); ++ suggest_fw_upgrade = true; ++ } ++ ++ if (suggest_fw_upgrade) ++ dev_info(dev, ++ "Consider upgrading MCU firmware with the omnia-mcutool utility.\n"); ++ ++ return 0; ++} ++ ++static int omnia_mcu_read_board_info(struct omnia_mcu *mcu) ++{ ++ u8 reply[1 + OMNIA_BOARD_INFO_LEN]; ++ int err; ++ ++ err = omnia_cmd_read(mcu->client, OMNIA_CMD_BOARD_INFO_GET, reply, ++ sizeof(reply)); ++ if (err) ++ return err; ++ ++ if (reply[0] != OMNIA_BOARD_INFO_LEN) ++ return -EIO; ++ ++ mcu->board_serial_number = get_unaligned_le64(&reply[1]); ++ ++ /* we can't use ether_addr_copy() because reply is not u16-aligned */ ++ memcpy(mcu->board_first_mac, &reply[9], sizeof(mcu->board_first_mac)); ++ ++ mcu->board_revision = reply[15]; ++ ++ return 0; ++} ++ ++static int omnia_mcu_probe(struct i2c_client *client) ++{ ++ struct device *dev = &client->dev; ++ struct omnia_mcu *mcu; ++ int err; ++ ++ if (!client->irq) ++ return dev_err_probe(dev, -EINVAL, "IRQ resource not found\n"); ++ ++ mcu = devm_kzalloc(dev, sizeof(*mcu), GFP_KERNEL); ++ if (!mcu) ++ return -ENOMEM; ++ ++ mcu->client = client; ++ i2c_set_clientdata(client, mcu); ++ ++ err = omnia_mcu_read_features(mcu); ++ if (err) ++ return dev_err_probe(dev, err, ++ "Cannot determine MCU supported features\n"); ++ ++ if (mcu->features & OMNIA_FEAT_BOARD_INFO) { ++ err = omnia_mcu_read_board_info(mcu); ++ if (err) ++ return dev_err_probe(dev, err, ++ "Cannot read board info\n"); ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id of_omnia_mcu_match[] = { ++ { .compatible = "cznic,turris-omnia-mcu" }, ++ {} ++}; ++ ++static struct i2c_driver omnia_mcu_driver = { ++ .probe = omnia_mcu_probe, ++ .driver = { ++ .name = "turris-omnia-mcu", ++ .of_match_table = of_omnia_mcu_match, ++ .dev_groups = omnia_mcu_groups, ++ }, ++}; ++module_i2c_driver(omnia_mcu_driver); ++ ++MODULE_AUTHOR("Marek Behun "); ++MODULE_DESCRIPTION("CZ.NIC's Turris Omnia MCU"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/platform/cznic/turris-omnia-mcu.h +@@ -0,0 +1,74 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * CZ.NIC's Turris Omnia MCU driver ++ * ++ * 2024 by Marek Behún ++ */ ++ ++#ifndef __TURRIS_OMNIA_MCU_H ++#define __TURRIS_OMNIA_MCU_H ++ ++#include ++#include ++#include ++ ++struct i2c_client; ++ ++struct omnia_mcu { ++ struct i2c_client *client; ++ const char *type; ++ u32 features; ++ ++ /* board information */ ++ u64 board_serial_number; ++ u8 board_first_mac[ETH_ALEN]; ++ u8 board_revision; ++}; ++ ++int omnia_cmd_write_read(const struct i2c_client *client, ++ void *cmd, unsigned int cmd_len, ++ void *reply, unsigned int reply_len); ++ ++static inline int omnia_cmd_read(const struct i2c_client *client, u8 cmd, ++ void *reply, unsigned int len) ++{ ++ return omnia_cmd_write_read(client, &cmd, 1, reply, len); ++} ++ ++static inline int omnia_cmd_read_u32(const struct i2c_client *client, u8 cmd, ++ u32 *dst) ++{ ++ __le32 reply; ++ int err; ++ ++ err = omnia_cmd_read(client, cmd, &reply, sizeof(reply)); ++ if (err) ++ return err; ++ ++ *dst = le32_to_cpu(reply); ++ ++ return 0; ++} ++ ++static inline int omnia_cmd_read_u16(const struct i2c_client *client, u8 cmd, ++ u16 *dst) ++{ ++ __le16 reply; ++ int err; ++ ++ err = omnia_cmd_read(client, cmd, &reply, sizeof(reply)); ++ if (err) ++ return err; ++ ++ *dst = le16_to_cpu(reply); ++ ++ return 0; ++} ++ ++static inline int omnia_cmd_read_u8(const struct i2c_client *client, u8 cmd, ++ u8 *reply) ++{ ++ return omnia_cmd_read(client, cmd, reply, sizeof(*reply)); ++} ++ ++#endif /* __TURRIS_OMNIA_MCU_H */ +--- /dev/null ++++ b/include/linux/turris-omnia-mcu-interface.h +@@ -0,0 +1,249 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * CZ.NIC's Turris Omnia MCU I2C interface commands definitions ++ * ++ * 2024 by Marek Behún ++ */ ++ ++#ifndef __TURRIS_OMNIA_MCU_INTERFACE_H ++#define __TURRIS_OMNIA_MCU_INTERFACE_H ++ ++#include ++#include ++ ++enum omnia_commands_e { ++ OMNIA_CMD_GET_STATUS_WORD = 0x01, /* slave sends status word back */ ++ OMNIA_CMD_GENERAL_CONTROL = 0x02, ++ OMNIA_CMD_LED_MODE = 0x03, /* default/user */ ++ OMNIA_CMD_LED_STATE = 0x04, /* LED on/off */ ++ OMNIA_CMD_LED_COLOR = 0x05, /* LED number + RED + GREEN + BLUE */ ++ OMNIA_CMD_USER_VOLTAGE = 0x06, ++ OMNIA_CMD_SET_BRIGHTNESS = 0x07, ++ OMNIA_CMD_GET_BRIGHTNESS = 0x08, ++ OMNIA_CMD_GET_RESET = 0x09, ++ OMNIA_CMD_GET_FW_VERSION_APP = 0x0A, /* 20B git hash number */ ++ OMNIA_CMD_SET_WATCHDOG_STATE = 0x0B, /* 0 - disable ++ * 1 - enable / ping ++ * after boot watchdog is started ++ * with 2 minutes timeout ++ */ ++ ++ /* OMNIA_CMD_WATCHDOG_STATUS = 0x0C, not implemented anymore */ ++ ++ OMNIA_CMD_GET_WATCHDOG_STATE = 0x0D, ++ OMNIA_CMD_GET_FW_VERSION_BOOT = 0x0E, /* 20B Git hash number */ ++ OMNIA_CMD_GET_FW_CHECKSUM = 0x0F, /* 4B length, 4B checksum */ ++ ++ /* available if FEATURES_SUPPORTED bit set in status word */ ++ OMNIA_CMD_GET_FEATURES = 0x10, ++ ++ /* available if EXT_CMD bit set in features */ ++ OMNIA_CMD_GET_EXT_STATUS_DWORD = 0x11, ++ OMNIA_CMD_EXT_CONTROL = 0x12, ++ OMNIA_CMD_GET_EXT_CONTROL_STATUS = 0x13, ++ ++ /* available if NEW_INT_API bit set in features */ ++ OMNIA_CMD_GET_INT_AND_CLEAR = 0x14, ++ OMNIA_CMD_GET_INT_MASK = 0x15, ++ OMNIA_CMD_SET_INT_MASK = 0x16, ++ ++ /* available if FLASHING bit set in features */ ++ OMNIA_CMD_FLASH = 0x19, ++ ++ /* available if WDT_PING bit set in features */ ++ OMNIA_CMD_SET_WDT_TIMEOUT = 0x20, ++ OMNIA_CMD_GET_WDT_TIMELEFT = 0x21, ++ ++ /* available if POWEROFF_WAKEUP bit set in features */ ++ OMNIA_CMD_SET_WAKEUP = 0x22, ++ OMNIA_CMD_GET_UPTIME_AND_WAKEUP = 0x23, ++ OMNIA_CMD_POWER_OFF = 0x24, ++ ++ /* available if USB_OVC_PROT_SETTING bit set in features */ ++ OMNIA_CMD_SET_USB_OVC_PROT = 0x25, ++ OMNIA_CMD_GET_USB_OVC_PROT = 0x26, ++ ++ /* available if TRNG bit set in features */ ++ OMNIA_CMD_TRNG_COLLECT_ENTROPY = 0x28, ++ ++ /* available if CRYPTO bit set in features */ ++ OMNIA_CMD_CRYPTO_GET_PUBLIC_KEY = 0x29, ++ OMNIA_CMD_CRYPTO_SIGN_MESSAGE = 0x2A, ++ OMNIA_CMD_CRYPTO_COLLECT_SIGNATURE = 0x2B, ++ ++ /* available if BOARD_INFO it set in features */ ++ OMNIA_CMD_BOARD_INFO_GET = 0x2C, ++ OMNIA_CMD_BOARD_INFO_BURN = 0x2D, ++ ++ /* available only at address 0x2b (LED-controller) */ ++ /* available only if LED_GAMMA_CORRECTION bit set in features */ ++ OMNIA_CMD_SET_GAMMA_CORRECTION = 0x30, ++ OMNIA_CMD_GET_GAMMA_CORRECTION = 0x31, ++ ++ /* available only at address 0x2b (LED-controller) */ ++ /* available only if PER_LED_CORRECTION bit set in features */ ++ /* available only if FROM_BIT_16_INVALID bit NOT set in features */ ++ OMNIA_CMD_SET_LED_CORRECTIONS = 0x32, ++ OMNIA_CMD_GET_LED_CORRECTIONS = 0x33, ++}; ++ ++enum omnia_flashing_commands_e { ++ OMNIA_FLASH_CMD_UNLOCK = 0x01, ++ OMNIA_FLASH_CMD_SIZE_AND_CSUM = 0x02, ++ OMNIA_FLASH_CMD_PROGRAM = 0x03, ++ OMNIA_FLASH_CMD_RESET = 0x04, ++}; ++ ++enum omnia_sts_word_e { ++ OMNIA_STS_MCU_TYPE_MASK = GENMASK(1, 0), ++ OMNIA_STS_MCU_TYPE_STM32 = FIELD_PREP_CONST(OMNIA_STS_MCU_TYPE_MASK, 0), ++ OMNIA_STS_MCU_TYPE_GD32 = FIELD_PREP_CONST(OMNIA_STS_MCU_TYPE_MASK, 1), ++ OMNIA_STS_MCU_TYPE_MKL = FIELD_PREP_CONST(OMNIA_STS_MCU_TYPE_MASK, 2), ++ OMNIA_STS_FEATURES_SUPPORTED = BIT(2), ++ OMNIA_STS_USER_REGULATOR_NOT_SUPPORTED = BIT(3), ++ OMNIA_STS_CARD_DET = BIT(4), ++ OMNIA_STS_MSATA_IND = BIT(5), ++ OMNIA_STS_USB30_OVC = BIT(6), ++ OMNIA_STS_USB31_OVC = BIT(7), ++ OMNIA_STS_USB30_PWRON = BIT(8), ++ OMNIA_STS_USB31_PWRON = BIT(9), ++ OMNIA_STS_ENABLE_4V5 = BIT(10), ++ OMNIA_STS_BUTTON_MODE = BIT(11), ++ OMNIA_STS_BUTTON_PRESSED = BIT(12), ++ OMNIA_STS_BUTTON_COUNTER_MASK = GENMASK(15, 13), ++}; ++ ++enum omnia_ctl_byte_e { ++ OMNIA_CTL_LIGHT_RST = BIT(0), ++ OMNIA_CTL_HARD_RST = BIT(1), ++ /* BIT(2) is currently reserved */ ++ OMNIA_CTL_USB30_PWRON = BIT(3), ++ OMNIA_CTL_USB31_PWRON = BIT(4), ++ OMNIA_CTL_ENABLE_4V5 = BIT(5), ++ OMNIA_CTL_BUTTON_MODE = BIT(6), ++ OMNIA_CTL_BOOTLOADER = BIT(7), ++}; ++ ++enum omnia_features_e { ++ OMNIA_FEAT_PERIPH_MCU = BIT(0), ++ OMNIA_FEAT_EXT_CMDS = BIT(1), ++ OMNIA_FEAT_WDT_PING = BIT(2), ++ OMNIA_FEAT_LED_STATE_EXT_MASK = GENMASK(4, 3), ++ OMNIA_FEAT_LED_STATE_EXT = FIELD_PREP_CONST(OMNIA_FEAT_LED_STATE_EXT_MASK, 1), ++ OMNIA_FEAT_LED_STATE_EXT_V32 = FIELD_PREP_CONST(OMNIA_FEAT_LED_STATE_EXT_MASK, 2), ++ OMNIA_FEAT_LED_GAMMA_CORRECTION = BIT(5), ++ OMNIA_FEAT_NEW_INT_API = BIT(6), ++ OMNIA_FEAT_BOOTLOADER = BIT(7), ++ OMNIA_FEAT_FLASHING = BIT(8), ++ OMNIA_FEAT_NEW_MESSAGE_API = BIT(9), ++ OMNIA_FEAT_BRIGHTNESS_INT = BIT(10), ++ OMNIA_FEAT_POWEROFF_WAKEUP = BIT(11), ++ OMNIA_FEAT_CAN_OLD_MESSAGE_API = BIT(12), ++ OMNIA_FEAT_TRNG = BIT(13), ++ OMNIA_FEAT_CRYPTO = BIT(14), ++ OMNIA_FEAT_BOARD_INFO = BIT(15), ++ ++ /* ++ * Orginally the features command replied only 16 bits. If more were ++ * read, either the I2C transaction failed or 0xff bytes were sent. ++ * Therefore to consider bits 16 - 31 valid, one bit (20) was reserved ++ * to be zero. ++ */ ++ ++ /* Bits 16 - 19 correspond to bits 0 - 3 of status word */ ++ OMNIA_FEAT_MCU_TYPE_MASK = GENMASK(17, 16), ++ OMNIA_FEAT_MCU_TYPE_STM32 = FIELD_PREP_CONST(OMNIA_FEAT_MCU_TYPE_MASK, 0), ++ OMNIA_FEAT_MCU_TYPE_GD32 = FIELD_PREP_CONST(OMNIA_FEAT_MCU_TYPE_MASK, 1), ++ OMNIA_FEAT_MCU_TYPE_MKL = FIELD_PREP_CONST(OMNIA_FEAT_MCU_TYPE_MASK, 2), ++ OMNIA_FEAT_FEATURES_SUPPORTED = BIT(18), ++ OMNIA_FEAT_USER_REGULATOR_NOT_SUPPORTED = BIT(19), ++ ++ /* must not be set */ ++ OMNIA_FEAT_FROM_BIT_16_INVALID = BIT(20), ++ ++ OMNIA_FEAT_PER_LED_CORRECTION = BIT(21), ++ OMNIA_FEAT_USB_OVC_PROT_SETTING = BIT(22), ++}; ++ ++enum omnia_ext_sts_dword_e { ++ OMNIA_EXT_STS_SFP_nDET = BIT(0), ++ OMNIA_EXT_STS_LED_STATES_MASK = GENMASK(31, 12), ++ OMNIA_EXT_STS_WLAN0_MSATA_LED = BIT(12), ++ OMNIA_EXT_STS_WLAN1_LED = BIT(13), ++ OMNIA_EXT_STS_WLAN2_LED = BIT(14), ++ OMNIA_EXT_STS_WPAN0_LED = BIT(15), ++ OMNIA_EXT_STS_WPAN1_LED = BIT(16), ++ OMNIA_EXT_STS_WPAN2_LED = BIT(17), ++ OMNIA_EXT_STS_WAN_LED0 = BIT(18), ++ OMNIA_EXT_STS_WAN_LED1 = BIT(19), ++ OMNIA_EXT_STS_LAN0_LED0 = BIT(20), ++ OMNIA_EXT_STS_LAN0_LED1 = BIT(21), ++ OMNIA_EXT_STS_LAN1_LED0 = BIT(22), ++ OMNIA_EXT_STS_LAN1_LED1 = BIT(23), ++ OMNIA_EXT_STS_LAN2_LED0 = BIT(24), ++ OMNIA_EXT_STS_LAN2_LED1 = BIT(25), ++ OMNIA_EXT_STS_LAN3_LED0 = BIT(26), ++ OMNIA_EXT_STS_LAN3_LED1 = BIT(27), ++ OMNIA_EXT_STS_LAN4_LED0 = BIT(28), ++ OMNIA_EXT_STS_LAN4_LED1 = BIT(29), ++ OMNIA_EXT_STS_LAN5_LED0 = BIT(30), ++ OMNIA_EXT_STS_LAN5_LED1 = BIT(31), ++}; ++ ++enum omnia_ext_ctl_e { ++ OMNIA_EXT_CTL_nRES_MMC = BIT(0), ++ OMNIA_EXT_CTL_nRES_LAN = BIT(1), ++ OMNIA_EXT_CTL_nRES_PHY = BIT(2), ++ OMNIA_EXT_CTL_nPERST0 = BIT(3), ++ OMNIA_EXT_CTL_nPERST1 = BIT(4), ++ OMNIA_EXT_CTL_nPERST2 = BIT(5), ++ OMNIA_EXT_CTL_PHY_SFP = BIT(6), ++ OMNIA_EXT_CTL_PHY_SFP_AUTO = BIT(7), ++ OMNIA_EXT_CTL_nVHV_CTRL = BIT(8), ++}; ++ ++enum omnia_int_e { ++ OMNIA_INT_CARD_DET = BIT(0), ++ OMNIA_INT_MSATA_IND = BIT(1), ++ OMNIA_INT_USB30_OVC = BIT(2), ++ OMNIA_INT_USB31_OVC = BIT(3), ++ OMNIA_INT_BUTTON_PRESSED = BIT(4), ++ OMNIA_INT_SFP_nDET = BIT(5), ++ OMNIA_INT_BRIGHTNESS_CHANGED = BIT(6), ++ OMNIA_INT_TRNG = BIT(7), ++ OMNIA_INT_MESSAGE_SIGNED = BIT(8), ++ ++ OMNIA_INT_LED_STATES_MASK = GENMASK(31, 12), ++ OMNIA_INT_WLAN0_MSATA_LED = BIT(12), ++ OMNIA_INT_WLAN1_LED = BIT(13), ++ OMNIA_INT_WLAN2_LED = BIT(14), ++ OMNIA_INT_WPAN0_LED = BIT(15), ++ OMNIA_INT_WPAN1_LED = BIT(16), ++ OMNIA_INT_WPAN2_LED = BIT(17), ++ OMNIA_INT_WAN_LED0 = BIT(18), ++ OMNIA_INT_WAN_LED1 = BIT(19), ++ OMNIA_INT_LAN0_LED0 = BIT(20), ++ OMNIA_INT_LAN0_LED1 = BIT(21), ++ OMNIA_INT_LAN1_LED0 = BIT(22), ++ OMNIA_INT_LAN1_LED1 = BIT(23), ++ OMNIA_INT_LAN2_LED0 = BIT(24), ++ OMNIA_INT_LAN2_LED1 = BIT(25), ++ OMNIA_INT_LAN3_LED0 = BIT(26), ++ OMNIA_INT_LAN3_LED1 = BIT(27), ++ OMNIA_INT_LAN4_LED0 = BIT(28), ++ OMNIA_INT_LAN4_LED1 = BIT(29), ++ OMNIA_INT_LAN5_LED0 = BIT(30), ++ OMNIA_INT_LAN5_LED1 = BIT(31), ++}; ++ ++enum omnia_cmd_poweroff_e { ++ OMNIA_CMD_POWER_OFF_POWERON_BUTTON = BIT(0), ++ OMNIA_CMD_POWER_OFF_MAGIC = 0xdead, ++}; ++ ++enum omnia_cmd_usb_ovc_prot_e { ++ OMNIA_CMD_xET_USB_OVC_PROT_PORT_MASK = GENMASK(3, 0), ++ OMNIA_CMD_xET_USB_OVC_PROT_ENABLE = BIT(4), ++}; ++ ++#endif /* __TURRIS_OMNIA_MCU_INTERFACE_H */ diff --git a/lede/target/linux/mvebu/patches-6.6/820-v6.11-03-platform-cznic-turris-omnia-mcu-Add-support-for-MCU-.patch b/lede/target/linux/mvebu/patches-6.6/820-v6.11-03-platform-cznic-turris-omnia-mcu-Add-support-for-MCU-.patch new file mode 100644 index 0000000000..3309a773a9 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/820-v6.11-03-platform-cznic-turris-omnia-mcu-Add-support-for-MCU-.patch @@ -0,0 +1,1311 @@ +From 7f4f2744f9788312e12940b516b51a0a466b137e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 1 Jul 2024 13:30:05 +0200 +Subject: [PATCH 03/11] platform: cznic: turris-omnia-mcu: Add support for MCU + connected GPIOs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add support for GPIOs connected to the MCU on the Turris Omnia board. + +This includes: +- front button pin +- enable pins for USB regulators +- MiniPCIe / mSATA card presence pins in MiniPCIe port 0 +- LED output pins from WAN ethernet PHY, LAN switch and MiniPCIe ports +- on board revisions 32+ also various peripheral resets and another + voltage regulator enable pin + +Signed-off-by: Marek Behún +Acked-by: Bartosz Golaszewski +Link: https://lore.kernel.org/r/20240701113010.16447-4-kabel@kernel.org +Signed-off-by: Arnd Bergmann +--- + .../sysfs-bus-i2c-devices-turris-omnia-mcu | 16 + + drivers/platform/cznic/Kconfig | 15 + + drivers/platform/cznic/Makefile | 1 + + .../platform/cznic/turris-omnia-mcu-base.c | 3 +- + .../platform/cznic/turris-omnia-mcu-gpio.c | 1094 +++++++++++++++++ + drivers/platform/cznic/turris-omnia-mcu.h | 68 + + 6 files changed, 1196 insertions(+), 1 deletion(-) + create mode 100644 drivers/platform/cznic/turris-omnia-mcu-gpio.c + +--- a/Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu ++++ b/Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu +@@ -22,6 +22,22 @@ Description: (RO) Contains device first + + Format: %pM. + ++What: /sys/bus/i2c/devices//front_button_mode ++Date: September 2024 ++KernelVersion: 6.11 ++Contact: Marek Behún ++Description: (RW) The front button on the Turris Omnia router can be ++ configured either to change the intensity of all the LEDs on the ++ front panel, or to send the press event to the CPU as an ++ interrupt. ++ ++ This file switches between these two modes: ++ - "mcu" makes the button press event be handled by the MCU to ++ change the LEDs panel intensity. ++ - "cpu" makes the button press event be handled by the CPU. ++ ++ Format: %s. ++ + What: /sys/bus/i2c/devices//fw_features + Date: September 2024 + KernelVersion: 6.11 +--- a/drivers/platform/cznic/Kconfig ++++ b/drivers/platform/cznic/Kconfig +@@ -16,9 +16,24 @@ config TURRIS_OMNIA_MCU + tristate "Turris Omnia MCU driver" + depends on MACH_ARMADA_38X || COMPILE_TEST + depends on I2C ++ select GPIOLIB ++ select GPIOLIB_IRQCHIP + help + Say Y here to add support for the features implemented by the + microcontroller on the CZ.NIC's Turris Omnia SOHO router. ++ The features include: ++ - GPIO pins ++ - to get front button press events (the front button can be ++ configured either to generate press events to the CPU or to change ++ front LEDs panel brightness) ++ - to enable / disable USB port voltage regulators and to detect ++ USB overcurrent ++ - to detect MiniPCIe / mSATA card presence in MiniPCIe port 0 ++ - to configure resets of various peripherals on board revisions 32+ ++ - to enable / disable the VHV voltage regulator to the SOC in order ++ to be able to program SOC's OTP on board revisions 32+ ++ - to get input from the LED output pins of the WAN ethernet PHY, LAN ++ switch and MiniPCIe ports + To compile this driver as a module, choose M here; the module will be + called turris-omnia-mcu. + +--- a/drivers/platform/cznic/Makefile ++++ b/drivers/platform/cznic/Makefile +@@ -2,3 +2,4 @@ + + obj-$(CONFIG_TURRIS_OMNIA_MCU) += turris-omnia-mcu.o + turris-omnia-mcu-y := turris-omnia-mcu-base.o ++turris-omnia-mcu-y += turris-omnia-mcu-gpio.o +--- a/drivers/platform/cznic/turris-omnia-mcu-base.c ++++ b/drivers/platform/cznic/turris-omnia-mcu-base.c +@@ -196,6 +196,7 @@ static const struct attribute_group omni + + static const struct attribute_group *omnia_mcu_groups[] = { + &omnia_mcu_base_group, ++ &omnia_mcu_gpio_group, + NULL + }; + +@@ -370,7 +371,7 @@ static int omnia_mcu_probe(struct i2c_cl + "Cannot read board info\n"); + } + +- return 0; ++ return omnia_mcu_register_gpiochip(mcu); + } + + static const struct of_device_id of_omnia_mcu_match[] = { +--- /dev/null ++++ b/drivers/platform/cznic/turris-omnia-mcu-gpio.c +@@ -0,0 +1,1094 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * CZ.NIC's Turris Omnia MCU GPIO and IRQ driver ++ * ++ * 2024 by Marek Behún ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "turris-omnia-mcu.h" ++ ++#define OMNIA_CMD_INT_ARG_LEN 8 ++#define FRONT_BUTTON_RELEASE_DELAY_MS 50 ++ ++static const char * const omnia_mcu_gpio_templates[64] = { ++ /* GPIOs with value read from the 16-bit wide status */ ++ [4] = "MiniPCIe0 Card Detect", ++ [5] = "MiniPCIe0 mSATA Indicator", ++ [6] = "Front USB3 port over-current", ++ [7] = "Rear USB3 port over-current", ++ [8] = "Front USB3 port power", ++ [9] = "Rear USB3 port power", ++ [12] = "Front Button", ++ ++ /* GPIOs with value read from the 32-bit wide extended status */ ++ [16] = "SFP nDET", ++ [28] = "MiniPCIe0 LED", ++ [29] = "MiniPCIe1 LED", ++ [30] = "MiniPCIe2 LED", ++ [31] = "MiniPCIe0 PAN LED", ++ [32] = "MiniPCIe1 PAN LED", ++ [33] = "MiniPCIe2 PAN LED", ++ [34] = "WAN PHY LED0", ++ [35] = "WAN PHY LED1", ++ [36] = "LAN switch p0 LED0", ++ [37] = "LAN switch p0 LED1", ++ [38] = "LAN switch p1 LED0", ++ [39] = "LAN switch p1 LED1", ++ [40] = "LAN switch p2 LED0", ++ [41] = "LAN switch p2 LED1", ++ [42] = "LAN switch p3 LED0", ++ [43] = "LAN switch p3 LED1", ++ [44] = "LAN switch p4 LED0", ++ [45] = "LAN switch p4 LED1", ++ [46] = "LAN switch p5 LED0", ++ [47] = "LAN switch p5 LED1", ++ ++ /* GPIOs with value read from the 16-bit wide extended control status */ ++ [48] = "eMMC nRESET", ++ [49] = "LAN switch nRESET", ++ [50] = "WAN PHY nRESET", ++ [51] = "MiniPCIe0 nPERST", ++ [52] = "MiniPCIe1 nPERST", ++ [53] = "MiniPCIe2 nPERST", ++ [54] = "WAN PHY SFP mux", ++ [56] = "VHV power disable", ++}; ++ ++struct omnia_gpio { ++ u8 cmd; ++ u8 ctl_cmd; ++ u8 bit; ++ u8 ctl_bit; ++ u8 int_bit; ++ u16 feat; ++ u16 feat_mask; ++}; ++ ++#define OMNIA_GPIO_INVALID_INT_BIT 0xff ++ ++#define _DEF_GPIO(_cmd, _ctl_cmd, _bit, _ctl_bit, _int_bit, _feat, _feat_mask) \ ++ { \ ++ .cmd = _cmd, \ ++ .ctl_cmd = _ctl_cmd, \ ++ .bit = _bit, \ ++ .ctl_bit = _ctl_bit, \ ++ .int_bit = (_int_bit) < 0 ? OMNIA_GPIO_INVALID_INT_BIT \ ++ : (_int_bit), \ ++ .feat = _feat, \ ++ .feat_mask = _feat_mask, \ ++ } ++ ++#define _DEF_GPIO_STS(_name) \ ++ _DEF_GPIO(OMNIA_CMD_GET_STATUS_WORD, 0, __bf_shf(OMNIA_STS_ ## _name), \ ++ 0, __bf_shf(OMNIA_INT_ ## _name), 0, 0) ++ ++#define _DEF_GPIO_CTL(_name) \ ++ _DEF_GPIO(OMNIA_CMD_GET_STATUS_WORD, OMNIA_CMD_GENERAL_CONTROL, \ ++ __bf_shf(OMNIA_STS_ ## _name), __bf_shf(OMNIA_CTL_ ## _name), \ ++ -1, 0, 0) ++ ++#define _DEF_GPIO_EXT_STS(_name, _feat) \ ++ _DEF_GPIO(OMNIA_CMD_GET_EXT_STATUS_DWORD, 0, \ ++ __bf_shf(OMNIA_EXT_STS_ ## _name), 0, \ ++ __bf_shf(OMNIA_INT_ ## _name), \ ++ OMNIA_FEAT_ ## _feat | OMNIA_FEAT_EXT_CMDS, \ ++ OMNIA_FEAT_ ## _feat | OMNIA_FEAT_EXT_CMDS) ++ ++#define _DEF_GPIO_EXT_STS_LED(_name, _ledext) \ ++ _DEF_GPIO(OMNIA_CMD_GET_EXT_STATUS_DWORD, 0, \ ++ __bf_shf(OMNIA_EXT_STS_ ## _name), 0, \ ++ __bf_shf(OMNIA_INT_ ## _name), \ ++ OMNIA_FEAT_LED_STATE_ ## _ledext, \ ++ OMNIA_FEAT_LED_STATE_EXT_MASK) ++ ++#define _DEF_GPIO_EXT_STS_LEDALL(_name) \ ++ _DEF_GPIO(OMNIA_CMD_GET_EXT_STATUS_DWORD, 0, \ ++ __bf_shf(OMNIA_EXT_STS_ ## _name), 0, \ ++ __bf_shf(OMNIA_INT_ ## _name), \ ++ OMNIA_FEAT_LED_STATE_EXT_MASK, 0) ++ ++#define _DEF_GPIO_EXT_CTL(_name, _feat) \ ++ _DEF_GPIO(OMNIA_CMD_GET_EXT_CONTROL_STATUS, OMNIA_CMD_EXT_CONTROL, \ ++ __bf_shf(OMNIA_EXT_CTL_ ## _name), \ ++ __bf_shf(OMNIA_EXT_CTL_ ## _name), -1, \ ++ OMNIA_FEAT_ ## _feat | OMNIA_FEAT_EXT_CMDS, \ ++ OMNIA_FEAT_ ## _feat | OMNIA_FEAT_EXT_CMDS) ++ ++#define _DEF_INT(_name) \ ++ _DEF_GPIO(0, 0, 0, 0, __bf_shf(OMNIA_INT_ ## _name), 0, 0) ++ ++static inline bool is_int_bit_valid(const struct omnia_gpio *gpio) ++{ ++ return gpio->int_bit != OMNIA_GPIO_INVALID_INT_BIT; ++} ++ ++static const struct omnia_gpio omnia_gpios[64] = { ++ /* GPIOs with value read from the 16-bit wide status */ ++ [4] = _DEF_GPIO_STS(CARD_DET), ++ [5] = _DEF_GPIO_STS(MSATA_IND), ++ [6] = _DEF_GPIO_STS(USB30_OVC), ++ [7] = _DEF_GPIO_STS(USB31_OVC), ++ [8] = _DEF_GPIO_CTL(USB30_PWRON), ++ [9] = _DEF_GPIO_CTL(USB31_PWRON), ++ ++ /* brightness changed interrupt, no GPIO */ ++ [11] = _DEF_INT(BRIGHTNESS_CHANGED), ++ ++ [12] = _DEF_GPIO_STS(BUTTON_PRESSED), ++ ++ /* TRNG interrupt, no GPIO */ ++ [13] = _DEF_INT(TRNG), ++ ++ /* MESSAGE_SIGNED interrupt, no GPIO */ ++ [14] = _DEF_INT(MESSAGE_SIGNED), ++ ++ /* GPIOs with value read from the 32-bit wide extended status */ ++ [16] = _DEF_GPIO_EXT_STS(SFP_nDET, PERIPH_MCU), ++ [28] = _DEF_GPIO_EXT_STS_LEDALL(WLAN0_MSATA_LED), ++ [29] = _DEF_GPIO_EXT_STS_LEDALL(WLAN1_LED), ++ [30] = _DEF_GPIO_EXT_STS_LEDALL(WLAN2_LED), ++ [31] = _DEF_GPIO_EXT_STS_LED(WPAN0_LED, EXT), ++ [32] = _DEF_GPIO_EXT_STS_LED(WPAN1_LED, EXT), ++ [33] = _DEF_GPIO_EXT_STS_LED(WPAN2_LED, EXT), ++ [34] = _DEF_GPIO_EXT_STS_LEDALL(WAN_LED0), ++ [35] = _DEF_GPIO_EXT_STS_LED(WAN_LED1, EXT_V32), ++ [36] = _DEF_GPIO_EXT_STS_LEDALL(LAN0_LED0), ++ [37] = _DEF_GPIO_EXT_STS_LEDALL(LAN0_LED1), ++ [38] = _DEF_GPIO_EXT_STS_LEDALL(LAN1_LED0), ++ [39] = _DEF_GPIO_EXT_STS_LEDALL(LAN1_LED1), ++ [40] = _DEF_GPIO_EXT_STS_LEDALL(LAN2_LED0), ++ [41] = _DEF_GPIO_EXT_STS_LEDALL(LAN2_LED1), ++ [42] = _DEF_GPIO_EXT_STS_LEDALL(LAN3_LED0), ++ [43] = _DEF_GPIO_EXT_STS_LEDALL(LAN3_LED1), ++ [44] = _DEF_GPIO_EXT_STS_LEDALL(LAN4_LED0), ++ [45] = _DEF_GPIO_EXT_STS_LEDALL(LAN4_LED1), ++ [46] = _DEF_GPIO_EXT_STS_LEDALL(LAN5_LED0), ++ [47] = _DEF_GPIO_EXT_STS_LEDALL(LAN5_LED1), ++ ++ /* GPIOs with value read from the 16-bit wide extended control status */ ++ [48] = _DEF_GPIO_EXT_CTL(nRES_MMC, PERIPH_MCU), ++ [49] = _DEF_GPIO_EXT_CTL(nRES_LAN, PERIPH_MCU), ++ [50] = _DEF_GPIO_EXT_CTL(nRES_PHY, PERIPH_MCU), ++ [51] = _DEF_GPIO_EXT_CTL(nPERST0, PERIPH_MCU), ++ [52] = _DEF_GPIO_EXT_CTL(nPERST1, PERIPH_MCU), ++ [53] = _DEF_GPIO_EXT_CTL(nPERST2, PERIPH_MCU), ++ [54] = _DEF_GPIO_EXT_CTL(PHY_SFP, PERIPH_MCU), ++ [56] = _DEF_GPIO_EXT_CTL(nVHV_CTRL, PERIPH_MCU), ++}; ++ ++/* mapping from interrupts to indexes of GPIOs in the omnia_gpios array */ ++static const u8 omnia_int_to_gpio_idx[32] = { ++ [__bf_shf(OMNIA_INT_CARD_DET)] = 4, ++ [__bf_shf(OMNIA_INT_MSATA_IND)] = 5, ++ [__bf_shf(OMNIA_INT_USB30_OVC)] = 6, ++ [__bf_shf(OMNIA_INT_USB31_OVC)] = 7, ++ [__bf_shf(OMNIA_INT_BUTTON_PRESSED)] = 12, ++ [__bf_shf(OMNIA_INT_TRNG)] = 13, ++ [__bf_shf(OMNIA_INT_MESSAGE_SIGNED)] = 14, ++ [__bf_shf(OMNIA_INT_SFP_nDET)] = 16, ++ [__bf_shf(OMNIA_INT_BRIGHTNESS_CHANGED)] = 11, ++ [__bf_shf(OMNIA_INT_WLAN0_MSATA_LED)] = 28, ++ [__bf_shf(OMNIA_INT_WLAN1_LED)] = 29, ++ [__bf_shf(OMNIA_INT_WLAN2_LED)] = 30, ++ [__bf_shf(OMNIA_INT_WPAN0_LED)] = 31, ++ [__bf_shf(OMNIA_INT_WPAN1_LED)] = 32, ++ [__bf_shf(OMNIA_INT_WPAN2_LED)] = 33, ++ [__bf_shf(OMNIA_INT_WAN_LED0)] = 34, ++ [__bf_shf(OMNIA_INT_WAN_LED1)] = 35, ++ [__bf_shf(OMNIA_INT_LAN0_LED0)] = 36, ++ [__bf_shf(OMNIA_INT_LAN0_LED1)] = 37, ++ [__bf_shf(OMNIA_INT_LAN1_LED0)] = 38, ++ [__bf_shf(OMNIA_INT_LAN1_LED1)] = 39, ++ [__bf_shf(OMNIA_INT_LAN2_LED0)] = 40, ++ [__bf_shf(OMNIA_INT_LAN2_LED1)] = 41, ++ [__bf_shf(OMNIA_INT_LAN3_LED0)] = 42, ++ [__bf_shf(OMNIA_INT_LAN3_LED1)] = 43, ++ [__bf_shf(OMNIA_INT_LAN4_LED0)] = 44, ++ [__bf_shf(OMNIA_INT_LAN4_LED1)] = 45, ++ [__bf_shf(OMNIA_INT_LAN5_LED0)] = 46, ++ [__bf_shf(OMNIA_INT_LAN5_LED1)] = 47, ++}; ++ ++/* index of PHY_SFP GPIO in the omnia_gpios array */ ++#define OMNIA_GPIO_PHY_SFP_OFFSET 54 ++ ++static int omnia_ctl_cmd_locked(struct omnia_mcu *mcu, u8 cmd, u16 val, u16 mask) ++{ ++ unsigned int len; ++ u8 buf[5]; ++ ++ buf[0] = cmd; ++ ++ switch (cmd) { ++ case OMNIA_CMD_GENERAL_CONTROL: ++ buf[1] = val; ++ buf[2] = mask; ++ len = 3; ++ break; ++ ++ case OMNIA_CMD_EXT_CONTROL: ++ put_unaligned_le16(val, &buf[1]); ++ put_unaligned_le16(mask, &buf[3]); ++ len = 5; ++ break; ++ ++ default: ++ BUG(); ++ } ++ ++ return omnia_cmd_write(mcu->client, buf, len); ++} ++ ++static int omnia_ctl_cmd(struct omnia_mcu *mcu, u8 cmd, u16 val, u16 mask) ++{ ++ guard(mutex)(&mcu->lock); ++ ++ return omnia_ctl_cmd_locked(mcu, cmd, val, mask); ++} ++ ++static int omnia_gpio_request(struct gpio_chip *gc, unsigned int offset) ++{ ++ if (!omnia_gpios[offset].cmd) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static int omnia_gpio_get_direction(struct gpio_chip *gc, unsigned int offset) ++{ ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ ++ if (offset == OMNIA_GPIO_PHY_SFP_OFFSET) { ++ int val; ++ ++ scoped_guard(mutex, &mcu->lock) { ++ val = omnia_cmd_read_bit(mcu->client, ++ OMNIA_CMD_GET_EXT_CONTROL_STATUS, ++ OMNIA_EXT_CTL_PHY_SFP_AUTO); ++ if (val < 0) ++ return val; ++ } ++ ++ if (val) ++ return GPIO_LINE_DIRECTION_IN; ++ ++ return GPIO_LINE_DIRECTION_OUT; ++ } ++ ++ if (omnia_gpios[offset].ctl_cmd) ++ return GPIO_LINE_DIRECTION_OUT; ++ ++ return GPIO_LINE_DIRECTION_IN; ++} ++ ++static int omnia_gpio_direction_input(struct gpio_chip *gc, unsigned int offset) ++{ ++ const struct omnia_gpio *gpio = &omnia_gpios[offset]; ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ ++ if (offset == OMNIA_GPIO_PHY_SFP_OFFSET) ++ return omnia_ctl_cmd(mcu, OMNIA_CMD_EXT_CONTROL, ++ OMNIA_EXT_CTL_PHY_SFP_AUTO, ++ OMNIA_EXT_CTL_PHY_SFP_AUTO); ++ ++ if (gpio->ctl_cmd) ++ return -ENOTSUPP; ++ ++ return 0; ++} ++ ++static int omnia_gpio_direction_output(struct gpio_chip *gc, ++ unsigned int offset, int value) ++{ ++ const struct omnia_gpio *gpio = &omnia_gpios[offset]; ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ u16 val, mask; ++ ++ if (!gpio->ctl_cmd) ++ return -ENOTSUPP; ++ ++ mask = BIT(gpio->ctl_bit); ++ val = value ? mask : 0; ++ ++ if (offset == OMNIA_GPIO_PHY_SFP_OFFSET) ++ mask |= OMNIA_EXT_CTL_PHY_SFP_AUTO; ++ ++ return omnia_ctl_cmd(mcu, gpio->ctl_cmd, val, mask); ++} ++ ++static int omnia_gpio_get(struct gpio_chip *gc, unsigned int offset) ++{ ++ const struct omnia_gpio *gpio = &omnia_gpios[offset]; ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ ++ /* ++ * If firmware does not support the new interrupt API, we are informed ++ * of every change of the status word by an interrupt from MCU and save ++ * its value in the interrupt service routine. Simply return the saved ++ * value. ++ */ ++ if (gpio->cmd == OMNIA_CMD_GET_STATUS_WORD && ++ !(mcu->features & OMNIA_FEAT_NEW_INT_API)) ++ return test_bit(gpio->bit, &mcu->last_status); ++ ++ guard(mutex)(&mcu->lock); ++ ++ /* ++ * If firmware does support the new interrupt API, we may have cached ++ * the value of a GPIO in the interrupt service routine. If not, read ++ * the relevant bit now. ++ */ ++ if (is_int_bit_valid(gpio) && test_bit(gpio->int_bit, &mcu->is_cached)) ++ return test_bit(gpio->int_bit, &mcu->cached); ++ ++ return omnia_cmd_read_bit(mcu->client, gpio->cmd, BIT(gpio->bit)); ++} ++ ++static unsigned long * ++_relevant_field_for_sts_cmd(u8 cmd, unsigned long *sts, unsigned long *ext_sts, ++ unsigned long *ext_ctl) ++{ ++ switch (cmd) { ++ case OMNIA_CMD_GET_STATUS_WORD: ++ return sts; ++ case OMNIA_CMD_GET_EXT_STATUS_DWORD: ++ return ext_sts; ++ case OMNIA_CMD_GET_EXT_CONTROL_STATUS: ++ return ext_ctl; ++ default: ++ return NULL; ++ } ++} ++ ++static int omnia_gpio_get_multiple(struct gpio_chip *gc, unsigned long *mask, ++ unsigned long *bits) ++{ ++ unsigned long sts = 0, ext_sts = 0, ext_ctl = 0, *field; ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ struct i2c_client *client = mcu->client; ++ unsigned int i; ++ int err; ++ ++ /* determine which bits to read from the 3 possible commands */ ++ for_each_set_bit(i, mask, ARRAY_SIZE(omnia_gpios)) { ++ field = _relevant_field_for_sts_cmd(omnia_gpios[i].cmd, ++ &sts, &ext_sts, &ext_ctl); ++ if (!field) ++ continue; ++ ++ __set_bit(omnia_gpios[i].bit, field); ++ } ++ ++ guard(mutex)(&mcu->lock); ++ ++ if (mcu->features & OMNIA_FEAT_NEW_INT_API) { ++ /* read relevant bits from status */ ++ err = omnia_cmd_read_bits(client, OMNIA_CMD_GET_STATUS_WORD, ++ sts, &sts); ++ if (err) ++ return err; ++ } else { ++ /* ++ * Use status word value cached in the interrupt service routine ++ * if firmware does not support the new interrupt API. ++ */ ++ sts = mcu->last_status; ++ } ++ ++ /* read relevant bits from extended status */ ++ err = omnia_cmd_read_bits(client, OMNIA_CMD_GET_EXT_STATUS_DWORD, ++ ext_sts, &ext_sts); ++ if (err) ++ return err; ++ ++ /* read relevant bits from extended control */ ++ err = omnia_cmd_read_bits(client, OMNIA_CMD_GET_EXT_CONTROL_STATUS, ++ ext_ctl, &ext_ctl); ++ if (err) ++ return err; ++ ++ /* assign relevant bits in result */ ++ for_each_set_bit(i, mask, ARRAY_SIZE(omnia_gpios)) { ++ field = _relevant_field_for_sts_cmd(omnia_gpios[i].cmd, ++ &sts, &ext_sts, &ext_ctl); ++ if (!field) ++ continue; ++ ++ __assign_bit(i, bits, test_bit(omnia_gpios[i].bit, field)); ++ } ++ ++ return 0; ++} ++ ++static void omnia_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) ++{ ++ const struct omnia_gpio *gpio = &omnia_gpios[offset]; ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ u16 val, mask; ++ ++ if (!gpio->ctl_cmd) ++ return; ++ ++ mask = BIT(gpio->ctl_bit); ++ val = value ? mask : 0; ++ ++ omnia_ctl_cmd(mcu, gpio->ctl_cmd, val, mask); ++} ++ ++static void omnia_gpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, ++ unsigned long *bits) ++{ ++ unsigned long ctl = 0, ctl_mask = 0, ext_ctl = 0, ext_ctl_mask = 0; ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ unsigned int i; ++ ++ for_each_set_bit(i, mask, ARRAY_SIZE(omnia_gpios)) { ++ unsigned long *field, *field_mask; ++ u8 bit = omnia_gpios[i].ctl_bit; ++ ++ switch (omnia_gpios[i].ctl_cmd) { ++ case OMNIA_CMD_GENERAL_CONTROL: ++ field = &ctl; ++ field_mask = &ctl_mask; ++ break; ++ case OMNIA_CMD_EXT_CONTROL: ++ field = &ext_ctl; ++ field_mask = &ext_ctl_mask; ++ break; ++ default: ++ field = field_mask = NULL; ++ break; ++ } ++ ++ if (!field) ++ continue; ++ ++ __set_bit(bit, field_mask); ++ __assign_bit(bit, field, test_bit(i, bits)); ++ } ++ ++ guard(mutex)(&mcu->lock); ++ ++ if (ctl_mask) ++ omnia_ctl_cmd_locked(mcu, OMNIA_CMD_GENERAL_CONTROL, ++ ctl, ctl_mask); ++ ++ if (ext_ctl_mask) ++ omnia_ctl_cmd_locked(mcu, OMNIA_CMD_EXT_CONTROL, ++ ext_ctl, ext_ctl_mask); ++} ++ ++static bool omnia_gpio_available(struct omnia_mcu *mcu, ++ const struct omnia_gpio *gpio) ++{ ++ if (gpio->feat_mask) ++ return (mcu->features & gpio->feat_mask) == gpio->feat; ++ ++ if (gpio->feat) ++ return mcu->features & gpio->feat; ++ ++ return true; ++} ++ ++static int omnia_gpio_init_valid_mask(struct gpio_chip *gc, ++ unsigned long *valid_mask, ++ unsigned int ngpios) ++{ ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ ++ for (unsigned int i = 0; i < ngpios; i++) { ++ const struct omnia_gpio *gpio = &omnia_gpios[i]; ++ ++ if (gpio->cmd || is_int_bit_valid(gpio)) ++ __assign_bit(i, valid_mask, ++ omnia_gpio_available(mcu, gpio)); ++ else ++ __clear_bit(i, valid_mask); ++ } ++ ++ return 0; ++} ++ ++static int omnia_gpio_of_xlate(struct gpio_chip *gc, ++ const struct of_phandle_args *gpiospec, ++ u32 *flags) ++{ ++ u32 bank, gpio; ++ ++ if (WARN_ON(gpiospec->args_count != 3)) ++ return -EINVAL; ++ ++ if (flags) ++ *flags = gpiospec->args[2]; ++ ++ bank = gpiospec->args[0]; ++ gpio = gpiospec->args[1]; ++ ++ switch (bank) { ++ case 0: ++ return gpio < 16 ? gpio : -EINVAL; ++ case 1: ++ return gpio < 32 ? 16 + gpio : -EINVAL; ++ case 2: ++ return gpio < 16 ? 48 + gpio : -EINVAL; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static void omnia_irq_shutdown(struct irq_data *d) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(d); ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ irq_hw_number_t hwirq = irqd_to_hwirq(d); ++ u8 bit = omnia_gpios[hwirq].int_bit; ++ ++ __clear_bit(bit, &mcu->rising); ++ __clear_bit(bit, &mcu->falling); ++} ++ ++static void omnia_irq_mask(struct irq_data *d) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(d); ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ irq_hw_number_t hwirq = irqd_to_hwirq(d); ++ u8 bit = omnia_gpios[hwirq].int_bit; ++ ++ if (!omnia_gpios[hwirq].cmd) ++ __clear_bit(bit, &mcu->rising); ++ __clear_bit(bit, &mcu->mask); ++ gpiochip_disable_irq(gc, hwirq); ++} ++ ++static void omnia_irq_unmask(struct irq_data *d) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(d); ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ irq_hw_number_t hwirq = irqd_to_hwirq(d); ++ u8 bit = omnia_gpios[hwirq].int_bit; ++ ++ gpiochip_enable_irq(gc, hwirq); ++ __set_bit(bit, &mcu->mask); ++ if (!omnia_gpios[hwirq].cmd) ++ __set_bit(bit, &mcu->rising); ++} ++ ++static int omnia_irq_set_type(struct irq_data *d, unsigned int type) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(d); ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ irq_hw_number_t hwirq = irqd_to_hwirq(d); ++ struct device *dev = &mcu->client->dev; ++ u8 bit = omnia_gpios[hwirq].int_bit; ++ ++ if (!(type & IRQ_TYPE_EDGE_BOTH)) { ++ dev_err(dev, "irq %u: unsupported type %u\n", d->irq, type); ++ return -EINVAL; ++ } ++ ++ __assign_bit(bit, &mcu->rising, type & IRQ_TYPE_EDGE_RISING); ++ __assign_bit(bit, &mcu->falling, type & IRQ_TYPE_EDGE_FALLING); ++ ++ return 0; ++} ++ ++static void omnia_irq_bus_lock(struct irq_data *d) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(d); ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ ++ /* nothing to do if MCU firmware does not support new interrupt API */ ++ if (!(mcu->features & OMNIA_FEAT_NEW_INT_API)) ++ return; ++ ++ mutex_lock(&mcu->lock); ++} ++ ++/** ++ * omnia_mask_interleave - Interleaves the bytes from @rising and @falling ++ * @dst: the destination u8 array of interleaved bytes ++ * @rising: rising mask ++ * @falling: falling mask ++ * ++ * Interleaves the little-endian bytes from @rising and @falling words. ++ * ++ * If @rising = (r0, r1, r2, r3) and @falling = (f0, f1, f2, f3), the result is ++ * @dst = (r0, f0, r1, f1, r2, f2, r3, f3). ++ * ++ * The MCU receives an interrupt mask and reports a pending interrupt bitmap in ++ * this interleaved format. The rationale behind this is that the low-indexed ++ * bits are more important - in many cases, the user will be interested only in ++ * interrupts with indexes 0 to 7, and so the system can stop reading after ++ * first 2 bytes (r0, f0), to save time on the slow I2C bus. ++ * ++ * Feel free to remove this function and its inverse, omnia_mask_deinterleave, ++ * and use an appropriate bitmap_*() function once such a function exists. ++ */ ++static void ++omnia_mask_interleave(u8 *dst, unsigned long rising, unsigned long falling) ++{ ++ for (unsigned int i = 0; i < sizeof(u32); i++) { ++ dst[2 * i] = rising >> (8 * i); ++ dst[2 * i + 1] = falling >> (8 * i); ++ } ++} ++ ++/** ++ * omnia_mask_deinterleave - Deinterleaves the bytes into @rising and @falling ++ * @src: the source u8 array containing the interleaved bytes ++ * @rising: pointer where to store the rising mask gathered from @src ++ * @falling: pointer where to store the falling mask gathered from @src ++ * ++ * This is the inverse function to omnia_mask_interleave. ++ */ ++static void omnia_mask_deinterleave(const u8 *src, unsigned long *rising, ++ unsigned long *falling) ++{ ++ *rising = *falling = 0; ++ ++ for (unsigned int i = 0; i < sizeof(u32); i++) { ++ *rising |= src[2 * i] << (8 * i); ++ *falling |= src[2 * i + 1] << (8 * i); ++ } ++} ++ ++static void omnia_irq_bus_sync_unlock(struct irq_data *d) ++{ ++ struct gpio_chip *gc = irq_data_get_irq_chip_data(d); ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ struct device *dev = &mcu->client->dev; ++ u8 cmd[1 + OMNIA_CMD_INT_ARG_LEN]; ++ unsigned long rising, falling; ++ int err; ++ ++ /* nothing to do if MCU firmware does not support new interrupt API */ ++ if (!(mcu->features & OMNIA_FEAT_NEW_INT_API)) ++ return; ++ ++ cmd[0] = OMNIA_CMD_SET_INT_MASK; ++ ++ rising = mcu->rising & mcu->mask; ++ falling = mcu->falling & mcu->mask; ++ ++ /* interleave the rising and falling bytes into the command arguments */ ++ omnia_mask_interleave(&cmd[1], rising, falling); ++ ++ dev_dbg(dev, "set int mask %8ph\n", &cmd[1]); ++ ++ err = omnia_cmd_write(mcu->client, cmd, sizeof(cmd)); ++ if (err) { ++ dev_err(dev, "Cannot set mask: %d\n", err); ++ goto unlock; ++ } ++ ++ /* ++ * Remember which GPIOs have both rising and falling interrupts enabled. ++ * For those we will cache their value so that .get() method is faster. ++ * We also need to forget cached values of GPIOs that aren't cached ++ * anymore. ++ */ ++ mcu->both = rising & falling; ++ mcu->is_cached &= mcu->both; ++ ++unlock: ++ mutex_unlock(&mcu->lock); ++} ++ ++static const struct irq_chip omnia_mcu_irq_chip = { ++ .name = "Turris Omnia MCU interrupts", ++ .irq_shutdown = omnia_irq_shutdown, ++ .irq_mask = omnia_irq_mask, ++ .irq_unmask = omnia_irq_unmask, ++ .irq_set_type = omnia_irq_set_type, ++ .irq_bus_lock = omnia_irq_bus_lock, ++ .irq_bus_sync_unlock = omnia_irq_bus_sync_unlock, ++ .flags = IRQCHIP_IMMUTABLE, ++ GPIOCHIP_IRQ_RESOURCE_HELPERS, ++}; ++ ++static void omnia_irq_init_valid_mask(struct gpio_chip *gc, ++ unsigned long *valid_mask, ++ unsigned int ngpios) ++{ ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ ++ for (unsigned int i = 0; i < ngpios; i++) { ++ const struct omnia_gpio *gpio = &omnia_gpios[i]; ++ ++ if (is_int_bit_valid(gpio)) ++ __assign_bit(i, valid_mask, ++ omnia_gpio_available(mcu, gpio)); ++ else ++ __clear_bit(i, valid_mask); ++ } ++} ++ ++static int omnia_irq_init_hw(struct gpio_chip *gc) ++{ ++ struct omnia_mcu *mcu = gpiochip_get_data(gc); ++ u8 cmd[1 + OMNIA_CMD_INT_ARG_LEN] = {}; ++ ++ cmd[0] = OMNIA_CMD_SET_INT_MASK; ++ ++ return omnia_cmd_write(mcu->client, cmd, sizeof(cmd)); ++} ++ ++/* ++ * Determine how many bytes we need to read from the reply to the ++ * OMNIA_CMD_GET_INT_AND_CLEAR command in order to retrieve all unmasked ++ * interrupts. ++ */ ++static unsigned int ++omnia_irq_compute_pending_length(unsigned long rising, unsigned long falling) ++{ ++ return max(omnia_compute_reply_length(rising, true, 0), ++ omnia_compute_reply_length(falling, true, 1)); ++} ++ ++static bool omnia_irq_read_pending_new(struct omnia_mcu *mcu, ++ unsigned long *pending) ++{ ++ struct device *dev = &mcu->client->dev; ++ u8 reply[OMNIA_CMD_INT_ARG_LEN] = {}; ++ unsigned long rising, falling; ++ unsigned int len; ++ int err; ++ ++ len = omnia_irq_compute_pending_length(mcu->rising & mcu->mask, ++ mcu->falling & mcu->mask); ++ if (!len) ++ return false; ++ ++ guard(mutex)(&mcu->lock); ++ ++ err = omnia_cmd_read(mcu->client, OMNIA_CMD_GET_INT_AND_CLEAR, reply, ++ len); ++ if (err) { ++ dev_err(dev, "Cannot read pending IRQs: %d\n", err); ++ return false; ++ } ++ ++ /* deinterleave the reply bytes into rising and falling */ ++ omnia_mask_deinterleave(reply, &rising, &falling); ++ ++ rising &= mcu->mask; ++ falling &= mcu->mask; ++ *pending = rising | falling; ++ ++ /* cache values for GPIOs that have both edges enabled */ ++ mcu->is_cached &= ~(rising & falling); ++ mcu->is_cached |= mcu->both & (rising ^ falling); ++ mcu->cached = (mcu->cached | rising) & ~falling; ++ ++ return true; ++} ++ ++static int omnia_read_status_word_old_fw(struct omnia_mcu *mcu, ++ unsigned long *status) ++{ ++ u16 raw_status; ++ int err; ++ ++ err = omnia_cmd_read_u16(mcu->client, OMNIA_CMD_GET_STATUS_WORD, ++ &raw_status); ++ if (err) ++ return err; ++ ++ /* ++ * Old firmware has a bug wherein it never resets the USB port ++ * overcurrent bits back to zero. Ignore them. ++ */ ++ *status = raw_status & ~(OMNIA_STS_USB30_OVC | OMNIA_STS_USB31_OVC); ++ ++ return 0; ++} ++ ++static void button_release_emul_fn(struct work_struct *work) ++{ ++ struct omnia_mcu *mcu = container_of(to_delayed_work(work), ++ struct omnia_mcu, ++ button_release_emul_work); ++ ++ mcu->button_pressed_emul = false; ++ generic_handle_irq_safe(mcu->client->irq); ++} ++ ++static void ++fill_int_from_sts(unsigned long *rising, unsigned long *falling, ++ unsigned long rising_sts, unsigned long falling_sts, ++ unsigned long sts_bit, unsigned long int_bit) ++{ ++ if (rising_sts & sts_bit) ++ *rising |= int_bit; ++ if (falling_sts & sts_bit) ++ *falling |= int_bit; ++} ++ ++static bool omnia_irq_read_pending_old(struct omnia_mcu *mcu, ++ unsigned long *pending) ++{ ++ unsigned long status, rising_sts, falling_sts, rising, falling; ++ struct device *dev = &mcu->client->dev; ++ int err; ++ ++ guard(mutex)(&mcu->lock); ++ ++ err = omnia_read_status_word_old_fw(mcu, &status); ++ if (err) { ++ dev_err(dev, "Cannot read pending IRQs: %d\n", err); ++ return false; ++ } ++ ++ /* ++ * The old firmware triggers an interrupt whenever status word changes, ++ * but does not inform about which bits rose or fell. We need to compute ++ * this here by comparing with the last status word value. ++ * ++ * The OMNIA_STS_BUTTON_PRESSED bit needs special handling, because the ++ * old firmware clears the OMNIA_STS_BUTTON_PRESSED bit on successful ++ * completion of the OMNIA_CMD_GET_STATUS_WORD command, resulting in ++ * another interrupt: ++ * - first we get an interrupt, we read the status word where ++ * OMNIA_STS_BUTTON_PRESSED is present, ++ * - MCU clears the OMNIA_STS_BUTTON_PRESSED bit because we read the ++ * status word, ++ * - we get another interrupt because the status word changed again ++ * (the OMNIA_STS_BUTTON_PRESSED bit was cleared). ++ * ++ * The gpiolib-cdev, gpiolib-sysfs and gpio-keys input driver all call ++ * the gpiochip's .get() method after an edge event on a requested GPIO ++ * occurs. ++ * ++ * We ensure that the .get() method reads 1 for the button GPIO for some ++ * time. ++ */ ++ ++ if (status & OMNIA_STS_BUTTON_PRESSED) { ++ mcu->button_pressed_emul = true; ++ mod_delayed_work(system_wq, &mcu->button_release_emul_work, ++ msecs_to_jiffies(FRONT_BUTTON_RELEASE_DELAY_MS)); ++ } else if (mcu->button_pressed_emul) { ++ status |= OMNIA_STS_BUTTON_PRESSED; ++ } ++ ++ rising_sts = ~mcu->last_status & status; ++ falling_sts = mcu->last_status & ~status; ++ ++ mcu->last_status = status; ++ ++ /* ++ * Fill in the relevant interrupt bits from status bits for CARD_DET, ++ * MSATA_IND and BUTTON_PRESSED. ++ */ ++ rising = 0; ++ falling = 0; ++ fill_int_from_sts(&rising, &falling, rising_sts, falling_sts, ++ OMNIA_STS_CARD_DET, OMNIA_INT_CARD_DET); ++ fill_int_from_sts(&rising, &falling, rising_sts, falling_sts, ++ OMNIA_STS_MSATA_IND, OMNIA_INT_MSATA_IND); ++ fill_int_from_sts(&rising, &falling, rising_sts, falling_sts, ++ OMNIA_STS_BUTTON_PRESSED, OMNIA_INT_BUTTON_PRESSED); ++ ++ /* Use only bits that are enabled */ ++ rising &= mcu->rising & mcu->mask; ++ falling &= mcu->falling & mcu->mask; ++ *pending = rising | falling; ++ ++ return true; ++} ++ ++static bool omnia_irq_read_pending(struct omnia_mcu *mcu, ++ unsigned long *pending) ++{ ++ if (mcu->features & OMNIA_FEAT_NEW_INT_API) ++ return omnia_irq_read_pending_new(mcu, pending); ++ else ++ return omnia_irq_read_pending_old(mcu, pending); ++} ++ ++static irqreturn_t omnia_irq_thread_handler(int irq, void *dev_id) ++{ ++ struct omnia_mcu *mcu = dev_id; ++ struct irq_domain *domain; ++ unsigned long pending; ++ unsigned int i; ++ ++ if (!omnia_irq_read_pending(mcu, &pending)) ++ return IRQ_NONE; ++ ++ domain = mcu->gc.irq.domain; ++ ++ for_each_set_bit(i, &pending, 32) { ++ unsigned int nested_irq; ++ ++ nested_irq = irq_find_mapping(domain, omnia_int_to_gpio_idx[i]); ++ ++ handle_nested_irq(nested_irq); ++ } ++ ++ return IRQ_RETVAL(pending); ++} ++ ++static const char * const front_button_modes[] = { "mcu", "cpu" }; ++ ++static ssize_t front_button_mode_show(struct device *dev, ++ struct device_attribute *a, char *buf) ++{ ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ int val; ++ ++ if (mcu->features & OMNIA_FEAT_NEW_INT_API) { ++ val = omnia_cmd_read_bit(mcu->client, OMNIA_CMD_GET_STATUS_WORD, ++ OMNIA_STS_BUTTON_MODE); ++ if (val < 0) ++ return val; ++ } else { ++ val = !!(mcu->last_status & OMNIA_STS_BUTTON_MODE); ++ } ++ ++ return sysfs_emit(buf, "%s\n", front_button_modes[val]); ++} ++ ++static ssize_t front_button_mode_store(struct device *dev, ++ struct device_attribute *a, ++ const char *buf, size_t count) ++{ ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ int err, i; ++ ++ i = sysfs_match_string(front_button_modes, buf); ++ if (i < 0) ++ return i; ++ ++ err = omnia_ctl_cmd_locked(mcu, OMNIA_CMD_GENERAL_CONTROL, ++ i ? OMNIA_CTL_BUTTON_MODE : 0, ++ OMNIA_CTL_BUTTON_MODE); ++ if (err) ++ return err; ++ ++ return count; ++} ++static DEVICE_ATTR_RW(front_button_mode); ++ ++static struct attribute *omnia_mcu_gpio_attrs[] = { ++ &dev_attr_front_button_mode.attr, ++ NULL ++}; ++ ++const struct attribute_group omnia_mcu_gpio_group = { ++ .attrs = omnia_mcu_gpio_attrs, ++}; ++ ++int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu) ++{ ++ bool new_api = mcu->features & OMNIA_FEAT_NEW_INT_API; ++ struct device *dev = &mcu->client->dev; ++ unsigned long irqflags; ++ int err; ++ ++ err = devm_mutex_init(dev, &mcu->lock); ++ if (err) ++ return err; ++ ++ mcu->gc.request = omnia_gpio_request; ++ mcu->gc.get_direction = omnia_gpio_get_direction; ++ mcu->gc.direction_input = omnia_gpio_direction_input; ++ mcu->gc.direction_output = omnia_gpio_direction_output; ++ mcu->gc.get = omnia_gpio_get; ++ mcu->gc.get_multiple = omnia_gpio_get_multiple; ++ mcu->gc.set = omnia_gpio_set; ++ mcu->gc.set_multiple = omnia_gpio_set_multiple; ++ mcu->gc.init_valid_mask = omnia_gpio_init_valid_mask; ++ mcu->gc.can_sleep = true; ++ mcu->gc.names = omnia_mcu_gpio_templates; ++ mcu->gc.base = -1; ++ mcu->gc.ngpio = ARRAY_SIZE(omnia_gpios); ++ mcu->gc.label = "Turris Omnia MCU GPIOs"; ++ mcu->gc.parent = dev; ++ mcu->gc.owner = THIS_MODULE; ++ mcu->gc.of_gpio_n_cells = 3; ++ mcu->gc.of_xlate = omnia_gpio_of_xlate; ++ ++ gpio_irq_chip_set_chip(&mcu->gc.irq, &omnia_mcu_irq_chip); ++ /* This will let us handle the parent IRQ in the driver */ ++ mcu->gc.irq.parent_handler = NULL; ++ mcu->gc.irq.num_parents = 0; ++ mcu->gc.irq.parents = NULL; ++ mcu->gc.irq.default_type = IRQ_TYPE_NONE; ++ mcu->gc.irq.handler = handle_bad_irq; ++ mcu->gc.irq.threaded = true; ++ if (new_api) ++ mcu->gc.irq.init_hw = omnia_irq_init_hw; ++ mcu->gc.irq.init_valid_mask = omnia_irq_init_valid_mask; ++ ++ err = devm_gpiochip_add_data(dev, &mcu->gc, mcu); ++ if (err) ++ return dev_err_probe(dev, err, "Cannot add GPIO chip\n"); ++ ++ /* ++ * Before requesting the interrupt, if firmware does not support the new ++ * interrupt API, we need to cache the value of the status word, so that ++ * when it changes, we may compare the new value with the cached one in ++ * the interrupt handler. ++ */ ++ if (!new_api) { ++ err = omnia_read_status_word_old_fw(mcu, &mcu->last_status); ++ if (err) ++ return dev_err_probe(dev, err, ++ "Cannot read status word\n"); ++ ++ INIT_DELAYED_WORK(&mcu->button_release_emul_work, ++ button_release_emul_fn); ++ } ++ ++ irqflags = IRQF_ONESHOT; ++ if (new_api) ++ irqflags |= IRQF_TRIGGER_LOW; ++ else ++ irqflags |= IRQF_TRIGGER_FALLING; ++ ++ err = devm_request_threaded_irq(dev, mcu->client->irq, NULL, ++ omnia_irq_thread_handler, irqflags, ++ "turris-omnia-mcu", mcu); ++ if (err) ++ return dev_err_probe(dev, err, "Cannot request IRQ\n"); ++ ++ if (!new_api) { ++ /* ++ * The button_release_emul_work has to be initialized before the ++ * thread is requested, and on driver remove it needs to be ++ * canceled before the thread is freed. Therefore we can't use ++ * devm_delayed_work_autocancel() directly, because the order ++ * devm_delayed_work_autocancel(); ++ * devm_request_threaded_irq(); ++ * would cause improper release order: ++ * free_irq(); ++ * cancel_delayed_work_sync(); ++ * Instead we first initialize the work above, and only now ++ * after IRQ is requested we add the work devm action. ++ */ ++ err = devm_add_action(dev, devm_delayed_work_drop, ++ &mcu->button_release_emul_work); ++ if (err) ++ return err; ++ } ++ ++ return 0; ++} +--- a/drivers/platform/cznic/turris-omnia-mcu.h ++++ b/drivers/platform/cznic/turris-omnia-mcu.h +@@ -8,8 +8,12 @@ + #ifndef __TURRIS_OMNIA_MCU_H + #define __TURRIS_OMNIA_MCU_H + ++#include ++#include + #include ++#include + #include ++#include + #include + + struct i2c_client; +@@ -23,18 +27,78 @@ struct omnia_mcu { + u64 board_serial_number; + u8 board_first_mac[ETH_ALEN]; + u8 board_revision; ++ ++ /* GPIO chip */ ++ struct gpio_chip gc; ++ struct mutex lock; ++ unsigned long mask, rising, falling, both, cached, is_cached; ++ /* Old MCU firmware handling needs the following */ ++ struct delayed_work button_release_emul_work; ++ unsigned long last_status; ++ bool button_pressed_emul; + }; + + int omnia_cmd_write_read(const struct i2c_client *client, + void *cmd, unsigned int cmd_len, + void *reply, unsigned int reply_len); + ++static inline int omnia_cmd_write(const struct i2c_client *client, void *cmd, ++ unsigned int len) ++{ ++ return omnia_cmd_write_read(client, cmd, len, NULL, 0); ++} ++ + static inline int omnia_cmd_read(const struct i2c_client *client, u8 cmd, + void *reply, unsigned int len) + { + return omnia_cmd_write_read(client, &cmd, 1, reply, len); + } + ++static inline unsigned int ++omnia_compute_reply_length(unsigned long mask, bool interleaved, ++ unsigned int offset) ++{ ++ if (!mask) ++ return 0; ++ ++ return ((__fls(mask) >> 3) << interleaved) + 1 + offset; ++} ++ ++/* Returns 0 on success */ ++static inline int omnia_cmd_read_bits(const struct i2c_client *client, u8 cmd, ++ unsigned long bits, unsigned long *dst) ++{ ++ __le32 reply; ++ int err; ++ ++ if (!bits) { ++ *dst = 0; ++ return 0; ++ } ++ ++ err = omnia_cmd_read(client, cmd, &reply, ++ omnia_compute_reply_length(bits, false, 0)); ++ if (err) ++ return err; ++ ++ *dst = le32_to_cpu(reply) & bits; ++ ++ return 0; ++} ++ ++static inline int omnia_cmd_read_bit(const struct i2c_client *client, u8 cmd, ++ unsigned long bit) ++{ ++ unsigned long reply; ++ int err; ++ ++ err = omnia_cmd_read_bits(client, cmd, bit, &reply); ++ if (err) ++ return err; ++ ++ return !!reply; ++} ++ + static inline int omnia_cmd_read_u32(const struct i2c_client *client, u8 cmd, + u32 *dst) + { +@@ -71,4 +135,8 @@ static inline int omnia_cmd_read_u8(cons + return omnia_cmd_read(client, cmd, reply, sizeof(*reply)); + } + ++extern const struct attribute_group omnia_mcu_gpio_group; ++ ++int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu); ++ + #endif /* __TURRIS_OMNIA_MCU_H */ diff --git a/lede/target/linux/mvebu/patches-6.6/820-v6.11-04-platform-cznic-turris-omnia-mcu-Add-support-for-powe.patch b/lede/target/linux/mvebu/patches-6.6/820-v6.11-04-platform-cznic-turris-omnia-mcu-Add-support-for-powe.patch new file mode 100644 index 0000000000..2ef6242d70 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/820-v6.11-04-platform-cznic-turris-omnia-mcu-Add-support-for-powe.patch @@ -0,0 +1,415 @@ +From f69e0a731ab471f3a57c48258ad2d9990820c173 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 1 Jul 2024 13:30:06 +0200 +Subject: [PATCH 04/11] platform: cznic: turris-omnia-mcu: Add support for + poweroff and wakeup +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add support for true board poweroff (MCU can disable all unnecessary +voltage regulators) and wakeup at a specified time, implemented via a +RTC driver so that the rtcwake utility can be used to configure it. + +Signed-off-by: Marek Behún +Reviewed-by: Andy Shevchenko +Acked-by: Alexandre Belloni +Acked-by: Bartosz Golaszewski +Link: https://lore.kernel.org/r/20240701113010.16447-5-kabel@kernel.org +Signed-off-by: Arnd Bergmann +--- + .../sysfs-bus-i2c-devices-turris-omnia-mcu | 16 ++ + drivers/platform/cznic/Kconfig | 4 + + drivers/platform/cznic/Makefile | 1 + + .../platform/cznic/turris-omnia-mcu-base.c | 5 + + .../cznic/turris-omnia-mcu-sys-off-wakeup.c | 260 ++++++++++++++++++ + drivers/platform/cznic/turris-omnia-mcu.h | 20 ++ + 6 files changed, 306 insertions(+) + create mode 100644 drivers/platform/cznic/turris-omnia-mcu-sys-off-wakeup.c + +--- a/Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu ++++ b/Documentation/ABI/testing/sysfs-bus-i2c-devices-turris-omnia-mcu +@@ -38,6 +38,22 @@ Description: (RW) The front button on th + + Format: %s. + ++What: /sys/bus/i2c/devices//front_button_poweron ++Date: September 2024 ++KernelVersion: 6.11 ++Contact: Marek Behún ++Description: (RW) Newer versions of the microcontroller firmware of the ++ Turris Omnia router support powering off the router into true ++ low power mode. The router can be powered on by pressing the ++ front button. ++ ++ This file configures whether front button power on is enabled. ++ ++ This file is present only if the power off feature is supported ++ by the firmware. ++ ++ Format: %i. ++ + What: /sys/bus/i2c/devices//fw_features + Date: September 2024 + KernelVersion: 6.11 +--- a/drivers/platform/cznic/Kconfig ++++ b/drivers/platform/cznic/Kconfig +@@ -18,10 +18,14 @@ config TURRIS_OMNIA_MCU + depends on I2C + select GPIOLIB + select GPIOLIB_IRQCHIP ++ select RTC_CLASS + help + Say Y here to add support for the features implemented by the + microcontroller on the CZ.NIC's Turris Omnia SOHO router. + The features include: ++ - board poweroff into true low power mode (with voltage regulators ++ disabled) and the ability to configure wake up from this mode (via ++ rtcwake) + - GPIO pins + - to get front button press events (the front button can be + configured either to generate press events to the CPU or to change +--- a/drivers/platform/cznic/Makefile ++++ b/drivers/platform/cznic/Makefile +@@ -3,3 +3,4 @@ + obj-$(CONFIG_TURRIS_OMNIA_MCU) += turris-omnia-mcu.o + turris-omnia-mcu-y := turris-omnia-mcu-base.o + turris-omnia-mcu-y += turris-omnia-mcu-gpio.o ++turris-omnia-mcu-y += turris-omnia-mcu-sys-off-wakeup.o +--- a/drivers/platform/cznic/turris-omnia-mcu-base.c ++++ b/drivers/platform/cznic/turris-omnia-mcu-base.c +@@ -197,6 +197,7 @@ static const struct attribute_group omni + static const struct attribute_group *omnia_mcu_groups[] = { + &omnia_mcu_base_group, + &omnia_mcu_gpio_group, ++ &omnia_mcu_poweroff_group, + NULL + }; + +@@ -371,6 +372,10 @@ static int omnia_mcu_probe(struct i2c_cl + "Cannot read board info\n"); + } + ++ err = omnia_mcu_register_sys_off_and_wakeup(mcu); ++ if (err) ++ return err; ++ + return omnia_mcu_register_gpiochip(mcu); + } + +--- /dev/null ++++ b/drivers/platform/cznic/turris-omnia-mcu-sys-off-wakeup.c +@@ -0,0 +1,260 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * CZ.NIC's Turris Omnia MCU system off and RTC wakeup driver ++ * ++ * This is not a true RTC driver (in the sense that it does not provide a ++ * real-time clock), rather the MCU implements a wakeup from powered off state ++ * at a specified time relative to MCU boot, and we expose this feature via RTC ++ * alarm, so that it can be used via the rtcwake command, which is the standard ++ * Linux command for this. ++ * ++ * 2024 by Marek Behún ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "turris-omnia-mcu.h" ++ ++static int omnia_get_uptime_wakeup(const struct i2c_client *client, u32 *uptime, ++ u32 *wakeup) ++{ ++ __le32 reply[2]; ++ int err; ++ ++ err = omnia_cmd_read(client, OMNIA_CMD_GET_UPTIME_AND_WAKEUP, reply, ++ sizeof(reply)); ++ if (err) ++ return err; ++ ++ if (uptime) ++ *uptime = le32_to_cpu(reply[0]); ++ ++ if (wakeup) ++ *wakeup = le32_to_cpu(reply[1]); ++ ++ return 0; ++} ++ ++static int omnia_read_time(struct device *dev, struct rtc_time *tm) ++{ ++ u32 uptime; ++ int err; ++ ++ err = omnia_get_uptime_wakeup(to_i2c_client(dev), &uptime, NULL); ++ if (err) ++ return err; ++ ++ rtc_time64_to_tm(uptime, tm); ++ ++ return 0; ++} ++ ++static int omnia_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct omnia_mcu *mcu = i2c_get_clientdata(client); ++ u32 wakeup; ++ int err; ++ ++ err = omnia_get_uptime_wakeup(client, NULL, &wakeup); ++ if (err) ++ return err; ++ ++ alrm->enabled = !!wakeup; ++ rtc_time64_to_tm(wakeup ?: mcu->rtc_alarm, &alrm->time); ++ ++ return 0; ++} ++ ++static int omnia_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct omnia_mcu *mcu = i2c_get_clientdata(client); ++ ++ mcu->rtc_alarm = rtc_tm_to_time64(&alrm->time); ++ ++ if (alrm->enabled) ++ return omnia_cmd_write_u32(client, OMNIA_CMD_SET_WAKEUP, ++ mcu->rtc_alarm); ++ ++ return 0; ++} ++ ++static int omnia_alarm_irq_enable(struct device *dev, unsigned int enabled) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct omnia_mcu *mcu = i2c_get_clientdata(client); ++ ++ return omnia_cmd_write_u32(client, OMNIA_CMD_SET_WAKEUP, ++ enabled ? mcu->rtc_alarm : 0); ++} ++ ++static const struct rtc_class_ops omnia_rtc_ops = { ++ .read_time = omnia_read_time, ++ .read_alarm = omnia_read_alarm, ++ .set_alarm = omnia_set_alarm, ++ .alarm_irq_enable = omnia_alarm_irq_enable, ++}; ++ ++static int omnia_power_off(struct sys_off_data *data) ++{ ++ struct omnia_mcu *mcu = data->cb_data; ++ __be32 tmp; ++ u8 cmd[9]; ++ u16 arg; ++ int err; ++ ++ if (mcu->front_button_poweron) ++ arg = OMNIA_CMD_POWER_OFF_POWERON_BUTTON; ++ else ++ arg = 0; ++ ++ cmd[0] = OMNIA_CMD_POWER_OFF; ++ put_unaligned_le16(OMNIA_CMD_POWER_OFF_MAGIC, &cmd[1]); ++ put_unaligned_le16(arg, &cmd[3]); ++ ++ /* ++ * Although all values from and to MCU are passed in little-endian, the ++ * MCU's CRC unit uses big-endian CRC32 polynomial (0x04c11db7), so we ++ * need to use crc32_be() here. ++ */ ++ tmp = cpu_to_be32(get_unaligned_le32(&cmd[1])); ++ put_unaligned_le32(crc32_be(~0, (void *)&tmp, sizeof(tmp)), &cmd[5]); ++ ++ err = omnia_cmd_write(mcu->client, cmd, sizeof(cmd)); ++ if (err) ++ dev_err(&mcu->client->dev, ++ "Unable to send the poweroff command: %d\n", err); ++ ++ return NOTIFY_DONE; ++} ++ ++static int omnia_restart(struct sys_off_data *data) ++{ ++ struct omnia_mcu *mcu = data->cb_data; ++ u8 cmd[3]; ++ int err; ++ ++ cmd[0] = OMNIA_CMD_GENERAL_CONTROL; ++ ++ if (reboot_mode == REBOOT_HARD) ++ cmd[1] = cmd[2] = OMNIA_CTL_HARD_RST; ++ else ++ cmd[1] = cmd[2] = OMNIA_CTL_LIGHT_RST; ++ ++ err = omnia_cmd_write(mcu->client, cmd, sizeof(cmd)); ++ if (err) ++ dev_err(&mcu->client->dev, ++ "Unable to send the restart command: %d\n", err); ++ ++ /* ++ * MCU needs a little bit to process the I2C command, otherwise it will ++ * do a light reset based on SOC SYSRES_OUT pin. ++ */ ++ mdelay(1); ++ ++ return NOTIFY_DONE; ++} ++ ++static ssize_t front_button_poweron_show(struct device *dev, ++ struct device_attribute *a, char *buf) ++{ ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ ++ return sysfs_emit(buf, "%d\n", mcu->front_button_poweron); ++} ++ ++static ssize_t front_button_poweron_store(struct device *dev, ++ struct device_attribute *a, ++ const char *buf, size_t count) ++{ ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ bool val; ++ int err; ++ ++ err = kstrtobool(buf, &val); ++ if (err) ++ return err; ++ ++ mcu->front_button_poweron = val; ++ ++ return count; ++} ++static DEVICE_ATTR_RW(front_button_poweron); ++ ++static struct attribute *omnia_mcu_poweroff_attrs[] = { ++ &dev_attr_front_button_poweron.attr, ++ NULL ++}; ++ ++static umode_t poweroff_attrs_visible(struct kobject *kobj, struct attribute *a, ++ int n) ++{ ++ struct device *dev = kobj_to_dev(kobj); ++ struct omnia_mcu *mcu = dev_get_drvdata(dev); ++ ++ if (mcu->features & OMNIA_FEAT_POWEROFF_WAKEUP) ++ return a->mode; ++ ++ return 0; ++} ++ ++const struct attribute_group omnia_mcu_poweroff_group = { ++ .attrs = omnia_mcu_poweroff_attrs, ++ .is_visible = poweroff_attrs_visible, ++}; ++ ++int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu) ++{ ++ struct device *dev = &mcu->client->dev; ++ int err; ++ ++ /* MCU restart is always available */ ++ err = devm_register_sys_off_handler(dev, SYS_OFF_MODE_RESTART, ++ SYS_OFF_PRIO_FIRMWARE, ++ omnia_restart, mcu); ++ if (err) ++ return dev_err_probe(dev, err, ++ "Cannot register system restart handler\n"); ++ ++ /* ++ * Poweroff and wakeup are available only if POWEROFF_WAKEUP feature is ++ * present. ++ */ ++ if (!(mcu->features & OMNIA_FEAT_POWEROFF_WAKEUP)) ++ return 0; ++ ++ err = devm_register_sys_off_handler(dev, SYS_OFF_MODE_POWER_OFF, ++ SYS_OFF_PRIO_FIRMWARE, ++ omnia_power_off, mcu); ++ if (err) ++ return dev_err_probe(dev, err, ++ "Cannot register system power off handler\n"); ++ ++ mcu->rtcdev = devm_rtc_allocate_device(dev); ++ if (IS_ERR(mcu->rtcdev)) ++ return dev_err_probe(dev, PTR_ERR(mcu->rtcdev), ++ "Cannot allocate RTC device\n"); ++ ++ mcu->rtcdev->ops = &omnia_rtc_ops; ++ mcu->rtcdev->range_max = U32_MAX; ++ set_bit(RTC_FEATURE_ALARM_WAKEUP_ONLY, mcu->rtcdev->features); ++ ++ err = devm_rtc_register_device(mcu->rtcdev); ++ if (err) ++ return dev_err_probe(dev, err, "Cannot register RTC device\n"); ++ ++ mcu->front_button_poweron = true; ++ ++ return 0; ++} +--- a/drivers/platform/cznic/turris-omnia-mcu.h ++++ b/drivers/platform/cznic/turris-omnia-mcu.h +@@ -15,8 +15,10 @@ + #include + #include + #include ++#include + + struct i2c_client; ++struct rtc_device; + + struct omnia_mcu { + struct i2c_client *client; +@@ -36,6 +38,11 @@ struct omnia_mcu { + struct delayed_work button_release_emul_work; + unsigned long last_status; + bool button_pressed_emul; ++ ++ /* RTC device for configuring wake-up */ ++ struct rtc_device *rtcdev; ++ u32 rtc_alarm; ++ bool front_button_poweron; + }; + + int omnia_cmd_write_read(const struct i2c_client *client, +@@ -48,6 +55,17 @@ static inline int omnia_cmd_write(const + return omnia_cmd_write_read(client, cmd, len, NULL, 0); + } + ++static inline int omnia_cmd_write_u32(const struct i2c_client *client, u8 cmd, ++ u32 val) ++{ ++ u8 buf[5]; ++ ++ buf[0] = cmd; ++ put_unaligned_le32(val, &buf[1]); ++ ++ return omnia_cmd_write(client, buf, sizeof(buf)); ++} ++ + static inline int omnia_cmd_read(const struct i2c_client *client, u8 cmd, + void *reply, unsigned int len) + { +@@ -136,7 +154,9 @@ static inline int omnia_cmd_read_u8(cons + } + + extern const struct attribute_group omnia_mcu_gpio_group; ++extern const struct attribute_group omnia_mcu_poweroff_group; + + int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu); ++int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu); + + #endif /* __TURRIS_OMNIA_MCU_H */ diff --git a/lede/target/linux/mvebu/patches-6.6/820-v6.11-05-platform-cznic-turris-omnia-mcu-Add-support-for-MCU-.patch b/lede/target/linux/mvebu/patches-6.6/820-v6.11-05-platform-cznic-turris-omnia-mcu-Add-support-for-MCU-.patch new file mode 100644 index 0000000000..cf3f88bfcf --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/820-v6.11-05-platform-cznic-turris-omnia-mcu-Add-support-for-MCU-.patch @@ -0,0 +1,250 @@ +From 33ae4e4c86bc6ff298489fb8b743e2743dd0af6d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 1 Jul 2024 13:30:07 +0200 +Subject: [PATCH 05/11] platform: cznic: turris-omnia-mcu: Add support for MCU + watchdog +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add support for the watchdog mechanism provided by the MCU. + +Signed-off-by: Marek Behún +Reviewed-by: Andy Shevchenko +Reviewed-by: Guenter Roeck +Acked-by: Bartosz Golaszewski +Link: https://lore.kernel.org/r/20240701113010.16447-6-kabel@kernel.org +Signed-off-by: Arnd Bergmann +--- + drivers/platform/cznic/Kconfig | 2 + + drivers/platform/cznic/Makefile | 1 + + .../platform/cznic/turris-omnia-mcu-base.c | 4 + + .../cznic/turris-omnia-mcu-watchdog.c | 130 ++++++++++++++++++ + drivers/platform/cznic/turris-omnia-mcu.h | 24 ++++ + 5 files changed, 161 insertions(+) + create mode 100644 drivers/platform/cznic/turris-omnia-mcu-watchdog.c + +--- a/drivers/platform/cznic/Kconfig ++++ b/drivers/platform/cznic/Kconfig +@@ -19,6 +19,7 @@ config TURRIS_OMNIA_MCU + select GPIOLIB + select GPIOLIB_IRQCHIP + select RTC_CLASS ++ select WATCHDOG_CORE + help + Say Y here to add support for the features implemented by the + microcontroller on the CZ.NIC's Turris Omnia SOHO router. +@@ -26,6 +27,7 @@ config TURRIS_OMNIA_MCU + - board poweroff into true low power mode (with voltage regulators + disabled) and the ability to configure wake up from this mode (via + rtcwake) ++ - MCU watchdog + - GPIO pins + - to get front button press events (the front button can be + configured either to generate press events to the CPU or to change +--- a/drivers/platform/cznic/Makefile ++++ b/drivers/platform/cznic/Makefile +@@ -4,3 +4,4 @@ obj-$(CONFIG_TURRIS_OMNIA_MCU) += turris + turris-omnia-mcu-y := turris-omnia-mcu-base.o + turris-omnia-mcu-y += turris-omnia-mcu-gpio.o + turris-omnia-mcu-y += turris-omnia-mcu-sys-off-wakeup.o ++turris-omnia-mcu-y += turris-omnia-mcu-watchdog.o +--- a/drivers/platform/cznic/turris-omnia-mcu-base.c ++++ b/drivers/platform/cznic/turris-omnia-mcu-base.c +@@ -376,6 +376,10 @@ static int omnia_mcu_probe(struct i2c_cl + if (err) + return err; + ++ err = omnia_mcu_register_watchdog(mcu); ++ if (err) ++ return err; ++ + return omnia_mcu_register_gpiochip(mcu); + } + +--- /dev/null ++++ b/drivers/platform/cznic/turris-omnia-mcu-watchdog.c +@@ -0,0 +1,130 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * CZ.NIC's Turris Omnia MCU watchdog driver ++ * ++ * 2024 by Marek Behún ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "turris-omnia-mcu.h" ++ ++#define WATCHDOG_TIMEOUT 120 ++ ++static unsigned int timeout; ++module_param(timeout, int, 0); ++MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds"); ++ ++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 omnia_wdt_start(struct watchdog_device *wdt) ++{ ++ struct omnia_mcu *mcu = watchdog_get_drvdata(wdt); ++ ++ return omnia_cmd_write_u8(mcu->client, OMNIA_CMD_SET_WATCHDOG_STATE, 1); ++} ++ ++static int omnia_wdt_stop(struct watchdog_device *wdt) ++{ ++ struct omnia_mcu *mcu = watchdog_get_drvdata(wdt); ++ ++ return omnia_cmd_write_u8(mcu->client, OMNIA_CMD_SET_WATCHDOG_STATE, 0); ++} ++ ++static int omnia_wdt_ping(struct watchdog_device *wdt) ++{ ++ struct omnia_mcu *mcu = watchdog_get_drvdata(wdt); ++ ++ return omnia_cmd_write_u8(mcu->client, OMNIA_CMD_SET_WATCHDOG_STATE, 1); ++} ++ ++static int omnia_wdt_set_timeout(struct watchdog_device *wdt, ++ unsigned int timeout) ++{ ++ struct omnia_mcu *mcu = watchdog_get_drvdata(wdt); ++ ++ return omnia_cmd_write_u16(mcu->client, OMNIA_CMD_SET_WDT_TIMEOUT, ++ timeout * DECI); ++} ++ ++static unsigned int omnia_wdt_get_timeleft(struct watchdog_device *wdt) ++{ ++ struct omnia_mcu *mcu = watchdog_get_drvdata(wdt); ++ u16 timeleft; ++ int err; ++ ++ err = omnia_cmd_read_u16(mcu->client, OMNIA_CMD_GET_WDT_TIMELEFT, ++ &timeleft); ++ if (err) { ++ dev_err(&mcu->client->dev, "Cannot get watchdog timeleft: %d\n", ++ err); ++ return 0; ++ } ++ ++ return timeleft / DECI; ++} ++ ++static const struct watchdog_info omnia_wdt_info = { ++ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, ++ .identity = "Turris Omnia MCU Watchdog", ++}; ++ ++static const struct watchdog_ops omnia_wdt_ops = { ++ .owner = THIS_MODULE, ++ .start = omnia_wdt_start, ++ .stop = omnia_wdt_stop, ++ .ping = omnia_wdt_ping, ++ .set_timeout = omnia_wdt_set_timeout, ++ .get_timeleft = omnia_wdt_get_timeleft, ++}; ++ ++int omnia_mcu_register_watchdog(struct omnia_mcu *mcu) ++{ ++ struct device *dev = &mcu->client->dev; ++ u8 state; ++ int err; ++ ++ if (!(mcu->features & OMNIA_FEAT_WDT_PING)) ++ return 0; ++ ++ mcu->wdt.info = &omnia_wdt_info; ++ mcu->wdt.ops = &omnia_wdt_ops; ++ mcu->wdt.parent = dev; ++ mcu->wdt.min_timeout = 1; ++ mcu->wdt.max_timeout = 65535 / DECI; ++ ++ mcu->wdt.timeout = WATCHDOG_TIMEOUT; ++ watchdog_init_timeout(&mcu->wdt, timeout, dev); ++ ++ watchdog_set_drvdata(&mcu->wdt, mcu); ++ ++ omnia_wdt_set_timeout(&mcu->wdt, mcu->wdt.timeout); ++ ++ err = omnia_cmd_read_u8(mcu->client, OMNIA_CMD_GET_WATCHDOG_STATE, ++ &state); ++ if (err) ++ return dev_err_probe(dev, err, ++ "Cannot get MCU watchdog state\n"); ++ ++ if (state) ++ set_bit(WDOG_HW_RUNNING, &mcu->wdt.status); ++ ++ watchdog_set_nowayout(&mcu->wdt, nowayout); ++ watchdog_stop_on_reboot(&mcu->wdt); ++ err = devm_watchdog_register_device(dev, &mcu->wdt); ++ if (err) ++ return dev_err_probe(dev, err, ++ "Cannot register MCU watchdog\n"); ++ ++ return 0; ++} +--- a/drivers/platform/cznic/turris-omnia-mcu.h ++++ b/drivers/platform/cznic/turris-omnia-mcu.h +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -43,6 +44,9 @@ struct omnia_mcu { + struct rtc_device *rtcdev; + u32 rtc_alarm; + bool front_button_poweron; ++ ++ /* MCU watchdog */ ++ struct watchdog_device wdt; + }; + + int omnia_cmd_write_read(const struct i2c_client *client, +@@ -55,6 +59,25 @@ static inline int omnia_cmd_write(const + return omnia_cmd_write_read(client, cmd, len, NULL, 0); + } + ++static inline int omnia_cmd_write_u8(const struct i2c_client *client, u8 cmd, ++ u8 val) ++{ ++ u8 buf[2] = { cmd, val }; ++ ++ return omnia_cmd_write(client, buf, sizeof(buf)); ++} ++ ++static inline int omnia_cmd_write_u16(const struct i2c_client *client, u8 cmd, ++ u16 val) ++{ ++ u8 buf[3]; ++ ++ buf[0] = cmd; ++ put_unaligned_le16(val, &buf[1]); ++ ++ return omnia_cmd_write(client, buf, sizeof(buf)); ++} ++ + static inline int omnia_cmd_write_u32(const struct i2c_client *client, u8 cmd, + u32 val) + { +@@ -158,5 +181,6 @@ extern const struct attribute_group omni + + int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu); + int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu); ++int omnia_mcu_register_watchdog(struct omnia_mcu *mcu); + + #endif /* __TURRIS_OMNIA_MCU_H */ diff --git a/lede/target/linux/mvebu/patches-6.6/820-v6.11-06-platform-cznic-turris-omnia-mcu-Add-support-for-MCU-.patch b/lede/target/linux/mvebu/patches-6.6/820-v6.11-06-platform-cznic-turris-omnia-mcu-Add-support-for-MCU-.patch new file mode 100644 index 0000000000..35387e34c7 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/820-v6.11-06-platform-cznic-turris-omnia-mcu-Add-support-for-MCU-.patch @@ -0,0 +1,225 @@ +From b3ed8645c45567b598bef0868dca166f8ed166a0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 1 Jul 2024 13:30:08 +0200 +Subject: [PATCH 06/11] platform: cznic: turris-omnia-mcu: Add support for MCU + provided TRNG +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add support for true random number generator provided by the MCU. +New Omnia boards come without the Atmel SHA204-A chip. Instead the +crypto functionality is provided by new microcontroller, which has +a TRNG peripheral. + +Signed-off-by: Marek Behún +Acked-by: Bartosz Golaszewski +Link: https://lore.kernel.org/r/20240701113010.16447-7-kabel@kernel.org +Signed-off-by: Arnd Bergmann +--- + drivers/platform/cznic/Kconfig | 2 + + drivers/platform/cznic/Makefile | 1 + + .../platform/cznic/turris-omnia-mcu-base.c | 6 +- + .../platform/cznic/turris-omnia-mcu-gpio.c | 2 +- + .../platform/cznic/turris-omnia-mcu-trng.c | 105 ++++++++++++++++++ + drivers/platform/cznic/turris-omnia-mcu.h | 8 ++ + 6 files changed, 122 insertions(+), 2 deletions(-) + create mode 100644 drivers/platform/cznic/turris-omnia-mcu-trng.c + +--- a/drivers/platform/cznic/Kconfig ++++ b/drivers/platform/cznic/Kconfig +@@ -18,6 +18,7 @@ config TURRIS_OMNIA_MCU + depends on I2C + select GPIOLIB + select GPIOLIB_IRQCHIP ++ select HW_RANDOM + select RTC_CLASS + select WATCHDOG_CORE + help +@@ -27,6 +28,7 @@ config TURRIS_OMNIA_MCU + - board poweroff into true low power mode (with voltage regulators + disabled) and the ability to configure wake up from this mode (via + rtcwake) ++ - true random number generator (if available on the MCU) + - MCU watchdog + - GPIO pins + - to get front button press events (the front button can be +--- a/drivers/platform/cznic/Makefile ++++ b/drivers/platform/cznic/Makefile +@@ -4,4 +4,5 @@ obj-$(CONFIG_TURRIS_OMNIA_MCU) += turris + turris-omnia-mcu-y := turris-omnia-mcu-base.o + turris-omnia-mcu-y += turris-omnia-mcu-gpio.o + turris-omnia-mcu-y += turris-omnia-mcu-sys-off-wakeup.o ++turris-omnia-mcu-y += turris-omnia-mcu-trng.o + turris-omnia-mcu-y += turris-omnia-mcu-watchdog.o +--- a/drivers/platform/cznic/turris-omnia-mcu-base.c ++++ b/drivers/platform/cznic/turris-omnia-mcu-base.c +@@ -380,7 +380,11 @@ static int omnia_mcu_probe(struct i2c_cl + if (err) + return err; + +- return omnia_mcu_register_gpiochip(mcu); ++ err = omnia_mcu_register_gpiochip(mcu); ++ if (err) ++ return err; ++ ++ return omnia_mcu_register_trng(mcu); + } + + static const struct of_device_id of_omnia_mcu_match[] = { +--- a/drivers/platform/cznic/turris-omnia-mcu-gpio.c ++++ b/drivers/platform/cznic/turris-omnia-mcu-gpio.c +@@ -194,7 +194,7 @@ static const struct omnia_gpio omnia_gpi + }; + + /* mapping from interrupts to indexes of GPIOs in the omnia_gpios array */ +-static const u8 omnia_int_to_gpio_idx[32] = { ++const u8 omnia_int_to_gpio_idx[32] = { + [__bf_shf(OMNIA_INT_CARD_DET)] = 4, + [__bf_shf(OMNIA_INT_MSATA_IND)] = 5, + [__bf_shf(OMNIA_INT_USB30_OVC)] = 6, +--- /dev/null ++++ b/drivers/platform/cznic/turris-omnia-mcu-trng.c +@@ -0,0 +1,105 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * CZ.NIC's Turris Omnia MCU TRNG driver ++ * ++ * 2024 by Marek Behún ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../../gpio/gpiolib.h" ++ ++#include ++#include "turris-omnia-mcu.h" ++ ++#define OMNIA_CMD_TRNG_MAX_ENTROPY_LEN 64 ++ ++static irqreturn_t omnia_trng_irq_handler(int irq, void *dev_id) ++{ ++ struct omnia_mcu *mcu = dev_id; ++ ++ complete(&mcu->trng_entropy_ready); ++ ++ return IRQ_HANDLED; ++} ++ ++static int omnia_trng_read(struct hwrng *rng, void *data, size_t max, bool wait) ++{ ++ struct omnia_mcu *mcu = container_of(rng, struct omnia_mcu, trng); ++ u8 reply[1 + OMNIA_CMD_TRNG_MAX_ENTROPY_LEN]; ++ int err, bytes; ++ ++ if (!wait && !completion_done(&mcu->trng_entropy_ready)) ++ return 0; ++ ++ do { ++ if (wait_for_completion_interruptible(&mcu->trng_entropy_ready)) ++ return -ERESTARTSYS; ++ ++ err = omnia_cmd_read(mcu->client, ++ OMNIA_CMD_TRNG_COLLECT_ENTROPY, ++ reply, sizeof(reply)); ++ if (err) ++ return err; ++ ++ bytes = min3(reply[0], max, OMNIA_CMD_TRNG_MAX_ENTROPY_LEN); ++ } while (wait && !bytes); ++ ++ memcpy(data, &reply[1], bytes); ++ ++ return bytes; ++} ++ ++int omnia_mcu_register_trng(struct omnia_mcu *mcu) ++{ ++ struct device *dev = &mcu->client->dev; ++ u8 irq_idx, dummy; ++ int irq, err; ++ ++ if (!(mcu->features & OMNIA_FEAT_TRNG)) ++ return 0; ++ ++ irq_idx = omnia_int_to_gpio_idx[__bf_shf(OMNIA_INT_TRNG)]; ++ irq = gpiod_to_irq(gpiochip_get_desc(&mcu->gc, irq_idx)); ++ if (!irq) ++ return dev_err_probe(dev, -ENXIO, "Cannot get TRNG IRQ\n"); ++ ++ /* ++ * If someone else cleared the TRNG interrupt but did not read the ++ * entropy, a new interrupt won't be generated, and entropy collection ++ * will be stuck. Ensure an interrupt will be generated by executing ++ * the collect entropy command (and discarding the result). ++ */ ++ err = omnia_cmd_read(mcu->client, OMNIA_CMD_TRNG_COLLECT_ENTROPY, ++ &dummy, 1); ++ if (err) ++ return err; ++ ++ init_completion(&mcu->trng_entropy_ready); ++ ++ err = devm_request_threaded_irq(dev, irq, NULL, omnia_trng_irq_handler, ++ IRQF_ONESHOT, "turris-omnia-mcu-trng", ++ mcu); ++ if (err) ++ return dev_err_probe(dev, err, "Cannot request TRNG IRQ\n"); ++ ++ mcu->trng.name = "turris-omnia-mcu-trng"; ++ mcu->trng.read = omnia_trng_read; ++ ++ err = devm_hwrng_register(dev, &mcu->trng); ++ if (err) ++ return dev_err_probe(dev, err, "Cannot register TRNG\n"); ++ ++ return 0; ++} +--- a/drivers/platform/cznic/turris-omnia-mcu.h ++++ b/drivers/platform/cznic/turris-omnia-mcu.h +@@ -9,7 +9,9 @@ + #define __TURRIS_OMNIA_MCU_H + + #include ++#include + #include ++#include + #include + #include + #include +@@ -47,6 +49,10 @@ struct omnia_mcu { + + /* MCU watchdog */ + struct watchdog_device wdt; ++ ++ /* true random number generator */ ++ struct hwrng trng; ++ struct completion trng_entropy_ready; + }; + + int omnia_cmd_write_read(const struct i2c_client *client, +@@ -176,11 +182,13 @@ static inline int omnia_cmd_read_u8(cons + return omnia_cmd_read(client, cmd, reply, sizeof(*reply)); + } + ++extern const u8 omnia_int_to_gpio_idx[32]; + extern const struct attribute_group omnia_mcu_gpio_group; + extern const struct attribute_group omnia_mcu_poweroff_group; + + int omnia_mcu_register_gpiochip(struct omnia_mcu *mcu); + int omnia_mcu_register_sys_off_and_wakeup(struct omnia_mcu *mcu); ++int omnia_mcu_register_trng(struct omnia_mcu *mcu); + int omnia_mcu_register_watchdog(struct omnia_mcu *mcu); + + #endif /* __TURRIS_OMNIA_MCU_H */ diff --git a/lede/target/linux/mvebu/patches-6.6/820-v6.11-07-ARM-dts-turris-omnia-Add-MCU-system-controller-node.patch b/lede/target/linux/mvebu/patches-6.6/820-v6.11-07-ARM-dts-turris-omnia-Add-MCU-system-controller-node.patch new file mode 100644 index 0000000000..ad65de2f52 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/820-v6.11-07-ARM-dts-turris-omnia-Add-MCU-system-controller-node.patch @@ -0,0 +1,69 @@ +From 4f11095a4ae00b2fe4cebb21e36ee37cc62f5e1a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 1 Jul 2024 13:30:09 +0200 +Subject: [PATCH 07/11] ARM: dts: turris-omnia: Add MCU system-controller node +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Turris Omnia's MCU provides various features that can be configured over +I2C at address 0x2a. Add device-tree node. + +This does not carry a Fixes tag - we do not want this to get backported +to stable kernels for the following reason: U-Boot since v2022.10 +inserts a phy-reset-gpio property into the WAN ethernet node pointing to +the MCU node if it finds the MCU node with a cznic,turris-omnia-mcu +compatible. Thus if this change got backported to a stable kernel, the +WAN interface driver would defer probe indefinitely (since it would wait +for the turris-omnia-mcu driver which would not be present). + +Signed-off-by: Marek Behún +Reviewed-by: Andrew Lunn +Reviewed-by: Andy Shevchenko +Reviewed-by: Conor Dooley +Acked-by: Bartosz Golaszewski +Acked-by: Alexandre Belloni +Link: https://lore.kernel.org/r/20240701113010.16447-8-kabel@kernel.org +Signed-off-by: Arnd Bergmann +--- + .../dts/marvell/armada-385-turris-omnia.dts | 22 ++++++++++++++++++- + 1 file changed, 21 insertions(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts ++++ b/arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts +@@ -218,7 +218,22 @@ + #size-cells = <0>; + reg = <0>; + +- /* STM32F0 command interface at address 0x2a */ ++ mcu: system-controller@2a { ++ compatible = "cznic,turris-omnia-mcu"; ++ reg = <0x2a>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&mcu_pins>; ++ ++ interrupt-parent = <&gpio1>; ++ interrupts = <11 IRQ_TYPE_NONE>; ++ ++ gpio-controller; ++ #gpio-cells = <3>; ++ ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; + + led-controller@2b { + compatible = "cznic,turris-omnia-leds"; +@@ -503,6 +518,11 @@ + }; + + &pinctrl { ++ mcu_pins: mcu-pins { ++ marvell,pins = "mpp43"; ++ marvell,function = "gpio"; ++ }; ++ + pcawan_pins: pcawan-pins { + marvell,pins = "mpp46"; + marvell,function = "gpio"; diff --git a/lede/target/linux/mvebu/patches-6.6/820-v6.11-08-ARM-dts-turris-omnia-Add-GPIO-key-node-for-front-but.patch b/lede/target/linux/mvebu/patches-6.6/820-v6.11-08-ARM-dts-turris-omnia-Add-GPIO-key-node-for-front-but.patch new file mode 100644 index 0000000000..4b36167d66 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/820-v6.11-08-ARM-dts-turris-omnia-Add-GPIO-key-node-for-front-but.patch @@ -0,0 +1,46 @@ +From c3eeabe0b8d22d7c869278cc0cb35b83512fbed5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 1 Jul 2024 13:30:10 +0200 +Subject: [PATCH 08/11] ARM: dts: turris-omnia: Add GPIO key node for front + button +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Now that we have the MCU device-tree node, which acts as a GPIO +controller, add GPIO key node for the front button. + +Signed-off-by: Marek Behún +Reviewed-by: Andrew Lunn +Reviewed-by: Andy Shevchenko +Reviewed-by: Conor Dooley +Acked-by: Bartosz Golaszewski +Acked-by: Alexandre Belloni +Link: https://lore.kernel.org/r/20240701113010.16447-9-kabel@kernel.org +Signed-off-by: Arnd Bergmann +--- + .../boot/dts/marvell/armada-385-turris-omnia.dts | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts ++++ b/arch/arm/boot/dts/marvell/armada-385-turris-omnia.dts +@@ -112,6 +112,19 @@ + status = "disabled"; + }; + ++ gpio-keys { ++ compatible = "gpio-keys"; ++ ++ front-button { ++ label = "Front Button"; ++ linux,code = ; ++ linux,can-disable; ++ gpios = <&mcu 0 12 GPIO_ACTIVE_HIGH>; ++ /* debouncing is done by the microcontroller */ ++ debounce-interval = <0>; ++ }; ++ }; ++ + sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "SPDIF"; diff --git a/lede/target/linux/mvebu/patches-6.6/820-v6.11-09-platform-cznic-turris-omnia-mcu-Depend-on-OF.patch b/lede/target/linux/mvebu/patches-6.6/820-v6.11-09-platform-cznic-turris-omnia-mcu-Depend-on-OF.patch new file mode 100644 index 0000000000..80c9e1a3cc --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/820-v6.11-09-platform-cznic-turris-omnia-mcu-Depend-on-OF.patch @@ -0,0 +1,32 @@ +From 08838657bbc35494276c7ba4ef53f30a9816f8c9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 8 Jul 2024 13:40:01 +0200 +Subject: [PATCH 09/11] platform: cznic: turris-omnia-mcu: Depend on OF +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add depend on OF, otherwise the compilation fails with + error: no member named 'of_gpio_n_cells' in 'struct gpio_chip' + error: no member named 'of_xlate' in 'struct gpio_chip' + +Fixes: dfa556e45ae9 ("platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs") +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202407031646.trNSwajF-lkp@intel.com/ +Signed-off-by: Marek Behún +Link: https://lore.kernel.org/r/20240708114002.4285-2-kabel@kernel.org +Signed-off-by: Arnd Bergmann +--- + drivers/platform/cznic/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/platform/cznic/Kconfig ++++ b/drivers/platform/cznic/Kconfig +@@ -16,6 +16,7 @@ config TURRIS_OMNIA_MCU + tristate "Turris Omnia MCU driver" + depends on MACH_ARMADA_38X || COMPILE_TEST + depends on I2C ++ depends on OF + select GPIOLIB + select GPIOLIB_IRQCHIP + select HW_RANDOM diff --git a/lede/target/linux/mvebu/patches-6.6/820-v6.11-10-platform-cznic-turris-omnia-mcu-Depend-on-WATCHDOG.patch b/lede/target/linux/mvebu/patches-6.6/820-v6.11-10-platform-cznic-turris-omnia-mcu-Depend-on-WATCHDOG.patch new file mode 100644 index 0000000000..50e028752a --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/820-v6.11-10-platform-cznic-turris-omnia-mcu-Depend-on-WATCHDOG.patch @@ -0,0 +1,32 @@ +From 5e425e6eca155c162da58d4e58e896ed4109c7fd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Mon, 8 Jul 2024 13:40:02 +0200 +Subject: [PATCH 10/11] platform: cznic: turris-omnia-mcu: Depend on WATCHDOG +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add depend on WATCHDOG, otherwise modpost fails with + ERROR: modpost: "watchdog_init_timeout" [drivers/platform/cznic/turris-omnia-mcu.ko] undefined! + ERROR: modpost: "devm_watchdog_register_device" [drivers/platform/cznic/turris-omnia-mcu.ko] undefined! + +Fixes: ab89fb5fb92c ("platform: cznic: turris-omnia-mcu: Add support for MCU watchdog") +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202407040711.g19y3cWq-lkp@intel.com/ +Signed-off-by: Marek Behún +Link: https://lore.kernel.org/r/20240708114002.4285-3-kabel@kernel.org +Signed-off-by: Arnd Bergmann +--- + drivers/platform/cznic/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/platform/cznic/Kconfig ++++ b/drivers/platform/cznic/Kconfig +@@ -17,6 +17,7 @@ config TURRIS_OMNIA_MCU + depends on MACH_ARMADA_38X || COMPILE_TEST + depends on I2C + depends on OF ++ depends on WATCHDOG + select GPIOLIB + select GPIOLIB_IRQCHIP + select HW_RANDOM diff --git a/lede/target/linux/mvebu/patches-6.6/820-v6.11-11-platform-cznic-turris-omnia-mcu-fix-Kconfig-dependen.patch b/lede/target/linux/mvebu/patches-6.6/820-v6.11-11-platform-cznic-turris-omnia-mcu-fix-Kconfig-dependen.patch new file mode 100644 index 0000000000..30a476586e --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/820-v6.11-11-platform-cznic-turris-omnia-mcu-fix-Kconfig-dependen.patch @@ -0,0 +1,45 @@ +From 24c68c2525de5fcd0f3b16b2ad1028fb13b53393 Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Mon, 15 Jul 2024 08:02:30 +0200 +Subject: [PATCH 11/11] platform: cznic: turris-omnia-mcu: fix Kconfig + dependencies + +The newly added driver causes a Kconfig warning: + +WARNING: unmet direct dependencies detected for RTC_CLASS + Depends on [n]: !S390 [=y] + Selected by [m]: + - TURRIS_OMNIA_MCU [=m] && CZNIC_PLATFORMS [=y] && (MACH_ARMADA_38X || COMPILE_TEST [=y]) && I2C [=m] && OF [=y] && WATCHDOG [=y] + +The problem here is that it selects entire subsystems, which normal +device drivers should not do. Changes all of these to 'depends on' +instead. + +Fixes: dfa556e45ae9e ("platform: cznic: turris-omnia-mcu: Add support for MCU connected GPIOs") +Fixes: 90e700fd12b61 ("platform: cznic: turris-omnia-mcu: Add support for poweroff and wakeup") +Fixes: ab89fb5fb92c7 ("platform: cznic: turris-omnia-mcu: Add support for MCU watchdog") +Fixes: 41bb142a40289 ("platform: cznic: turris-omnia-mcu: Add support for MCU provided TRNG") +Reported-by: Nathan Chancellor +Signed-off-by: Arnd Bergmann +--- + drivers/platform/cznic/Kconfig | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/platform/cznic/Kconfig ++++ b/drivers/platform/cznic/Kconfig +@@ -18,11 +18,11 @@ config TURRIS_OMNIA_MCU + depends on I2C + depends on OF + depends on WATCHDOG +- select GPIOLIB ++ depends on GPIOLIB ++ depends on HW_RANDOM ++ depends on RTC_CLASS ++ depends on WATCHDOG_CORE + select GPIOLIB_IRQCHIP +- select HW_RANDOM +- select RTC_CLASS +- select WATCHDOG_CORE + help + Say Y here to add support for the features implemented by the + microcontroller on the CZ.NIC's Turris Omnia SOHO router. diff --git a/lede/target/linux/mvebu/patches-6.6/901-dt-bindings-Add-IEI-vendor-prefix-and-IEI-WT61P803-P.patch b/lede/target/linux/mvebu/patches-6.6/901-dt-bindings-Add-IEI-vendor-prefix-and-IEI-WT61P803-P.patch new file mode 100644 index 0000000000..2f7361c93e --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/901-dt-bindings-Add-IEI-vendor-prefix-and-IEI-WT61P803-P.patch @@ -0,0 +1,218 @@ +From aa4a0ccc41997f2da172165c92803abace43bd1c Mon Sep 17 00:00:00 2001 +From: Luka Kovacic +Date: Tue, 24 Aug 2021 12:44:32 +0000 +Subject: [PATCH 1/7] dt-bindings: Add IEI vendor prefix and IEI WT61P803 + PUZZLE driver bindings + +Add the IEI WT61P803 PUZZLE Device Tree bindings for MFD, HWMON and LED +drivers. A new vendor prefix is also added accordingly for +IEI Integration Corp. + +Signed-off-by: Luka Kovacic +Signed-off-by: Pavo Banicevic +Cc: Luka Perkov +Cc: Robert Marko +--- + .../hwmon/iei,wt61p803-puzzle-hwmon.yaml | 53 ++++++++++++ + .../leds/iei,wt61p803-puzzle-leds.yaml | 39 +++++++++ + .../bindings/mfd/iei,wt61p803-puzzle.yaml | 82 +++++++++++++++++++ + .../devicetree/bindings/vendor-prefixes.yaml | 2 + + 4 files changed, 176 insertions(+) + create mode 100644 Documentation/devicetree/bindings/hwmon/iei,wt61p803-puzzle-hwmon.yaml + create mode 100644 Documentation/devicetree/bindings/leds/iei,wt61p803-puzzle-leds.yaml + create mode 100644 Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml + +--- /dev/null ++++ b/Documentation/devicetree/bindings/hwmon/iei,wt61p803-puzzle-hwmon.yaml +@@ -0,0 +1,53 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/hwmon/iei,wt61p803-puzzle-hwmon.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: IEI WT61P803 PUZZLE MCU HWMON module from IEI Integration Corp. ++ ++maintainers: ++ - Luka Kovacic ++ ++description: | ++ This module is a part of the IEI WT61P803 PUZZLE MFD device. For more details ++ see Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml. ++ ++ The HWMON module is a sub-node of the MCU node in the Device Tree. ++ ++properties: ++ compatible: ++ const: iei,wt61p803-puzzle-hwmon ++ ++ "#address-cells": ++ const: 1 ++ ++ "#size-cells": ++ const: 0 ++ ++patternProperties: ++ "^fan-group@[0-1]$": ++ type: object ++ properties: ++ reg: ++ minimum: 0 ++ maximum: 1 ++ description: ++ Fan group ID ++ ++ cooling-levels: ++ minItems: 1 ++ maxItems: 255 ++ description: ++ Cooling levels for the fans (PWM value mapping) ++ description: | ++ Properties for each fan group. ++ required: ++ - reg ++ ++required: ++ - compatible ++ - "#address-cells" ++ - "#size-cells" ++ ++additionalProperties: false +--- /dev/null ++++ b/Documentation/devicetree/bindings/leds/iei,wt61p803-puzzle-leds.yaml +@@ -0,0 +1,39 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/leds/iei,wt61p803-puzzle-leds.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: IEI WT61P803 PUZZLE MCU LED module from IEI Integration Corp. ++ ++maintainers: ++ - Luka Kovacic ++ ++description: | ++ This module is a part of the IEI WT61P803 PUZZLE MFD device. For more details ++ see Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml. ++ ++ The LED module is a sub-node of the MCU node in the Device Tree. ++ ++properties: ++ compatible: ++ const: iei,wt61p803-puzzle-leds ++ ++ "#address-cells": ++ const: 1 ++ ++ "#size-cells": ++ const: 0 ++ ++ led@0: ++ type: object ++ $ref: common.yaml ++ description: | ++ Properties for a single LED. ++ ++required: ++ - compatible ++ - "#address-cells" ++ - "#size-cells" ++ ++additionalProperties: false +--- /dev/null ++++ b/Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml +@@ -0,0 +1,82 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/mfd/iei,wt61p803-puzzle.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: IEI WT61P803 PUZZLE MCU from IEI Integration Corp. ++ ++maintainers: ++ - Luka Kovacic ++ ++description: | ++ IEI WT61P803 PUZZLE MCU is embedded in some IEI Puzzle series boards. ++ It's used for controlling system power states, fans, LEDs and temperature ++ sensors. ++ ++ For Device Tree bindings of other sub-modules (HWMON, LEDs) refer to the ++ binding documents under the respective subsystem directories. ++ ++properties: ++ compatible: ++ const: iei,wt61p803-puzzle ++ ++ current-speed: ++ description: ++ Serial bus speed in bps ++ maxItems: 1 ++ ++ enable-beep: true ++ ++ hwmon: ++ $ref: /schemas/hwmon/iei,wt61p803-puzzle-hwmon.yaml ++ ++ leds: ++ $ref: /schemas/leds/iei,wt61p803-puzzle-leds.yaml ++ ++required: ++ - compatible ++ - current-speed ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ serial { ++ mcu { ++ compatible = "iei,wt61p803-puzzle"; ++ current-speed = <115200>; ++ enable-beep; ++ ++ leds { ++ compatible = "iei,wt61p803-puzzle-leds"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ led@0 { ++ reg = <0>; ++ function = LED_FUNCTION_POWER; ++ color = ; ++ }; ++ }; ++ ++ hwmon { ++ compatible = "iei,wt61p803-puzzle-hwmon"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ fan-group@0 { ++ #cooling-cells = <2>; ++ reg = <0x00>; ++ cooling-levels = <64 102 170 230 250>; ++ }; ++ ++ fan-group@1 { ++ #cooling-cells = <2>; ++ reg = <0x01>; ++ cooling-levels = <64 102 170 230 250>; ++ }; ++ }; ++ }; ++ }; +--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml ++++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml +@@ -611,6 +611,8 @@ patternProperties: + description: IC Plus Corp. + "^idt,.*": + description: Integrated Device Technologies, Inc. ++ "^iei,.*": ++ description: IEI Integration Corp. + "^ifi,.*": + description: Ingenieurburo Fur Ic-Technologie (I/F/I) + "^ilitek,.*": diff --git a/lede/target/linux/mvebu/patches-6.6/902-drivers-mfd-Add-a-driver-for-IEI-WT61P803-PUZZLE-MCU.patch b/lede/target/linux/mvebu/patches-6.6/902-drivers-mfd-Add-a-driver-for-IEI-WT61P803-PUZZLE-MCU.patch new file mode 100644 index 0000000000..2aac515eb1 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/902-drivers-mfd-Add-a-driver-for-IEI-WT61P803-PUZZLE-MCU.patch @@ -0,0 +1,1038 @@ +From 692cfa85272dd12995b427c0a7a585ced5d54f32 Mon Sep 17 00:00:00 2001 +From: Luka Kovacic +Date: Tue, 24 Aug 2021 12:44:33 +0000 +Subject: [PATCH 2/7] drivers: mfd: Add a driver for IEI WT61P803 PUZZLE MCU + +Add a driver for the IEI WT61P803 PUZZLE microcontroller, used in some +IEI Puzzle series devices. The microcontroller controls system power, +temperature sensors, fans and LEDs. + +This driver implements the core functionality for device communication +over the system serial (serdev bus). It handles MCU messages and the +internal MCU properties. Some properties can be managed over sysfs. + +Signed-off-by: Luka Kovacic +Signed-off-by: Pavo Banicevic +Cc: Luka Perkov +Cc: Robert Marko +--- + drivers/mfd/Kconfig | 9 + + drivers/mfd/Makefile | 1 + + drivers/mfd/iei-wt61p803-puzzle.c | 908 ++++++++++++++++++++++++ + include/linux/mfd/iei-wt61p803-puzzle.h | 66 ++ + 4 files changed, 984 insertions(+) + create mode 100644 drivers/mfd/iei-wt61p803-puzzle.c + create mode 100644 include/linux/mfd/iei-wt61p803-puzzle.h + +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -2274,6 +2274,15 @@ config SGI_MFD_IOC3 + If you have an SGI Origin, Octane, or a PCI IOC3 card, + then say Y. Otherwise say N. + ++config MFD_IEI_WT61P803_PUZZLE ++ tristate "IEI WT61P803 PUZZLE MCU driver" ++ depends on SERIAL_DEV_BUS ++ select MFD_CORE ++ help ++ IEI WT61P803 PUZZLE is a system power management microcontroller ++ used for fan control, temperature sensor reading, LED control ++ and system identification. ++ + config MFD_INTEL_M10_BMC_CORE + tristate + select MFD_CORE +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -244,6 +244,7 @@ obj-$(CONFIG_MFD_RT4831) += rt4831.o + obj-$(CONFIG_MFD_RT5033) += rt5033.o + obj-$(CONFIG_MFD_RT5120) += rt5120.o + obj-$(CONFIG_MFD_SKY81452) += sky81452.o ++obj-$(CONFIG_MFD_IEI_WT61P803_PUZZLE) += iei-wt61p803-puzzle.o + + obj-$(CONFIG_INTEL_SOC_PMIC) += intel_soc_pmic_crc.o + obj-$(CONFIG_INTEL_SOC_PMIC_BXTWC) += intel_soc_pmic_bxtwc.o +--- /dev/null ++++ b/drivers/mfd/iei-wt61p803-puzzle.c +@@ -0,0 +1,912 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* IEI WT61P803 PUZZLE MCU Driver ++ * System management microcontroller for fan control, temperature sensor reading, ++ * LED control and system identification on IEI Puzzle series ARM-based appliances. ++ * ++ * Copyright (C) 2020 Sartura Ltd. ++ * Author: Luka Kovacic ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* start, payload and XOR checksum at end */ ++#define IEI_WT61P803_PUZZLE_MAX_COMMAND_LENGTH (1 + 20 + 1) ++#define IEI_WT61P803_PUZZLE_RESP_BUF_SIZE 512 ++ ++#define IEI_WT61P803_PUZZLE_MAC_LENGTH 17 ++#define IEI_WT61P803_PUZZLE_SN_LENGTH 36 ++#define IEI_WT61P803_PUZZLE_VERSION_LENGTH 6 ++#define IEI_WT61P803_PUZZLE_BUILD_INFO_LENGTH 16 ++#define IEI_WT61P803_PUZZLE_PROTOCOL_VERSION_LENGTH 8 ++#define IEI_WT61P803_PUZZLE_NB_MAC 8 ++ ++/* Use HZ as a timeout value throughout the driver */ ++#define IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT HZ ++ ++enum iei_wt61p803_puzzle_attribute_type { ++ IEI_WT61P803_PUZZLE_VERSION, ++ IEI_WT61P803_PUZZLE_BUILD_INFO, ++ IEI_WT61P803_PUZZLE_BOOTLOADER_MODE, ++ IEI_WT61P803_PUZZLE_PROTOCOL_VERSION, ++ IEI_WT61P803_PUZZLE_SERIAL_NUMBER, ++ IEI_WT61P803_PUZZLE_MAC_ADDRESS, ++ IEI_WT61P803_PUZZLE_AC_RECOVERY_STATUS, ++ IEI_WT61P803_PUZZLE_POWER_LOSS_RECOVERY, ++ IEI_WT61P803_PUZZLE_POWER_STATUS, ++}; ++ ++struct iei_wt61p803_puzzle_device_attribute { ++ struct device_attribute dev_attr; ++ enum iei_wt61p803_puzzle_attribute_type type; ++ u8 index; ++}; ++ ++/** ++ * struct iei_wt61p803_puzzle_mcu_status - MCU flags state ++ * @ac_recovery_status_flag: AC Recovery Status Flag ++ * @power_loss_recovery: System recovery after power loss ++ * @power_status: System Power-on Method ++ */ ++struct iei_wt61p803_puzzle_mcu_status { ++ u8 ac_recovery_status_flag; ++ u8 power_loss_recovery; ++ u8 power_status; ++}; ++ ++/** ++ * struct iei_wt61p803_puzzle_reply - MCU reply ++ * @size: Size of the MCU reply ++ * @data: Full MCU reply buffer ++ * @state: Current state of the packet ++ * @received: Was the response fullfilled ++ */ ++struct iei_wt61p803_puzzle_reply { ++ size_t size; ++ unsigned char data[IEI_WT61P803_PUZZLE_RESP_BUF_SIZE]; ++ struct completion received; ++}; ++ ++/** ++ * struct iei_wt61p803_puzzle_mcu_version - MCU version status ++ * @version: Primary firmware version ++ * @build_info: Build date and time ++ * @bootloader_mode: Status of the MCU operation ++ * @protocol_version: MCU communication protocol version ++ * @serial_number: Device factory serial number ++ * @mac_address: Device factory MAC addresses ++ * ++ * Last element of arrays is reserved for '\0'. ++ */ ++struct iei_wt61p803_puzzle_mcu_version { ++ char version[IEI_WT61P803_PUZZLE_VERSION_LENGTH + 1]; ++ char build_info[IEI_WT61P803_PUZZLE_BUILD_INFO_LENGTH + 1]; ++ bool bootloader_mode; ++ char protocol_version[IEI_WT61P803_PUZZLE_PROTOCOL_VERSION_LENGTH + 1]; ++ char serial_number[IEI_WT61P803_PUZZLE_SN_LENGTH + 1]; ++ char mac_address[IEI_WT61P803_PUZZLE_NB_MAC][IEI_WT61P803_PUZZLE_MAC_LENGTH + 1]; ++}; ++ ++/** ++ * struct iei_wt61p803_puzzle - IEI WT61P803 PUZZLE MCU Driver ++ * @serdev: Pointer to underlying serdev device ++ * @dev: Pointer to underlying dev device ++ * @reply_lock: Reply mutex lock ++ * @reply: Pointer to the iei_wt61p803_puzzle_reply struct ++ * @version: MCU version related data ++ * @status: MCU status related data ++ * @response_buffer Command response buffer allocation ++ * @lock General member mutex lock ++ */ ++struct iei_wt61p803_puzzle { ++ struct serdev_device *serdev; ++ struct device *dev; ++ struct mutex reply_lock; /* lock to prevent multiple firmware calls */ ++ struct iei_wt61p803_puzzle_reply *reply; ++ struct iei_wt61p803_puzzle_mcu_version version; ++ struct iei_wt61p803_puzzle_mcu_status status; ++ unsigned char response_buffer[IEI_WT61P803_PUZZLE_BUF_SIZE]; ++ struct mutex lock; /* lock to protect response buffer */ ++}; ++ ++static unsigned char iei_wt61p803_puzzle_checksum(unsigned char *buf, size_t len) ++{ ++ unsigned char checksum = 0; ++ size_t i; ++ ++ for (i = 0; i < len; i++) ++ checksum ^= buf[i]; ++ return checksum; ++} ++ ++static int iei_wt61p803_puzzle_process_resp(struct iei_wt61p803_puzzle *mcu, ++ const unsigned char *raw_resp_data, size_t size) ++{ ++ unsigned char checksum; ++ ++ /* Check the incoming frame header */ ++ if (!(raw_resp_data[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START || ++ raw_resp_data[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER || ++ (raw_resp_data[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM && ++ raw_resp_data[1] == IEI_WT61P803_PUZZLE_CMD_EEPROM_READ))) { ++ if (mcu->reply->size + size >= sizeof(mcu->reply->data)) ++ return -EIO; ++ ++ /* Append the frame to existing data */ ++ memcpy(mcu->reply->data + mcu->reply->size, raw_resp_data, size); ++ mcu->reply->size += size; ++ } else { ++ if (size >= sizeof(mcu->reply->data)) ++ return -EIO; ++ ++ /* Start processing a new frame */ ++ memcpy(mcu->reply->data, raw_resp_data, size); ++ mcu->reply->size = size; ++ } ++ ++ checksum = iei_wt61p803_puzzle_checksum(mcu->reply->data, mcu->reply->size - 1); ++ if (checksum != mcu->reply->data[mcu->reply->size - 1]) { ++ /* The checksum isn't matched yet, wait for new frames */ ++ return size; ++ } ++ ++ /* Received all the data */ ++ complete(&mcu->reply->received); ++ ++ return size; ++} ++ ++static int iei_wt61p803_puzzle_recv_buf(struct serdev_device *serdev, ++ const unsigned char *data, size_t size) ++{ ++ struct iei_wt61p803_puzzle *mcu = serdev_device_get_drvdata(serdev); ++ int ret; ++ ++ ret = iei_wt61p803_puzzle_process_resp(mcu, data, size); ++ /* Return the number of processed bytes if function returns error, ++ * discard the remaining incoming data, since the frame this data ++ * belongs to is broken anyway ++ */ ++ if (ret < 0) ++ return size; ++ ++ return ret; ++} ++ ++static const struct serdev_device_ops iei_wt61p803_puzzle_serdev_device_ops = { ++ .receive_buf = iei_wt61p803_puzzle_recv_buf, ++ .write_wakeup = serdev_device_write_wakeup, ++}; ++ ++/** ++ * iei_wt61p803_puzzle_write_command_watchdog() - Watchdog of the normal cmd ++ * @mcu: Pointer to the iei_wt61p803_puzzle core MFD struct ++ * @cmd: Pointer to the char array to send (size should be content + 1 (xor)) ++ * @size: Size of the cmd char array ++ * @reply_data: Pointer to the reply/response data array (should be allocated) ++ * @reply_size: Pointer to size_t (size of reply_data) ++ * @retry_count: Number of times to retry sending the command to the MCU ++ */ ++int iei_wt61p803_puzzle_write_command_watchdog(struct iei_wt61p803_puzzle *mcu, ++ unsigned char *cmd, size_t size, ++ unsigned char *reply_data, ++ size_t *reply_size, int retry_count) ++{ ++ struct device *dev = &mcu->serdev->dev; ++ int ret, i; ++ ++ for (i = 0; i < retry_count; i++) { ++ ret = iei_wt61p803_puzzle_write_command(mcu, cmd, size, ++ reply_data, reply_size); ++ if (ret != -ETIMEDOUT) ++ return ret; ++ } ++ ++ dev_err(dev, "Command response timed out. Retries: %d\n", retry_count); ++ ++ return -ETIMEDOUT; ++} ++EXPORT_SYMBOL_GPL(iei_wt61p803_puzzle_write_command_watchdog); ++ ++/** ++ * iei_wt61p803_puzzle_write_command() - Send a structured command to the MCU ++ * @mcu: Pointer to the iei_wt61p803_puzzle core MFD struct ++ * @cmd: Pointer to the char array to send (size should be content + 1 (xor)) ++ * @size: Size of the cmd char array ++ * @reply_data: Pointer to the reply/response data array (should be allocated) ++ * ++ * Sends a structured command to the MCU. ++ */ ++int iei_wt61p803_puzzle_write_command(struct iei_wt61p803_puzzle *mcu, ++ unsigned char *cmd, size_t size, ++ unsigned char *reply_data, ++ size_t *reply_size) ++{ ++ struct device *dev = &mcu->serdev->dev; ++ int ret; ++ ++ if (size <= 1 || size > IEI_WT61P803_PUZZLE_MAX_COMMAND_LENGTH) ++ return -EINVAL; ++ ++ mutex_lock(&mcu->reply_lock); ++ ++ cmd[size - 1] = iei_wt61p803_puzzle_checksum(cmd, size - 1); ++ ++ /* Initialize reply struct */ ++ reinit_completion(&mcu->reply->received); ++ mcu->reply->size = 0; ++ usleep_range(2000, 10000); ++ serdev_device_write_flush(mcu->serdev); ++ ret = serdev_device_write_buf(mcu->serdev, cmd, size); ++ if (ret < 0) ++ goto exit; ++ ++ serdev_device_wait_until_sent(mcu->serdev, IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT); ++ ret = wait_for_completion_timeout(&mcu->reply->received, ++ IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT); ++ if (ret == 0) { ++ dev_err(dev, "Command reply receive timeout\n"); ++ ret = -ETIMEDOUT; ++ goto exit; ++ } ++ ++ *reply_size = mcu->reply->size; ++ /* Copy the received data, as it will not be available after a new frame is received */ ++ memcpy(reply_data, mcu->reply->data, mcu->reply->size); ++ ret = 0; ++exit: ++ mutex_unlock(&mcu->reply_lock); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(iei_wt61p803_puzzle_write_command); ++ ++static int iei_wt61p803_puzzle_buzzer(struct iei_wt61p803_puzzle *mcu, bool long_beep) ++{ ++ unsigned char *resp_buf = mcu->response_buffer; ++ unsigned char buzzer_cmd[4] = {}; ++ size_t reply_size; ++ int ret; ++ ++ buzzer_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; ++ buzzer_cmd[1] = IEI_WT61P803_PUZZLE_CMD_FUNCTION_SINGLE; ++ buzzer_cmd[2] = long_beep ? '3' : '2'; /* Buzzer 1.5 / 0.5 second beep */ ++ ++ mutex_lock(&mcu->lock); ++ ret = iei_wt61p803_puzzle_write_command(mcu, buzzer_cmd, sizeof(buzzer_cmd), ++ resp_buf, &reply_size); ++ if (ret) ++ goto exit; ++ ++ if (reply_size != 3) { ++ ret = -EIO; ++ goto exit; ++ } ++ ++ if (!(resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && ++ resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && ++ resp_buf[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK)) { ++ ret = -EPROTO; ++ goto exit; ++ } ++exit: ++ mutex_unlock(&mcu->lock); ++ return ret; ++} ++ ++static int iei_wt61p803_puzzle_get_version(struct iei_wt61p803_puzzle *mcu) ++{ ++ unsigned char version_cmd[3] = { ++ IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER, ++ IEI_WT61P803_PUZZLE_CMD_OTHER_VERSION, ++ }; ++ unsigned char build_info_cmd[3] = { ++ IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER, ++ IEI_WT61P803_PUZZLE_CMD_OTHER_BUILD, ++ }; ++ unsigned char bootloader_mode_cmd[3] = { ++ IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER, ++ IEI_WT61P803_PUZZLE_CMD_OTHER_BOOTLOADER_MODE, ++ }; ++ unsigned char protocol_version_cmd[3] = { ++ IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER, ++ IEI_WT61P803_PUZZLE_CMD_OTHER_PROTOCOL_VERSION, ++ }; ++ unsigned char *rb = mcu->response_buffer; ++ size_t reply_size; ++ int ret; ++ ++ mutex_lock(&mcu->lock); ++ ++ ret = iei_wt61p803_puzzle_write_command(mcu, version_cmd, sizeof(version_cmd), ++ rb, &reply_size); ++ if (ret) ++ goto err; ++ if (reply_size < 7) { ++ ret = -EIO; ++ goto err; ++ } ++ sprintf(mcu->version.version, "v%c.%.3s", rb[2], &rb[3]); ++ ++ ret = iei_wt61p803_puzzle_write_command(mcu, build_info_cmd, ++ sizeof(build_info_cmd), rb, ++ &reply_size); ++ if (ret) ++ goto err; ++ if (reply_size < 15) { ++ ret = -EIO; ++ goto err; ++ } ++ sprintf(mcu->version.build_info, "%c%c/%c%c/%.4s %c%c:%c%c", ++ rb[8], rb[9], rb[6], rb[7], &rb[2], rb[10], rb[11], ++ rb[12], rb[13]); ++ ++ ret = iei_wt61p803_puzzle_write_command(mcu, bootloader_mode_cmd, ++ sizeof(bootloader_mode_cmd), rb, ++ &reply_size); ++ if (ret) ++ goto err; ++ if (reply_size < 4) { ++ ret = -EIO; ++ goto err; ++ } ++ if (rb[2] == IEI_WT61P803_PUZZLE_CMD_OTHER_MODE_APPS) ++ mcu->version.bootloader_mode = false; ++ else if (rb[2] == IEI_WT61P803_PUZZLE_CMD_OTHER_MODE_BOOTLOADER) ++ mcu->version.bootloader_mode = true; ++ ++ ret = iei_wt61p803_puzzle_write_command(mcu, protocol_version_cmd, ++ sizeof(protocol_version_cmd), rb, ++ &reply_size); ++ if (ret) ++ goto err; ++ if (reply_size < 9) { ++ ret = -EIO; ++ goto err; ++ } ++ sprintf(mcu->version.protocol_version, "v%c.%c%c%c%c%c", ++ rb[7], rb[6], rb[5], rb[4], rb[3], rb[2]); ++err: ++ mutex_unlock(&mcu->lock); ++ return ret; ++} ++ ++static int iei_wt61p803_puzzle_get_mcu_status(struct iei_wt61p803_puzzle *mcu) ++{ ++ unsigned char mcu_status_cmd[5] = { ++ IEI_WT61P803_PUZZLE_CMD_HEADER_START, ++ IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER, ++ IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_STATUS, ++ IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_STATUS, ++ }; ++ unsigned char *resp_buf = mcu->response_buffer; ++ size_t reply_size; ++ int ret; ++ ++ mutex_lock(&mcu->lock); ++ ret = iei_wt61p803_puzzle_write_command(mcu, mcu_status_cmd, sizeof(mcu_status_cmd), ++ resp_buf, &reply_size); ++ if (ret) ++ goto exit; ++ if (reply_size < 20) { ++ ret = -EIO; ++ goto exit; ++ } ++ ++ /* Response format: ++ * (IDX RESPONSE) ++ * 0 @ ++ * 1 O ++ * 2 S ++ * 3 S ++ * ... ++ * 5 AC Recovery Status Flag ++ * ... ++ * 10 Power Loss Recovery ++ * ... ++ * 19 Power Status (system power on method) ++ * 20 XOR checksum ++ */ ++ if (resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && ++ resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER && ++ resp_buf[2] == IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_STATUS && ++ resp_buf[3] == IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_STATUS) { ++ mcu->status.ac_recovery_status_flag = resp_buf[5]; ++ mcu->status.power_loss_recovery = resp_buf[10]; ++ mcu->status.power_status = resp_buf[19]; ++ } ++exit: ++ mutex_unlock(&mcu->lock); ++ return ret; ++} ++ ++static int iei_wt61p803_puzzle_get_serial_number(struct iei_wt61p803_puzzle *mcu) ++{ ++ unsigned char *resp_buf = mcu->response_buffer; ++ unsigned char serial_number_cmd[5] = { ++ IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM, ++ IEI_WT61P803_PUZZLE_CMD_EEPROM_READ, ++ 0x00, /* EEPROM read address */ ++ 0x24, /* Data length */ ++ }; ++ size_t reply_size; ++ int ret; ++ ++ mutex_lock(&mcu->lock); ++ ret = iei_wt61p803_puzzle_write_command(mcu, serial_number_cmd, ++ sizeof(serial_number_cmd), ++ resp_buf, &reply_size); ++ if (ret) ++ goto err; ++ ++ if (reply_size < IEI_WT61P803_PUZZLE_SN_LENGTH + 4) { ++ ret = -EIO; ++ goto err; ++ } ++ ++ sprintf(mcu->version.serial_number, "%.*s", ++ IEI_WT61P803_PUZZLE_SN_LENGTH, resp_buf + 4); ++err: ++ mutex_unlock(&mcu->lock); ++ return ret; ++} ++ ++static int iei_wt61p803_puzzle_write_serial_number(struct iei_wt61p803_puzzle *mcu, ++ unsigned char serial_number[36]) ++{ ++ unsigned char *resp_buf = mcu->response_buffer; ++ unsigned char serial_number_header[4] = { ++ IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM, ++ IEI_WT61P803_PUZZLE_CMD_EEPROM_WRITE, ++ 0x00, /* EEPROM write address */ ++ 0xC, /* Data length */ ++ }; ++ unsigned char serial_number_cmd[4 + 12 + 1]; /* header, serial number, XOR checksum */ ++ int ret, sn_counter; ++ size_t reply_size; ++ ++ /* The MCU can only handle 22 byte messages, send the S/N in 12 byte chunks */ ++ mutex_lock(&mcu->lock); ++ for (sn_counter = 0; sn_counter < 3; sn_counter++) { ++ serial_number_header[2] = 0x0 + 0xC * sn_counter; ++ ++ memcpy(serial_number_cmd, serial_number_header, sizeof(serial_number_header)); ++ memcpy(serial_number_cmd + sizeof(serial_number_header), ++ serial_number + 0xC * sn_counter, 0xC); ++ ++ ret = iei_wt61p803_puzzle_write_command(mcu, serial_number_cmd, ++ sizeof(serial_number_cmd), ++ resp_buf, &reply_size); ++ if (ret) ++ goto err; ++ if (reply_size != 3) { ++ ret = -EIO; ++ goto err; ++ } ++ if (!(resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && ++ resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && ++ resp_buf[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK)) { ++ ret = -EPROTO; ++ goto err; ++ } ++ } ++ ++ sprintf(mcu->version.serial_number, "%.*s", ++ IEI_WT61P803_PUZZLE_SN_LENGTH, serial_number); ++err: ++ mutex_unlock(&mcu->lock); ++ return ret; ++} ++ ++static int iei_wt61p803_puzzle_get_mac_address(struct iei_wt61p803_puzzle *mcu, int index) ++{ ++ unsigned char *resp_buf = mcu->response_buffer; ++ unsigned char mac_address_cmd[5] = { ++ IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM, ++ IEI_WT61P803_PUZZLE_CMD_EEPROM_READ, ++ 0x00, /* EEPROM read address */ ++ 0x11, /* Data length */ ++ }; ++ size_t reply_size; ++ int ret; ++ ++ mutex_lock(&mcu->lock); ++ mac_address_cmd[2] = 0x24 + 0x11 * index; ++ ++ ret = iei_wt61p803_puzzle_write_command(mcu, mac_address_cmd, ++ sizeof(mac_address_cmd), ++ resp_buf, &reply_size); ++ if (ret) ++ goto err; ++ ++ if (reply_size < 22) { ++ ret = -EIO; ++ goto err; ++ } ++ ++ sprintf(mcu->version.mac_address[index], "%.*s", ++ IEI_WT61P803_PUZZLE_MAC_LENGTH, resp_buf + 4); ++err: ++ mutex_unlock(&mcu->lock); ++ return ret; ++} ++ ++static int ++iei_wt61p803_puzzle_write_mac_address(struct iei_wt61p803_puzzle *mcu, ++ unsigned char mac_address[IEI_WT61P803_PUZZLE_MAC_LENGTH], ++ int mac_address_idx) ++{ ++ unsigned char mac_address_cmd[4 + IEI_WT61P803_PUZZLE_MAC_LENGTH + 1]; ++ unsigned char *resp_buf = mcu->response_buffer; ++ unsigned char mac_address_header[4] = { ++ IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM, ++ IEI_WT61P803_PUZZLE_CMD_EEPROM_WRITE, ++ 0x00, /* EEPROM write address */ ++ 0x11, /* Data length */ ++ }; ++ size_t reply_size; ++ int ret; ++ ++ if (mac_address_idx < 0 || mac_address_idx >= IEI_WT61P803_PUZZLE_NB_MAC) ++ return -EINVAL; ++ ++ mac_address_header[2] = 0x24 + 0x11 * mac_address_idx; ++ ++ /* Concat mac_address_header, mac_address to mac_address_cmd */ ++ memcpy(mac_address_cmd, mac_address_header, sizeof(mac_address_header)); ++ memcpy(mac_address_cmd + sizeof(mac_address_header), mac_address, ++ IEI_WT61P803_PUZZLE_MAC_LENGTH); ++ ++ mutex_lock(&mcu->lock); ++ ret = iei_wt61p803_puzzle_write_command(mcu, mac_address_cmd, ++ sizeof(mac_address_cmd), ++ resp_buf, &reply_size); ++ if (ret) ++ goto err; ++ if (reply_size != 3) { ++ ret = -EIO; ++ goto err; ++ } ++ if (!(resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && ++ resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && ++ resp_buf[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK)) { ++ ret = -EPROTO; ++ goto err; ++ } ++ ++ sprintf(mcu->version.mac_address[mac_address_idx], "%.*s", ++ IEI_WT61P803_PUZZLE_MAC_LENGTH, mac_address); ++err: ++ mutex_unlock(&mcu->lock); ++ return ret; ++} ++ ++static int iei_wt61p803_puzzle_write_power_loss_recovery(struct iei_wt61p803_puzzle *mcu, ++ int power_loss_recovery_action) ++{ ++ unsigned char *resp_buf = mcu->response_buffer; ++ unsigned char power_loss_recovery_cmd[5] = {}; ++ size_t reply_size; ++ int ret; ++ ++ if (power_loss_recovery_action < 0 || power_loss_recovery_action > 4) ++ return -EINVAL; ++ ++ power_loss_recovery_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; ++ power_loss_recovery_cmd[1] = IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER; ++ power_loss_recovery_cmd[2] = IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_POWER_LOSS; ++ power_loss_recovery_cmd[3] = hex_asc[power_loss_recovery_action]; ++ ++ mutex_lock(&mcu->lock); ++ ret = iei_wt61p803_puzzle_write_command(mcu, power_loss_recovery_cmd, ++ sizeof(power_loss_recovery_cmd), ++ resp_buf, &reply_size); ++ if (ret) ++ goto exit; ++ mcu->status.power_loss_recovery = power_loss_recovery_action; ++exit: ++ mutex_unlock(&mcu->lock); ++ return ret; ++} ++ ++#define to_puzzle_dev_attr(_attr) \ ++ container_of(_attr, struct iei_wt61p803_puzzle_device_attribute, dev_attr) ++ ++static ssize_t show_output(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev); ++ struct iei_wt61p803_puzzle_device_attribute *pattr = to_puzzle_dev_attr(attr); ++ int ret; ++ ++ switch (pattr->type) { ++ case IEI_WT61P803_PUZZLE_VERSION: ++ return scnprintf(buf, PAGE_SIZE, "%s\n", mcu->version.version); ++ case IEI_WT61P803_PUZZLE_BUILD_INFO: ++ return scnprintf(buf, PAGE_SIZE, "%s\n", mcu->version.build_info); ++ case IEI_WT61P803_PUZZLE_BOOTLOADER_MODE: ++ return scnprintf(buf, PAGE_SIZE, "%d\n", mcu->version.bootloader_mode); ++ case IEI_WT61P803_PUZZLE_PROTOCOL_VERSION: ++ return scnprintf(buf, PAGE_SIZE, "%s\n", mcu->version.protocol_version); ++ case IEI_WT61P803_PUZZLE_SERIAL_NUMBER: ++ ret = iei_wt61p803_puzzle_get_serial_number(mcu); ++ if (!ret) ++ ret = scnprintf(buf, PAGE_SIZE, "%s\n", mcu->version.serial_number); ++ else ++ ret = 0; ++ return ret; ++ case IEI_WT61P803_PUZZLE_MAC_ADDRESS: ++ ret = iei_wt61p803_puzzle_get_mac_address(mcu, pattr->index); ++ if (!ret) ++ ret = scnprintf(buf, PAGE_SIZE, "%s\n", ++ mcu->version.mac_address[pattr->index]); ++ else ++ ret = 0; ++ return ret; ++ case IEI_WT61P803_PUZZLE_AC_RECOVERY_STATUS: ++ case IEI_WT61P803_PUZZLE_POWER_LOSS_RECOVERY: ++ case IEI_WT61P803_PUZZLE_POWER_STATUS: ++ ret = iei_wt61p803_puzzle_get_mcu_status(mcu); ++ if (ret) ++ return ret; ++ ++ mutex_lock(&mcu->lock); ++ switch (pattr->type) { ++ case IEI_WT61P803_PUZZLE_AC_RECOVERY_STATUS: ++ ret = scnprintf(buf, PAGE_SIZE, "%x\n", ++ mcu->status.ac_recovery_status_flag); ++ break; ++ case IEI_WT61P803_PUZZLE_POWER_LOSS_RECOVERY: ++ ret = scnprintf(buf, PAGE_SIZE, "%x\n", mcu->status.power_loss_recovery); ++ break; ++ case IEI_WT61P803_PUZZLE_POWER_STATUS: ++ ret = scnprintf(buf, PAGE_SIZE, "%x\n", mcu->status.power_status); ++ break; ++ default: ++ ret = 0; ++ break; ++ } ++ mutex_unlock(&mcu->lock); ++ return ret; ++ default: ++ return 0; ++ } ++ ++ return 0; ++} ++ ++static ssize_t store_output(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t len) ++{ ++ unsigned char serial_number[IEI_WT61P803_PUZZLE_SN_LENGTH]; ++ unsigned char mac_address[IEI_WT61P803_PUZZLE_MAC_LENGTH]; ++ struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev); ++ struct iei_wt61p803_puzzle_device_attribute *pattr = to_puzzle_dev_attr(attr); ++ int power_loss_recovery_action = 0; ++ int ret; ++ ++ switch (pattr->type) { ++ case IEI_WT61P803_PUZZLE_SERIAL_NUMBER: ++ if (len != (size_t)(IEI_WT61P803_PUZZLE_SN_LENGTH + 1)) ++ return -EINVAL; ++ memcpy(serial_number, buf, sizeof(serial_number)); ++ ret = iei_wt61p803_puzzle_write_serial_number(mcu, serial_number); ++ if (ret) ++ return ret; ++ return len; ++ case IEI_WT61P803_PUZZLE_MAC_ADDRESS: ++ if (len != (size_t)(IEI_WT61P803_PUZZLE_MAC_LENGTH + 1)) ++ return -EINVAL; ++ ++ memcpy(mac_address, buf, sizeof(mac_address)); ++ ++ if (strlen(attr->attr.name) != 13) ++ return -EIO; ++ ++ ret = iei_wt61p803_puzzle_write_mac_address(mcu, mac_address, pattr->index); ++ if (ret) ++ return ret; ++ return len; ++ case IEI_WT61P803_PUZZLE_POWER_LOSS_RECOVERY: ++ ret = kstrtoint(buf, 10, &power_loss_recovery_action); ++ if (ret) ++ return ret; ++ ret = iei_wt61p803_puzzle_write_power_loss_recovery(mcu, ++ power_loss_recovery_action); ++ if (ret) ++ return ret; ++ return len; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++#define IEI_WT61P803_PUZZLE_ATTR(_name, _mode, _show, _store, _type, _index) \ ++ struct iei_wt61p803_puzzle_device_attribute dev_attr_##_name = \ ++ { .dev_attr = __ATTR(_name, _mode, _show, _store), \ ++ .type = _type, \ ++ .index = _index } ++ ++#define IEI_WT61P803_PUZZLE_ATTR_RO(_name, _type, _id) \ ++ IEI_WT61P803_PUZZLE_ATTR(_name, 0444, show_output, NULL, _type, _id) ++ ++#define IEI_WT61P803_PUZZLE_ATTR_RW(_name, _type, _id) \ ++ IEI_WT61P803_PUZZLE_ATTR(_name, 0644, show_output, store_output, _type, _id) ++ ++static IEI_WT61P803_PUZZLE_ATTR_RO(version, IEI_WT61P803_PUZZLE_VERSION, 0); ++static IEI_WT61P803_PUZZLE_ATTR_RO(build_info, IEI_WT61P803_PUZZLE_BUILD_INFO, 0); ++static IEI_WT61P803_PUZZLE_ATTR_RO(bootloader_mode, IEI_WT61P803_PUZZLE_BOOTLOADER_MODE, 0); ++static IEI_WT61P803_PUZZLE_ATTR_RO(protocol_version, IEI_WT61P803_PUZZLE_PROTOCOL_VERSION, 0); ++static IEI_WT61P803_PUZZLE_ATTR_RW(serial_number, IEI_WT61P803_PUZZLE_SERIAL_NUMBER, 0); ++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_0, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 0); ++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_1, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 1); ++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_2, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 2); ++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_3, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 3); ++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_4, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 4); ++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_5, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 5); ++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_6, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 6); ++static IEI_WT61P803_PUZZLE_ATTR_RW(mac_address_7, IEI_WT61P803_PUZZLE_MAC_ADDRESS, 7); ++static IEI_WT61P803_PUZZLE_ATTR_RO(ac_recovery_status, IEI_WT61P803_PUZZLE_AC_RECOVERY_STATUS, 0); ++static IEI_WT61P803_PUZZLE_ATTR_RW(power_loss_recovery, IEI_WT61P803_PUZZLE_POWER_LOSS_RECOVERY, 0); ++static IEI_WT61P803_PUZZLE_ATTR_RO(power_status, IEI_WT61P803_PUZZLE_POWER_STATUS, 0); ++ ++static struct attribute *iei_wt61p803_puzzle_attrs[] = { ++ &dev_attr_version.dev_attr.attr, ++ &dev_attr_build_info.dev_attr.attr, ++ &dev_attr_bootloader_mode.dev_attr.attr, ++ &dev_attr_protocol_version.dev_attr.attr, ++ &dev_attr_serial_number.dev_attr.attr, ++ &dev_attr_mac_address_0.dev_attr.attr, ++ &dev_attr_mac_address_1.dev_attr.attr, ++ &dev_attr_mac_address_2.dev_attr.attr, ++ &dev_attr_mac_address_3.dev_attr.attr, ++ &dev_attr_mac_address_4.dev_attr.attr, ++ &dev_attr_mac_address_5.dev_attr.attr, ++ &dev_attr_mac_address_6.dev_attr.attr, ++ &dev_attr_mac_address_7.dev_attr.attr, ++ &dev_attr_ac_recovery_status.dev_attr.attr, ++ &dev_attr_power_loss_recovery.dev_attr.attr, ++ &dev_attr_power_status.dev_attr.attr, ++ NULL ++}; ++ATTRIBUTE_GROUPS(iei_wt61p803_puzzle); ++ ++static int iei_wt61p803_puzzle_sysfs_create(struct device *dev, ++ struct iei_wt61p803_puzzle *mcu) ++{ ++ int ret; ++ ++ ret = sysfs_create_groups(&mcu->dev->kobj, iei_wt61p803_puzzle_groups); ++ if (ret) ++ mfd_remove_devices(mcu->dev); ++ ++ return ret; ++} ++ ++static int iei_wt61p803_puzzle_sysfs_remove(struct device *dev, ++ struct iei_wt61p803_puzzle *mcu) ++{ ++ /* Remove sysfs groups */ ++ sysfs_remove_groups(&mcu->dev->kobj, iei_wt61p803_puzzle_groups); ++ mfd_remove_devices(mcu->dev); ++ ++ return 0; ++} ++ ++static int iei_wt61p803_puzzle_probe(struct serdev_device *serdev) ++{ ++ struct device *dev = &serdev->dev; ++ struct iei_wt61p803_puzzle *mcu; ++ u32 baud; ++ int ret; ++ ++ /* Read the baud rate from 'current-speed', because the MCU supports different rates */ ++ if (device_property_read_u32(dev, "current-speed", &baud)) { ++ dev_err(dev, ++ "'current-speed' is not specified in device node\n"); ++ return -EINVAL; ++ } ++ dev_dbg(dev, "Driver baud rate: %d\n", baud); ++ ++ /* Allocate the memory */ ++ mcu = devm_kzalloc(dev, sizeof(*mcu), GFP_KERNEL); ++ if (!mcu) ++ return -ENOMEM; ++ ++ mcu->reply = devm_kzalloc(dev, sizeof(*mcu->reply), GFP_KERNEL); ++ if (!mcu->reply) ++ return -ENOMEM; ++ ++ /* Initialize device struct data */ ++ mcu->serdev = serdev; ++ mcu->dev = dev; ++ init_completion(&mcu->reply->received); ++ ret = devm_mutex_init(dev, &mcu->reply_lock); ++ if (ret) ++ return ret; ++ ret = devm_mutex_init(dev, &mcu->lock); ++ if (ret) ++ return ret; ++ ++ /* Setup UART interface */ ++ serdev_device_set_drvdata(serdev, mcu); ++ serdev_device_set_client_ops(serdev, &iei_wt61p803_puzzle_serdev_device_ops); ++ ret = devm_serdev_device_open(dev, serdev); ++ if (ret) ++ return ret; ++ serdev_device_set_baudrate(serdev, baud); ++ serdev_device_set_flow_control(serdev, false); ++ ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE); ++ if (ret) { ++ dev_err(dev, "Failed to set parity\n"); ++ return ret; ++ } ++ ++ ret = iei_wt61p803_puzzle_get_version(mcu); ++ if (ret) ++ return ret; ++ ++ dev_dbg(dev, "MCU version: %s\n", mcu->version.version); ++ dev_dbg(dev, "MCU firmware build info: %s\n", mcu->version.build_info); ++ dev_dbg(dev, "MCU in bootloader mode: %s\n", ++ mcu->version.bootloader_mode ? "true" : "false"); ++ dev_dbg(dev, "MCU protocol version: %s\n", mcu->version.protocol_version); ++ ++ if (device_property_read_bool(dev, "enable-beep")) { ++ ret = iei_wt61p803_puzzle_buzzer(mcu, false); ++ if (ret) ++ return ret; ++ } ++ ++ ret = iei_wt61p803_puzzle_sysfs_create(dev, mcu); ++ if (ret) ++ return ret; ++ ++ return devm_of_platform_populate(dev); ++} ++ ++static void iei_wt61p803_puzzle_remove(struct serdev_device *serdev) ++{ ++ struct device *dev = &serdev->dev; ++ struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev); ++ ++ iei_wt61p803_puzzle_sysfs_remove(dev, mcu); ++} ++ ++static const struct of_device_id iei_wt61p803_puzzle_dt_ids[] = { ++ { .compatible = "iei,wt61p803-puzzle" }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(of, iei_wt61p803_puzzle_dt_ids); ++ ++static struct serdev_device_driver iei_wt61p803_puzzle_drv = { ++ .probe = iei_wt61p803_puzzle_probe, ++ .remove = iei_wt61p803_puzzle_remove, ++ .driver = { ++ .name = "iei-wt61p803-puzzle", ++ .of_match_table = iei_wt61p803_puzzle_dt_ids, ++ }, ++}; ++ ++module_serdev_device_driver(iei_wt61p803_puzzle_drv); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Luka Kovacic "); ++MODULE_DESCRIPTION("IEI WT61P803 PUZZLE MCU Driver"); +--- /dev/null ++++ b/include/linux/mfd/iei-wt61p803-puzzle.h +@@ -0,0 +1,66 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* IEI WT61P803 PUZZLE MCU Driver ++ * System management microcontroller for fan control, temperature sensor reading, ++ * LED control and system identification on IEI Puzzle series ARM-based appliances. ++ * ++ * Copyright (C) 2020 Sartura Ltd. ++ * Author: Luka Kovacic ++ */ ++ ++#ifndef _MFD_IEI_WT61P803_PUZZLE_H_ ++#define _MFD_IEI_WT61P803_PUZZLE_H_ ++ ++#define IEI_WT61P803_PUZZLE_BUF_SIZE 512 ++ ++/* Command magic numbers */ ++#define IEI_WT61P803_PUZZLE_CMD_HEADER_START 0x40 /* @ */ ++#define IEI_WT61P803_PUZZLE_CMD_HEADER_START_OTHER 0x25 /* % */ ++#define IEI_WT61P803_PUZZLE_CMD_HEADER_EEPROM 0xF7 ++ ++#define IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK 0x30 /* 0 */ ++#define IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK 0x70 ++ ++#define IEI_WT61P803_PUZZLE_CMD_EEPROM_READ 0xA1 ++#define IEI_WT61P803_PUZZLE_CMD_EEPROM_WRITE 0xA0 ++ ++#define IEI_WT61P803_PUZZLE_CMD_OTHER_VERSION 0x56 /* V */ ++#define IEI_WT61P803_PUZZLE_CMD_OTHER_BUILD 0x42 /* B */ ++#define IEI_WT61P803_PUZZLE_CMD_OTHER_BOOTLOADER_MODE 0x4D /* M */ ++#define IEI_WT61P803_PUZZLE_CMD_OTHER_MODE_BOOTLOADER 0x30 ++#define IEI_WT61P803_PUZZLE_CMD_OTHER_MODE_APPS 0x31 ++#define IEI_WT61P803_PUZZLE_CMD_OTHER_PROTOCOL_VERSION 0x50 /* P */ ++ ++#define IEI_WT61P803_PUZZLE_CMD_FUNCTION_SINGLE 0x43 /* C */ ++#define IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER 0x4F /* O */ ++#define IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_STATUS 0x53 /* S */ ++#define IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_POWER_LOSS 0x41 /* A */ ++ ++#define IEI_WT61P803_PUZZLE_CMD_LED 0x52 /* R */ ++#define IEI_WT61P803_PUZZLE_CMD_LED_POWER 0x31 /* 1 */ ++ ++#define IEI_WT61P803_PUZZLE_CMD_TEMP 0x54 /* T */ ++#define IEI_WT61P803_PUZZLE_CMD_TEMP_ALL 0x41 /* A */ ++ ++#define IEI_WT61P803_PUZZLE_CMD_FAN 0x46 /* F */ ++#define IEI_WT61P803_PUZZLE_CMD_FAN_PWM_READ 0x5A /* Z */ ++#define IEI_WT61P803_PUZZLE_CMD_FAN_PWM_WRITE 0x57 /* W */ ++#define IEI_WT61P803_PUZZLE_CMD_FAN_PWM_BASE 0x30 ++#define IEI_WT61P803_PUZZLE_CMD_FAN_RPM_BASE 0x41 /* A */ ++ ++#define IEI_WT61P803_PUZZLE_CMD_FAN_PWM(x) (IEI_WT61P803_PUZZLE_CMD_FAN_PWM_BASE + (x)) /* 0 - 1 */ ++#define IEI_WT61P803_PUZZLE_CMD_FAN_RPM(x) (IEI_WT61P803_PUZZLE_CMD_FAN_RPM_BASE + (x)) /* 0 - 5 */ ++ ++struct iei_wt61p803_puzzle_mcu_version; ++struct iei_wt61p803_puzzle_reply; ++struct iei_wt61p803_puzzle; ++ ++int iei_wt61p803_puzzle_write_command_watchdog(struct iei_wt61p803_puzzle *mcu, ++ unsigned char *cmd, size_t size, ++ unsigned char *reply_data, size_t *reply_size, ++ int retry_count); ++ ++int iei_wt61p803_puzzle_write_command(struct iei_wt61p803_puzzle *mcu, ++ unsigned char *cmd, size_t size, ++ unsigned char *reply_data, size_t *reply_size); ++ ++#endif /* _MFD_IEI_WT61P803_PUZZLE_H_ */ diff --git a/lede/target/linux/mvebu/patches-6.6/903-drivers-hwmon-Add-the-IEI-WT61P803-PUZZLE-HWMON-driv.patch b/lede/target/linux/mvebu/patches-6.6/903-drivers-hwmon-Add-the-IEI-WT61P803-PUZZLE-HWMON-driv.patch new file mode 100644 index 0000000000..eca2bb81e4 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/903-drivers-hwmon-Add-the-IEI-WT61P803-PUZZLE-HWMON-driv.patch @@ -0,0 +1,503 @@ +From e3310a638cd310bfd93dbbc6d2732ab6aea18dd2 Mon Sep 17 00:00:00 2001 +From: Luka Kovacic +Date: Tue, 24 Aug 2021 12:44:34 +0000 +Subject: [PATCH 3/7] drivers: hwmon: Add the IEI WT61P803 PUZZLE HWMON driver + +Add the IEI WT61P803 PUZZLE HWMON driver, that handles the fan speed +control via PWM, reading fan speed and reading on-board temperature +sensors. + +The driver registers a HWMON device and a simple thermal cooling device to +enable in-kernel fan management. + +This driver depends on the IEI WT61P803 PUZZLE MFD driver. + +Signed-off-by: Luka Kovacic +Signed-off-by: Pavo Banicevic +Acked-by: Guenter Roeck +Cc: Luka Perkov +Cc: Robert Marko +--- + drivers/hwmon/Kconfig | 8 + + drivers/hwmon/Makefile | 1 + + drivers/hwmon/iei-wt61p803-puzzle-hwmon.c | 445 ++++++++++++++++++++++ + 3 files changed, 454 insertions(+) + create mode 100644 drivers/hwmon/iei-wt61p803-puzzle-hwmon.c + +--- a/drivers/hwmon/Kconfig ++++ b/drivers/hwmon/Kconfig +@@ -785,6 +785,14 @@ config SENSORS_IBMPOWERNV + This driver can also be built as a module. If so, the module + will be called ibmpowernv. + ++config SENSORS_IEI_WT61P803_PUZZLE_HWMON ++ tristate "IEI WT61P803 PUZZLE MFD HWMON Driver" ++ depends on MFD_IEI_WT61P803_PUZZLE ++ help ++ The IEI WT61P803 PUZZLE MFD HWMON Driver handles reading fan speed ++ and writing fan PWM values. It also supports reading on-board ++ temperature sensors. ++ + config SENSORS_IIO_HWMON + tristate "Hwmon driver that uses channels specified via iio maps" + depends on IIO +--- a/drivers/hwmon/Makefile ++++ b/drivers/hwmon/Makefile +@@ -90,6 +90,7 @@ obj-$(CONFIG_SENSORS_HS3001) += hs3001.o + obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o + obj-$(CONFIG_SENSORS_I5500) += i5500_temp.o + obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o ++obj-$(CONFIG_SENSORS_IEI_WT61P803_PUZZLE_HWMON) += iei-wt61p803-puzzle-hwmon.o + obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o + obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o + obj-$(CONFIG_SENSORS_IBMPOWERNV)+= ibmpowernv.o +--- /dev/null ++++ b/drivers/hwmon/iei-wt61p803-puzzle-hwmon.c +@@ -0,0 +1,447 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* IEI WT61P803 PUZZLE MCU HWMON Driver ++ * ++ * Copyright (C) 2020 Sartura Ltd. ++ * Author: Luka Kovacic ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define IEI_WT61P803_PUZZLE_HWMON_MAX_PWM 2 ++#define IEI_WT61P803_PUZZLE_HWMON_MAX_PWM_VAL 255 ++ ++/** ++ * struct iei_wt61p803_puzzle_thermal_cooling_device - Thermal cooling device instance ++ * @mcu_hwmon: Parent driver struct pointer ++ * @tcdev: Thermal cooling device pointer ++ * @name: Thermal cooling device name ++ * @pwm_channel: Controlled PWM channel (0 or 1) ++ * @cooling_levels: Thermal cooling device cooling levels (DT) ++ * @cur_level: Current cooling level ++ * @num_levels: Number of cooling levels ++ */ ++struct iei_wt61p803_puzzle_thermal_cooling_device { ++ struct iei_wt61p803_puzzle_hwmon *mcu_hwmon; ++ struct thermal_cooling_device *tcdev; ++ char name[THERMAL_NAME_LENGTH]; ++ int pwm_channel; ++ u32 *cooling_levels; ++ int cur_level; ++ u8 num_levels; ++}; ++ ++/** ++ * struct iei_wt61p803_puzzle_hwmon - MCU HWMON Driver ++ * @mcu: MCU struct pointer ++ * @response_buffer Global MCU response buffer ++ * @thermal_cooling_dev_present: Per-channel thermal cooling device control indicator ++ * @cdev: Per-channel thermal cooling device private structure ++ */ ++struct iei_wt61p803_puzzle_hwmon { ++ struct iei_wt61p803_puzzle *mcu; ++ unsigned char response_buffer[IEI_WT61P803_PUZZLE_BUF_SIZE]; ++ bool thermal_cooling_dev_present[IEI_WT61P803_PUZZLE_HWMON_MAX_PWM]; ++ struct iei_wt61p803_puzzle_thermal_cooling_device ++ *cdev[IEI_WT61P803_PUZZLE_HWMON_MAX_PWM]; ++ struct mutex lock; /* mutex to protect response_buffer array */ ++}; ++ ++#define raw_temp_to_milidegree_celsius(x) (((x) - 0x80) * 1000) ++static int iei_wt61p803_puzzle_read_temp_sensor(struct iei_wt61p803_puzzle_hwmon *mcu_hwmon, ++ int channel, long *value) ++{ ++ unsigned char *resp_buf = mcu_hwmon->response_buffer; ++ unsigned char temp_sensor_ntc_cmd[4] = { ++ IEI_WT61P803_PUZZLE_CMD_HEADER_START, ++ IEI_WT61P803_PUZZLE_CMD_TEMP, ++ IEI_WT61P803_PUZZLE_CMD_TEMP_ALL, ++ }; ++ size_t reply_size; ++ int ret; ++ ++ mutex_lock(&mcu_hwmon->lock); ++ ret = iei_wt61p803_puzzle_write_command(mcu_hwmon->mcu, temp_sensor_ntc_cmd, ++ sizeof(temp_sensor_ntc_cmd), resp_buf, ++ &reply_size); ++ if (ret) ++ goto exit; ++ ++ if (reply_size != 7) { ++ ret = -EIO; ++ goto exit; ++ } ++ ++ /* Check the number of NTC values */ ++ if (resp_buf[3] != '2') { ++ ret = -EIO; ++ goto exit; ++ } ++ ++ *value = raw_temp_to_milidegree_celsius(resp_buf[4 + channel]); ++exit: ++ mutex_unlock(&mcu_hwmon->lock); ++ return ret; ++} ++ ++#define raw_fan_val_to_rpm(x, y) ((((x) << 8 | (y)) / 2) * 60) ++static int iei_wt61p803_puzzle_read_fan_speed(struct iei_wt61p803_puzzle_hwmon *mcu_hwmon, ++ int channel, long *value) ++{ ++ unsigned char *resp_buf = mcu_hwmon->response_buffer; ++ unsigned char fan_speed_cmd[4] = {}; ++ size_t reply_size; ++ int ret; ++ ++ fan_speed_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; ++ fan_speed_cmd[1] = IEI_WT61P803_PUZZLE_CMD_FAN; ++ fan_speed_cmd[2] = IEI_WT61P803_PUZZLE_CMD_FAN_RPM(channel); ++ ++ mutex_lock(&mcu_hwmon->lock); ++ ret = iei_wt61p803_puzzle_write_command(mcu_hwmon->mcu, fan_speed_cmd, ++ sizeof(fan_speed_cmd), resp_buf, ++ &reply_size); ++ if (ret) ++ goto exit; ++ ++ if (reply_size != 7) { ++ ret = -EIO; ++ goto exit; ++ } ++ ++ *value = raw_fan_val_to_rpm(resp_buf[3], resp_buf[4]); ++exit: ++ mutex_unlock(&mcu_hwmon->lock); ++ return ret; ++} ++ ++static int iei_wt61p803_puzzle_write_pwm_channel(struct iei_wt61p803_puzzle_hwmon *mcu_hwmon, ++ int channel, long pwm_set_val) ++{ ++ unsigned char *resp_buf = mcu_hwmon->response_buffer; ++ unsigned char pwm_set_cmd[6] = {}; ++ size_t reply_size; ++ int ret; ++ ++ pwm_set_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; ++ pwm_set_cmd[1] = IEI_WT61P803_PUZZLE_CMD_FAN; ++ pwm_set_cmd[2] = IEI_WT61P803_PUZZLE_CMD_FAN_PWM_WRITE; ++ pwm_set_cmd[3] = IEI_WT61P803_PUZZLE_CMD_FAN_PWM(channel); ++ pwm_set_cmd[4] = pwm_set_val; ++ ++ mutex_lock(&mcu_hwmon->lock); ++ ret = iei_wt61p803_puzzle_write_command(mcu_hwmon->mcu, pwm_set_cmd, ++ sizeof(pwm_set_cmd), resp_buf, ++ &reply_size); ++ if (ret) ++ goto exit; ++ ++ if (reply_size != 3) { ++ ret = -EIO; ++ goto exit; ++ } ++ ++ if (!(resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && ++ resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && ++ resp_buf[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK)) { ++ ret = -EIO; ++ goto exit; ++ } ++exit: ++ mutex_unlock(&mcu_hwmon->lock); ++ return ret; ++} ++ ++static int iei_wt61p803_puzzle_read_pwm_channel(struct iei_wt61p803_puzzle_hwmon *mcu_hwmon, ++ int channel, long *value) ++{ ++ unsigned char *resp_buf = mcu_hwmon->response_buffer; ++ unsigned char pwm_get_cmd[5] = {}; ++ size_t reply_size; ++ int ret; ++ ++ pwm_get_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; ++ pwm_get_cmd[1] = IEI_WT61P803_PUZZLE_CMD_FAN; ++ pwm_get_cmd[2] = IEI_WT61P803_PUZZLE_CMD_FAN_PWM_READ; ++ pwm_get_cmd[3] = IEI_WT61P803_PUZZLE_CMD_FAN_PWM(channel); ++ ++ ret = iei_wt61p803_puzzle_write_command(mcu_hwmon->mcu, pwm_get_cmd, ++ sizeof(pwm_get_cmd), resp_buf, ++ &reply_size); ++ if (ret) ++ return ret; ++ ++ if (reply_size != 5) ++ return -EIO; ++ ++ if (resp_buf[2] != IEI_WT61P803_PUZZLE_CMD_FAN_PWM_READ) ++ return -EIO; ++ ++ *value = resp_buf[3]; ++ ++ return 0; ++} ++ ++static int iei_wt61p803_puzzle_read(struct device *dev, enum hwmon_sensor_types type, ++ u32 attr, int channel, long *val) ++{ ++ struct iei_wt61p803_puzzle_hwmon *mcu_hwmon = dev_get_drvdata(dev->parent); ++ ++ switch (type) { ++ case hwmon_pwm: ++ return iei_wt61p803_puzzle_read_pwm_channel(mcu_hwmon, channel, val); ++ case hwmon_fan: ++ return iei_wt61p803_puzzle_read_fan_speed(mcu_hwmon, channel, val); ++ case hwmon_temp: ++ return iei_wt61p803_puzzle_read_temp_sensor(mcu_hwmon, channel, val); ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int iei_wt61p803_puzzle_write(struct device *dev, enum hwmon_sensor_types type, ++ u32 attr, int channel, long val) ++{ ++ struct iei_wt61p803_puzzle_hwmon *mcu_hwmon = dev_get_drvdata(dev->parent); ++ ++ return iei_wt61p803_puzzle_write_pwm_channel(mcu_hwmon, channel, val); ++} ++ ++static umode_t iei_wt61p803_puzzle_is_visible(const void *data, enum hwmon_sensor_types type, ++ u32 attr, int channel) ++{ ++ const struct iei_wt61p803_puzzle_hwmon *mcu_hwmon = data; ++ ++ switch (type) { ++ case hwmon_pwm: ++ if (mcu_hwmon->thermal_cooling_dev_present[channel]) ++ return 0444; ++ if (attr == hwmon_pwm_input) ++ return 0644; ++ break; ++ case hwmon_fan: ++ if (attr == hwmon_fan_input) ++ return 0444; ++ break; ++ case hwmon_temp: ++ if (attr == hwmon_temp_input) ++ return 0444; ++ break; ++ default: ++ return 0; ++ } ++ ++ return 0; ++} ++ ++static const struct hwmon_ops iei_wt61p803_puzzle_hwmon_ops = { ++ .is_visible = iei_wt61p803_puzzle_is_visible, ++ .read = iei_wt61p803_puzzle_read, ++ .write = iei_wt61p803_puzzle_write, ++}; ++ ++static const struct hwmon_channel_info *iei_wt61p803_puzzle_info[] = { ++ HWMON_CHANNEL_INFO(pwm, ++ HWMON_PWM_INPUT, ++ HWMON_PWM_INPUT), ++ HWMON_CHANNEL_INFO(fan, ++ HWMON_F_INPUT, ++ HWMON_F_INPUT, ++ HWMON_F_INPUT, ++ HWMON_F_INPUT, ++ HWMON_F_INPUT), ++ HWMON_CHANNEL_INFO(temp, ++ HWMON_T_INPUT, ++ HWMON_T_INPUT), ++ NULL ++}; ++ ++static const struct hwmon_chip_info iei_wt61p803_puzzle_chip_info = { ++ .ops = &iei_wt61p803_puzzle_hwmon_ops, ++ .info = iei_wt61p803_puzzle_info, ++}; ++ ++static int iei_wt61p803_puzzle_get_max_state(struct thermal_cooling_device *tcdev, ++ unsigned long *state) ++{ ++ struct iei_wt61p803_puzzle_thermal_cooling_device *cdev = tcdev->devdata; ++ ++ if (!cdev) ++ return -EINVAL; ++ ++ *state = cdev->num_levels - 1; ++ return 0; ++} ++ ++static int iei_wt61p803_puzzle_get_cur_state(struct thermal_cooling_device *tcdev, ++ unsigned long *state) ++{ ++ struct iei_wt61p803_puzzle_thermal_cooling_device *cdev = tcdev->devdata; ++ ++ if (!cdev) ++ return -EINVAL; ++ ++ if (cdev->cur_level < 0) ++ return -EAGAIN; ++ ++ *state = cdev->cur_level; ++ return 0; ++} ++ ++static int iei_wt61p803_puzzle_set_cur_state(struct thermal_cooling_device *tcdev, ++ unsigned long state) ++{ ++ struct iei_wt61p803_puzzle_thermal_cooling_device *cdev = tcdev->devdata; ++ u8 pwm_level; ++ ++ if (!cdev) ++ return -EINVAL; ++ ++ if (state >= cdev->num_levels) ++ return -EINVAL; ++ ++ if (state == cdev->cur_level) ++ return 0; ++ ++ cdev->cur_level = state; ++ pwm_level = cdev->cooling_levels[state]; ++ ++ return iei_wt61p803_puzzle_write_pwm_channel(cdev->mcu_hwmon, cdev->pwm_channel, pwm_level); ++} ++ ++static const struct thermal_cooling_device_ops iei_wt61p803_puzzle_cooling_ops = { ++ .get_max_state = iei_wt61p803_puzzle_get_max_state, ++ .get_cur_state = iei_wt61p803_puzzle_get_cur_state, ++ .set_cur_state = iei_wt61p803_puzzle_set_cur_state, ++}; ++ ++static int ++iei_wt61p803_puzzle_enable_thermal_cooling_dev(struct device *dev, ++ struct fwnode_handle *child, ++ struct iei_wt61p803_puzzle_hwmon *mcu_hwmon) ++{ ++ struct iei_wt61p803_puzzle_thermal_cooling_device *cdev; ++ u32 pwm_channel; ++ u8 num_levels; ++ int i, ret; ++ ++ ret = fwnode_property_read_u32(child, "reg", &pwm_channel); ++ if (ret) ++ return ret; ++ ++ mcu_hwmon->thermal_cooling_dev_present[pwm_channel] = true; ++ ++ num_levels = fwnode_property_count_u32(child, "cooling-levels"); ++ if (!num_levels) ++ return -EINVAL; ++ ++ cdev = devm_kzalloc(dev, sizeof(*cdev), GFP_KERNEL); ++ if (!cdev) ++ return -ENOMEM; ++ ++ cdev->cooling_levels = devm_kmalloc_array(dev, num_levels, sizeof(u32), GFP_KERNEL); ++ if (!cdev->cooling_levels) ++ return -ENOMEM; ++ ++ ret = fwnode_property_read_u32_array(child, "cooling-levels", ++ cdev->cooling_levels, ++ num_levels); ++ if (ret) { ++ dev_err(dev, "Couldn't read property 'cooling-levels'\n"); ++ return ret; ++ } ++ ++ for (i = 0; i < num_levels; i++) { ++ if (cdev->cooling_levels[i] > ++ IEI_WT61P803_PUZZLE_HWMON_MAX_PWM_VAL) { ++ dev_err(dev, "iei_wt61p803_fan state[%d]:%d > %d\n", i, ++ cdev->cooling_levels[i], ++ IEI_WT61P803_PUZZLE_HWMON_MAX_PWM_VAL); ++ return -EINVAL; ++ } ++ } ++ ++ cdev->mcu_hwmon = mcu_hwmon; ++ cdev->pwm_channel = pwm_channel; ++ cdev->num_levels = num_levels; ++ cdev->cur_level = -1; ++ mcu_hwmon->cdev[pwm_channel] = cdev; ++ ++ snprintf(cdev->name, THERMAL_NAME_LENGTH, "wt61p803_puzzle_%d", pwm_channel); ++ cdev->tcdev = devm_thermal_of_cooling_device_register(dev, to_of_node(child), cdev->name, ++ cdev, &iei_wt61p803_puzzle_cooling_ops); ++ if (IS_ERR(cdev->tcdev)) ++ return PTR_ERR(cdev->tcdev); ++ ++ return 0; ++} ++ ++static int iei_wt61p803_puzzle_hwmon_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev->parent); ++ struct iei_wt61p803_puzzle_hwmon *mcu_hwmon; ++ struct fwnode_handle *child; ++ struct device *hwmon_dev; ++ int ret; ++ ++ mcu_hwmon = devm_kzalloc(dev, sizeof(*mcu_hwmon), GFP_KERNEL); ++ if (!mcu_hwmon) ++ return -ENOMEM; ++ ++ mcu_hwmon->mcu = mcu; ++ platform_set_drvdata(pdev, mcu_hwmon); ++ ret = devm_mutex_init(dev, &mcu_hwmon->lock); ++ if (ret) ++ return ret; ++ ++ hwmon_dev = devm_hwmon_device_register_with_info(dev, "iei_wt61p803_puzzle", ++ mcu_hwmon, ++ &iei_wt61p803_puzzle_chip_info, ++ NULL); ++ if (IS_ERR(hwmon_dev)) ++ return PTR_ERR(hwmon_dev); ++ ++ /* Control fans via PWM lines via Linux Kernel */ ++ if (IS_ENABLED(CONFIG_THERMAL)) { ++ device_for_each_child_node(dev, child) { ++ ret = iei_wt61p803_puzzle_enable_thermal_cooling_dev(dev, child, mcu_hwmon); ++ if (ret) { ++ dev_err(dev, "Enabling the PWM fan failed\n"); ++ fwnode_handle_put(child); ++ return ret; ++ } ++ } ++ } ++ return 0; ++} ++ ++static const struct of_device_id iei_wt61p803_puzzle_hwmon_id_table[] = { ++ { .compatible = "iei,wt61p803-puzzle-hwmon" }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, iei_wt61p803_puzzle_hwmon_id_table); ++ ++static struct platform_driver iei_wt61p803_puzzle_hwmon_driver = { ++ .driver = { ++ .name = "iei-wt61p803-puzzle-hwmon", ++ .of_match_table = iei_wt61p803_puzzle_hwmon_id_table, ++ }, ++ .probe = iei_wt61p803_puzzle_hwmon_probe, ++}; ++ ++module_platform_driver(iei_wt61p803_puzzle_hwmon_driver); ++ ++MODULE_DESCRIPTION("IEI WT61P803 PUZZLE MCU HWMON Driver"); ++MODULE_AUTHOR("Luka Kovacic "); ++MODULE_LICENSE("GPL v2"); diff --git a/lede/target/linux/mvebu/patches-6.6/904-drivers-leds-Add-the-IEI-WT61P803-PUZZLE-LED-driver.patch b/lede/target/linux/mvebu/patches-6.6/904-drivers-leds-Add-the-IEI-WT61P803-PUZZLE-LED-driver.patch new file mode 100644 index 0000000000..a9cb46bbd8 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/904-drivers-leds-Add-the-IEI-WT61P803-PUZZLE-LED-driver.patch @@ -0,0 +1,207 @@ +From f3b44eb69cc561cf05d00506dcec0dd9be003ed8 Mon Sep 17 00:00:00 2001 +From: Luka Kovacic +Date: Tue, 24 Aug 2021 12:44:35 +0000 +Subject: [PATCH 4/7] drivers: leds: Add the IEI WT61P803 PUZZLE LED driver + +Add support for the IEI WT61P803 PUZZLE LED driver. +Currently only the front panel power LED is supported, +since it is the only LED on this board wired through the +MCU. + +The LED is wired directly to the on-board MCU controller +and is toggled using an MCU command. + +Support for more LEDs is going to be added in case more +boards implement this microcontroller, as LEDs use many +different GPIOs. + +This driver depends on the IEI WT61P803 PUZZLE MFD driver. + +Signed-off-by: Luka Kovacic +Signed-off-by: Pavo Banicevic +Cc: Luka Perkov +Cc: Robert Marko +--- + drivers/leds/Kconfig | 8 ++ + drivers/leds/Makefile | 1 + + drivers/leds/leds-iei-wt61p803-puzzle.c | 147 ++++++++++++++++++++++++ + 3 files changed, 156 insertions(+) + create mode 100644 drivers/leds/leds-iei-wt61p803-puzzle.c + +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -316,6 +316,14 @@ config LEDS_IPAQ_MICRO + Choose this option if you want to use the notification LED on + Compaq/HP iPAQ h3100 and h3600. + ++config LEDS_IEI_WT61P803_PUZZLE ++ tristate "LED Support for the IEI WT61P803 PUZZLE MCU" ++ depends on LEDS_CLASS ++ depends on MFD_IEI_WT61P803_PUZZLE ++ help ++ This option enables support for LEDs controlled by the IEI WT61P803 ++ M801 MCU. ++ + config LEDS_HP6XX + tristate "LED Support for the HP Jornada 6xx" + depends on LEDS_CLASS +--- a/drivers/leds/Makefile ++++ b/drivers/leds/Makefile +@@ -34,6 +34,7 @@ obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx. + obj-$(CONFIG_LEDS_INTEL_SS4200) += leds-ss4200.o + obj-$(CONFIG_LEDS_IP30) += leds-ip30.o + obj-$(CONFIG_LEDS_IPAQ_MICRO) += leds-ipaq-micro.o ++obj-$(CONFIG_LEDS_IEI_WT61P803_PUZZLE) += leds-iei-wt61p803-puzzle.o + obj-$(CONFIG_LEDS_IS31FL319X) += leds-is31fl319x.o + obj-$(CONFIG_LEDS_IS31FL32XX) += leds-is31fl32xx.o + obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o +--- /dev/null ++++ b/drivers/leds/leds-iei-wt61p803-puzzle.c +@@ -0,0 +1,147 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* IEI WT61P803 PUZZLE MCU LED Driver ++ * ++ * Copyright (C) 2020 Sartura Ltd. ++ * Author: Luka Kovacic ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++enum iei_wt61p803_puzzle_led_state { ++ IEI_LED_OFF = 0x30, ++ IEI_LED_ON = 0x31, ++ IEI_LED_BLINK_5HZ = 0x32, ++ IEI_LED_BLINK_1HZ = 0x33, ++}; ++ ++/** ++ * struct iei_wt61p803_puzzle_led - MCU LED Driver ++ * @cdev: LED classdev ++ * @mcu: MCU struct pointer ++ * @response_buffer Global MCU response buffer ++ * @lock: General mutex lock to protect simultaneous R/W access to led_power_state ++ * @led_power_state: State of the front panel power LED ++ */ ++struct iei_wt61p803_puzzle_led { ++ struct led_classdev cdev; ++ struct iei_wt61p803_puzzle *mcu; ++ unsigned char response_buffer[IEI_WT61P803_PUZZLE_BUF_SIZE]; ++ struct mutex lock; /* mutex to protect led_power_state */ ++ int led_power_state; ++}; ++ ++static inline struct iei_wt61p803_puzzle_led *cdev_to_iei_wt61p803_puzzle_led ++ (struct led_classdev *led_cdev) ++{ ++ return container_of(led_cdev, struct iei_wt61p803_puzzle_led, cdev); ++} ++ ++static int iei_wt61p803_puzzle_led_brightness_set_blocking(struct led_classdev *cdev, ++ enum led_brightness brightness) ++{ ++ struct iei_wt61p803_puzzle_led *priv = cdev_to_iei_wt61p803_puzzle_led(cdev); ++ unsigned char *resp_buf = priv->response_buffer; ++ unsigned char led_power_cmd[5] = {}; ++ size_t reply_size; ++ int ret; ++ ++ led_power_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; ++ led_power_cmd[1] = IEI_WT61P803_PUZZLE_CMD_LED; ++ led_power_cmd[2] = IEI_WT61P803_PUZZLE_CMD_LED_POWER; ++ led_power_cmd[3] = brightness == LED_OFF ? IEI_LED_OFF : IEI_LED_ON; ++ ++ ret = iei_wt61p803_puzzle_write_command(priv->mcu, led_power_cmd, ++ sizeof(led_power_cmd), ++ resp_buf, ++ &reply_size); ++ if (ret) ++ return ret; ++ ++ if (reply_size != 3) ++ return -EIO; ++ ++ if (!(resp_buf[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && ++ resp_buf[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && ++ resp_buf[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK)) ++ return -EIO; ++ ++ mutex_lock(&priv->lock); ++ priv->led_power_state = brightness; ++ mutex_unlock(&priv->lock); ++ ++ return 0; ++} ++ ++static enum led_brightness iei_wt61p803_puzzle_led_brightness_get(struct led_classdev *cdev) ++{ ++ struct iei_wt61p803_puzzle_led *priv = cdev_to_iei_wt61p803_puzzle_led(cdev); ++ int led_state; ++ ++ mutex_lock(&priv->lock); ++ led_state = priv->led_power_state; ++ mutex_unlock(&priv->lock); ++ ++ return led_state; ++} ++ ++static int iei_wt61p803_puzzle_led_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev->parent); ++ struct iei_wt61p803_puzzle_led *priv; ++ struct led_init_data init_data = {}; ++ struct fwnode_handle *child; ++ int ret; ++ ++ if (device_get_child_node_count(dev) != 1) ++ return -EINVAL; ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->mcu = mcu; ++ priv->led_power_state = 1; ++ mutex_init(&priv->lock); ++ dev_set_drvdata(dev, priv); ++ ++ child = device_get_next_child_node(dev, NULL); ++ init_data.fwnode = child; ++ ++ priv->cdev.brightness_set_blocking = iei_wt61p803_puzzle_led_brightness_set_blocking; ++ priv->cdev.brightness_get = iei_wt61p803_puzzle_led_brightness_get; ++ priv->cdev.max_brightness = 1; ++ ++ ret = devm_led_classdev_register_ext(dev, &priv->cdev, &init_data); ++ if (ret) ++ dev_err(dev, "Could not register LED\n"); ++ ++ fwnode_handle_put(child); ++ return ret; ++} ++ ++static const struct of_device_id iei_wt61p803_puzzle_led_of_match[] = { ++ { .compatible = "iei,wt61p803-puzzle-leds" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, iei_wt61p803_puzzle_led_of_match); ++ ++static struct platform_driver iei_wt61p803_puzzle_led_driver = { ++ .driver = { ++ .name = "iei-wt61p803-puzzle-led", ++ .of_match_table = iei_wt61p803_puzzle_led_of_match, ++ }, ++ .probe = iei_wt61p803_puzzle_led_probe, ++}; ++module_platform_driver(iei_wt61p803_puzzle_led_driver); ++ ++MODULE_DESCRIPTION("IEI WT61P803 PUZZLE front panel LED driver"); ++MODULE_AUTHOR("Luka Kovacic "); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:leds-iei-wt61p803-puzzle"); diff --git a/lede/target/linux/mvebu/patches-6.6/905-Documentation-ABI-Add-iei-wt61p803-puzzle-driver-sys.patch b/lede/target/linux/mvebu/patches-6.6/905-Documentation-ABI-Add-iei-wt61p803-puzzle-driver-sys.patch new file mode 100644 index 0000000000..b1d420ef0a --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/905-Documentation-ABI-Add-iei-wt61p803-puzzle-driver-sys.patch @@ -0,0 +1,82 @@ +From 2fab3b4956c5b2f83c1e1abffc1df39de2933d83 Mon Sep 17 00:00:00 2001 +From: Luka Kovacic +Date: Tue, 24 Aug 2021 12:44:36 +0000 +Subject: [PATCH 5/7] Documentation/ABI: Add iei-wt61p803-puzzle driver sysfs + interface documentation + +Add the iei-wt61p803-puzzle driver sysfs interface documentation to allow +monitoring and control of the microcontroller from user space. + +Signed-off-by: Luka Kovacic +Signed-off-by: Pavo Banicevic +Cc: Luka Perkov +Cc: Robert Marko +--- + .../testing/sysfs-driver-iei-wt61p803-puzzle | 61 +++++++++++++++++++ + 1 file changed, 61 insertions(+) + create mode 100644 Documentation/ABI/testing/sysfs-driver-iei-wt61p803-puzzle + +--- /dev/null ++++ b/Documentation/ABI/testing/sysfs-driver-iei-wt61p803-puzzle +@@ -0,0 +1,61 @@ ++What: /sys/bus/serial/devices/.../mac_address_* ++Date: September 2020 ++Contact: Luka Kovacic ++Description: (RW) Internal factory assigned MAC address values ++ ++What: /sys/bus/serial/devices/.../serial_number ++Date: September 2020 ++Contact: Luka Kovacic ++Description: (RW) Internal factory assigned serial number ++ ++What: /sys/bus/serial/devices/.../version ++Date: September 2020 ++Contact: Luka Kovacic ++Description: (RO) Internal MCU firmware version ++ ++What: /sys/bus/serial/devices/.../protocol_version ++Date: September 2020 ++Contact: Luka Kovacic ++Description: (RO) Internal MCU communication protocol version ++ ++What: /sys/bus/serial/devices/.../power_loss_recovery ++Date: September 2020 ++Contact: Luka Kovacic ++Description: (RW) Host platform power loss recovery settings ++ Value mapping: 0 - Always-On, 1 - Always-Off, 2 - Always-AC, 3 - Always-WA ++ ++What: /sys/bus/serial/devices/.../bootloader_mode ++Date: September 2020 ++Contact: Luka Kovacic ++Description: (RO) Internal MCU bootloader mode status ++ Value mapping: ++ 0 - normal mode ++ 1 - bootloader mode ++ ++What: /sys/bus/serial/devices/.../power_status ++Date: September 2020 ++Contact: Luka Kovacic ++Description: (RO) Power status indicates the host platform power on method. ++ Value mapping (bitwise list): ++ 0x80 - Null ++ 0x40 - Firmware flag ++ 0x20 - Power loss detection flag (powered off) ++ 0x10 - Power loss detection flag (AC mode) ++ 0x08 - Button power on ++ 0x04 - Wake-on-LAN power on ++ 0x02 - RTC alarm power on ++ 0x01 - AC recover power on ++ ++What: /sys/bus/serial/devices/.../build_info ++Date: September 2020 ++Contact: Luka Kovacic ++Description: (RO) Internal MCU firmware build date ++ Format: yyyy/mm/dd hh:mm ++ ++What: /sys/bus/serial/devices/.../ac_recovery_status ++Date: September 2020 ++Contact: Luka Kovacic ++Description: (RO) Host platform AC recovery status value ++ Value mapping: ++ 0 - board has not been recovered from power down ++ 1 - board has been recovered from power down diff --git a/lede/target/linux/mvebu/patches-6.6/906-Documentation-hwmon-Add-iei-wt61p803-puzzle-hwmon-dr.patch b/lede/target/linux/mvebu/patches-6.6/906-Documentation-hwmon-Add-iei-wt61p803-puzzle-hwmon-dr.patch new file mode 100644 index 0000000000..77e9fa298e --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/906-Documentation-hwmon-Add-iei-wt61p803-puzzle-hwmon-dr.patch @@ -0,0 +1,74 @@ +From 0aff3e5923fecc6842473ad07a688d6e2f2c2d55 Mon Sep 17 00:00:00 2001 +From: Luka Kovacic +Date: Tue, 24 Aug 2021 12:44:37 +0000 +Subject: [PATCH 6/7] Documentation/hwmon: Add iei-wt61p803-puzzle hwmon driver + documentation + +Add the iei-wt61p803-puzzle driver hwmon driver interface documentation. + +Signed-off-by: Luka Kovacic +Signed-off-by: Pavo Banicevic +Cc: Luka Perkov +Cc: Robert Marko +--- + .../hwmon/iei-wt61p803-puzzle-hwmon.rst | 43 +++++++++++++++++++ + Documentation/hwmon/index.rst | 1 + + 2 files changed, 44 insertions(+) + create mode 100644 Documentation/hwmon/iei-wt61p803-puzzle-hwmon.rst + +--- /dev/null ++++ b/Documentation/hwmon/iei-wt61p803-puzzle-hwmon.rst +@@ -0,0 +1,43 @@ ++.. SPDX-License-Identifier: GPL-2.0-only ++ ++Kernel driver iei-wt61p803-puzzle-hwmon ++======================================= ++ ++Supported chips: ++ * IEI WT61P803 PUZZLE for IEI Puzzle M801 ++ ++ Prefix: 'iei-wt61p803-puzzle-hwmon' ++ ++Author: Luka Kovacic ++ ++ ++Description ++----------- ++ ++This driver adds fan and temperature sensor reading for some IEI Puzzle ++series boards. ++ ++Sysfs attributes ++---------------- ++ ++The following attributes are supported: ++ ++- IEI WT61P803 PUZZLE for IEI Puzzle M801 ++ ++/sys files in hwmon subsystem ++----------------------------- ++ ++================= == ===================================================== ++fan[1-5]_input RO files for fan speed (in RPM) ++pwm[1-2] RW files for fan[1-2] target duty cycle (0..255) ++temp[1-2]_input RO files for temperature sensors, in millidegree Celsius ++================= == ===================================================== ++ ++/sys files in thermal subsystem ++------------------------------- ++ ++================= == ===================================================== ++cur_state RW file for current cooling state of the cooling device ++ (0..max_state) ++max_state RO file for maximum cooling state of the cooling device ++================= == ===================================================== +--- a/Documentation/hwmon/index.rst ++++ b/Documentation/hwmon/index.rst +@@ -82,6 +82,7 @@ Hardware Monitoring Kernel Drivers + ibmaem + ibm-cffps + ibmpowernv ++ iei-wt61p803-puzzle-hwmon + ina209 + ina2xx + ina238 diff --git a/lede/target/linux/mvebu/patches-6.6/907-MAINTAINERS-Add-an-entry-for-the-IEI-WT61P803-PUZZLE.patch b/lede/target/linux/mvebu/patches-6.6/907-MAINTAINERS-Add-an-entry-for-the-IEI-WT61P803-PUZZLE.patch new file mode 100644 index 0000000000..d70bfe9a1a --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/907-MAINTAINERS-Add-an-entry-for-the-IEI-WT61P803-PUZZLE.patch @@ -0,0 +1,41 @@ +From 12479baad28d2a08c6cb9e83471057635fa1635c Mon Sep 17 00:00:00 2001 +From: Luka Kovacic +Date: Tue, 24 Aug 2021 12:44:38 +0000 +Subject: [PATCH 7/7] MAINTAINERS: Add an entry for the IEI WT61P803 PUZZLE + driver + +Add an entry for the IEI WT61P803 PUZZLE driver (MFD, HWMON, LED drivers). + +Signed-off-by: Luka Kovacic +Signed-off-by: Pavo Banicevic +Cc: Luka Perkov +Cc: Robert Marko +--- + MAINTAINERS | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -10143,6 +10143,22 @@ IFCVF VIRTIO DATA PATH ACCELERATOR + R: Zhu Lingshan + F: drivers/vdpa/ifcvf/ + ++IEI WT61P803 M801 MFD DRIVER ++M: Luka Kovacic ++M: Luka Perkov ++M: Goran Medic ++L: linux-kernel@vger.kernel.org ++S: Maintained ++F: Documentation/ABI/stable/sysfs-driver-iei-wt61p803-puzzle ++F: Documentation/devicetree/bindings/hwmon/iei,wt61p803-puzzle-hwmon.yaml ++F: Documentation/devicetree/bindings/leds/iei,wt61p803-puzzle-leds.yaml ++F: Documentation/devicetree/bindings/mfd/iei,wt61p803-puzzle.yaml ++F: Documentation/hwmon/iei-wt61p803-puzzle-hwmon.rst ++F: drivers/hwmon/iei-wt61p803-puzzle-hwmon.c ++F: drivers/leds/leds-iei-wt61p803-puzzle.c ++F: drivers/mfd/iei-wt61p803-puzzle.c ++F: include/linux/mfd/iei-wt61p803-puzzle.h ++ + IFE PROTOCOL + M: Yotam Gigi + M: Jamal Hadi Salim diff --git a/lede/target/linux/mvebu/patches-6.6/910-drivers-leds-wt61p803-puzzle-improvements.patch b/lede/target/linux/mvebu/patches-6.6/910-drivers-leds-wt61p803-puzzle-improvements.patch new file mode 100644 index 0000000000..8de403773a --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/910-drivers-leds-wt61p803-puzzle-improvements.patch @@ -0,0 +1,273 @@ +--- a/drivers/leds/leds-iei-wt61p803-puzzle.c ++++ b/drivers/leds/leds-iei-wt61p803-puzzle.c +@@ -9,9 +9,13 @@ + #include + #include + #include ++#include + #include + #include + #include ++#include ++ ++#define IEI_LEDS_MAX 4 + + enum iei_wt61p803_puzzle_led_state { + IEI_LED_OFF = 0x30, +@@ -33,7 +37,11 @@ struct iei_wt61p803_puzzle_led { + struct iei_wt61p803_puzzle *mcu; + unsigned char response_buffer[IEI_WT61P803_PUZZLE_BUF_SIZE]; + struct mutex lock; /* mutex to protect led_power_state */ ++ struct work_struct work; + int led_power_state; ++ int id; ++ u8 blinking; ++ bool active_low; + }; + + static inline struct iei_wt61p803_puzzle_led *cdev_to_iei_wt61p803_puzzle_led +@@ -51,10 +59,18 @@ static int iei_wt61p803_puzzle_led_brigh + size_t reply_size; + int ret; + ++ if (priv->blinking) { ++ if (brightness == LED_OFF) ++ priv->blinking = 0; ++ else ++ return 0; ++ } ++ + led_power_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; + led_power_cmd[1] = IEI_WT61P803_PUZZLE_CMD_LED; +- led_power_cmd[2] = IEI_WT61P803_PUZZLE_CMD_LED_POWER; +- led_power_cmd[3] = brightness == LED_OFF ? IEI_LED_OFF : IEI_LED_ON; ++ led_power_cmd[2] = IEI_WT61P803_PUZZLE_CMD_LED_SET(priv->id); ++ led_power_cmd[3] = ((brightness == LED_OFF) ^ priv->active_low) ? ++ IEI_LED_OFF : priv->blinking?priv->blinking:IEI_LED_ON; + + ret = iei_wt61p803_puzzle_write_command(priv->mcu, led_power_cmd, + sizeof(led_power_cmd), +@@ -90,39 +106,168 @@ static enum led_brightness iei_wt61p803_ + return led_state; + } + ++static void iei_wt61p803_puzzle_led_apply_blink(struct work_struct *work) ++{ ++ struct iei_wt61p803_puzzle_led *priv = container_of(work, struct iei_wt61p803_puzzle_led, work); ++ unsigned char led_blink_cmd[5] = {}; ++ unsigned char resp_buf[IEI_WT61P803_PUZZLE_BUF_SIZE]; ++ size_t reply_size; ++ ++ led_blink_cmd[0] = IEI_WT61P803_PUZZLE_CMD_HEADER_START; ++ led_blink_cmd[1] = IEI_WT61P803_PUZZLE_CMD_LED; ++ led_blink_cmd[2] = IEI_WT61P803_PUZZLE_CMD_LED_SET(priv->id); ++ led_blink_cmd[3] = priv->blinking; ++ ++ iei_wt61p803_puzzle_write_command(priv->mcu, led_blink_cmd, ++ sizeof(led_blink_cmd), ++ resp_buf, ++ &reply_size); ++ ++ return; ++} ++ ++static int iei_wt61p803_puzzle_led_set_blink(struct led_classdev *cdev, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ struct iei_wt61p803_puzzle_led *priv = cdev_to_iei_wt61p803_puzzle_led(cdev); ++ u8 blink_mode = 0; ++ int ret = 0; ++ ++ /* set defaults */ ++ if (!*delay_on && !*delay_off) { ++ *delay_on = 500; ++ *delay_off = 500; ++ } ++ ++ /* minimum delay for soft-driven blinking is 100ms to keep load low */ ++ if (*delay_on < 100) ++ *delay_on = 100; ++ ++ if (*delay_off < 100) ++ *delay_off = 100; ++ ++ /* offload blinking to hardware, if possible */ ++ if (*delay_on != *delay_off) { ++ ret = -EINVAL; ++ } else if (*delay_on == 100) { ++ blink_mode = IEI_LED_BLINK_5HZ; ++ *delay_on = 100; ++ *delay_off = 100; ++ } else if (*delay_on <= 500) { ++ blink_mode = IEI_LED_BLINK_1HZ; ++ *delay_on = 500; ++ *delay_off = 500; ++ } else { ++ ret = -EINVAL; ++ } ++ ++ mutex_lock(&priv->lock); ++ priv->blinking = blink_mode; ++ mutex_unlock(&priv->lock); ++ ++ if (blink_mode) ++ schedule_work(&priv->work); ++ ++ return ret; ++} ++ ++ ++static int iei_wt61p803_puzzle_led_set_dt_default(struct led_classdev *cdev, ++ struct device_node *np) ++{ ++ const char *state; ++ int ret = 0; ++ ++ state = of_get_property(np, "default-state", NULL); ++ if (state) { ++ if (!strcmp(state, "on")) { ++ ret = ++ iei_wt61p803_puzzle_led_brightness_set_blocking( ++ cdev, cdev->max_brightness); ++ } else { ++ ret = iei_wt61p803_puzzle_led_brightness_set_blocking( ++ cdev, LED_OFF); ++ } ++ } ++ ++ return ret; ++} ++ + static int iei_wt61p803_puzzle_led_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; ++ struct device_node *np = dev_of_node(dev); ++ struct device_node *child; + struct iei_wt61p803_puzzle *mcu = dev_get_drvdata(dev->parent); + struct iei_wt61p803_puzzle_led *priv; +- struct led_init_data init_data = {}; +- struct fwnode_handle *child; + int ret; ++ u32 reg; + +- if (device_get_child_node_count(dev) != 1) ++ if (device_get_child_node_count(dev) > IEI_LEDS_MAX) + return -EINVAL; + +- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; +- +- priv->mcu = mcu; +- priv->led_power_state = 1; +- mutex_init(&priv->lock); +- dev_set_drvdata(dev, priv); +- +- child = device_get_next_child_node(dev, NULL); +- init_data.fwnode = child; +- +- priv->cdev.brightness_set_blocking = iei_wt61p803_puzzle_led_brightness_set_blocking; +- priv->cdev.brightness_get = iei_wt61p803_puzzle_led_brightness_get; +- priv->cdev.max_brightness = 1; ++ for_each_available_child_of_node(np, child) { ++ struct led_init_data init_data = {}; + +- ret = devm_led_classdev_register_ext(dev, &priv->cdev, &init_data); +- if (ret) +- dev_err(dev, "Could not register LED\n"); ++ ret = of_property_read_u32(child, "reg", ®); ++ if (ret) { ++ dev_err(dev, "Failed to read led 'reg' property\n"); ++ goto put_child_node; ++ } ++ ++ if (reg > IEI_LEDS_MAX) { ++ dev_err(dev, "Invalid led reg %u\n", reg); ++ ret = -EINVAL; ++ goto put_child_node; ++ } ++ ++ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) { ++ ret = -ENOMEM; ++ goto put_child_node; ++ } ++ ++ ret = devm_mutex_init(dev, &priv->lock); ++ if (ret) ++ goto put_child_node; ++ ++ dev_set_drvdata(dev, priv); ++ ++ if (of_property_read_bool(child, "active-low")) ++ priv->active_low = true; ++ ++ priv->mcu = mcu; ++ priv->id = reg; ++ priv->led_power_state = 1; ++ priv->blinking = 0; ++ init_data.fwnode = of_fwnode_handle(child); ++ ++ priv->cdev.brightness_set_blocking = iei_wt61p803_puzzle_led_brightness_set_blocking; ++ priv->cdev.brightness_get = iei_wt61p803_puzzle_led_brightness_get; ++ priv->cdev.blink_set = iei_wt61p803_puzzle_led_set_blink; ++ ++ priv->cdev.max_brightness = 1; ++ ++ INIT_WORK(&priv->work, iei_wt61p803_puzzle_led_apply_blink); ++ ++ ret = iei_wt61p803_puzzle_led_set_dt_default(&priv->cdev, child); ++ if (ret) { ++ dev_err(dev, "Could apply default from DT\n"); ++ goto put_child_node; ++ } ++ ++ ret = devm_led_classdev_register_ext(dev, &priv->cdev, &init_data); ++ if (ret) { ++ dev_err(dev, "Could not register LED\n"); ++ goto put_child_node; ++ } ++ } ++ ++ return ret; + +- fwnode_handle_put(child); ++put_child_node: ++ of_node_put(child); + return ret; + } + +--- a/include/linux/mfd/iei-wt61p803-puzzle.h ++++ b/include/linux/mfd/iei-wt61p803-puzzle.h +@@ -36,7 +36,7 @@ + #define IEI_WT61P803_PUZZLE_CMD_FUNCTION_OTHER_POWER_LOSS 0x41 /* A */ + + #define IEI_WT61P803_PUZZLE_CMD_LED 0x52 /* R */ +-#define IEI_WT61P803_PUZZLE_CMD_LED_POWER 0x31 /* 1 */ ++#define IEI_WT61P803_PUZZLE_CMD_LED_SET(n) (0x30 | (n)) + + #define IEI_WT61P803_PUZZLE_CMD_TEMP 0x54 /* T */ + #define IEI_WT61P803_PUZZLE_CMD_TEMP_ALL 0x41 /* A */ +--- a/drivers/mfd/iei-wt61p803-puzzle.c ++++ b/drivers/mfd/iei-wt61p803-puzzle.c +@@ -176,6 +176,9 @@ static int iei_wt61p803_puzzle_recv_buf( + struct iei_wt61p803_puzzle *mcu = serdev_device_get_drvdata(serdev); + int ret; + ++ print_hex_dump_debug("puzzle-mcu rx: ", DUMP_PREFIX_NONE, ++ 16, 1, data, size, false); ++ + ret = iei_wt61p803_puzzle_process_resp(mcu, data, size); + /* Return the number of processed bytes if function returns error, + * discard the remaining incoming data, since the frame this data +@@ -246,6 +249,9 @@ int iei_wt61p803_puzzle_write_command(st + + cmd[size - 1] = iei_wt61p803_puzzle_checksum(cmd, size - 1); + ++ print_hex_dump_debug("puzzle-mcu tx: ", DUMP_PREFIX_NONE, ++ 16, 1, cmd, size, false); ++ + /* Initialize reply struct */ + reinit_completion(&mcu->reply->received); + mcu->reply->size = 0; diff --git a/lede/target/linux/mvebu/patches-6.6/911-drivers-leds-wt61p803-puzzle-mcu-retry.patch b/lede/target/linux/mvebu/patches-6.6/911-drivers-leds-wt61p803-puzzle-mcu-retry.patch new file mode 100644 index 0000000000..2f0b1788ff --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/911-drivers-leds-wt61p803-puzzle-mcu-retry.patch @@ -0,0 +1,63 @@ +--- a/drivers/mfd/iei-wt61p803-puzzle.c ++++ b/drivers/mfd/iei-wt61p803-puzzle.c +@@ -241,6 +241,7 @@ int iei_wt61p803_puzzle_write_command(st + { + struct device *dev = &mcu->serdev->dev; + int ret; ++ int retries; + + if (size <= 1 || size > IEI_WT61P803_PUZZLE_MAX_COMMAND_LENGTH) + return -EINVAL; +@@ -252,24 +253,36 @@ int iei_wt61p803_puzzle_write_command(st + print_hex_dump_debug("puzzle-mcu tx: ", DUMP_PREFIX_NONE, + 16, 1, cmd, size, false); + ++ retries = 3; + /* Initialize reply struct */ +- reinit_completion(&mcu->reply->received); +- mcu->reply->size = 0; +- usleep_range(2000, 10000); +- serdev_device_write_flush(mcu->serdev); +- ret = serdev_device_write_buf(mcu->serdev, cmd, size); +- if (ret < 0) +- goto exit; +- +- serdev_device_wait_until_sent(mcu->serdev, IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT); +- ret = wait_for_completion_timeout(&mcu->reply->received, +- IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT); +- if (ret == 0) { +- dev_err(dev, "Command reply receive timeout\n"); +- ret = -ETIMEDOUT; +- goto exit; ++ while (retries) { ++ reinit_completion(&mcu->reply->received); ++ mcu->reply->size = 0; ++ usleep_range(2000, 10000); ++ serdev_device_write_flush(mcu->serdev); ++ ret = serdev_device_write_buf(mcu->serdev, cmd, size); ++ if (ret < 0) ++ goto exit; ++ ++ serdev_device_wait_until_sent(mcu->serdev, IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT); ++ ret = wait_for_completion_timeout(&mcu->reply->received, ++ IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT); ++ retries--; ++ if (ret == 0) { ++ if (retries == 0) { ++ dev_err(dev, "Command reply receive timeout\n"); ++ ret = -ETIMEDOUT; ++ goto exit; ++ } ++ } ++ else { ++ if (mcu->reply->data[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START && ++ mcu->reply->data[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK && ++ mcu->reply->data[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK) { ++ break; ++ } ++ } + } +- + *reply_size = mcu->reply->size; + /* Copy the received data, as it will not be available after a new frame is received */ + memcpy(reply_data, mcu->reply->data, mcu->reply->size); diff --git a/lede/target/linux/mvebu/patches-6.6/912-drivers-hwmon-wt61p803-puzzle-thermal-zone.patch b/lede/target/linux/mvebu/patches-6.6/912-drivers-hwmon-wt61p803-puzzle-thermal-zone.patch new file mode 100644 index 0000000000..4633c03855 --- /dev/null +++ b/lede/target/linux/mvebu/patches-6.6/912-drivers-hwmon-wt61p803-puzzle-thermal-zone.patch @@ -0,0 +1,10 @@ +--- a/drivers/hwmon/iei-wt61p803-puzzle-hwmon.c ++++ b/drivers/hwmon/iei-wt61p803-puzzle-hwmon.c +@@ -251,6 +251,7 @@ static const struct hwmon_ops iei_wt61p8 + }; + + static const struct hwmon_channel_info *iei_wt61p803_puzzle_info[] = { ++ HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ), + HWMON_CHANNEL_INFO(pwm, + HWMON_PWM_INPUT, + HWMON_PWM_INPUT), diff --git a/lede/target/linux/qualcommax/Makefile b/lede/target/linux/qualcommax/Makefile index bf63827ac7..25d8f5f7ef 100644 --- a/lede/target/linux/qualcommax/Makefile +++ b/lede/target/linux/qualcommax/Makefile @@ -8,8 +8,8 @@ KERNELNAME:=Image dtbs CPU_TYPE:=cortex-a53 SUBTARGETS:=ipq50xx ipq60xx ipq807x -KERNEL_PATCHVER:=6.1 -KERNEL_TESTING_PATCHVER:=6.6 +KERNEL_PATCHVER:=6.6 +KERNEL_TESTING_PATCHVER:=6.1 include $(INCLUDE_DIR)/target.mk DEFAULT_PACKAGES += \ @@ -19,6 +19,6 @@ DEFAULT_PACKAGES += \ kmod-qca-nss-ecm kmod-qca-nss-drv-bridge-mgr \ kmod-qca-nss-drv-vlan kmod-qca-nss-drv-pppoe \ kmod-ath11k-ahb wpad-openssl uboot-envtools \ - e2fsprogs f2fsck mkf2fs losetup automount + e2fsprogs f2fsck mkf2fs losetup automount autocore-arm $(eval $(call BuildTarget)) diff --git a/lede/target/linux/sifiveu/Makefile b/lede/target/linux/sifiveu/Makefile index f88164e7af..17424525ff 100644 --- a/lede/target/linux/sifiveu/Makefile +++ b/lede/target/linux/sifiveu/Makefile @@ -11,7 +11,8 @@ FEATURES:=ext4 KERNELNAME:=Image dtbs SUBTARGETS:=generic -KERNEL_PATCHVER:=5.15 +KERNEL_PATCHVER:=6.6 +KERNEL_TESTING_PATCHVER:=5.15 include $(INCLUDE_DIR)/target.mk diff --git a/lede/target/linux/sifiveu/config-6.6 b/lede/target/linux/sifiveu/config-6.6 new file mode 100644 index 0000000000..595090be19 --- /dev/null +++ b/lede/target/linux/sifiveu/config-6.6 @@ -0,0 +1,402 @@ +CONFIG_64BIT=y +# CONFIG_ACPI is not set +CONFIG_ARCH_CLOCKSOURCE_INIT=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=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_MAX=17 +CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y +CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y +CONFIG_ARCH_RV64I=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_STACKWALK=y +# CONFIG_ARCH_THEAD is not set +CONFIG_ARCH_WANTS_THP_SWAP=y +CONFIG_ASN1=y +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_ATA=y +CONFIG_ATA_VERBOSE_ERROR=y +# CONFIG_AX45MP_L2_CACHE is not set +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_MQ_PCI=y +CONFIG_CAVIUM_PTP=y +CONFIG_CC_HAVE_STACKPROTECTOR_TLS=y +CONFIG_CLK_ANALOGBITS_WRPLL_CLN28HPC=y +CONFIG_CLK_SIFIVE=y +CONFIG_CLK_SIFIVE_PRCI=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CLZ_TAB=y +CONFIG_CMODEL_MEDANY=y +# CONFIG_CMODEL_MEDLOW is not set +CONFIG_COMMON_CLK=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +# CONFIG_COMPAT_32BIT_TIME is not set +CONFIG_COMPAT_BRK=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y +CONFIG_COREDUMP=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_CPU_ISOLATION=y +CONFIG_CPU_RMAP=y +CONFIG_CRC16=y +# CONFIG_CRC32_SARWATE is not set +CONFIG_CRC32_SLICEBY8=y +CONFIG_CRC7=y +CONFIG_CRC_ITU_T=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_DRBG_HMAC=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_ECHAINIV=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1 +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_RSA=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_DNOTIFY=y +CONFIG_DTC=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_EDAC=y +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_LEGACY_SYSFS=y +CONFIG_EDAC_SIFIVE=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EFI=y +CONFIG_EFIVAR_FS=m +# CONFIG_EFI_BOOTLOADER_CONTROL is not set +# CONFIG_EFI_CAPSULE_LOADER is not set +# CONFIG_EFI_COCO_SECRET is not set +# CONFIG_EFI_DISABLE_PCI_DMA is not set +# CONFIG_EFI_DISABLE_RUNTIME is not set +CONFIG_EFI_EARLYCON=y +CONFIG_EFI_ESRT=y +CONFIG_EFI_GENERIC_STUB=y +CONFIG_EFI_PARAMS_FROM_FDT=y +CONFIG_EFI_RUNTIME_WRAPPERS=y +CONFIG_EFI_STUB=y +# CONFIG_EFI_TEST is not set +# CONFIG_EFI_ZBOOT is not set +CONFIG_ELF_CORE=y +# CONFIG_ERRATA_ANDES is not set +CONFIG_ERRATA_SIFIVE=y +CONFIG_ERRATA_SIFIVE_CIP_1200=y +CONFIG_ERRATA_SIFIVE_CIP_453=y +# CONFIG_ERRATA_THEAD is not set +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_EXT4_FS=y +CONFIG_FAILOVER=y +CONFIG_FAT_FS=y +CONFIG_FHANDLE=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FONT_8x16=y +CONFIG_FONT_AUTOSELECT=y +CONFIG_FONT_SUPPORT=y +CONFIG_FPU=y +CONFIG_FRAME_POINTER=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FWNODE_MDIO=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=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_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_INJECTION=y +CONFIG_GENERIC_IRQ_MULTI_HANDLER=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_MSI_IRQ_DOMAIN=y +CONFIG_GENERIC_PCI_IOMAP=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_CDEV_V1=y +CONFIG_GPIO_GENERIC=y +CONFIG_GPIO_SIFIVE=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HID=y +CONFIG_HID_GENERIC=y +CONFIG_HOTPLUG_PCI=y +# CONFIG_HOTPLUG_PCI_CPCI is not set +CONFIG_HOTPLUG_PCI_PCIE=y +CONFIG_HOTPLUG_PCI_SHPC=y +CONFIG_HVC_DRIVER=y +CONFIG_HVC_RISCV_SBI=y +CONFIG_HW_CONSOLE=y +CONFIG_HZ_PERIODIC=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_OCORES=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INPUT=y +# CONFIG_IOMMUFD is not set +# CONFIG_IOMMU_DEBUGFS is not set +CONFIG_IOMMU_SUPPORT=y +CONFIG_IO_URING=y +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_STACKS=y +CONFIG_IRQ_WORK=y +CONFIG_JBD2=y +CONFIG_KALLSYMS=y +CONFIG_KEYS=y +CONFIG_LEDS_PWM=y +CONFIG_LEDS_TRIGGER_DISK=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +CONFIG_LIBFDT=y +CONFIG_LOCALVERSION_AUTO=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_MACB=y +# CONFIG_MACB_PCI is not set +CONFIG_MACB_USE_HWSTAMP=y +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y +CONFIG_MEMFD_CREATE=y +CONFIG_MFD_SYSCON=y +CONFIG_MICROSEMI_PHY=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_CADENCE=y +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SPI=y +CONFIG_MMIOWB=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MODULE_SECTIONS=y +CONFIG_MPILIB=y +CONFIG_MQ_IOSCHED_DEADLINE=y +CONFIG_MQ_IOSCHED_KYBER=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NET_FAILOVER=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_PTP_CLASSIFY=y +CONFIG_NET_SELFTESTS=y +CONFIG_NLS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_NONPORTABLE is not set +CONFIG_NR_CPUS=8 +CONFIG_NVMEM=y +CONFIG_NVMEM_SYSFS=y +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_DMA_DEFAULT_COHERENT=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_OID_REGISTRY=y +CONFIG_PADATA=y +CONFIG_PAGE_OFFSET=0xff60000000000000 +CONFIG_PAGE_POOL=y +CONFIG_PAGE_REPORTING=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEAER_INJECT=m +CONFIG_PCIEASPM=y +CONFIG_PCIEASPM_DEFAULT=y +# CONFIG_PCIEASPM_PERFORMANCE is not set +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_DPC=y +CONFIG_PCIE_DW=y +CONFIG_PCIE_DW_HOST=y +CONFIG_PCIE_ECRC=y +CONFIG_PCIE_FU740=y +CONFIG_PCIE_PTM=y +CONFIG_PCIE_XILINX=y +CONFIG_PCI_DEBUG=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_ECAM=y +CONFIG_PCI_HOST_COMMON=y +CONFIG_PCI_HOST_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PCI_SW_SWITCHTEC=y +CONFIG_PGTABLE_LEVELS=5 +CONFIG_PHYLIB=y +CONFIG_PHYLINK=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PORTABLE=y +CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_POWER_RESET_GPIO_RESTART=y +CONFIG_POWER_RESET_RESTART=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_RESET_SYSCON_POWEROFF=y +CONFIG_PPS=y +CONFIG_PREEMPT_NONE_BUILD=y +CONFIG_PRINTK_TIME=y +CONFIG_PTP_1588_CLOCK=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_PWM=y +CONFIG_PWM_SIFIVE=y +CONFIG_PWM_SYSFS=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RAS=y +CONFIG_RATIONAL=y +CONFIG_RCU_TRACE=y +CONFIG_RD_GZIP=y +CONFIG_REALTEK_PHY=y +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y +# CONFIG_RESET_ATTACK_MITIGATION is not set +CONFIG_RESET_CONTROLLER=y +CONFIG_RESET_SIMPLE=y +CONFIG_RFS_ACCEL=y +CONFIG_RISCV=y +CONFIG_RISCV_ALTERNATIVE=y +# CONFIG_RISCV_BOOT_SPINWAIT is not set +CONFIG_RISCV_DMA_NONCOHERENT=y +CONFIG_RISCV_INTC=y +CONFIG_RISCV_ISA_C=y +CONFIG_RISCV_ISA_FALLBACK=y +CONFIG_RISCV_ISA_SVNAPOT=y +CONFIG_RISCV_ISA_SVPBMT=y +CONFIG_RISCV_ISA_V=y +CONFIG_RISCV_ISA_V_DEFAULT_ENABLE=y +CONFIG_RISCV_ISA_ZBB=y +CONFIG_RISCV_ISA_ZICBOM=y +CONFIG_RISCV_ISA_ZICBOZ=y +CONFIG_RISCV_SBI=y +CONFIG_RISCV_SBI_V01=y +CONFIG_RISCV_TIMER=y +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_DRV_EFI is not set +CONFIG_RTC_I2C_AND_SPI=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_SCHED_DEBUG=y +CONFIG_SCSI=y +CONFIG_SCSI_COMMON=y +CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y +CONFIG_SERIAL_8250_EXAR=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_EARLYCON_RISCV_SBI=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_SIFIVE=y +CONFIG_SERIAL_SIFIVE_CONSOLE=y +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +CONFIG_SG_POOL=y +CONFIG_SIFIVE_CCACHE=y +CONFIG_SIFIVE_PLIC=y +CONFIG_SMP=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +# CONFIG_SOC_MICROCHIP_POLARFIRE is not set +CONFIG_SOC_SIFIVE=y +# CONFIG_SOC_STARFIVE is not set +# CONFIG_SOC_VIRT is not set +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_BITBANG=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPI_SIFIVE=y +CONFIG_SRCU=y +CONFIG_STACKTRACE=y +CONFIG_SWIOTLB=y +CONFIG_SWPHY=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +# CONFIG_SYSFB_SIMPLEFB is not set +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_THREAD_SIZE_ORDER=2 +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TOOLCHAIN_HAS_ZICBOM=y +CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE=y +CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI=y +CONFIG_TRACE_CLOCK=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_TUNE_GENERIC=y +CONFIG_UCS2_STRING=y +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_USB=y +CONFIG_USB_COMMON=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set +CONFIG_USB_EHCI_PCI=y +CONFIG_USB_HID=y +CONFIG_USB_NET_DRIVERS=y +CONFIG_USB_PCI=y +CONFIG_USB_STORAGE=y +CONFIG_USB_SUPPORT=y +# CONFIG_USB_UHCI_HCD is not set +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PCI=y +# CONFIG_USB_XHCI_PLATFORM is not set +CONFIG_VFAT_FS=y +CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 +CONFIG_VMAP_STACK=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_WATCHDOG_CORE=y +CONFIG_XPS=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZONE_DMA32=y diff --git a/lede/target/linux/sifiveu/patches-6.6/0001-riscv-sifive-fu740-cpu-1-2-3-4-set-compatible-to-sif.patch b/lede/target/linux/sifiveu/patches-6.6/0001-riscv-sifive-fu740-cpu-1-2-3-4-set-compatible-to-sif.patch new file mode 100644 index 0000000000..9a1c968139 --- /dev/null +++ b/lede/target/linux/sifiveu/patches-6.6/0001-riscv-sifive-fu740-cpu-1-2-3-4-set-compatible-to-sif.patch @@ -0,0 +1,49 @@ +From ab5c8f5492cce16ff2104393e2f1fa64a3ff6e88 Mon Sep 17 00:00:00 2001 +From: David Abdurachmanov +Date: Wed, 17 Feb 2021 06:06:14 -0800 +Subject: [PATCH 1/7] riscv: sifive: fu740: cpu{1,2,3,4} set compatible to + sifive,u74-mc + +Signed-off-by: David Abdurachmanov +--- + arch/riscv/boot/dts/sifive/fu740-c000.dtsi | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/arch/riscv/boot/dts/sifive/fu740-c000.dtsi ++++ b/arch/riscv/boot/dts/sifive/fu740-c000.dtsi +@@ -39,7 +39,7 @@ + }; + }; + cpu1: cpu@1 { +- compatible = "sifive,bullet0", "riscv"; ++ compatible = "sifive,u74-mc", "sifive,bullet0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; +@@ -63,7 +63,7 @@ + }; + }; + cpu2: cpu@2 { +- compatible = "sifive,bullet0", "riscv"; ++ compatible = "sifive,u74-mc", "sifive,bullet0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; +@@ -87,7 +87,7 @@ + }; + }; + cpu3: cpu@3 { +- compatible = "sifive,bullet0", "riscv"; ++ compatible = "sifive,u74-mc", "sifive,bullet0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; +@@ -111,7 +111,7 @@ + }; + }; + cpu4: cpu@4 { +- compatible = "sifive,bullet0", "riscv"; ++ compatible = "sifive,u74-mc", "sifive,bullet0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; diff --git a/lede/target/linux/sifiveu/patches-6.6/0004-riscv-sifive-unmatched-add-gpio-poweroff-node.patch b/lede/target/linux/sifiveu/patches-6.6/0004-riscv-sifive-unmatched-add-gpio-poweroff-node.patch new file mode 100644 index 0000000000..07170d7c76 --- /dev/null +++ b/lede/target/linux/sifiveu/patches-6.6/0004-riscv-sifive-unmatched-add-gpio-poweroff-node.patch @@ -0,0 +1,26 @@ +From 14ede57943bc4209755d08daf93ac7be967d7fbe Mon Sep 17 00:00:00 2001 +From: David Abdurachmanov +Date: Mon, 13 Sep 2021 02:18:30 -0700 +Subject: [PATCH 4/7] riscv: sifive: unmatched: add gpio-poweroff node + +Add gpio-poweroff node to allow powering off the system. + +Signed-off-by: David Abdurachmanov +--- + arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts ++++ b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts +@@ -86,6 +86,11 @@ + }; + }; + }; ++ ++ gpio-poweroff { ++ compatible = "gpio-poweroff"; ++ gpios = <&gpio 2 GPIO_ACTIVE_LOW>; ++ }; + }; + + &uart0 { diff --git a/lede/target/linux/sifiveu/patches-6.6/0005-riscv-sifive-unleashed-define-opp-table-cpufreq.patch b/lede/target/linux/sifiveu/patches-6.6/0005-riscv-sifive-unleashed-define-opp-table-cpufreq.patch new file mode 100644 index 0000000000..905e3cccb7 --- /dev/null +++ b/lede/target/linux/sifiveu/patches-6.6/0005-riscv-sifive-unleashed-define-opp-table-cpufreq.patch @@ -0,0 +1,116 @@ +From d3cf2859a056273400fbdf9d389b75750ff6ca5e Mon Sep 17 00:00:00 2001 +From: David Abdurachmanov +Date: Fri, 14 May 2021 05:27:51 -0700 +Subject: [PATCH 6/7] riscv: sifive: unleashed: define opp table (cpufreq) + +Source: https://github.com/sifive/riscv-linux/commits/dev/paulw/cpufreq-dt-aloe-v5.3-rc4 + +Signed-off-by: David Abdurachmanov +--- + arch/riscv/Kconfig | 8 +++++ + arch/riscv/boot/dts/sifive/fu540-c000.dtsi | 5 ++++ + .../riscv/boot/dts/sifive/hifive-unleashed-a00.dts | 34 ++++++++++++++++++++++ + 3 files changed, 47 insertions(+) + +--- a/arch/riscv/Kconfig ++++ b/arch/riscv/Kconfig +@@ -901,6 +901,14 @@ config PORTABLE + select MMU + select OF + ++menu "CPU Power Management" ++ ++source "drivers/cpuidle/Kconfig" ++ ++source "drivers/cpufreq/Kconfig" ++ ++endmenu ++ + menu "Power management options" + + source "kernel/power/Kconfig" +--- a/arch/riscv/boot/dts/sifive/fu540-c000.dtsi ++++ b/arch/riscv/boot/dts/sifive/fu540-c000.dtsi +@@ -30,6 +30,7 @@ + i-cache-size = <16384>; + reg = <0>; + riscv,isa = "rv64imac"; ++ clocks = <&prci FU540_PRCI_CLK_COREPLL>; + status = "disabled"; + cpu0_intc: interrupt-controller { + #interrupt-cells = <1>; +@@ -54,6 +55,7 @@ + reg = <1>; + riscv,isa = "rv64imafdc"; + tlb-split; ++ clocks = <&prci FU540_PRCI_CLK_COREPLL>; + next-level-cache = <&l2cache>; + cpu1_intc: interrupt-controller { + #interrupt-cells = <1>; +@@ -78,6 +80,7 @@ + reg = <2>; + riscv,isa = "rv64imafdc"; + tlb-split; ++ clocks = <&prci FU540_PRCI_CLK_COREPLL>; + next-level-cache = <&l2cache>; + cpu2_intc: interrupt-controller { + #interrupt-cells = <1>; +@@ -102,6 +105,7 @@ + reg = <3>; + riscv,isa = "rv64imafdc"; + tlb-split; ++ clocks = <&prci FU540_PRCI_CLK_COREPLL>; + next-level-cache = <&l2cache>; + cpu3_intc: interrupt-controller { + #interrupt-cells = <1>; +@@ -126,6 +130,7 @@ + reg = <4>; + riscv,isa = "rv64imafdc"; + tlb-split; ++ clocks = <&prci FU540_PRCI_CLK_COREPLL>; + next-level-cache = <&l2cache>; + cpu4_intc: interrupt-controller { + #interrupt-cells = <1>; +--- a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts ++++ b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts +@@ -80,6 +80,40 @@ + label = "d4"; + }; + }; ++ ++ fu540_c000_opp_table: opp-table { ++ compatible = "operating-points-v2"; ++ opp-shared; ++ ++ opp-350000000 { ++ opp-hz = /bits/ 64 <350000000>; ++ }; ++ opp-700000000 { ++ opp-hz = /bits/ 64 <700000000>; ++ }; ++ opp-999999999 { ++ opp-hz = /bits/ 64 <999999999>; ++ }; ++ opp-1400000000 { ++ opp-hz = /bits/ 64 <1400000000>; ++ }; ++ }; ++}; ++ ++&cpu0 { ++ operating-points-v2 = <&fu540_c000_opp_table>; ++}; ++&cpu1 { ++ operating-points-v2 = <&fu540_c000_opp_table>; ++}; ++&cpu2 { ++ operating-points-v2 = <&fu540_c000_opp_table>; ++}; ++&cpu3 { ++ operating-points-v2 = <&fu540_c000_opp_table>; ++}; ++&cpu4 { ++ operating-points-v2 = <&fu540_c000_opp_table>; + }; + + &uart0 { diff --git a/lede/target/linux/uml/Makefile b/lede/target/linux/uml/Makefile index ae8ea5d309..0df089e8ea 100644 --- a/lede/target/linux/uml/Makefile +++ b/lede/target/linux/uml/Makefile @@ -19,7 +19,7 @@ BOARD:=uml BOARDNAME:=User Mode Linux FEATURES:=squashfs ext4 audio source-only -KERNEL_PATCHVER:=5.4 +KERNEL_PATCHVER:=6.6 include $(INCLUDE_DIR)/target.mk diff --git a/lede/target/linux/uml/config-6.6 b/lede/target/linux/uml/config-6.6 new file mode 100644 index 0000000000..60d1ce0713 --- /dev/null +++ b/lede/target/linux/uml/config-6.6 @@ -0,0 +1,158 @@ +CONFIG_3_LEVEL_PGTABLES=y +CONFIG_64BIT=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_NO_PREEMPT=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_BLK_DEV_COW_COMMON=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_UBD=y +CONFIG_BLK_DEV_UBD_SYNC=y +CONFIG_BLK_MQ_VIRTIO=y +CONFIG_BUFFER_HEAD=y +CONFIG_CDROM=y +# CONFIG_COMMON_CLK is not set +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +# CONFIG_COMPAT_32BIT_TIME is not set +CONFIG_CON_CHAN="xterm" +CONFIG_CON_ZERO_CHAN="fd:0,fd:1" +CONFIG_CPU_SUP_AMD=y +CONFIG_CPU_SUP_CENTAUR=y +CONFIG_CPU_SUP_HYGON=y +CONFIG_CPU_SUP_INTEL=y +CONFIG_CPU_SUP_ZHAOXIN=y +CONFIG_CRC16=y +CONFIG_CRYPTO_CRC32=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_SHA1=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DNOTIFY=y +# CONFIG_EARLY_PRINTK is not set +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_EXT4_FS=y +CONFIG_F2FS_FS=y +CONFIG_FAILOVER=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FUNCTION_ALIGNMENT=0 +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=y +CONFIG_GENERIC_CLOCKEVENTS=y +# CONFIG_GENERIC_CPU is not set +CONFIG_GENERIC_CPU_DEVICES=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GPIO_CDEV=y +CONFIG_HOSTFS=y +CONFIG_HVC_DRIVER=y +CONFIG_HW_RANDOM=y +CONFIG_HZ_PERIODIC=y +CONFIG_IA32_FEAT_CTL=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INIT_ENV_ARG_LIMIT=128 +CONFIG_IRQ_WORK=y +CONFIG_ISO9660_FS=y +CONFIG_JBD2=y +# CONFIG_JFFS2_FS is not set +CONFIG_KALLSYMS=y +CONFIG_KERNEL_STACK_ORDER=2 +CONFIG_LOCK_DEBUGGING_SUPPORT=y +# CONFIG_MATOM is not set +CONFIG_MAY_HAVE_RUNTIME_DEPS=y +CONFIG_MCONSOLE=y +# CONFIG_MCORE2 is not set +CONFIG_MIGRATION=y +CONFIG_MK8=y +# CONFIG_MMAPPER is not set +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_MODULES_USE_ELF_RELA=y +# CONFIG_MPSC is not set +CONFIG_NAMESPACES=y +CONFIG_NEED_PER_CPU_KM=y +CONFIG_NET_EGRESS=y +CONFIG_NET_FAILOVER=y +CONFIG_NET_INGRESS=y +# CONFIG_NET_NS is not set +CONFIG_NET_XGRESS=y +CONFIG_NLS=y +CONFIG_NO_DMA=y +CONFIG_NO_IOMEM=y +CONFIG_NO_IOPORT_MAP=y +CONFIG_NR_CPUS=1 +CONFIG_NULL_CHAN=y +# CONFIG_OF is not set +CONFIG_PAGE_POOL=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +CONFIG_PAHOLE_HAS_LANG_EXCLUDE=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PORT_CHAN=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_PREEMPT_NONE_BUILD=y +# CONFIG_PROCESSOR_SELECT is not set +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_PTY_CHAN=y +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RD_BZIP2=y +CONFIG_RD_GZIP=y +CONFIG_RELAY=y +CONFIG_SG_POOL=y +CONFIG_SOFT_WATCHDOG=m +CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y +CONFIG_SSL=y +CONFIG_SSL_CHAN="pty" +CONFIG_STACKTRACE=y +CONFIG_STDERR_CONSOLE=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TINY_SRCU=y +CONFIG_TOOLS_SUPPORT_RELR=y +CONFIG_TTY_CHAN=y +CONFIG_UML=y +CONFIG_UML_NET=y +CONFIG_UML_NET_DAEMON=y +CONFIG_UML_NET_DAEMON_DEFAULT_SOCK="/tmp/uml.ctl" +CONFIG_UML_NET_DETERMINISTIC_MAC=y +CONFIG_UML_NET_ETHERTAP=y +CONFIG_UML_NET_MCAST=y +# CONFIG_UML_NET_PCAP is not set +CONFIG_UML_NET_SLIP=y +CONFIG_UML_NET_SLIRP=y +CONFIG_UML_NET_TUNTAP=y +# CONFIG_UML_NET_VDE is not set +CONFIG_UML_NET_VECTOR=y +# CONFIG_UML_PCI_OVER_VIRTIO is not set +CONFIG_UML_RANDOM=y +CONFIG_UML_TIME_TRAVEL_SUPPORT=y +# CONFIG_UML_WATCHDOG is not set +CONFIG_UML_X86=y +# CONFIG_USER_NS is not set +CONFIG_VIRTIO=y +CONFIG_VIRTIO_ANCHOR=y +CONFIG_VIRTIO_BLK=y +CONFIG_VIRTIO_CONSOLE=y +CONFIG_VIRTIO_NET=y +CONFIG_VIRTIO_UML=y +CONFIG_VMAP_STACK=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_WATCHDOG_CORE=y +CONFIG_X86_64=y +CONFIG_X86_CMOV=y +CONFIG_X86_CMPXCHG64=y +CONFIG_X86_INTEL_USERCOPY=y +CONFIG_X86_INTERNODE_CACHE_SHIFT=6 +CONFIG_X86_L1_CACHE_SHIFT=6 +CONFIG_X86_MINIMUM_CPU_FAMILY=64 +CONFIG_X86_TSC=y +CONFIG_X86_USE_PPRO_CHECKSUM=y +CONFIG_X86_VMX_FEATURE_NAMES=y +CONFIG_XTERM_CHAN=y +CONFIG_XTERM_CHAN_DEFAULT_EMULATOR="xterm" +CONFIG_ZLIB_INFLATE=y diff --git a/lede/target/linux/uml/image/Makefile b/lede/target/linux/uml/image/Makefile index 45ab0cfbcd..f00ccab0e4 100644 --- a/lede/target/linux/uml/image/Makefile +++ b/lede/target/linux/uml/image/Makefile @@ -30,4 +30,4 @@ $(eval $(call BuildImage)) $(eval $(call TestHostCommand,glibc-static, \ Please install a static glibc package. (Missing libutil.a, librt.a or libpthread.a), \ echo 'int main(int argc, char **argv) { login(0); timer_gettime(0, 0); return 0; }' | \ - gcc -include utmp.h -x c -o $(TMP_DIR)/a.out - -static -lutil -lrt)) + gcc -include utmp.h -include time.h -x c -o $(TMP_DIR)/a.out - -static -lutil -lrt)) diff --git a/lede/target/linux/uml/patches-6.6/101-mconsole-exec.patch b/lede/target/linux/uml/patches-6.6/101-mconsole-exec.patch new file mode 100644 index 0000000000..0afd777836 --- /dev/null +++ b/lede/target/linux/uml/patches-6.6/101-mconsole-exec.patch @@ -0,0 +1,213 @@ +# +# Minimalist mconsole exec patch +# +# 3.10 version (with bit more synchronous behavior) by fingon at iki dot fi +# Adaptation to kernel 3.3.8 made by David Fernández (david at dit.upm.es) for +# Starting point: mconsole-exec-2.6.30.patch for kernel 2.6.30 +# Author of original patch: Paolo Giarrusso, aka Blaisorblade +# (http://www.user-mode-linux.org/~blaisorblade) +# +# Known misfeatures: +# +# - If output is too long, blocks (and breaks horribly) +# (this misfeature from 3.10 patches, when minimalizing the patch; +# workaround: redirect to a shared filesystem if long output is expected) +# +# - Nothing useful is done with stdin +# +--- a/arch/um/drivers/mconsole.h ++++ b/arch/um/drivers/mconsole.h +@@ -85,6 +85,7 @@ extern void mconsole_cad(struct mc_reque + extern void mconsole_stop(struct mc_request *req); + extern void mconsole_go(struct mc_request *req); + extern void mconsole_log(struct mc_request *req); ++extern void mconsole_exec(struct mc_request *req); + extern void mconsole_proc(struct mc_request *req); + extern void mconsole_stack(struct mc_request *req); + +--- a/arch/um/drivers/mconsole_kern.c ++++ b/arch/um/drivers/mconsole_kern.c +@@ -4,6 +4,7 @@ + * Copyright (C) 2001 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com) + */ + ++#include + #include + #include + #include +@@ -27,6 +28,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -124,6 +126,59 @@ void mconsole_log(struct mc_request *req + mconsole_reply(req, "", 0, 0); + } + ++void mconsole_exec(struct mc_request *req) ++{ ++ struct subprocess_info *sub_info; ++ int res, len; ++ struct file *out; ++ char buf[MCONSOLE_MAX_DATA]; ++ ++ char *envp[] = { ++ "HOME=/", "TERM=linux", ++ "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin", ++ NULL ++ }; ++ char *argv[] = { ++ "/bin/sh", "-c", ++ req->request.data + strlen("exec "), ++ NULL ++ }; ++ ++ sub_info = call_usermodehelper_setup("/bin/sh", argv, envp, GFP_ATOMIC, NULL, NULL, NULL); ++ if (sub_info == NULL) { ++ mconsole_reply(req, "call_usermodehelper_setup failed", 1, 0); ++ return; ++ } ++ res = call_usermodehelper_stdoutpipe(sub_info, &out); ++ if (res < 0) { ++ kfree(sub_info); ++ mconsole_reply(req, "call_usermodehelper_stdoutpipe failed", 1, 0); ++ return; ++ } ++ ++ res = call_usermodehelper_exec(sub_info, UMH_WAIT_PROC); ++ if (res < 0) { ++ kfree(sub_info); ++ mconsole_reply(req, "call_usermodehelper_exec failed", 1, 0); ++ return; ++ } ++ ++ for (;;) { ++ len = out->f_op->read(out, buf, sizeof(buf), &out->f_pos); ++ if (len < 0) { ++ mconsole_reply(req, "reading output failed", 1, 0); ++ break; ++ } ++ if (len == 0) ++ break; ++ mconsole_reply_len(req, buf, len, 0, 1); ++ } ++ fput(out); ++ ++ mconsole_reply_len(req, NULL, 0, 0, 0); ++} ++ ++ + void mconsole_proc(struct mc_request *req) + { + struct vfsmount *mnt = proc_mnt; +@@ -190,6 +245,7 @@ void mconsole_proc(struct mc_request *re + stop - pause the UML; it will do nothing until it receives a 'go' \n\ + go - continue the UML after a 'stop' \n\ + log - make UML enter into the kernel log\n\ ++ exec - pass to /bin/sh -c synchronously\n\ + proc - returns the contents of the UML's /proc/\n\ + stack - returns the stack of the specified pid\n\ + " +--- a/arch/um/drivers/mconsole_user.c ++++ b/arch/um/drivers/mconsole_user.c +@@ -30,6 +30,7 @@ static struct mconsole_command commands[ + { "stop", mconsole_stop, MCONSOLE_PROC }, + { "go", mconsole_go, MCONSOLE_INTR }, + { "log", mconsole_log, MCONSOLE_INTR }, ++ { "exec", mconsole_exec, MCONSOLE_PROC }, + { "proc", mconsole_proc, MCONSOLE_PROC }, + { "stack", mconsole_stack, MCONSOLE_INTR }, + }; +--- a/arch/um/os-Linux/file.c ++++ b/arch/um/os-Linux/file.c +@@ -560,6 +560,8 @@ int os_create_unix_socket(const char *fi + + addr.sun_family = AF_UNIX; + ++ if (len > sizeof(addr.sun_path)) ++ len = sizeof(addr.sun_path); + snprintf(addr.sun_path, len, "%s", file); + + err = bind(sock, (struct sockaddr *) &addr, sizeof(addr)); +--- a/include/linux/kmod.h ++++ b/include/linux/kmod.h +@@ -32,4 +32,6 @@ static inline int request_module_nowait( + #define try_then_request_module(x, mod...) (x) + #endif + ++int call_usermodehelper_stdoutpipe(struct subprocess_info *sub_info, struct file **filp); ++ + #endif /* __LINUX_KMOD_H__ */ +--- a/include/linux/umh.h ++++ b/include/linux/umh.h +@@ -23,6 +23,7 @@ struct subprocess_info { + const char *path; + char **argv; + char **envp; ++ struct file *stdout; + int wait; + int retval; + int (*init)(struct subprocess_info *info, struct cred *new); +--- a/kernel/umh.c ++++ b/kernel/umh.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + #include + +@@ -71,6 +72,28 @@ static int call_usermodehelper_exec_asyn + flush_signal_handlers(current, 1); + spin_unlock_irq(¤t->sighand->siglock); + ++ /* Install output when needed */ ++ if (sub_info->stdout) { ++ struct files_struct *f = current->files; ++ struct fdtable *fdt; ++ ++ sys_close(1); ++ sys_close(2); ++ get_file(sub_info->stdout); ++ fd_install(1, sub_info->stdout); ++ fd_install(2, sub_info->stdout); ++ spin_lock(&f->file_lock); ++ fdt = files_fdtable(f); ++ __set_bit(1, fdt->open_fds); ++ __clear_bit(1, fdt->close_on_exec); ++ __set_bit(2, fdt->open_fds); ++ __clear_bit(2, fdt->close_on_exec); ++ spin_unlock(&f->file_lock); ++ ++ /* disallow core files */ ++ current->signal->rlim[RLIMIT_CORE] = (struct rlimit){0, 0}; ++ } ++ + /* + * Initial kernel threads share ther FS with init, in order to + * get the init root directory. But we've now created a new +@@ -330,6 +353,20 @@ static void helper_unlock(void) + wake_up(&running_helpers_waitq); + } + ++int call_usermodehelper_stdoutpipe(struct subprocess_info *sub_info, ++ struct file **filp) ++{ ++ struct file *f[2]; ++ ++ if (create_pipe_files(f, 0) < 0) ++ return PTR_ERR(f); ++ ++ sub_info->stdout = f[1]; ++ *filp = f[0]; ++ return 0; ++} ++EXPORT_SYMBOL(call_usermodehelper_stdoutpipe); ++ + /** + * call_usermodehelper_setup - prepare to call a usermode helper + * @path: path to usermode executable diff --git a/lede/target/linux/uml/patches-6.6/102-pseudo-random-mac.patch b/lede/target/linux/uml/patches-6.6/102-pseudo-random-mac.patch new file mode 100644 index 0000000000..2b42459fe8 --- /dev/null +++ b/lede/target/linux/uml/patches-6.6/102-pseudo-random-mac.patch @@ -0,0 +1,151 @@ +=============================================================================== + +This patch makes MAC addresses of network interfaces predictable. In +particular, it adds a small routine that computes MAC addresses of based on +a SHA1 hash of the virtual machine name and interface ID. + +TECHNICAL INFORMATION: + +Applies to vanilla kernel 3.9.4. + +=============================================================================== +--- a/arch/um/drivers/Kconfig ++++ b/arch/um/drivers/Kconfig +@@ -143,6 +143,20 @@ config UML_NET + enable at least one of the following transport options to actually + make use of UML networking. + ++config UML_NET_DETERMINISTIC_MAC ++ bool "Use deterministic MAC addresses for network interfaces" ++ default y ++ depends on UML_NET ++ select CRYPTO_SHA1 ++ help ++ Virtual network devices inside a User-Mode Linux instance must be ++ assigned a MAC (Ethernet) address. If none is specified on the UML ++ command line, one must be automatically computed. If this option is ++ enabled, a randomly generated address is used. Otherwise, if this ++ option is disabled, the address is generated from a SHA1 hash of ++ the umid of the UML instance and the interface name. The latter choice ++ is useful to make MAC addresses predictable. ++ + config UML_NET_ETHERTAP + bool "Ethertap transport (obsolete)" + depends on UML_NET +--- a/arch/um/drivers/net_kern.c ++++ b/arch/um/drivers/net_kern.c +@@ -25,6 +25,14 @@ + #include + #include + ++#include ++#include ++#include ++#include ++#include ++#include ++#include "os.h" ++ + #define DRIVER_NAME "uml-netdev" + + static DEFINE_SPINLOCK(opened_lock); +@@ -274,9 +282,55 @@ static const struct ethtool_ops uml_net_ + .get_ts_info = ethtool_op_get_ts_info, + }; + ++#ifdef CONFIG_UML_NET_DETERMINISTIC_MAC ++ ++/* Compute a SHA1 hash of the UML instance's id and ++ * * an interface name. */ ++static int compute_hash(const char *umid, const char *ifname, char *hash) ++{ ++ struct ahash_request *desc = NULL; ++ struct crypto_ahash *tfm = NULL; ++ struct scatterlist sg; ++ char *vmif = NULL; ++ int ret = -ENOMEM; ++ ++ vmif = kmalloc(1024, GFP_KERNEL); ++ if (!vmif) ++ goto out; ++ ++ strcpy (vmif, umid); ++ strcat (vmif, ifname); ++ ++ tfm = crypto_alloc_ahash("sha1", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) ++ goto out; ++ ++ desc = ahash_request_alloc(tfm, GFP_KERNEL); ++ if (!desc) ++ goto out; ++ ++ crypto_ahash_clear_flags(tfm, ~0); ++ ++ sg_init_table(&sg, 1); ++ sg_set_buf(&sg, vmif, strlen(vmif)); ++ ++ ahash_request_set_crypt(desc, &sg, hash, strlen(vmif)); ++ ++ ret = crypto_ahash_digest(desc); ++out: ++ crypto_free_ahash(tfm); ++ ahash_request_free(desc); ++ kfree(vmif); ++ ++ return ret; ++} ++ ++#endif ++ + void uml_net_setup_etheraddr(struct net_device *dev, char *str) + { + u8 addr[ETH_ALEN]; ++ u8 hash[SHA1_DIGEST_SIZE]; + char *end; + int i; + +@@ -320,9 +374,26 @@ void uml_net_setup_etheraddr(struct net_ + return; + + random: ++#ifndef CONFIG_UML_NET_DETERMINISTIC_MAC + printk(KERN_INFO + "Choosing a random ethernet address for device %s\n", dev->name); + eth_hw_addr_random(dev); ++#else ++ printk(KERN_INFO ++ "Computing a digest to use as ethernet address for device %s\n", dev->name); ++ if (compute_hash(get_umid(), dev->name, hash) < 0) { ++ printk(KERN_WARNING ++ "Could not compute digest to use as ethernet address for device %s. " ++ "Using random address instead.\n", dev->name); ++ eth_random_addr(addr); ++ } ++ else { ++ for (i=0; i < 6; i++) ++ addr[i] = (hash[i] + hash[i+6]) % 0x100; ++ } ++ addr [0] &= 0xfe; /* clear multicast bit */ ++ addr [0] |= 0x02; /* set local assignment bit (IEEE802) */ ++#endif + } + + static DEFINE_SPINLOCK(devices_lock); +--- a/kernel/umh.c ++++ b/kernel/umh.c +@@ -354,12 +354,12 @@ static void helper_unlock(void) + } + + int call_usermodehelper_stdoutpipe(struct subprocess_info *sub_info, +- struct file **filp) ++ struct file **filp) + { + struct file *f[2]; + + if (create_pipe_files(f, 0) < 0) +- return PTR_ERR(f); ++ return PTR_ERR(f); + + sub_info->stdout = f[1]; + *filp = f[0]; diff --git a/mieru/Makefile b/mieru/Makefile index 130adcb531..40fbc1f2aa 100644 --- a/mieru/Makefile +++ b/mieru/Makefile @@ -32,7 +32,7 @@ PROJECT_NAME=$(shell basename "${ROOT}") # - pkg/version/current.go # # Use `tools/bump_version.sh` script to change all those files at one shot. -VERSION="3.14.1" +VERSION="3.15.0" # Build binaries and installation packages. .PHONY: build diff --git a/mieru/build/package/mieru/amd64/debian/DEBIAN/control b/mieru/build/package/mieru/amd64/debian/DEBIAN/control index 34d7f5b999..20c0caa020 100755 --- a/mieru/build/package/mieru/amd64/debian/DEBIAN/control +++ b/mieru/build/package/mieru/amd64/debian/DEBIAN/control @@ -1,5 +1,5 @@ Package: mieru -Version: 3.14.1 +Version: 3.15.0 Section: net Priority: optional Architecture: amd64 diff --git a/mieru/build/package/mieru/amd64/rpm/mieru.spec b/mieru/build/package/mieru/amd64/rpm/mieru.spec index 579e40e4ad..69544a8e13 100644 --- a/mieru/build/package/mieru/amd64/rpm/mieru.spec +++ b/mieru/build/package/mieru/amd64/rpm/mieru.spec @@ -1,5 +1,5 @@ Name: mieru -Version: 3.14.1 +Version: 3.15.0 Release: 1%{?dist} Summary: Mieru proxy client License: GPLv3+ diff --git a/mieru/build/package/mieru/arm64/debian/DEBIAN/control b/mieru/build/package/mieru/arm64/debian/DEBIAN/control index 1ed523a4ec..b04ef879f6 100755 --- a/mieru/build/package/mieru/arm64/debian/DEBIAN/control +++ b/mieru/build/package/mieru/arm64/debian/DEBIAN/control @@ -1,5 +1,5 @@ Package: mieru -Version: 3.14.1 +Version: 3.15.0 Section: net Priority: optional Architecture: arm64 diff --git a/mieru/build/package/mieru/arm64/rpm/mieru.spec b/mieru/build/package/mieru/arm64/rpm/mieru.spec index 579e40e4ad..69544a8e13 100644 --- a/mieru/build/package/mieru/arm64/rpm/mieru.spec +++ b/mieru/build/package/mieru/arm64/rpm/mieru.spec @@ -1,5 +1,5 @@ Name: mieru -Version: 3.14.1 +Version: 3.15.0 Release: 1%{?dist} Summary: Mieru proxy client License: GPLv3+ diff --git a/mieru/build/package/mita/amd64/debian/DEBIAN/control b/mieru/build/package/mita/amd64/debian/DEBIAN/control index 165b08952a..2d3f727c0d 100755 --- a/mieru/build/package/mita/amd64/debian/DEBIAN/control +++ b/mieru/build/package/mita/amd64/debian/DEBIAN/control @@ -1,5 +1,5 @@ Package: mita -Version: 3.14.1 +Version: 3.15.0 Section: net Priority: optional Architecture: amd64 diff --git a/mieru/build/package/mita/amd64/rpm/mita.spec b/mieru/build/package/mita/amd64/rpm/mita.spec index 25c95f0a70..ccbaede121 100644 --- a/mieru/build/package/mita/amd64/rpm/mita.spec +++ b/mieru/build/package/mita/amd64/rpm/mita.spec @@ -1,5 +1,5 @@ Name: mita -Version: 3.14.1 +Version: 3.15.0 Release: 1%{?dist} Summary: Mieru proxy server License: GPLv3+ diff --git a/mieru/build/package/mita/arm64/debian/DEBIAN/control b/mieru/build/package/mita/arm64/debian/DEBIAN/control index 69e5e57760..9e196ed1d9 100755 --- a/mieru/build/package/mita/arm64/debian/DEBIAN/control +++ b/mieru/build/package/mita/arm64/debian/DEBIAN/control @@ -1,5 +1,5 @@ Package: mita -Version: 3.14.1 +Version: 3.15.0 Section: net Priority: optional Architecture: arm64 diff --git a/mieru/build/package/mita/arm64/rpm/mita.spec b/mieru/build/package/mita/arm64/rpm/mita.spec index b4ba96507c..283511dcb3 100644 --- a/mieru/build/package/mita/arm64/rpm/mita.spec +++ b/mieru/build/package/mita/arm64/rpm/mita.spec @@ -1,5 +1,5 @@ Name: mita -Version: 3.14.1 +Version: 3.15.0 Release: 1%{?dist} Summary: Mieru proxy server License: GPLv3+ diff --git a/mieru/docs/operation.md b/mieru/docs/operation.md index 5a81061649..e6cbd3fc6b 100644 --- a/mieru/docs/operation.md +++ b/mieru/docs/operation.md @@ -151,12 +151,12 @@ You can run the commands `mita get users` and `mita get quotas` on the server to ``` $ mita get users User LastActive 1DayDownload 1DayUpload 30DaysDownload 30DaysUpload -abcd 2025-04-23T01:02:03Z 19.4MiB 1.8MiB 19.4MiB 1.8MiB +abcd 2025-04-23T01:02:03Z 938.1MiB 12.9MiB 4.0GiB 31.8MiB $ mita get quotas User Days Limit Usage -abcd 1 10.0GiB 21.2MiB -abcd 10 40.0GiB 21.2MiB +abcd 1 10.0GiB 951.1MiB +abcd 7 40.0GiB 4.0GiB ``` ## Environment Variables diff --git a/mieru/docs/operation.zh_CN.md b/mieru/docs/operation.zh_CN.md index 78f732d57e..01b3db9b01 100644 --- a/mieru/docs/operation.zh_CN.md +++ b/mieru/docs/operation.zh_CN.md @@ -151,12 +151,12 @@ mieru start ``` $ mita get users User LastActive 1DayDownload 1DayUpload 30DaysDownload 30DaysUpload -abcd 2025-04-23T01:02:03Z 19.4MiB 1.8MiB 19.4MiB 1.8MiB +abcd 2025-04-23T01:02:03Z 938.1MiB 12.9MiB 4.0GiB 31.8MiB $ mita get quotas User Days Limit Usage -abcd 1 10.0GiB 21.2MiB -abcd 10 40.0GiB 21.2MiB +abcd 1 10.0GiB 951.1MiB +abcd 7 40.0GiB 4.0GiB ``` ## 环境变量 diff --git a/mieru/docs/server-install.md b/mieru/docs/server-install.md index b3da7e3d8a..05c795e541 100644 --- a/mieru/docs/server-install.md +++ b/mieru/docs/server-install.md @@ -2,38 +2,48 @@ The proxy server software mita needs to run on Linux. We provide both debian and RPM installers for installing mita on Debian / Ubuntu and Fedora / CentOS / Red Hat Enterprise Linux series distributions. -Before installation and configuration, connect to the server via SSH and then execute the following commands. +## Use installation script + +Follow the installation script and complete the server installation and configuration. + +```sh +curl -fSsLO https://raw.githubusercontent.com/enfein/mieru/refs/heads/main/tools/setup.py +chmod +x setup.py +sudo python3 setup.py +``` + +Or you can manually install and configure proxy server using the steps below. ## Download mita installation package ```sh # Debian / Ubuntu - X86_64 -curl -LSO https://github.com/enfein/mieru/releases/download/v3.14.1/mita_3.14.1_amd64.deb +curl -LSO https://github.com/enfein/mieru/releases/download/v3.15.0/mita_3.15.0_amd64.deb # Debian / Ubuntu - ARM 64 -curl -LSO https://github.com/enfein/mieru/releases/download/v3.14.1/mita_3.14.1_arm64.deb +curl -LSO https://github.com/enfein/mieru/releases/download/v3.15.0/mita_3.15.0_arm64.deb # RedHat / CentOS / Rocky Linux - X86_64 -curl -LSO https://github.com/enfein/mieru/releases/download/v3.14.1/mita-3.14.1-1.x86_64.rpm +curl -LSO https://github.com/enfein/mieru/releases/download/v3.15.0/mita-3.15.0-1.x86_64.rpm # RedHat / CentOS / Rocky Linux - ARM 64 -curl -LSO https://github.com/enfein/mieru/releases/download/v3.14.1/mita-3.14.1-1.aarch64.rpm +curl -LSO https://github.com/enfein/mieru/releases/download/v3.15.0/mita-3.15.0-1.aarch64.rpm ``` ## Install mita package ```sh # Debian / Ubuntu - X86_64 -sudo dpkg -i mita_3.14.1_amd64.deb +sudo dpkg -i mita_3.15.0_amd64.deb # Debian / Ubuntu - ARM 64 -sudo dpkg -i mita_3.14.1_arm64.deb +sudo dpkg -i mita_3.15.0_arm64.deb # RedHat / CentOS / Rocky Linux - X86_64 -sudo rpm -Uvh --force mita-3.14.1-1.x86_64.rpm +sudo rpm -Uvh --force mita-3.15.0-1.x86_64.rpm # RedHat / CentOS / Rocky Linux - ARM 64 -sudo rpm -Uvh --force mita-3.14.1-1.aarch64.rpm +sudo rpm -Uvh --force mita-3.15.0-1.aarch64.rpm ``` Those instructions can also be used to upgrade the version of mita software package. diff --git a/mieru/docs/server-install.zh_CN.md b/mieru/docs/server-install.zh_CN.md index 821b445ef1..66de9acd01 100644 --- a/mieru/docs/server-install.zh_CN.md +++ b/mieru/docs/server-install.zh_CN.md @@ -2,38 +2,48 @@ 代理服务器软件 mita 需要运行在 Linux 系统中。我们提供了 debian 和 RPM 安装包,便于用户在 Debian / Ubuntu 和 Fedora / CentOS / Red Hat Enterprise Linux 系列发行版中安装 mita。 -在安装和配置开始之前,先通过 SSH 连接到服务器,再执行下面的指令。 +## 使用安装脚本 + +遵循安装脚本并完成服务器的安装和配置。 + +```sh +curl -fSsLO https://raw.githubusercontent.com/enfein/mieru/refs/heads/main/tools/setup.py +chmod +x setup.py +sudo python3 setup.py +``` + +或者,你也可以使用以下步骤手动安装并配置代理服务器。 ## 下载 mita 安装包 ```sh # Debian / Ubuntu - X86_64 -curl -LSO https://github.com/enfein/mieru/releases/download/v3.14.1/mita_3.14.1_amd64.deb +curl -LSO https://github.com/enfein/mieru/releases/download/v3.15.0/mita_3.15.0_amd64.deb # Debian / Ubuntu - ARM 64 -curl -LSO https://github.com/enfein/mieru/releases/download/v3.14.1/mita_3.14.1_arm64.deb +curl -LSO https://github.com/enfein/mieru/releases/download/v3.15.0/mita_3.15.0_arm64.deb # RedHat / CentOS / Rocky Linux - X86_64 -curl -LSO https://github.com/enfein/mieru/releases/download/v3.14.1/mita-3.14.1-1.x86_64.rpm +curl -LSO https://github.com/enfein/mieru/releases/download/v3.15.0/mita-3.15.0-1.x86_64.rpm # RedHat / CentOS / Rocky Linux - ARM 64 -curl -LSO https://github.com/enfein/mieru/releases/download/v3.14.1/mita-3.14.1-1.aarch64.rpm +curl -LSO https://github.com/enfein/mieru/releases/download/v3.15.0/mita-3.15.0-1.aarch64.rpm ``` ## 安装 mita 软件包 ```sh # Debian / Ubuntu - X86_64 -sudo dpkg -i mita_3.14.1_amd64.deb +sudo dpkg -i mita_3.15.0_amd64.deb # Debian / Ubuntu - ARM 64 -sudo dpkg -i mita_3.14.1_arm64.deb +sudo dpkg -i mita_3.15.0_arm64.deb # RedHat / CentOS / Rocky Linux - X86_64 -sudo rpm -Uvh --force mita-3.14.1-1.x86_64.rpm +sudo rpm -Uvh --force mita-3.15.0-1.x86_64.rpm # RedHat / CentOS / Rocky Linux - ARM 64 -sudo rpm -Uvh --force mita-3.14.1-1.aarch64.rpm +sudo rpm -Uvh --force mita-3.15.0-1.aarch64.rpm ``` 上述指令也可以用来升级 mita 软件包的版本。 diff --git a/mieru/pkg/version/current.go b/mieru/pkg/version/current.go index 2862886274..5cd33fafab 100644 --- a/mieru/pkg/version/current.go +++ b/mieru/pkg/version/current.go @@ -16,5 +16,5 @@ package version const ( - AppVersion = "3.14.1" + AppVersion = "3.15.0" ) diff --git a/mieru/test/deploy/singbox/Dockerfile b/mieru/test/deploy/singbox/Dockerfile deleted file mode 100644 index 7f9f52d9e6..0000000000 --- a/mieru/test/deploy/singbox/Dockerfile +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (C) 2025 mieru authors -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Assume this file is executed with `docker build -f` from the root dir of mieru project. - -FROM ubuntu:24.04 - -WORKDIR /test - -# Copy binaries, data and test script into the container. -COPY sing-box mita httpserver sockshttpclient socksudpclient udpserver \ - test/deploy/singbox/singbox-config.json \ - test/deploy/singbox/server_tcp.json \ - test/deploy/singbox/libtest.sh \ - test/deploy/singbox/test_tcp.sh \ - test/deploy/singbox/test.sh /test/ - -# Create mita user and server config directory. -RUN /usr/sbin/useradd --no-create-home --user-group mita && \ - mkdir -p /etc/mita && \ - chown -R mita:mita /etc/mita && \ - chmod 775 /etc/mita && \ - mkdir -p /var/lib/mita && \ - chown -R mita:mita /var/lib/mita && \ - chmod 775 /var/lib/mita && \ - mkdir -p /var/run/mita && \ - chown -R mita:mita /var/run/mita && \ - chmod 775 /var/run/mita - -CMD ["/test/test.sh"] diff --git a/mieru/test/deploy/singbox/libtest.sh b/mieru/test/deploy/singbox/libtest.sh deleted file mode 100755 index 8c52b8a2b9..0000000000 --- a/mieru/test/deploy/singbox/libtest.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash - -# Copyright (C) 2025 mieru authors -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -function print_mieru_server_thread_dump() { - echo "========== BEGIN OF MIERU SERVER THREAD DUMP ==========" - ./mita get thread-dump - echo "========== END OF MIERU SERVER THREAD DUMP ==========" -} - -function print_mieru_server_metrics() { - echo "========== BEGIN OF MIERU SERVER METRICS ==========" - ./mita get metrics - ./mita get memory-statistics - echo "========== END OF MIERU SERVER METRICS ==========" -} diff --git a/mieru/test/deploy/singbox/server_tcp.json b/mieru/test/deploy/singbox/server_tcp.json deleted file mode 100644 index b1cf045cab..0000000000 --- a/mieru/test/deploy/singbox/server_tcp.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "portBindings": [ - { - "portRange": "8964-8965", - "protocol": "TCP" - }, - { - "port": 9648, - "protocol": "TCP" - }, - { - "port": 6489, - "protocol": "TCP" - }, - { - "port": 4896, - "protocol": "TCP" - } - ], - "users": [ - { - "name": "baozi", - "password": "manlianpenfen" - } - ], - "advancedSettings": { - "allowLocalDestination": true - }, - "loggingLevel": "INFO" -} diff --git a/mieru/test/deploy/singbox/singbox-config.json b/mieru/test/deploy/singbox/singbox-config.json deleted file mode 100644 index 031f884f13..0000000000 --- a/mieru/test/deploy/singbox/singbox-config.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "inbounds": [ - { - "type": "mixed", - "tag": "mixed-in", - "listen": "0.0.0.0", - "listen_port": 1080 - } - ], - "outbounds": [ - { - "type": "mieru", - "tag": "mieru-out", - "server": "127.0.0.1", - "server_port": 8964, - "transport": "TCP", - "username": "baozi", - "password": "manlianpenfen" - } - ], - "route": { - "rules": [ - { - "inbound": ["mixed-in"], - "action": "route", - "outbound": "mieru-out" - } - ] - }, - "log": { - "level": "warn" - } -} diff --git a/mieru/test/deploy/singbox/test.sh b/mieru/test/deploy/singbox/test.sh deleted file mode 100755 index 140f5d24ed..0000000000 --- a/mieru/test/deploy/singbox/test.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/bash - -# Copyright (C) 2025 mieru authors -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Make sure this script has executable permission: -# git update-index --chmod=+x - -set -e - -# Load test library. -source ./libtest.sh - -# Start http server. -./httpserver & -sleep 2 - -# Start UDP server. -./udpserver -port=9090 & -sleep 1 - -# Start mieru server daemon. -./mita run & -sleep 1 - -# Run TCP test. -echo "========== BEGIN OF TCP TEST ==========" -./test_tcp.sh -echo "========== END OF TCP TEST ==========" - -echo "Test is successful." -sleep 1 -exit 0 diff --git a/mieru/test/deploy/singbox/test_tcp.sh b/mieru/test/deploy/singbox/test_tcp.sh deleted file mode 100755 index f640448334..0000000000 --- a/mieru/test/deploy/singbox/test_tcp.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/bin/bash - -# Copyright (C) 2025 mieru authors -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Make sure this script has executable permission: -# git update-index --chmod=+x - -# Load test library. -source ./libtest.sh - -# Update mieru server with TCP config. -./mita apply config server_tcp.json -if [[ "$?" -ne 0 ]]; then - echo "command 'mita apply config server_tcp.json' failed" - exit 1 -fi -echo "mieru server config:" -./mita describe config - -# Start mieru server proxy. -./mita start -if [[ "$?" -ne 0 ]]; then - echo "command 'mita start' failed" - exit 1 -fi - -# Start sing-box. -./sing-box run -c singbox-config.json & -sleep 1 - -# Start testing. -sleep 2 -echo ">>> socks5 - new connections - TCP <<<" -./sockshttpclient -dst_host=127.0.0.1 -dst_port=8080 \ - -local_proxy_host=127.0.0.1 -local_proxy_port=1080 \ - -test_case=new_conn -num_request=3000 -if [ "$?" -ne "0" ]; then - print_mieru_server_thread_dump - echo "TCP - test socks5 new_conn failed." - exit 1 -fi - -sleep 1 -echo ">>> http - new connections - TCP <<<" -./sockshttpclient -proxy_mode=http -dst_host=127.0.0.1 -dst_port=8080 \ - -local_http_host=127.0.0.1 -local_http_port=1080 \ - -test_case=new_conn -num_request=1000 -if [ "$?" -ne "0" ]; then - print_mieru_server_thread_dump - echo "TCP - test HTTP new_conn failed." - exit 1 -fi - -sleep 1 -echo ">>> socks5 - reuse one connection - TCP <<<" -./sockshttpclient -dst_host=127.0.0.1 -dst_port=8080 \ - -local_proxy_host=127.0.0.1 -local_proxy_port=1080 \ - -test_case=reuse_conn -test_time_sec=30 -if [ "$?" -ne "0" ]; then - print_mieru_server_thread_dump - echo "TCP - test socks5 reuse_conn failed." - exit 1 -fi - -sleep 1 -echo ">>> socks5 UDP associate - TCP <<<" -./socksudpclient -dst_host=127.0.0.1 -dst_port=9090 \ - -local_proxy_host=127.0.0.1 -local_proxy_port=1080 \ - -interval_ms=10 -num_request=100 -num_conn=60 -if [ "$?" -ne "0" ]; then - print_mieru_server_thread_dump - echo "TCP - test socks5 udp_associate failed." - exit 1 -fi - -# Print metrics and memory statistics. -print_mieru_server_metrics -sleep 1 - -# Stop mieru server proxy. -./mita stop -if [[ "$?" -ne 0 ]]; then - echo "command 'mita stop' failed" - exit 1 -fi -sleep 1 diff --git a/openwrt-packages/quickstart/Makefile b/openwrt-packages/quickstart/Makefile index 07c101589f..d619896768 100644 --- a/openwrt-packages/quickstart/Makefile +++ b/openwrt-packages/quickstart/Makefile @@ -10,11 +10,11 @@ include $(TOPDIR)/rules.mk PKG_ARCH_quickstart:=$(ARCH) PKG_NAME:=quickstart -PKG_VERSION:=0.9.8 +PKG_VERSION:=0.9.9 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/linkease/istore-packages/releases/download/prebuilt/ -PKG_HASH:=2550903f42f9b939cc2307f096fe16048a714e368496301ea68e9bb0623c8aa4 +PKG_HASH:=7716e89b4d95364698e8cfd50241e5f4d7a3bea869895fd9e55b97763ac4bca0 PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-binary-$(PKG_VERSION) diff --git a/shadowsocks-android/build.gradle.kts b/shadowsocks-android/build.gradle.kts index 690093429c..6f27534e72 100644 --- a/shadowsocks-android/build.gradle.kts +++ b/shadowsocks-android/build.gradle.kts @@ -1,8 +1,8 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id("com.github.ben-manes.versions") version "0.52.0" - id("com.google.devtools.ksp") version "2.1.20-2.0.0" apply false + alias(libs.plugins.versions) + alias(libs.plugins.ksp) apply false } buildscript { @@ -15,15 +15,14 @@ buildscript { } dependencies { - val kotlinVersion = rootProject.extra["kotlinVersion"].toString() - classpath(rootProject.extra["androidPlugin"].toString()) - classpath(kotlin("gradle-plugin", kotlinVersion)) - classpath("com.google.android.gms:oss-licenses-plugin:0.10.6") - classpath("com.google.firebase:firebase-crashlytics-gradle:3.0.3") - classpath("com.google.gms:google-services:4.4.2") - classpath("com.vanniktech:gradle-maven-publish-plugin:0.31.0") - classpath("org.jetbrains.dokka:dokka-gradle-plugin:2.0.0") - classpath("org.mozilla.rust-android-gradle:plugin:0.9.6") + classpath(libs.android.gradle) + classpath(libs.dokka) + classpath(libs.firebase.crashlytics.gradle) + classpath(libs.google.oss.licenses) + classpath(libs.google.services) + classpath(libs.gradle.maven.publish) + classpath(libs.kotlin.gradle) + classpath(libs.rust.android) } } diff --git a/shadowsocks-android/buildSrc/build.gradle.kts b/shadowsocks-android/buildSrc/build.gradle.kts index 5355a6ea89..1adc10bafb 100644 --- a/shadowsocks-android/buildSrc/build.gradle.kts +++ b/shadowsocks-android/buildSrc/build.gradle.kts @@ -5,6 +5,6 @@ plugins { apply(from = "../repositories.gradle.kts") dependencies { - implementation(rootProject.extra["androidPlugin"].toString()) - implementation(kotlin("gradle-plugin", rootProject.extra["kotlinVersion"].toString())) + implementation(libs.android.gradle) + implementation(libs.kotlin.gradle) } diff --git a/shadowsocks-android/buildSrc/settings.gradle.kts b/shadowsocks-android/buildSrc/settings.gradle.kts new file mode 100644 index 0000000000..b5a0fabf66 --- /dev/null +++ b/shadowsocks-android/buildSrc/settings.gradle.kts @@ -0,0 +1,7 @@ +dependencyResolutionManagement { + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} diff --git a/shadowsocks-android/buildSrc/src/main/kotlin/Helpers.kt b/shadowsocks-android/buildSrc/src/main/kotlin/Helpers.kt index 7a6387deb2..ac4eba4ae2 100644 --- a/shadowsocks-android/buildSrc/src/main/kotlin/Helpers.kt +++ b/shadowsocks-android/buildSrc/src/main/kotlin/Helpers.kt @@ -8,8 +8,6 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension import java.util.Locale -const val lifecycleVersion = "2.8.7" - private val Project.android get() = extensions.getByName("android") private val BaseExtension.lint get() = (this as CommonExtension<*, *, *, *, *, *>).lint @@ -42,12 +40,6 @@ fun Project.setupCommon() { } extensions.getByName("kotlin").compilerOptions.jvmTarget .set(JvmTarget.fromTarget(javaVersion.toString())) - - dependencies { - add("testImplementation", "junit:junit:4.13.2") - add("androidTestImplementation", "androidx.test:runner:1.6.2") - add("androidTestImplementation", "androidx.test.espresso:espresso-core:3.6.1") - } } fun Project.setupCore() { @@ -65,7 +57,6 @@ fun Project.setupCore() { } buildFeatures.buildConfig = true } - dependencies.add("coreLibraryDesugaring", "com.android.tools:desugar_jdk_libs:2.1.5") } fun Project.setupApp() { diff --git a/shadowsocks-android/core/build.gradle.kts b/shadowsocks-android/core/build.gradle.kts index 2f0b5736f7..c0eed268bf 100644 --- a/shadowsocks-android/core/build.gradle.kts +++ b/shadowsocks-android/core/build.gradle.kts @@ -88,27 +88,26 @@ tasks.register("cargoClean") { tasks.clean.dependsOn("cargoClean") dependencies { - val coroutinesVersion = "1.10.2" - val roomVersion = "2.7.0" - val workVersion = "2.10.0" - api(project(":plugin")) - api("androidx.core:core-ktx:1.16.0") - api("com.google.android.material:material:1.12.0") - - api("androidx.lifecycle:lifecycle-livedata-core-ktx:$lifecycleVersion") - api("androidx.preference:preference:1.2.1") - api("androidx.room:room-runtime:$roomVersion") - api("androidx.work:work-multiprocess:$workVersion") - api("androidx.work:work-runtime-ktx:$workVersion") - api("com.google.android.gms:play-services-oss-licenses:17.1.0") - api("com.google.firebase:firebase-analytics:22.4.0") - api("com.google.firebase:firebase-crashlytics:19.4.2") - api("com.jakewharton.timber:timber:5.0.1") - api("dnsjava:dnsjava:3.6.3") - api("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion") - api("org.jetbrains.kotlinx:kotlinx-coroutines-play-services:$coroutinesVersion") - ksp("androidx.room:room-compiler:$roomVersion") - androidTestImplementation("androidx.room:room-testing:$roomVersion") - androidTestImplementation("androidx.test.ext:junit-ktx:1.2.1") + api(libs.androidx.core.ktx) + api(libs.androidx.lifecycle.livedata.core.ktx) + api(libs.androidx.preference) + api(libs.androidx.room.runtime) + api(libs.androidx.work.multiprocess) + api(libs.androidx.work.runtime.ktx) + api(libs.dnsjava) + api(libs.firebase.analytics) + api(libs.firebase.crashlytics) + api(libs.kotlinx.coroutines.android) + api(libs.kotlinx.coroutines.play.services) + api(libs.material) + api(libs.play.services.oss.licenses) + api(libs.timber) + coreLibraryDesugaring(libs.desugar) + ksp(libs.androidx.room.compiler) + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(libs.androidx.junit.ktx) + androidTestImplementation(libs.androidx.room.testing) + androidTestImplementation(libs.androidx.test.runner) } diff --git a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/.github/workflows/build-nightly-release.yml b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/.github/workflows/build-nightly-release.yml index 730a54aea8..895585b5f0 100644 --- a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/.github/workflows/build-nightly-release.yml +++ b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/.github/workflows/build-nightly-release.yml @@ -20,12 +20,12 @@ jobs: toolchain: stable - target: aarch64-unknown-linux-musl toolchain: stable - - target: mips-unknown-linux-gnu - toolchain: nightly - - target: mipsel-unknown-linux-gnu - toolchain: nightly - - target: mips64el-unknown-linux-gnuabi64 - toolchain: nightly + #- target: mips-unknown-linux-gnu + # toolchain: nightly + #- target: mipsel-unknown-linux-gnu + # toolchain: nightly + #- target: mips64el-unknown-linux-gnuabi64 + # toolchain: nightly steps: - name: Free Disk Space (Ubuntu) diff --git a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/.github/workflows/clippy-check.yml b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/.github/workflows/clippy-check.yml index 1f8dbc177b..4ae180ecc9 100644 --- a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/.github/workflows/clippy-check.yml +++ b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/.github/workflows/clippy-check.yml @@ -21,10 +21,6 @@ jobs: - uses: Swatinem/rust-cache@v2 - if: ${{ runner.os == 'Windows' }} uses: ilammy/setup-nasm@v1 - - name: Install Protoc - uses: arduino/setup-protoc@v3 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Install Rust run: | rustup set profile minimal diff --git a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/Cargo.lock b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/Cargo.lock index 4433c0063c..8bcc8d3dfd 100644 --- a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/Cargo.lock +++ b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/Cargo.lock @@ -287,7 +287,7 @@ dependencies = [ "bitflags 2.9.0", "cexpr", "clang-sys", - "itertools", + "itertools 0.12.1", "lazy_static", "lazycell", "proc-macro2", @@ -298,6 +298,24 @@ dependencies = [ "syn 2.0.100", ] +[[package]] +name = "bindgen" +version = "0.71.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" +dependencies = [ + "bitflags 2.9.0", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "proc-macro2", + "quote", + "regex", + "rustc-hash 2.1.1", + "shlex", + "syn 2.0.100", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -324,9 +342,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.7.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17679a8d69b6d7fd9cd9801a536cec9fa5e5970b69f9d4747f70b39b031f5e7" +checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" dependencies = [ "arrayref", "arrayvec", @@ -369,9 +387,9 @@ dependencies = [ [[package]] name = "brotli" -version = "7.0.0" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd" +checksum = "cf19e729cdbd51af9a397fb9ef8ac8378007b797f8273cfbfdf45dcaa316167b" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -380,9 +398,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "4.0.2" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74fa05ad7d803d413eb8380983b092cbbaf9a85f151b871360e7b00cd7060b37" +checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -403,7 +421,7 @@ dependencies = [ "indexmap", "js-sys", "once_cell", - "rand 0.9.0", + "rand 0.9.1", "serde", "serde_bytes", "serde_json", @@ -490,9 +508,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.16" +version = "1.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" dependencies = [ "jobserver", "libc", @@ -592,18 +610,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.32" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83" +checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.32" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8" +checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" dependencies = [ "anstream", "anstyle", @@ -706,9 +724,9 @@ checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] name = "crossbeam-channel" -version = "0.5.14" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] @@ -777,9 +795,18 @@ checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" [[package]] name = "defmt" -version = "0.3.10" +version = "0.3.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f6162c53f659f65d00619fe31f14556a6e9f8752ccc4a41bd177ffcf3d6130" +checksum = "f0963443817029b2024136fc4dd07a5107eb8f977eaf18fcd1fdeb11306b64ad" +dependencies = [ + "defmt 1.0.1", +] + +[[package]] +name = "defmt" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "548d977b6da32fa1d1fda2876453da1e7df63ad0304c8b3dae4dbe7b96f39b78" dependencies = [ "bitflags 1.3.2", "defmt-macros", @@ -787,9 +814,9 @@ dependencies = [ [[package]] name = "defmt-macros" -version = "0.4.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d135dd939bad62d7490b0002602d35b358dce5fd9233a709d3c1ef467d4bde6" +checksum = "3d4fc12a85bcf441cfe44344c4b72d58493178ce635338a3f3b78943aceb258e" dependencies = [ "defmt-parser", "proc-macro-error2", @@ -800,9 +827,9 @@ dependencies = [ [[package]] name = "defmt-parser" -version = "0.4.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3983b127f13995e68c1e29071e5d115cd96f215ccb5e6812e3728cd6f92653b3" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" dependencies = [ "thiserror 2.0.12", ] @@ -888,9 +915,9 @@ dependencies = [ [[package]] name = "dynosaur" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1b7ff6b5c4d1df9f75c6bcce5cebfa480a448d298b0c83a07b3f5bb318ad10f" +checksum = "277b2cb52d2df4acece06bb16bc0bb0a006970c7bf504eac2d310927a6f65890" dependencies = [ "dynosaur_derive", "trait-variant", @@ -898,9 +925,9 @@ dependencies = [ [[package]] name = "dynosaur_derive" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a600ac649c596084163b9bcde422e9973a321dd190b9d8b15dde23986e53f425" +checksum = "7a4102713839a8c01c77c165bc38ef2e83948f6397fa1e1dcfacec0f07b149d3" dependencies = [ "proc-macro2", "quote", @@ -985,9 +1012,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.7" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" dependencies = [ "anstream", "anstyle", @@ -1014,9 +1041,9 @@ dependencies = [ [[package]] name = "etherparse" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b14e4ac78394e3ea04edbbc412099cf54f2f52ded51efb79c466a282729399d2" +checksum = "3ff83a5facf1a7cbfef93cfb48d6d4fb6a1f42d8ac2341a96b3255acb4d4f860" dependencies = [ "arrayvec", ] @@ -1034,9 +1061,9 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ "event-listener", "pin-project-lite", @@ -1072,9 +1099,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" +checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" dependencies = [ "crc32fast", "miniz_oxide", @@ -1417,7 +1444,7 @@ dependencies = [ "once_cell", "pin-project-lite", "quinn", - "rand 0.9.0", + "rand 0.9.1", "ring", "rustls", "serde", @@ -1444,7 +1471,7 @@ dependencies = [ "once_cell", "parking_lot", "quinn", - "rand 0.9.0", + "rand 0.9.1", "resolv-conf", "rustls", "serde", @@ -1595,9 +1622,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2" dependencies = [ "bytes", "futures-channel", @@ -1605,6 +1632,7 @@ dependencies = [ "http", "http-body", "hyper", + "libc", "pin-project-lite", "socket2", "tokio", @@ -1614,16 +1642,17 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.61" +version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", - "windows-core 0.52.0", + "windows-core 0.61.0", ] [[package]] @@ -1676,9 +1705,9 @@ dependencies = [ [[package]] name = "icu_locid_transform_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" +checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" [[package]] name = "icu_normalizer" @@ -1700,9 +1729,9 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" [[package]] name = "icu_properties" @@ -1721,9 +1750,9 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" [[package]] name = "icu_provider" @@ -1855,6 +1884,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.15" @@ -1883,9 +1921,9 @@ dependencies = [ [[package]] name = "jiff" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d699bc6dfc879fb1bf9bdff0d4c56f0884fc6f0d0eb0fba397a6d00cd9a6b85e" +checksum = "c102670231191d07d37a35af3eb77f1f0dbf7a71be51a962dcd57ea607be7260" dependencies = [ "jiff-static", "log", @@ -1896,9 +1934,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d16e75759ee0aa64c57a56acbf43916987b20c77373cb7e808979e02b93c9f9" +checksum = "4cdde31a9d349f1b1f51a0b3714a5940ac022976f4b49485fc04be052b183b4c" dependencies = [ "proc-macro2", "quote", @@ -1907,10 +1945,11 @@ dependencies = [ [[package]] name = "jobserver" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ + "getrandom 0.3.2", "libc", ] @@ -1969,9 +2008,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.171" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libloading" @@ -1985,9 +2024,9 @@ dependencies = [ [[package]] name = "libmimalloc-sys" -version = "0.1.40" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07d0e07885d6a754b9c7993f2625187ad694ee985d60f23355ff0e7077261502" +checksum = "ec9d6fac27761dabcd4ee73571cdb06b7022dc99089acbe5435691edffaac0f4" dependencies = [ "cc", "libc", @@ -2010,7 +2049,7 @@ version = "0.17.1+9.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b7869a512ae9982f4d46ba482c2a304f1efd80c6412a3d4bf57bb79a619679f" dependencies = [ - "bindgen", + "bindgen 0.69.5", "bzip2-sys", "cc", "libc", @@ -2054,9 +2093,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" dependencies = [ "serde", ] @@ -2157,9 +2196,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "mimalloc" -version = "0.1.44" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99585191385958383e13f6b822e6b6d8d9cf928e7d286ceb092da92b43c87bc1" +checksum = "995942f432bbb4822a7e9c3faa87a695185b0d09273ba85f097b54f4e458f2af" dependencies = [ "libmimalloc-sys", ] @@ -2325,9 +2364,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.1" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" dependencies = [ "critical-section", "portable-atomic", @@ -2341,9 +2380,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.71" +version = "0.10.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" +checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" dependencies = [ "bitflags 2.9.0", "cfg-if", @@ -2382,9 +2421,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.106" +version = "0.9.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" +checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07" dependencies = [ "cc", "libc", @@ -2472,9 +2511,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.15" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" +checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6" dependencies = [ "memchr", "thiserror 2.0.12", @@ -2483,9 +2522,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.15" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e" +checksum = "d725d9cfd79e87dccc9341a2ef39d1b6f6353d68c4b33c177febbe1a402c97c5" dependencies = [ "pest", "pest_generator", @@ -2493,9 +2532,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.15" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b" +checksum = "db7d01726be8ab66ab32f9df467ae8b1148906685bbe75c82d1e65d7f5b3f841" dependencies = [ "pest", "pest_meta", @@ -2506,9 +2545,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.15" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea" +checksum = "7f9f832470494906d1fca5329f8ab5791cc60beb230c74815dff541cbd2b5ca0" dependencies = [ "once_cell", "pest", @@ -2624,7 +2663,7 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.8.23", + "zerocopy 0.8.24", ] [[package]] @@ -2702,7 +2741,7 @@ checksum = "b820744eb4dc9b57a3398183639c511b5a26d2ed702cedd3febaa1393caa22cc" dependencies = [ "bytes", "getrandom 0.3.2", - "rand 0.9.0", + "rand 0.9.1", "ring", "rustc-hash 2.1.1", "rustls", @@ -2716,9 +2755,9 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e46f3055866785f6b92bc6164b76be02ca8f2eb4b002c0354b28cf4c119e5944" +checksum = "541d0f57c6ec747a90738a52741d3221f7960e8ac2f0ff4b1a63680e033b4ab5" dependencies = [ "cfg_aliases", "libc", @@ -2762,13 +2801,12 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", - "zerocopy 0.8.23", ] [[package]] @@ -2978,13 +3016,13 @@ dependencies = [ [[package]] name = "rpassword" -version = "7.3.1" +version = "7.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80472be3c897911d0137b2d2b9055faf6eeac5b14e324073d83bc17b191d7e3f" +checksum = "66d4c8b64f049c6721ec8ccec37ddfc3d641c4a7fca57e8f2a89de509c73df39" dependencies = [ "libc", "rtoolbox", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -3046,9 +3084,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e56a18552996ac8d29ecc3b190b4fdbb2d91ca4ec396de7bbffaf43f3d637e96" +checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" dependencies = [ "bitflags 2.9.0", "errno", @@ -3104,9 +3142,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.0" +version = "0.103.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa4eeac2588ffff23e9d7a7e9b3f971c5fb5b7ebc9452745e0c232c64f83b2f" +checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" dependencies = [ "ring", "rustls-pki-types", @@ -3212,9 +3250,9 @@ checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "sendfd" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604b71b8fc267e13bb3023a2c901126c8f349393666a6d98ac1ae5729b701798" +checksum = "b183bfd5b1bc64ab0c1ef3ee06b008a9ef1b68a7d3a99ba566fbfe7a7c6d745b" dependencies = [ "libc", "tokio", @@ -3321,7 +3359,7 @@ dependencies = [ [[package]] name = "shadowsocks" -version = "1.23.0" +version = "1.23.1" dependencies = [ "aes", "arc-swap", @@ -3342,7 +3380,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project", - "rand 0.9.0", + "rand 0.9.1", "sendfd", "serde", "serde_json", @@ -3379,7 +3417,7 @@ dependencies = [ "ghash", "hkdf", "md-5", - "rand 0.9.0", + "rand 0.9.1", "ring-compat", "sha1", "sm4", @@ -3388,7 +3426,7 @@ dependencies = [ [[package]] name = "shadowsocks-rust" -version = "1.23.0" +version = "1.23.2" dependencies = [ "base64", "build-time", @@ -3409,7 +3447,7 @@ dependencies = [ "mimalloc", "mime", "qrcode", - "rand 0.9.0", + "rand 0.9.1", "reqwest", "rpassword", "rpmalloc", @@ -3429,7 +3467,7 @@ dependencies = [ [[package]] name = "shadowsocks-service" -version = "1.23.0" +version = "1.23.2" dependencies = [ "arc-swap", "brotli", @@ -3459,7 +3497,7 @@ dependencies = [ "nix", "once_cell", "pin-project", - "rand 0.9.0", + "rand 0.9.1", "regex", "rocksdb", "rustls-native-certs", @@ -3551,7 +3589,7 @@ dependencies = [ "bitflags 1.3.2", "byteorder", "cfg-if", - "defmt", + "defmt 0.3.100", "heapless", "log", "managed", @@ -3577,9 +3615,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" dependencies = [ "libc", "windows-sys 0.52.0", @@ -3587,9 +3625,9 @@ dependencies = [ [[package]] name = "spin" -version = "0.9.8" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" dependencies = [ "lock_api", ] @@ -3720,9 +3758,9 @@ checksum = "3b7ad73e635dd232c2c2106d59269f59a61de421cc6b95252d2d932094ff1f40" [[package]] name = "tempfile" -version = "3.19.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488960f40a3fd53d72c2a29a58722561dee8afdd175bd88e3db4677d7b2ba600" +checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" dependencies = [ "fastrand", "getrandom 0.3.2", @@ -3803,9 +3841,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.40" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d9c75b47bdff86fa3334a3db91356b8d7d86a9b839dab7d0bdc5c3d3a077618" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa", @@ -3826,9 +3864,9 @@ checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" -version = "0.2.21" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29aa485584182073ed57fd5004aa09c371f021325014694e432313345865fd04" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" dependencies = [ "num-conv", "time-core", @@ -3861,9 +3899,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.44.1" +version = "1.44.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" +checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" dependencies = [ "backtrace", "bytes", @@ -4047,9 +4085,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tun" -version = "0.7.13" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9298ac5c7f0076908d7a168c634bf4867b4a7d5725eb6356863f8640c6c35ef1" +checksum = "caaf6aa0a713f0e3b20157f6048d113b6256c045e0e2d80734d54cf1c72dc24a" dependencies = [ "bytes", "cfg-if", @@ -4390,13 +4428,26 @@ version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" dependencies = [ - "windows-implement", - "windows-interface", + "windows-implement 0.58.0", + "windows-interface 0.58.0", "windows-result 0.2.0", "windows-strings 0.1.0", "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.61.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" +dependencies = [ + "windows-implement 0.60.0", + "windows-interface 0.59.1", + "windows-link", + "windows-result 0.3.2", + "windows-strings 0.4.0", +] + [[package]] name = "windows-implement" version = "0.58.0" @@ -4408,6 +4459,17 @@ dependencies = [ "syn 2.0.100", ] +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + [[package]] name = "windows-interface" version = "0.58.0" @@ -4419,6 +4481,17 @@ dependencies = [ "syn 2.0.100", ] +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + [[package]] name = "windows-link" version = "0.1.1" @@ -4484,6 +4557,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-strings" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -4803,11 +4885,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.23" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" +checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" dependencies = [ - "zerocopy-derive 0.8.23", + "zerocopy-derive 0.8.24", ] [[package]] @@ -4823,9 +4905,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.23" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" +checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" dependencies = [ "proc-macro2", "quote", @@ -4892,19 +4974,20 @@ dependencies = [ [[package]] name = "zstd-safe" -version = "7.2.3" +version = "7.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3051792fbdc2e1e143244dc28c60f73d8470e93f3f9cbd0ead44da5ed802722" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.14+zstd.1.5.7" +version = "2.0.15+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb060d4926e4ac3a3ad15d864e99ceb5f343c6b34f5bd6d81ae6ed417311be5" +checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" dependencies = [ + "bindgen 0.71.1", "cc", "pkg-config", ] diff --git a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/Cargo.toml b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/Cargo.toml index 41abf0eef7..1b1cbba756 100644 --- a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/Cargo.toml +++ b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "shadowsocks-rust" -version = "1.23.0" +version = "1.23.2" authors = ["Shadowsocks Contributors"] description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls." repository = "https://github.com/shadowsocks/shadowsocks-rust" @@ -242,7 +242,7 @@ jemallocator = { version = "0.5", optional = true } snmalloc-rs = { version = "0.3", optional = true } rpmalloc = { version = "0.2", optional = true } -shadowsocks-service = { version = "1.23.0", path = "./crates/shadowsocks-service" } +shadowsocks-service = { version = "1.23.2", path = "./crates/shadowsocks-service" } windows-service = { version = "0.8", optional = true } diff --git a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/README.md b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/README.md index c0941ae02f..7e42eabd92 100644 --- a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/README.md +++ b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/README.md @@ -125,6 +125,8 @@ systemctl restart snap.shadowsocks-rust.sslocal-daemon.service systemctl status snap.shadowsocks-rust.sslocal-daemon.service ``` +Default configuration file path probably is `/var/snap/shadowsocks-rust/common/etc/shadowsocks-rust/config.json`. + ### **Download release** Download static-linked build [here](https://github.com/shadowsocks/shadowsocks-rust/releases). @@ -302,7 +304,7 @@ Create a ShadowSocks' configuration file. Example Detailed explanation of the configuration file could be found in [shadowsocks' documentation](https://github.com/shadowsocks/shadowsocks/wiki). (Link to original project, not maintained anymore !) -> :warning: For snap installations, configuration file is most probably located in `/var/snap/shadowsocks-rust/common/etc/shadowsocks-rust/config.json` (see https://github.com/shadowsocks/shadowsocks-rust/issues/621 / https://github.com/shadowsocks/shadowsocks-rust/issues/1146) +> :warning: For snap installations, configuration file is most probably located in `/var/snap/shadowsocks-rust/common/etc/shadowsocks-rust/config.json` (see / ) In shadowsocks-rust, we also have an extended configuration file format, which is able to define more than one server. You can also disable individual servers. diff --git a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks-service/Cargo.toml b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks-service/Cargo.toml index 8cb207d1c5..46e24bba36 100644 --- a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks-service/Cargo.toml +++ b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks-service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "shadowsocks-service" -version = "1.23.0" +version = "1.23.2" authors = ["Shadowsocks Contributors"] description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls." repository = "https://github.com/shadowsocks/shadowsocks-rust" @@ -129,7 +129,7 @@ once_cell = "1.17" thiserror = "2.0" arc-swap = "1.7" -spin = { version = "0.9" } +spin = { version = "0.10" } lru_time_cache = "0.11" bytes = "1.7" byte_string = "1.0" @@ -166,9 +166,7 @@ http-body-util = { version = "0.1", optional = true } http = { version = "1.1", optional = true } httparse = { version = "1.9", optional = true } -hickory-resolver = { version = "0.25", optional = true, features = [ - "serde", -] } +hickory-resolver = { version = "0.25", optional = true, features = ["serde"] } idna = "1.0" ipnet = "2.10" @@ -177,27 +175,29 @@ regex = "1.4" mime = { version = "0.3", optional = true } flate2 = { version = "1.0", optional = true } -brotli = { version = "7.0", optional = true } +brotli = { version = "8.0", optional = true } zstd = { version = "0.13", optional = true } tun = { version = "0.7", optional = true, features = ["async"] } -etherparse = { version = "0.17", optional = true } +etherparse = { version = "0.18", optional = true } smoltcp = { version = "0.12", optional = true, default-features = false, features = [ "std", "log", "medium-ip", "proto-ipv4", + "proto-ipv4-fragmentation", "proto-ipv6", "socket-icmp", "socket-udp", "socket-tcp", + "socket-tcp-cubic", ] } serde = { version = "1.0", features = ["derive"] } json5 = "0.4" bson = { version = "2.13.0", optional = true } -shadowsocks = { version = "1.23.0", path = "../shadowsocks", default-features = false } +shadowsocks = { version = "1.23.1", path = "../shadowsocks", default-features = false } # Just for the ioctl call macro [target.'cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "openbsd"))'.dependencies] diff --git a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks-service/src/local/tun/mod.rs b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks-service/src/local/tun/mod.rs index e10ea913d7..f0d3537cd6 100644 --- a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks-service/src/local/tun/mod.rs +++ b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks-service/src/local/tun/mod.rs @@ -4,6 +4,7 @@ use std::os::unix::io::RawFd; use std::{ io::{self, ErrorKind}, + mem, net::{IpAddr, SocketAddr}, sync::Arc, time::Duration, @@ -41,7 +42,7 @@ cfg_if! { use crate::local::{context::ServiceContext, loadbalancing::PingBalancer}; -use self::{ip_packet::IpPacket, tcp::TcpTun, udp::UdpTun}; +use self::{ip_packet::IpPacket, tcp::TcpTun, udp::UdpTun, virt_device::TokenBuffer}; mod ip_packet; mod tcp; @@ -191,7 +192,16 @@ impl Tun { let address_broadcast = address_net.broadcast(); - let mut packet_buffer = vec![0u8; 65536].into_boxed_slice(); + let create_packet_buffer = || { + const PACKET_BUFFER_SIZE: usize = 65536; + let mut packet_buffer = TokenBuffer::with_capacity(PACKET_BUFFER_SIZE); + unsafe { + packet_buffer.set_len(PACKET_BUFFER_SIZE); + } + packet_buffer + }; + + let mut packet_buffer = create_packet_buffer(); let mut udp_cleanup_timer = time::interval(self.udp_cleanup_interval); loop { @@ -200,10 +210,14 @@ impl Tun { n = self.device.read(&mut packet_buffer) => { let n = n?; - let packet = &mut packet_buffer[..n]; - trace!("[TUN] received IP packet {:?}", ByteStr::new(packet)); + let mut packet_buffer = mem::replace(&mut packet_buffer, create_packet_buffer()); + unsafe { + packet_buffer.set_len(n); + } - if let Err(err) = self.handle_tun_frame(&address_broadcast, packet).await { + trace!("[TUN] received IP packet {:?}", ByteStr::new(&packet_buffer)); + + if let Err(err) = self.handle_tun_frame(&address_broadcast, packet_buffer).await { error!("[TUN] handle IP frame failed, error: {}", err); } } @@ -254,11 +268,15 @@ impl Tun { } } - async fn handle_tun_frame(&mut self, device_broadcast_addr: &IpAddr, frame: &[u8]) -> smoltcp::wire::Result<()> { - let packet = match IpPacket::new_checked(frame)? { + async fn handle_tun_frame( + &mut self, + device_broadcast_addr: &IpAddr, + frame: TokenBuffer, + ) -> smoltcp::wire::Result<()> { + let packet = match IpPacket::new_checked(frame.as_ref())? { Some(packet) => packet, None => { - warn!("unrecognized IP packet {:?}", ByteStr::new(frame)); + warn!("unrecognized IP packet {:?}", ByteStr::new(&frame)); return Ok(()); } }; diff --git a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks-service/src/local/tun/tcp.rs b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks-service/src/local/tun/tcp.rs index d5d0f0f50e..11eda653f5 100644 --- a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks-service/src/local/tun/tcp.rs +++ b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks-service/src/local/tun/tcp.rs @@ -18,8 +18,8 @@ use log::{debug, error, trace}; use shadowsocks::{net::TcpSocketOpts, relay::socks5::Address}; use smoltcp::{ iface::{Config as InterfaceConfig, Interface, PollResult, SocketHandle, SocketSet}, - phy::{DeviceCapabilities, Medium}, - socket::tcp::{Socket as TcpSocket, SocketBuffer as TcpSocketBuffer, State as TcpState}, + phy::{Checksum, DeviceCapabilities, Medium}, + socket::tcp::{CongestionControl, Socket as TcpSocket, SocketBuffer as TcpSocketBuffer, State as TcpState}, storage::RingBuffer, time::{Duration as SmolDuration, Instant as SmolInstant}, wire::{HardwareAddress, IpAddress, IpCidr, Ipv4Address, Ipv6Address, TcpPacket}, @@ -40,11 +40,11 @@ use crate::{ net::utils::to_ipv4_mapped, }; -use super::virt_device::VirtTunDevice; +use super::virt_device::{TokenBuffer, VirtTunDevice}; -// NOTE: Default buffer could contain 20 AEAD packets -const DEFAULT_TCP_SEND_BUFFER_SIZE: u32 = 0x3FFF * 20; -const DEFAULT_TCP_RECV_BUFFER_SIZE: u32 = 0x3FFF * 20; +// NOTE: Default buffer could contain 5 AEAD packets +const DEFAULT_TCP_SEND_BUFFER_SIZE: u32 = (0x3FFFu32 * 5).next_power_of_two(); +const DEFAULT_TCP_RECV_BUFFER_SIZE: u32 = (0x3FFFu32 * 5).next_power_of_two(); #[derive(Debug, Clone, Copy, Eq, PartialEq)] enum TcpSocketState { @@ -243,8 +243,8 @@ pub struct TcpTun { manager_socket_creation_tx: mpsc::UnboundedSender, manager_running: Arc, balancer: PingBalancer, - iface_rx: mpsc::UnboundedReceiver>, - iface_tx: mpsc::UnboundedSender>, + iface_rx: mpsc::UnboundedReceiver, + iface_tx: mpsc::UnboundedSender, iface_tx_avail: Arc, } @@ -261,6 +261,11 @@ impl TcpTun { let mut capabilities = DeviceCapabilities::default(); capabilities.medium = Medium::Ip; capabilities.max_transmission_unit = mtu as usize; + capabilities.checksum.ipv4 = Checksum::Tx; + capabilities.checksum.tcp = Checksum::Tx; + capabilities.checksum.udp = Checksum::Tx; + capabilities.checksum.icmpv4 = Checksum::Tx; + capabilities.checksum.icmpv6 = Checksum::Tx; let (mut device, iface_rx, iface_tx, iface_tx_avail) = VirtTunDevice::new(capabilities); @@ -516,6 +521,8 @@ impl TcpTun { socket.set_timeout(Some(SmolDuration::from_secs(7200))); // NO ACK delay // socket.set_ack_delay(None); + // Enable Cubic congestion control + socket.set_congestion_control(CongestionControl::Cubic); if let Err(err) = socket.listen(dst_addr) { return Err(io::Error::new(ErrorKind::Other, format!("listen error: {:?}", err))); @@ -544,8 +551,8 @@ impl TcpTun { Ok(()) } - pub async fn drive_interface_state(&mut self, frame: &[u8]) { - if self.iface_tx.send(frame.to_vec()).is_err() { + pub async fn drive_interface_state(&mut self, frame: TokenBuffer) { + if self.iface_tx.send(frame).is_err() { panic!("interface send channel closed unexpectedly"); } @@ -554,7 +561,7 @@ impl TcpTun { self.manager_notify.notify(); } - pub async fn recv_packet(&mut self) -> Vec { + pub async fn recv_packet(&mut self) -> TokenBuffer { match self.iface_rx.recv().await { Some(v) => v, None => unreachable!("channel closed unexpectedly"), diff --git a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks-service/src/local/tun/virt_device.rs b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks-service/src/local/tun/virt_device.rs index 6fdc797dd7..9115e2f4f1 100644 --- a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks-service/src/local/tun/virt_device.rs +++ b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks-service/src/local/tun/virt_device.rs @@ -2,12 +2,16 @@ use std::{ marker::PhantomData, + mem, + ops::{Deref, DerefMut}, sync::{ - Arc, + Arc, Mutex, atomic::{AtomicBool, Ordering}, }, }; +use bytes::BytesMut; +use once_cell::sync::Lazy; use smoltcp::{ phy::{self, Device, DeviceCapabilities}, time::Instant, @@ -16,8 +20,8 @@ use tokio::sync::mpsc; pub struct VirtTunDevice { capabilities: DeviceCapabilities, - in_buf: mpsc::UnboundedReceiver>, - out_buf: mpsc::UnboundedSender>, + in_buf: mpsc::UnboundedReceiver, + out_buf: mpsc::UnboundedSender, in_buf_avail: Arc, } @@ -27,8 +31,8 @@ impl VirtTunDevice { capabilities: DeviceCapabilities, ) -> ( Self, - mpsc::UnboundedReceiver>, - mpsc::UnboundedSender>, + mpsc::UnboundedReceiver, + mpsc::UnboundedSender, Arc, ) { let (iface_tx, iface_output) = mpsc::unbounded_channel(); @@ -81,7 +85,7 @@ impl Device for VirtTunDevice { } pub struct VirtRxToken<'a> { - buffer: Vec, + buffer: TokenBuffer, phantom_device: PhantomData<&'a VirtTunDevice>, } @@ -101,9 +105,65 @@ impl phy::TxToken for VirtTxToken<'_> { where F: FnOnce(&mut [u8]) -> R, { - let mut buffer = vec![0u8; len]; + let mut buffer = TokenBuffer::with_capacity(len); + unsafe { + buffer.set_len(len); + } + let result = f(&mut buffer); self.0.out_buf.send(buffer).expect("channel closed unexpectly"); result } } + +// Maximun number of TokenBuffer cached globally. +// +// Each of them has capacity 65536 (defined in tun/mod.rs), so 64 * 65536 = 4MB. +const TOKEN_BUFFER_LIST_MAX_SIZE: usize = 64; +static TOKEN_BUFFER_LIST: Lazy>> = Lazy::new(|| Mutex::new(Vec::new())); + +pub struct TokenBuffer { + buffer: BytesMut, +} + +impl Drop for TokenBuffer { + fn drop(&mut self) { + let mut list = TOKEN_BUFFER_LIST.lock().unwrap(); + if list.len() >= TOKEN_BUFFER_LIST_MAX_SIZE { + return; + } + + let empty_buffer = BytesMut::new(); + let mut buffer = mem::replace(&mut self.buffer, empty_buffer); + buffer.clear(); + + list.push(buffer); + } +} + +impl TokenBuffer { + pub fn with_capacity(cap: usize) -> TokenBuffer { + let mut list = TOKEN_BUFFER_LIST.lock().unwrap(); + if let Some(mut buffer) = list.pop() { + buffer.reserve(cap); + return TokenBuffer { buffer }; + } + TokenBuffer { + buffer: BytesMut::with_capacity(cap), + } + } +} + +impl Deref for TokenBuffer { + type Target = BytesMut; + + fn deref(&self) -> &Self::Target { + &self.buffer + } +} + +impl DerefMut for TokenBuffer { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.buffer + } +} diff --git a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/Cargo.toml b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/Cargo.toml index e6ed8466ea..f4b1417182 100644 --- a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/Cargo.toml +++ b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "shadowsocks" -version = "1.23.0" +version = "1.23.1" authors = ["Shadowsocks Contributors"] description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls." repository = "https://github.com/shadowsocks/shadowsocks-rust" @@ -58,7 +58,7 @@ byte_string = "1.0" base64 = "0.22" url = "2.5" once_cell = "1.17" -spin = { version = "0.9", features = ["std"] } +spin = { version = "0.10", features = ["std"] } pin-project = "1.1" bloomfilter = { version = "3.0.0", optional = true } thiserror = "2.0" @@ -72,7 +72,7 @@ percent-encoding = "2.1" futures = "0.3" trait-variant = "0.1" -dynosaur = "0.1.2" +dynosaur = "0.2.0" socket2 = { version = "0.5", features = ["all"] } tokio = { version = "1.9.0", features = [ diff --git a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/config.rs b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/config.rs index 8f21c2ee19..51d61b6bec 100644 --- a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/config.rs +++ b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/config.rs @@ -394,6 +394,10 @@ pub enum ServerConfigError { /// Key length mismatch #[error("invalid key length for {0}, expecting {1} bytes, but found {2} bytes")] InvalidKeyLength(CipherKind, usize, usize), + + /// User Key (ipsk) length mismatch + #[error("invalid user key length for {0}, expecting {1} bytes, but found {2} bytes")] + InvalidUserKeyLength(CipherKind, usize, usize), } /// Configuration for a server @@ -538,6 +542,22 @@ where for ipsk in split_iter { match USER_KEY_BASE64_ENGINE.decode(ipsk) { Ok(v) => { + // Double check identity key's length + match method { + CipherKind::AEAD2022_BLAKE3_AES_128_GCM => { + // AES-128 + if v.len() != 16 { + return Err(ServerConfigError::InvalidUserKeyLength(method, 16, v.len())); + } + } + CipherKind::AEAD2022_BLAKE3_AES_256_GCM => { + // AES-256 + if v.len() != 32 { + return Err(ServerConfigError::InvalidUserKeyLength(method, 32, v.len())); + } + } + _ => unreachable!("{} doesn't support EIH", method), + } identity_keys.push(Bytes::from(v)); } Err(err) => { diff --git a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/mod.rs b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/mod.rs index cd6f05aebe..42d3d3301e 100644 --- a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/mod.rs +++ b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/mod.rs @@ -28,10 +28,21 @@ fn set_common_sockopt_for_connect(addr: SocketAddr, socket: &TcpSocket, opts: &C (SocketAddr::V4(..), SocketAddr::V4(..)) => { socket.bind(baddr)?; } + (SocketAddr::V4(v4baddr), SocketAddr::V6(..)) => { + socket.bind(SocketAddr::new(v4baddr.ip().to_ipv6_mapped().into(), v4baddr.port()))?; + } (SocketAddr::V6(..), SocketAddr::V6(..)) => { socket.bind(baddr)?; } - _ => {} + (SocketAddr::V6(v6baddr), SocketAddr::V4(..)) => match v6baddr.ip().to_ipv4_mapped() { + Some(v4baddr) => socket.bind(SocketAddr::new(v4baddr.into(), v6baddr.port()))?, + None => { + return Err(io::Error::new( + ErrorKind::InvalidInput, + "bind_local_addr is not a valid IPv4-mapped IPv6 address", + )); + } + }, } } diff --git a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/bsd/freebsd.rs b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/bsd/freebsd.rs index f2095b3c96..da865d2078 100644 --- a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/bsd/freebsd.rs +++ b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/bsd/freebsd.rs @@ -1,5 +1,6 @@ use std::{ - io, mem, + io::{self, ErrorKind}, + mem, net::{Ipv4Addr, Ipv6Addr, SocketAddr}, os::unix::io::{AsRawFd, RawFd}, pin::Pin, @@ -228,7 +229,18 @@ pub fn set_disable_ip_fragmentation(af: AddrFamily, socket: &S) -> i pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result { let bind_addr = match (af, config.bind_local_addr) { (AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(), + (AddrFamily::Ipv4, Some(SocketAddr::V6(addr))) => { + // Map IPv6 bind_local_addr to IPv4 if AF is IPv4 + match addr.ip().to_ipv4_mapped() { + Some(addr) => SocketAddr::new(addr.into(), 0), + None => return Err(io::Error::new(ErrorKind::InvalidInput, "Invalid IPv6 address")), + } + } (AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(), + (AddrFamily::Ipv6, Some(SocketAddr::V4(addr))) => { + // Map IPv4 bind_local_addr to IPv6 if AF is IPv6 + SocketAddr::new(addr.ip().to_ipv6_mapped().into(), 0) + } (AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0), (AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0), }; diff --git a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/bsd/macos.rs b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/bsd/macos.rs index 5c67933a3d..2d65020378 100644 --- a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/bsd/macos.rs +++ b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/bsd/macos.rs @@ -356,7 +356,18 @@ pub fn set_disable_ip_fragmentation(af: AddrFamily, socket: &S) -> i pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result { let bind_addr = match (af, config.bind_local_addr) { (AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(), + (AddrFamily::Ipv4, Some(SocketAddr::V6(addr))) => { + // Map IPv6 bind_local_addr to IPv4 if AF is IPv4 + match addr.ip().to_ipv4_mapped() { + Some(addr) => SocketAddr::new(addr.into(), 0), + None => return Err(io::Error::new(ErrorKind::InvalidInput, "Invalid IPv6 address")), + } + } (AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(), + (AddrFamily::Ipv6, Some(SocketAddr::V4(addr))) => { + // Map IPv4 bind_local_addr to IPv6 if AF is IPv6 + SocketAddr::new(addr.ip().to_ipv6_mapped().into(), 0) + } (AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0), (AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0), }; diff --git a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/linux/mod.rs b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/linux/mod.rs index 356c5a33c1..58a9a15da7 100644 --- a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/linux/mod.rs +++ b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/linux/mod.rs @@ -1,5 +1,6 @@ use std::{ - io, mem, + io::{self, ErrorKind}, + mem, net::{Ipv4Addr, Ipv6Addr, SocketAddr}, os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}, pin::Pin, @@ -55,7 +56,7 @@ impl TcpStream { // This is a workaround for VPNService #[cfg(target_os = "android")] if !addr.ip().is_loopback() { - use std::{io::ErrorKind, time::Duration}; + use std::time::Duration; use tokio::time; if let Some(ref path) = opts.vpn_protect_path { @@ -287,7 +288,18 @@ pub fn set_disable_ip_fragmentation(af: AddrFamily, socket: &S) -> i pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result { let bind_addr = match (af, config.bind_local_addr) { (AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(), + (AddrFamily::Ipv4, Some(SocketAddr::V6(addr))) => { + // Map IPv6 bind_local_addr to IPv4 if AF is IPv4 + match addr.ip().to_ipv4_mapped() { + Some(addr) => SocketAddr::new(addr.into(), 0), + None => return Err(io::Error::new(ErrorKind::InvalidInput, "Invalid IPv6 address")), + } + } (AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(), + (AddrFamily::Ipv6, Some(SocketAddr::V4(addr))) => { + // Map IPv4 bind_local_addr to IPv6 if AF is IPv6 + SocketAddr::new(addr.ip().to_ipv6_mapped().into(), 0) + } (AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0), (AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0), }; @@ -320,7 +332,7 @@ pub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, config: &ConnectOp // This is a workaround for VPNService #[cfg(target_os = "android")] { - use std::{io::ErrorKind, time::Duration}; + use std::time::Duration; use tokio::time; if let Some(ref path) = config.vpn_protect_path { @@ -385,10 +397,7 @@ fn set_bindtodevice(socket: &S, iface: &str) -> io::Result<()> { cfg_if! { if #[cfg(target_os = "android")] { - use std::{ - io::ErrorKind, - path::Path, - }; + use std::path::Path; use tokio::io::AsyncReadExt; use super::uds::UnixStream; diff --git a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/others.rs b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/others.rs index 15cac8f01c..81fc78b688 100644 --- a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/others.rs +++ b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/unix/others.rs @@ -1,6 +1,6 @@ use std::{ - io, - net::{Ipv4Addr, Ipv6Addr, SocketAddr}, + io::{self, ErrorKind}, + net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, ops::{Deref, DerefMut}, os::fd::AsRawFd, pin::Pin, @@ -15,7 +15,7 @@ use tokio::{ use crate::net::{ AcceptOpts, AddrFamily, ConnectOpts, - sys::{ErrorKind, set_common_sockopt_after_connect, set_common_sockopt_for_connect}, + sys::{set_common_sockopt_after_connect, set_common_sockopt_for_connect}, }; /// A wrapper of `TcpStream` @@ -82,7 +82,19 @@ pub fn set_disable_ip_fragmentation(_af: AddrFamily, _socket: &S) -> pub async fn create_outbound_udp_socket(af: AddrFamily, config: &ConnectOpts) -> io::Result { let bind_addr = match (af, config.bind_local_addr) { (AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(), + (AddrFamily::Ipv4, Some(SocketAddr::V6(addr))) => { + // Map IPv6 bind_local_addr to IPv4 if AF is IPv4 + match addr.ip().to_ipv4_mapped() { + Some(addr) => SocketAddr::new(IpAddr::from(addr), 0), + None => return Err(io::Error::new(ErrorKind::InvalidInput, "Invalid IPv6 address")), + } + } (AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(), + (AddrFamily::Ipv6, Some(SocketAddr::V4(addr))) => { + // Map IPv4 bind_local_addr to IPv6 if AF is IPv6 + let ip_addr: IpAddr = addr.ip().to_ipv6_mapped().into(); + SocketAddr::new(ip_addr, 0) + } (AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0), (AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0), }; diff --git a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/windows/mod.rs b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/windows/mod.rs index 05d8008f2b..fb3d462c2d 100644 --- a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/windows/mod.rs +++ b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/net/sys/windows/mod.rs @@ -468,7 +468,18 @@ pub async fn create_inbound_udp_socket(addr: &SocketAddr, ipv6_only: bool) -> io pub async fn create_outbound_udp_socket(af: AddrFamily, opts: &ConnectOpts) -> io::Result { let bind_addr = match (af, opts.bind_local_addr) { (AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(), + (AddrFamily::Ipv4, Some(SocketAddr::V6(addr))) => { + // Map IPv6 bind_local_addr to IPv4 if AF is IPv4 + match addr.ip().to_ipv4_mapped() { + Some(addr) => SocketAddr::new(addr.into(), 0), + None => return Err(io::Error::new(ErrorKind::InvalidInput, "Invalid IPv6 address")), + } + } (AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(), + (AddrFamily::Ipv6, Some(SocketAddr::V4(addr))) => { + // Map IPv4 bind_local_addr to IPv6 if AF is IPv6 + SocketAddr::new(addr.ip().to_ipv6_mapped().into(), 0) + } (AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0), (AddrFamily::Ipv6, ..) => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0), }; diff --git a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/relay/socks5.rs b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/relay/socks5.rs index 000cc79739..8ccb2b7a46 100644 --- a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/relay/socks5.rs +++ b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/crates/shadowsocks/src/relay/socks5.rs @@ -478,7 +478,7 @@ fn write_domain_name_address(dnaddr: &str, port: u16, buf: &mut B) { "domain name length must be smaller than 256" ); buf.put_u8(dnaddr.len() as u8); - buf.put_slice(dnaddr[..].as_bytes()); + buf.put_slice(dnaddr.as_bytes()); buf.put_u16(port); } @@ -837,7 +837,7 @@ impl UdpAssociateHeader { } } -/// Username/Password Authentication Inittial Negociation +/// Username/Password Authentication Initial Negotiation /// /// https://datatracker.ietf.org/doc/html/rfc1929 /// @@ -880,7 +880,7 @@ impl PasswdAuthRequest { let mut ver_buf = [0u8; 1]; let _ = r.read_exact(&mut ver_buf).await?; - // The only valid subnegociation version + // The only valid subnegotiation version if ver_buf[0] != 0x01 { return Err(Error::UnsupportedPasswdAuthVersion(ver_buf[0])); } diff --git a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/debian/changelog b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/debian/changelog index fb15bdffad..8e87dd64f0 100644 --- a/shadowsocks-android/core/src/main/rust/shadowsocks-rust/debian/changelog +++ b/shadowsocks-android/core/src/main/rust/shadowsocks-rust/debian/changelog @@ -1,3 +1,22 @@ +shadowsocks-rust (1.23.2) unstable; urgency=medium + + ## Bug Fixes + + - #1940 `local-tun`: Fixes `panic` when resizing cached buffers + +shadowsocks-rust (1.23.1) unstable; urgency=medium + + ## Features + + - #1922 `local-tun`: Enable congestion control algorithm for TCP connections + - #1923 `local-tun`: Disable TCP package receive checksum for improving performance + - `local-tun`: Buffer for receiving/sending packets from/to `tun` device are cached globally + + ## Bug Fixes + + - #1929 `outbound_bind_addr` for UDP sockets failed to `bind()` if it is an IPv4 address + - Double check IPSK key length (AEAD-2022) when reading from configuration file + shadowsocks-rust (1.23.0) unstable; urgency=medium ## Features, Breaking Changes diff --git a/shadowsocks-android/gradle/libs.versions.toml b/shadowsocks-android/gradle/libs.versions.toml new file mode 100644 index 0000000000..b6ab3c6408 --- /dev/null +++ b/shadowsocks-android/gradle/libs.versions.toml @@ -0,0 +1,54 @@ +[versions] +camera = "1.4.2" +coroutines = "1.10.2" +lifecycle = "2.9.0" +room = "2.7.1" +work = "2.10.1" + +[libraries] +android-gradle = "com.android.tools.build:gradle:8.10.0" +androidx-browser = "androidx.browser:browser:1.8.0" +androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "camera" } +androidx-camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "camera" } +androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "camera" } +androidx-concurrent-futures-ktx = "androidx.concurrent:concurrent-futures-ktx:1.2.0" +androidx-constraintlayout = "androidx.constraintlayout:constraintlayout:2.2.1" +androidx-core-ktx = "androidx.core:core-ktx:1.16.0" +androidx-espresso-core = "androidx.test.espresso:espresso-core:3.6.1" +androidx-junit-ktx = "androidx.test.ext:junit-ktx:1.2.1" +androidx-leanback-preference = "androidx.leanback:leanback-preference:1.2.0" +androidx-lifecycle-livedata-core-ktx = { module = "androidx.lifecycle:lifecycle-livedata-core-ktx", version.ref = "lifecycle" } +androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycle" } +androidx-preference = "androidx.preference:preference:1.2.1" +androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" } +androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" } +androidx-room-testing = { module = "androidx.room:room-testing", version.ref = "room" } +androidx-test-runner = "androidx.test:runner:1.6.2" +androidx-work-multiprocess = { module = "androidx.work:work-multiprocess", version.ref = "work" } +androidx-work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version.ref = "work" } +barcode-scanning = "com.google.mlkit:barcode-scanning:17.3.0" +desugar = "com.android.tools:desugar_jdk_libs:2.1.5" +dnsjava = "dnsjava:dnsjava:3.6.3" +dokka = "org.jetbrains.dokka:dokka-gradle-plugin:2.0.0" +fastscroll = "me.zhanghai.android.fastscroll:library:1.3.0" +firebase-analytics = "com.google.firebase:firebase-analytics:22.4.0" +firebase-crashlytics = "com.google.firebase:firebase-crashlytics:19.4.3" +firebase-crashlytics-gradle = "com.google.firebase:firebase-crashlytics-gradle:3.0.3" +google-oss-licenses = "com.google.android.gms:oss-licenses-plugin:0.10.6" +google-services = "com.google.gms:google-services:4.4.2" +gradle-maven-publish = "com.vanniktech:gradle-maven-publish-plugin:0.31.0" +junit = "junit:junit:4.13.2" +kotlin-gradle = "org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.20" +kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "coroutines" } +kotlinx-coroutines-play-services = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-play-services", version.ref = "coroutines" } +locale-api = "com.twofortyfouram:android-plugin-api-for-locale:1.0.4" +material = "com.google.android.material:material:1.12.0" +play-services-oss-licenses = "com.google.android.gms:play-services-oss-licenses:17.1.0" +preferencex-simplemenu = "com.takisoft.preferencex:preferencex-simplemenu:1.1.0" +rust-android = "org.mozilla.rust-android-gradle:plugin:0.9.6" +timber = "com.jakewharton.timber:timber:5.0.1" +zxing = "com.google.zxing:core:3.5.3" + +[plugins] +ksp = "com.google.devtools.ksp:2.1.20-2.0.1" +versions = "com.github.ben-manes.versions:0.52.0" diff --git a/shadowsocks-android/gradle/wrapper/gradle-wrapper.properties b/shadowsocks-android/gradle/wrapper/gradle-wrapper.properties index 37f853b1c8..ca025c83a7 100644 --- a/shadowsocks-android/gradle/wrapper/gradle-wrapper.properties +++ b/shadowsocks-android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/shadowsocks-android/mobile/build.gradle.kts b/shadowsocks-android/mobile/build.gradle.kts index 6356d568b4..4cd077fc63 100644 --- a/shadowsocks-android/mobile/build.gradle.kts +++ b/shadowsocks-android/mobile/build.gradle.kts @@ -15,18 +15,20 @@ android { } dependencies { - val cameraxVersion = "1.4.2" - - implementation("androidx.browser:browser:1.8.0") - implementation("androidx.camera:camera-camera2:$cameraxVersion") - implementation("androidx.camera:camera-lifecycle:$cameraxVersion") - implementation("androidx.camera:camera-view:$cameraxVersion") - implementation("androidx.concurrent:concurrent-futures-ktx:1.2.0") - implementation("androidx.constraintlayout:constraintlayout:2.2.1") - implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion") - implementation("com.google.mlkit:barcode-scanning:17.3.0") - implementation("com.google.zxing:core:3.5.3") - implementation("com.takisoft.preferencex:preferencex-simplemenu:1.1.0") - implementation("com.twofortyfouram:android-plugin-api-for-locale:1.0.4") - implementation("me.zhanghai.android.fastscroll:library:1.3.0") + coreLibraryDesugaring(libs.desugar) + implementation(libs.androidx.browser) + implementation(libs.androidx.camera.camera2) + implementation(libs.androidx.camera.lifecycle) + implementation(libs.androidx.camera.view) + implementation(libs.androidx.concurrent.futures.ktx) + implementation(libs.androidx.constraintlayout) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.barcode.scanning) + implementation(libs.fastscroll) + implementation(libs.locale.api) + implementation(libs.preferencex.simplemenu) + implementation(libs.zxing) + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(libs.androidx.test.runner) } diff --git a/shadowsocks-android/plugin/build.gradle.kts b/shadowsocks-android/plugin/build.gradle.kts index c53d55ede1..5bac8ca61b 100644 --- a/shadowsocks-android/plugin/build.gradle.kts +++ b/shadowsocks-android/plugin/build.gradle.kts @@ -13,8 +13,11 @@ android { } dependencies { - api(kotlin("stdlib-jdk8")) + coreLibraryDesugaring(libs.desugar) api("androidx.core:core-ktx:1.7.0") api("androidx.fragment:fragment-ktx:1.5.5") api("com.google.android.material:material:1.6.0") + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.test.runner) + androidTestImplementation(libs.androidx.espresso.core) } diff --git a/shadowsocks-android/repositories.gradle.kts b/shadowsocks-android/repositories.gradle.kts index 9da871b7a2..b93e748adf 100644 --- a/shadowsocks-android/repositories.gradle.kts +++ b/shadowsocks-android/repositories.gradle.kts @@ -1,8 +1,3 @@ -rootProject.extra.apply { - set("androidPlugin", "com.android.tools.build:gradle:8.9.1") - set("kotlinVersion", "2.1.20") -} - repositories { google() mavenCentral() diff --git a/shadowsocks-android/tv/build.gradle.kts b/shadowsocks-android/tv/build.gradle.kts index 33c8c205e2..da9687eb9f 100644 --- a/shadowsocks-android/tv/build.gradle.kts +++ b/shadowsocks-android/tv/build.gradle.kts @@ -27,5 +27,9 @@ android { } dependencies { - implementation("androidx.leanback:leanback-preference:1.1.0-rc01") + coreLibraryDesugaring(libs.desugar) + implementation(libs.androidx.leanback.preference) + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(libs.androidx.test.runner) } diff --git a/v2rayn/v2rayN/ServiceLib/Handler/Fmt/VmessFmt.cs b/v2rayn/v2rayN/ServiceLib/Handler/Fmt/VmessFmt.cs index 71b4c0c230..5892236fdb 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/Fmt/VmessFmt.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/Fmt/VmessFmt.cs @@ -6,9 +6,9 @@ public class VmessFmt : BaseFmt { msg = ResUI.ConfigurationFormatIncorrect; ProfileItem? item; - if (str.IndexOf('?') > 0 && str.IndexOf('&') > 0) + if (str.IndexOf('@') > 0) { - item = ResolveStdVmess(str); + item = ResolveStdVmess(str) ?? ResolveVmess(str, out msg); } else { diff --git a/xray-core/.github/workflows/release-win7.yml b/xray-core/.github/workflows/release-win7.yml index 6595dc07a5..be9173e348 100644 --- a/xray-core/.github/workflows/release-win7.yml +++ b/xray-core/.github/workflows/release-win7.yml @@ -9,7 +9,38 @@ on: types: [opened, synchronize, reopened] jobs: + check-assets: + runs-on: ubuntu-latest + steps: + - name: Restore Geodat Cache + uses: actions/cache/restore@v4 + with: + path: resources + key: xray-geodat- + + - name: Check Assets Existence + id: check-assets + run: | + [ -d 'resources' ] || mkdir resources + LIST=('geoip.dat' 'geosite.dat') + for FILE_NAME in "${LIST[@]}" + do + echo -e "Checking ${FILE_NAME}..." + if [ -s "./resources/${FILE_NAME}" ]; then + echo -e "${FILE_NAME} exists." + else + echo -e "${FILE_NAME} does not exist." + echo "missing=true" >> $GITHUB_OUTPUT + break + fi + done + + - name: Sleep for 90 seconds if Assets Missing + if: steps.check-assets.outputs.missing == 'true' + run: sleep 90 + build: + needs: check-assets permissions: contents: write strategy: diff --git a/xray-core/.github/workflows/release.yml b/xray-core/.github/workflows/release.yml index c52f585e3e..b18e94adcb 100644 --- a/xray-core/.github/workflows/release.yml +++ b/xray-core/.github/workflows/release.yml @@ -9,7 +9,53 @@ on: types: [opened, synchronize, reopened] jobs: + check-assets: + runs-on: ubuntu-latest + steps: + - name: Restore Geodat Cache + uses: actions/cache/restore@v4 + with: + path: resources + key: xray-geodat- + + - name: Check Assets Existence + id: check-assets + run: | + [ -d 'resources' ] || mkdir resources + LIST=('geoip.dat' 'geosite.dat') + for FILE_NAME in "${LIST[@]}" + do + echo -e "Checking ${FILE_NAME}..." + if [ -s "./resources/${FILE_NAME}" ]; then + echo -e "${FILE_NAME} exists." + else + echo -e "${FILE_NAME} does not exist." + echo "missing=true" >> $GITHUB_OUTPUT + break + fi + done + + - name: Trigger Asset Update Workflow if Assets Missing + if: steps.check-assets.outputs.missing == 'true' + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { owner, repo } = context.repo; + await github.rest.actions.createWorkflowDispatch({ + owner, + repo, + workflow_id: 'scheduled-assets-update.yml', + ref: context.ref + }); + console.log('Triggered scheduled-assets-update.yml due to missing assets on branch:', context.ref); + + - name: Sleep for 90 seconds if Assets Missing + if: steps.check-assets.outputs.missing == 'true' + run: sleep 90 + build: + needs: check-assets permissions: contents: write strategy: diff --git a/xray-core/.github/workflows/scheduled-assets-update.yml b/xray-core/.github/workflows/scheduled-assets-update.yml index c5149d92d4..089c3b333d 100644 --- a/xray-core/.github/workflows/scheduled-assets-update.yml +++ b/xray-core/.github/workflows/scheduled-assets-update.yml @@ -1,6 +1,6 @@ name: Scheduled assets update -# NOTE: This Github Actions is required by other actions, for preparing other packaging assets in a +# NOTE: This Github Actions is required by other actions, for preparing other packaging assets in a # routine manner, for example: GeoIP/GeoSite. # Currently updating: # - Geodat (GeoIP/Geosite) @@ -9,7 +9,7 @@ on: workflow_dispatch: schedule: # Update GeoData on every day (22:30 UTC) - - cron: '30 22 * * *' + - cron: "30 22 * * *" push: # Prevent triggering update request storm paths: diff --git a/xray-core/.github/workflows/test.yml b/xray-core/.github/workflows/test.yml index 7ef9de6538..c853a1435b 100644 --- a/xray-core/.github/workflows/test.yml +++ b/xray-core/.github/workflows/test.yml @@ -6,7 +6,36 @@ on: types: [opened, synchronize, reopened] jobs: + check-assets: + runs-on: ubuntu-latest + steps: + - name: Restore Geodat Cache + uses: actions/cache/restore@v4 + with: + path: resources + key: xray-geodat- + - name: Check Assets Existence + id: check-assets + run: | + [ -d 'resources' ] || mkdir resources + LIST=('geoip.dat' 'geosite.dat') + for FILE_NAME in "${LIST[@]}" + do + echo -e "Checking ${FILE_NAME}..." + if [ -s "./resources/${FILE_NAME}" ]; then + echo -e "${FILE_NAME} exists." + else + echo -e "${FILE_NAME} does not exist." + echo "missing=true" >> $GITHUB_OUTPUT + break + fi + done + - name: Sleep for 90 seconds if Assets Missing + if: steps.check-assets.outputs.missing == 'true' + run: sleep 90 + test: + needs: check-assets permissions: contents: read runs-on: ${{ matrix.os }} diff --git a/xray-core/go.mod b/xray-core/go.mod index d162fec85c..7df5469dfe 100644 --- a/xray-core/go.mod +++ b/xray-core/go.mod @@ -9,11 +9,11 @@ require ( github.com/golang/mock v1.7.0-rc.1 github.com/google/go-cmp v0.7.0 github.com/gorilla/websocket v1.5.3 - github.com/miekg/dns v1.1.65 + github.com/miekg/dns v1.1.66 github.com/pelletier/go-toml v1.9.5 github.com/pires/go-proxyproto v0.8.1 github.com/quic-go/quic-go v0.51.0 - github.com/refraction-networking/utls v1.7.1 + github.com/refraction-networking/utls v1.7.2 github.com/sagernet/sing v0.5.1 github.com/sagernet/sing-shadowsocks v0.2.7 github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 @@ -31,7 +31,7 @@ require ( google.golang.org/protobuf v1.36.6 gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5 h12.io/socks v1.0.3 - lukechampine.com/blake3 v1.4.0 + lukechampine.com/blake3 v1.4.1 ) require ( @@ -49,10 +49,10 @@ require ( github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect github.com/vishvananda/netns v0.0.4 // indirect go.uber.org/mock v0.5.0 // indirect - golang.org/x/mod v0.23.0 // indirect + golang.org/x/mod v0.24.0 // indirect golang.org/x/text v0.25.0 // indirect golang.org/x/time v0.7.0 // indirect - golang.org/x/tools v0.30.0 // indirect + golang.org/x/tools v0.32.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/xray-core/go.sum b/xray-core/go.sum index b06e1f7df3..a2f32a1bf5 100644 --- a/xray-core/go.sum +++ b/xray-core/go.sum @@ -38,8 +38,8 @@ github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0N github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/miekg/dns v1.1.65 h1:0+tIPHzUW0GCge7IiK3guGP57VAw7hoPDfApjkMD1Fc= -github.com/miekg/dns v1.1.65/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck= +github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE= +github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE= github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= @@ -56,8 +56,8 @@ github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= github.com/quic-go/quic-go v0.51.0 h1:K8exxe9zXxeRKxaXxi/GpUqYiTrtdiWP8bo1KFya6Wc= github.com/quic-go/quic-go v0.51.0/go.mod h1:MFlGGpcpJqRAfmYi6NC2cptDPSxRWTOGNuP4wqrWmzQ= -github.com/refraction-networking/utls v1.7.1 h1:dxg+jla3uocgN8HtX+ccwDr68uCBBO3qLrkZUbqkcw0= -github.com/refraction-networking/utls v1.7.1/go.mod h1:TUhh27RHMGtQvjQq+RyO11P6ZNQNBb3N0v7wsEjKAIQ= +github.com/refraction-networking/utls v1.7.2 h1:XOgYzit7lAKaa7kzAO5BJR9l4X/H200eVUD4s8SF8/s= +github.com/refraction-networking/utls v1.7.2/go.mod h1:TUhh27RHMGtQvjQq+RyO11P6ZNQNBb3N0v7wsEjKAIQ= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s= github.com/sagernet/sing v0.5.1 h1:mhL/MZVq0TjuvHcpYcFtmSD1BFOxZ/+8ofbNZcg1k1Y= @@ -100,8 +100,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= -golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +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/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -132,8 +132,8 @@ golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= -golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= +golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= +golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= 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-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -160,5 +160,5 @@ gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5 h1:sfK5nHuG7lRFZ2FdTT3RimOq gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5/go.mod h1:3r5CMtNQMKIvBlrmM9xWUNamjKBYPOWyXOjmg5Kts3g= h12.io/socks v1.0.3 h1:Ka3qaQewws4j4/eDQnOdpr4wXsC//dXtWvftlIcCQUo= h12.io/socks v1.0.3/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck= -lukechampine.com/blake3 v1.4.0 h1:xDbKOZCVbnZsfzM6mHSYcGRHZ3YrLDzqz8XnV4uaD5w= -lukechampine.com/blake3 v1.4.0/go.mod h1:MQJNQCTnR+kwOP/JEZSxj3MaQjp80FOFSNMMHXcSeX0= +lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg= +lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo=